1- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
22use rustc_data_structures:: temp_dir:: MaybeTempDir ;
3- use rustc_errors:: Handler ;
3+ use rustc_errors:: { ErrorReported , Handler } ;
44use rustc_fs_util:: fix_windows_verbatim_for_gcc;
55use rustc_hir:: def_id:: CrateNum ;
6- use rustc_middle:: middle:: cstore:: { DllCallingConvention , DllImport } ;
6+ use rustc_middle:: middle:: cstore:: DllImport ;
77use rustc_middle:: middle:: dependency_format:: Linkage ;
88use rustc_session:: config:: { self , CFGuard , CrateType , DebugInfo , LdImpl , Strip } ;
99use rustc_session:: config:: { OutputFilenames , OutputType , PrintRequest } ;
@@ -35,7 +35,6 @@ use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, Se
3535use tempfile:: Builder as TempFileBuilder ;
3636
3737use std:: ffi:: OsString ;
38- use std:: iter:: FromIterator ;
3938use std:: path:: { Path , PathBuf } ;
4039use std:: process:: { ExitStatus , Output , Stdio } ;
4140use std:: { ascii, char, env, fmt, fs, io, mem, str} ;
@@ -54,7 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
5453 sess : & ' a Session ,
5554 codegen_results : & CodegenResults ,
5655 outputs : & OutputFilenames ,
57- ) {
56+ ) -> Result < ( ) , ErrorReported > {
5857 let _timer = sess. timer ( "link_binary" ) ;
5958 let output_metadata = sess. opts . output_types . contains_key ( & OutputType :: Metadata ) ;
6059 for & crate_type in sess. crate_types ( ) . iter ( ) {
@@ -95,11 +94,17 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
9594 match crate_type {
9695 CrateType :: Rlib => {
9796 let _timer = sess. timer ( "link_rlib" ) ;
98- link_rlib :: < B > ( sess, codegen_results, RlibFlavor :: Normal , & out_filename, & path)
99- . build ( ) ;
97+ link_rlib :: < B > (
98+ sess,
99+ codegen_results,
100+ RlibFlavor :: Normal ,
101+ & out_filename,
102+ & path,
103+ ) ?
104+ . build ( ) ;
100105 }
101106 CrateType :: Staticlib => {
102- link_staticlib :: < B > ( sess, codegen_results, & out_filename, & path) ;
107+ link_staticlib :: < B > ( sess, codegen_results, & out_filename, & path) ? ;
103108 }
104109 _ => {
105110 link_natively :: < B > (
@@ -145,6 +150,8 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
145150 }
146151 }
147152 } ) ;
153+
154+ Ok ( ( ) )
148155}
149156
150157pub fn each_linked_rlib (
@@ -220,7 +227,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
220227 flavor : RlibFlavor ,
221228 out_filename : & Path ,
222229 tmpdir : & MaybeTempDir ,
223- ) -> B {
230+ ) -> Result < B , ErrorReported > {
224231 info ! ( "preparing rlib to {:?}" , out_filename) ;
225232 let mut ab = <B as ArchiveBuilder >:: new ( sess, out_filename, None ) ;
226233
@@ -259,7 +266,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
259266 }
260267
261268 for ( raw_dylib_name, raw_dylib_imports) in
262- collate_raw_dylibs ( sess, & codegen_results. crate_info . used_libraries )
269+ collate_raw_dylibs ( sess, & codegen_results. crate_info . used_libraries ) ?
263270 {
264271 ab. inject_dll_import_lib ( & raw_dylib_name, & raw_dylib_imports, tmpdir) ;
265272 }
@@ -312,7 +319,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
312319 }
313320 }
314321 }
315- return ab ;
322+ return Ok ( ab ) ;
316323
317324 // For rlibs we "pack" rustc metadata into a dummy object file. When rustc
318325 // creates a dylib crate type it will pass `--whole-archive` (or the
@@ -454,65 +461,40 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
454461fn collate_raw_dylibs (
455462 sess : & Session ,
456463 used_libraries : & [ NativeLib ] ,
457- ) -> Vec < ( String , Vec < DllImport > ) > {
458- let mut dylib_table: FxHashMap < String , FxHashSet < DllImport > > = FxHashMap :: default ( ) ;
464+ ) -> Result < Vec < ( String , Vec < DllImport > ) > , ErrorReported > {
465+ // Use index maps to preserve original order of imports and libraries.
466+ let mut dylib_table = FxIndexMap :: < String , FxIndexMap < Symbol , & DllImport > > :: default ( ) ;
459467
460468 for lib in used_libraries {
461469 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- ) ) ;
470+ let ext = if matches ! ( lib. verbatim, Some ( true ) ) { "" } else { ".dll" } ;
471+ let name = format ! ( "{}{}" , lib. name. expect( "unnamed raw-dylib library" ) , ext) ;
472+ let imports = dylib_table. entry ( name. clone ( ) ) . or_default ( ) ;
473+ for import in & lib. dll_imports {
474+ if let Some ( old_import) = imports. insert ( import. name , import) {
475+ // FIXME: when we add support for ordinals, figure out if we need to do anything
476+ // if we have two DllImport values with the same name but different ordinals.
477+ if import. calling_convention != old_import. calling_convention {
478+ sess. span_err (
479+ import. span ,
480+ & format ! (
481+ "multiple declarations of external function `{}` from \
482+ library `{}` have different calling conventions",
483+ import. name, name,
484+ ) ,
485+ ) ;
486+ }
510487 }
511488 }
512489 }
513490 }
514-
515- result
491+ sess. compile_status ( ) ?;
492+ Ok ( dylib_table
493+ . into_iter ( )
494+ . map ( |( name, imports) | {
495+ ( name, imports. into_iter ( ) . map ( |( _, import) | import. clone ( ) ) . collect ( ) )
496+ } )
497+ . collect ( ) )
516498}
517499
518500/// Create a static archive.
@@ -531,9 +513,9 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
531513 codegen_results : & CodegenResults ,
532514 out_filename : & Path ,
533515 tempdir : & MaybeTempDir ,
534- ) {
516+ ) -> Result < ( ) , ErrorReported > {
535517 let mut ab =
536- link_rlib :: < B > ( sess, codegen_results, RlibFlavor :: StaticlibBase , out_filename, tempdir) ;
518+ link_rlib :: < B > ( sess, codegen_results, RlibFlavor :: StaticlibBase , out_filename, tempdir) ? ;
537519 let mut all_native_libs = vec ! [ ] ;
538520
539521 let res = each_linked_rlib ( & codegen_results. crate_info , & mut |cnum, path| {
@@ -581,6 +563,8 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
581563 print_native_static_libs ( sess, & all_native_libs) ;
582564 }
583565 }
566+
567+ Ok ( ( ) )
584568}
585569
586570fn escape_stdout_stderr_string ( s : & [ u8 ] ) -> String {
0 commit comments