@@ -3,7 +3,7 @@ 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:: DllImport ;
6
+ use rustc_middle:: middle:: cstore:: { DllCallingConvention , 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 } ;
@@ -34,8 +34,8 @@ use object::write::Object;
34
34
use object:: { Architecture , BinaryFormat , Endianness , FileFlags , SectionFlags , SectionKind } ;
35
35
use tempfile:: Builder as TempFileBuilder ;
36
36
37
- use std:: cmp:: Ordering ;
38
37
use std:: ffi:: OsString ;
38
+ use std:: iter:: FromIterator ;
39
39
use std:: path:: { Path , PathBuf } ;
40
40
use std:: process:: { ExitStatus , Output , Stdio } ;
41
41
use std:: { ascii, char, env, fmt, fs, io, mem, str} ;
@@ -259,7 +259,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
259
259
}
260
260
261
261
for ( raw_dylib_name, raw_dylib_imports) in
262
- collate_raw_dylibs ( & codegen_results. crate_info . used_libraries )
262
+ collate_raw_dylibs ( sess , & codegen_results. crate_info . used_libraries )
263
263
{
264
264
ab. inject_dll_import_lib ( & raw_dylib_name, & raw_dylib_imports, tmpdir) ;
265
265
}
@@ -451,8 +451,11 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
451
451
/// then the CodegenResults value contains one NativeLib instance for each block. However, the
452
452
/// linker appears to expect only a single import library for each library used, so we need to
453
453
/// collate the symbols together by library name before generating the import libraries.
454
- fn collate_raw_dylibs ( used_libraries : & [ NativeLib ] ) -> Vec < ( String , Vec < DllImport > ) > {
455
- let mut dylib_table: FxHashMap < String , FxHashSet < Symbol > > = FxHashMap :: default ( ) ;
454
+ fn collate_raw_dylibs (
455
+ sess : & Session ,
456
+ used_libraries : & [ NativeLib ] ,
457
+ ) -> Vec < ( String , Vec < DllImport > ) > {
458
+ let mut dylib_table: FxHashMap < String , FxHashSet < DllImport > > = FxHashMap :: default ( ) ;
456
459
457
460
for lib in used_libraries {
458
461
if lib. kind == NativeLibKind :: RawDylib {
@@ -464,35 +467,51 @@ fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImpor
464
467
} else {
465
468
format ! ( "{}.dll" , name)
466
469
} ;
467
- dylib_table
468
- . entry ( name)
469
- . or_default ( )
470
- . extend ( lib. dll_imports . iter ( ) . map ( |import| import. name ) ) ;
470
+ dylib_table. entry ( name) . or_default ( ) . extend ( lib. dll_imports . iter ( ) . cloned ( ) ) ;
471
471
}
472
472
}
473
473
474
- // FIXME: when we add support for ordinals, fix this to propagate ordinals. Also figure out
475
- // what we should do if we have two DllImport values with the same name but different
476
- // ordinals.
477
- let mut result = dylib_table
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
478
480
. into_iter ( )
479
- . map ( |( lib_name, imported_names) | {
480
- let mut names = imported_names
481
- . iter ( )
482
- . map ( |name| DllImport { name : * name, ordinal : None } )
483
- . collect :: < Vec < _ > > ( ) ;
484
- names. sort_unstable_by ( |a : & DllImport , b : & DllImport | {
485
- match a. name . as_str ( ) . cmp ( & b. name . as_str ( ) ) {
486
- Ordering :: Equal => a. ordinal . cmp ( & b. ordinal ) ,
487
- x => x,
488
- }
489
- } ) ;
490
- ( lib_name, names)
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)
491
485
} )
492
486
. collect :: < Vec < _ > > ( ) ;
493
487
result. sort_unstable_by ( |a : & ( String , Vec < DllImport > ) , b : & ( String , Vec < DllImport > ) | {
494
488
a. 0 . cmp ( & b. 0 )
495
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
+ ) ) ;
510
+ }
511
+ }
512
+ }
513
+ }
514
+
496
515
result
497
516
}
498
517
0 commit comments