|
1 | | -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
| 1 | +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; |
2 | 2 | use rustc_data_structures::temp_dir::MaybeTempDir; |
3 | 3 | use rustc_errors::Handler; |
4 | 4 | use rustc_fs_util::fix_windows_verbatim_for_gcc; |
5 | 5 | use rustc_hir::def_id::CrateNum; |
6 | | -use rustc_middle::middle::cstore::{DllCallingConvention, DllImport}; |
| 6 | +use rustc_middle::middle::cstore::DllImport; |
7 | 7 | use rustc_middle::middle::dependency_format::Linkage; |
8 | 8 | use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; |
9 | 9 | use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; |
@@ -35,7 +35,6 @@ use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, Se |
35 | 35 | use tempfile::Builder as TempFileBuilder; |
36 | 36 |
|
37 | 37 | use std::ffi::OsString; |
38 | | -use std::iter::FromIterator; |
39 | 38 | use std::path::{Path, PathBuf}; |
40 | 39 | use std::process::{ExitStatus, Output, Stdio}; |
41 | 40 | use std::{ascii, char, env, fmt, fs, io, mem, str}; |
@@ -455,64 +454,39 @@ fn collate_raw_dylibs( |
455 | 454 | sess: &Session, |
456 | 455 | used_libraries: &[NativeLib], |
457 | 456 | ) -> 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(); |
459 | 459 |
|
460 | 460 | for lib in used_libraries { |
461 | 461 | 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 | + } |
510 | 479 | } |
511 | 480 | } |
512 | 481 | } |
513 | 482 | } |
514 | 483 |
|
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() |
516 | 490 | } |
517 | 491 |
|
518 | 492 | /// Create a static archive. |
|
0 commit comments