|
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