Skip to content

Commit 8b9ce0e

Browse files
committed
Simplify and fix raw dylib collation
1 parent ca99e3e commit 8b9ce0e

File tree

3 files changed

+31
-57
lines changed

3 files changed

+31
-57
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+27-53
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
22
use rustc_data_structures::temp_dir::MaybeTempDir;
33
use rustc_errors::Handler;
44
use rustc_fs_util::fix_windows_verbatim_for_gcc;
55
use rustc_hir::def_id::CrateNum;
6-
use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
6+
use rustc_middle::middle::cstore::DllImport;
77
use rustc_middle::middle::dependency_format::Linkage;
88
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
99
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
@@ -35,7 +35,6 @@ use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, Se
3535
use tempfile::Builder as TempFileBuilder;
3636

3737
use std::ffi::OsString;
38-
use std::iter::FromIterator;
3938
use std::path::{Path, PathBuf};
4039
use std::process::{ExitStatus, Output, Stdio};
4140
use std::{ascii, char, env, fmt, fs, io, mem, str};
@@ -455,64 +454,39 @@ fn collate_raw_dylibs(
455454
sess: &Session,
456455
used_libraries: &[NativeLib],
457456
) -> Vec<(String, Vec<DllImport>)> {
458-
let mut dylib_table: FxHashMap<String, FxHashSet<DllImport>> = FxHashMap::default();
457+
// Use index maps to preserve original order of imports and libraries.
458+
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
459459

460460
for lib in used_libraries {
461461
if lib.kind == NativeLibKind::RawDylib {
462-
let name = lib.name.unwrap_or_else(||
463-
bug!("`link` attribute with kind = \"raw-dylib\" and no name should have caused error earlier")
464-
);
465-
let name = if matches!(lib.verbatim, Some(true)) {
466-
name.to_string()
467-
} else {
468-
format!("{}.dll", name)
469-
};
470-
dylib_table.entry(name).or_default().extend(lib.dll_imports.iter().cloned());
471-
}
472-
}
473-
474-
// Rustc already signals an error if we have two imports with the same name but different
475-
// calling conventions (or function signatures), so we don't have pay attention to those
476-
// when ordering.
477-
// FIXME: when we add support for ordinals, figure out if we need to do anything if we
478-
// have two DllImport values with the same name but different ordinals.
479-
let mut result: Vec<(String, Vec<DllImport>)> = dylib_table
480-
.into_iter()
481-
.map(|(lib_name, import_table)| {
482-
let mut imports = Vec::from_iter(import_table.into_iter());
483-
imports.sort_unstable_by_key(|x: &DllImport| x.name.as_str());
484-
(lib_name, imports)
485-
})
486-
.collect::<Vec<_>>();
487-
result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
488-
a.0.cmp(&b.0)
489-
});
490-
let result = result;
491-
492-
// Check for multiple imports with the same name but different calling conventions or
493-
// (when relevant) argument list sizes. Rustc only signals an error for this if the
494-
// declarations are at the same scope level; if one shadows the other, we only get a lint
495-
// warning.
496-
for (library, imports) in &result {
497-
let mut import_table: FxHashMap<Symbol, DllCallingConvention> = FxHashMap::default();
498-
for import in imports {
499-
if let Some(old_convention) =
500-
import_table.insert(import.name, import.calling_convention)
501-
{
502-
if import.calling_convention != old_convention {
503-
sess.span_fatal(
504-
import.span,
505-
&format!(
506-
"multiple definitions of external function `{}` from library `{}` have different calling conventions",
507-
import.name,
508-
library,
509-
));
462+
let ext = if matches!(lib.verbatim, Some(true)) { "" } else { ".dll" };
463+
let name = format!("{}{}", lib.name.expect("unnamed raw-dylib library"), ext);
464+
let imports = dylib_table.entry(name.clone()).or_default();
465+
for import in &lib.dll_imports {
466+
if let Some(old_import) = imports.insert(import.name, import) {
467+
// FIXME: when we add support for ordinals, figure out if we need to do anything
468+
// if we have two DllImport values with the same name but different ordinals.
469+
if import.calling_convention != old_import.calling_convention {
470+
sess.span_err(
471+
import.span,
472+
&format!(
473+
"multiple declarations of external function `{}` from \
474+
library `{}` have different calling conventions",
475+
import.name, name,
476+
),
477+
);
478+
}
510479
}
511480
}
512481
}
513482
}
514483

515-
result
484+
dylib_table
485+
.into_iter()
486+
.map(|(name, imports)| {
487+
(name, imports.into_iter().map(|(_, import)| import.clone()).collect())
488+
})
489+
.collect()
516490
}
517491

518492
/// Create a static archive.

compiler/rustc_metadata/src/rmeta/encoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1574,7 +1574,7 @@ impl EncodeContext<'a, 'tcx> {
15741574
fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
15751575
empty_proc_macro!(self);
15761576
let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
1577-
self.lazy(used_libraries.iter().cloned())
1577+
self.lazy(used_libraries.iter())
15781578
}
15791579

15801580
fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {

compiler/rustc_middle/src/middle/cstore.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub enum LinkagePreference {
6666
RequireStatic,
6767
}
6868

69-
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
69+
#[derive(Debug, Encodable, Decodable, HashStable)]
7070
pub struct NativeLib {
7171
pub kind: NativeLibKind,
7272
pub name: Option<Symbol>,
@@ -77,7 +77,7 @@ pub struct NativeLib {
7777
pub dll_imports: Vec<DllImport>,
7878
}
7979

80-
#[derive(Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
80+
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
8181
pub struct DllImport {
8282
pub name: Symbol,
8383
pub ordinal: Option<u16>,
@@ -94,7 +94,7 @@ pub struct DllImport {
9494
///
9595
/// The usize value, where present, indicates the size of the function's argument list
9696
/// in bytes.
97-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
97+
#[derive(Clone, PartialEq, Debug, Encodable, Decodable, HashStable)]
9898
pub enum DllCallingConvention {
9999
C,
100100
Stdcall(usize),

0 commit comments

Comments
 (0)