99// except according to those terms.
1010
1111use back:: wasm;
12- use cc:: windows_registry;
1312use super :: archive:: { ArchiveBuilder , ArchiveConfig } ;
1413use super :: bytecode:: RLIB_BYTECODE_EXTENSION ;
14+ use rustc_codegen_ssa:: back:: linker:: Linker ;
15+ use rustc_codegen_ssa:: back:: link:: { remove, ignored_for_lto, each_linked_rlib, linker_and_flavor,
16+ get_linker} ;
17+ use rustc_codegen_ssa:: back:: command:: Command ;
1518use super :: rpath:: RPathConfig ;
1619use super :: rpath;
1720use metadata:: METADATA_FILENAME ;
@@ -20,10 +23,9 @@ use rustc::session::config::{RUST_CGU_EXT, Lto};
2023use rustc:: session:: filesearch;
2124use rustc:: session:: search_paths:: PathKind ;
2225use rustc:: session:: Session ;
23- use rustc:: middle:: cstore:: { NativeLibrary , LibSource , NativeLibraryKind } ;
26+ use rustc:: middle:: cstore:: { NativeLibrary , NativeLibraryKind } ;
2427use rustc:: middle:: dependency_format:: Linkage ;
25- use rustc_codegen_ssa:: CrateInfo ;
26- use CodegenResults ;
28+ use rustc_codegen_ssa:: CodegenResults ;
2729use rustc:: util:: common:: time;
2830use rustc_fs_util:: fix_windows_verbatim_for_gcc;
2931use rustc:: hir:: def_id:: CrateNum ;
@@ -34,6 +36,7 @@ use rustc_codegen_utils::linker::Linker;
3436use rustc_codegen_utils:: command:: Command ;
3537use context:: get_reloc_model;
3638use llvm;
39+ use LlvmCodegenBackend ;
3740
3841use std:: ascii;
3942use std:: char;
@@ -51,77 +54,11 @@ pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default
5154 invalid_output_for_target, out_filename, check_file_is_writeable,
5255 filename_for_metadata} ;
5356
54- // The third parameter is for env vars, used on windows to set up the
55- // path for MSVC to find its DLLs, and gcc to find its bundled
56- // toolchain
57- pub fn get_linker ( sess : & Session , linker : & Path , flavor : LinkerFlavor ) -> ( PathBuf , Command ) {
58- let msvc_tool = windows_registry:: find_tool ( & sess. opts . target_triple . triple ( ) , "link.exe" ) ;
59-
60- // If our linker looks like a batch script on Windows then to execute this
61- // we'll need to spawn `cmd` explicitly. This is primarily done to handle
62- // emscripten where the linker is `emcc.bat` and needs to be spawned as
63- // `cmd /c emcc.bat ...`.
64- //
65- // This worked historically but is needed manually since #42436 (regression
66- // was tagged as #42791) and some more info can be found on #44443 for
67- // emscripten itself.
68- let mut cmd = match linker. to_str ( ) {
69- Some ( linker) if cfg ! ( windows) && linker. ends_with ( ".bat" ) => Command :: bat_script ( linker) ,
70- _ => match flavor {
71- LinkerFlavor :: Lld ( f) => Command :: lld ( linker, f) ,
72- LinkerFlavor :: Msvc
73- if sess. opts . cg . linker . is_none ( ) && sess. target . target . options . linker . is_none ( ) =>
74- {
75- Command :: new ( msvc_tool. as_ref ( ) . map ( |t| t. path ( ) ) . unwrap_or ( linker) )
76- } ,
77- _ => Command :: new ( linker) ,
78- }
79- } ;
80-
81- // The compiler's sysroot often has some bundled tools, so add it to the
82- // PATH for the child.
83- let mut new_path = sess. host_filesearch ( PathKind :: All )
84- . get_tools_search_paths ( ) ;
85- let mut msvc_changed_path = false ;
86- if sess. target . target . options . is_like_msvc {
87- if let Some ( ref tool) = msvc_tool {
88- cmd. args ( tool. args ( ) ) ;
89- for & ( ref k, ref v) in tool. env ( ) {
90- if k == "PATH" {
91- new_path. extend ( env:: split_paths ( v) ) ;
92- msvc_changed_path = true ;
93- } else {
94- cmd. env ( k, v) ;
95- }
96- }
97- }
98- }
99-
100- if !msvc_changed_path {
101- if let Some ( path) = env:: var_os ( "PATH" ) {
102- new_path. extend ( env:: split_paths ( & path) ) ;
103- }
104- }
105- cmd. env ( "PATH" , env:: join_paths ( new_path) . unwrap ( ) ) ;
106-
107- ( linker. to_path_buf ( ) , cmd)
108- }
109-
110- pub fn remove ( sess : & Session , path : & Path ) {
111- match fs:: remove_file ( path) {
112- Ok ( ..) => { }
113- Err ( e) => {
114- sess. err ( & format ! ( "failed to remove {}: {}" ,
115- path. display( ) ,
116- e) ) ;
117- }
118- }
119- }
12057
12158/// Perform the linkage portion of the compilation phase. This will generate all
12259/// of the requested outputs for this compilation session.
12360pub ( crate ) fn link_binary ( sess : & Session ,
124- codegen_results : & CodegenResults ,
61+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
12562 outputs : & OutputFilenames ,
12663 crate_name : & str ) -> Vec < PathBuf > {
12764 let mut out_filenames = Vec :: new ( ) ;
@@ -220,62 +157,8 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
220157 false
221158}
222159
223- pub ( crate ) fn each_linked_rlib ( sess : & Session ,
224- info : & CrateInfo ,
225- f : & mut dyn FnMut ( CrateNum , & Path ) ) -> Result < ( ) , String > {
226- let crates = info. used_crates_static . iter ( ) ;
227- let fmts = sess. dependency_formats . borrow ( ) ;
228- let fmts = fmts. get ( & config:: CrateType :: Executable )
229- . or_else ( || fmts. get ( & config:: CrateType :: Staticlib ) )
230- . or_else ( || fmts. get ( & config:: CrateType :: Cdylib ) )
231- . or_else ( || fmts. get ( & config:: CrateType :: ProcMacro ) ) ;
232- let fmts = match fmts {
233- Some ( f) => f,
234- None => return Err ( "could not find formats for rlibs" . to_string ( ) )
235- } ;
236- for & ( cnum, ref path) in crates {
237- match fmts. get ( cnum. as_usize ( ) - 1 ) {
238- Some ( & Linkage :: NotLinked ) |
239- Some ( & Linkage :: IncludedFromDylib ) => continue ,
240- Some ( _) => { }
241- None => return Err ( "could not find formats for rlibs" . to_string ( ) )
242- }
243- let name = & info. crate_name [ & cnum] ;
244- let path = match * path {
245- LibSource :: Some ( ref p) => p,
246- LibSource :: MetadataOnly => {
247- return Err ( format ! ( "could not find rlib for: `{}`, found rmeta (metadata) file" ,
248- name) )
249- }
250- LibSource :: None => {
251- return Err ( format ! ( "could not find rlib for: `{}`" , name) )
252- }
253- } ;
254- f ( cnum, & path) ;
255- }
256- Ok ( ( ) )
257- }
258-
259- /// Returns a boolean indicating whether the specified crate should be ignored
260- /// during LTO.
261- ///
262- /// Crates ignored during LTO are not lumped together in the "massive object
263- /// file" that we create and are linked in their normal rlib states. See
264- /// comments below for what crates do not participate in LTO.
265- ///
266- /// It's unusual for a crate to not participate in LTO. Typically only
267- /// compiler-specific and unstable crates have a reason to not participate in
268- /// LTO.
269- pub ( crate ) fn ignored_for_lto ( sess : & Session , info : & CrateInfo , cnum : CrateNum ) -> bool {
270- // If our target enables builtin function lowering in LLVM then the
271- // crates providing these functions don't participate in LTO (e.g.
272- // no_builtins or compiler builtins crates).
273- !sess. target . target . options . no_builtins &&
274- ( info. is_no_builtins . contains ( & cnum) || info. compiler_builtins == Some ( cnum) )
275- }
276-
277160fn link_binary_output ( sess : & Session ,
278- codegen_results : & CodegenResults ,
161+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
279162 crate_type : config:: CrateType ,
280163 outputs : & OutputFilenames ,
281164 crate_name : & str ) -> Vec < PathBuf > {
@@ -362,8 +245,11 @@ fn archive_config<'a>(sess: &'a Session,
362245/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
363246/// directory being searched for `extern crate` (observing an incomplete file).
364247/// The returned path is the temporary file containing the complete metadata.
365- fn emit_metadata < ' a > ( sess : & ' a Session , codegen_results : & CodegenResults , tmpdir : & TempDir )
366- -> PathBuf {
248+ fn emit_metadata < ' a > (
249+ sess : & ' a Session ,
250+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
251+ tmpdir : & TempDir
252+ ) -> PathBuf {
367253 let out_filename = tmpdir. path ( ) . join ( METADATA_FILENAME ) ;
368254 let result = fs:: write ( & out_filename, & codegen_results. metadata . raw_data ) ;
369255
@@ -386,7 +272,7 @@ enum RlibFlavor {
386272// all of the object files from native libraries. This is done by unzipping
387273// native libraries and inserting all of the contents into this archive.
388274fn link_rlib < ' a > ( sess : & ' a Session ,
389- codegen_results : & CodegenResults ,
275+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
390276 flavor : RlibFlavor ,
391277 out_filename : & Path ,
392278 tmpdir : & TempDir ) -> ArchiveBuilder < ' a > {
@@ -500,7 +386,7 @@ fn link_rlib<'a>(sess: &'a Session,
500386// link in the metadata object file (and also don't prepare the archive with a
501387// metadata file).
502388fn link_staticlib ( sess : & Session ,
503- codegen_results : & CodegenResults ,
389+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
504390 out_filename : & Path ,
505391 tempdir : & TempDir ) {
506392 let mut ab = link_rlib ( sess,
@@ -585,77 +471,14 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) {
585471 }
586472}
587473
588- pub fn linker_and_flavor ( sess : & Session ) -> ( PathBuf , LinkerFlavor ) {
589- fn infer_from (
590- sess : & Session ,
591- linker : Option < PathBuf > ,
592- flavor : Option < LinkerFlavor > ,
593- ) -> Option < ( PathBuf , LinkerFlavor ) > {
594- match ( linker, flavor) {
595- ( Some ( linker) , Some ( flavor) ) => Some ( ( linker, flavor) ) ,
596- // only the linker flavor is known; use the default linker for the selected flavor
597- ( None , Some ( flavor) ) => Some ( ( PathBuf :: from ( match flavor {
598- LinkerFlavor :: Em => if cfg ! ( windows) { "emcc.bat" } else { "emcc" } ,
599- LinkerFlavor :: Gcc => "cc" ,
600- LinkerFlavor :: Ld => "ld" ,
601- LinkerFlavor :: Msvc => "link.exe" ,
602- LinkerFlavor :: Lld ( _) => "lld" ,
603- } ) , flavor) ) ,
604- ( Some ( linker) , None ) => {
605- let stem = linker. file_stem ( ) . and_then ( |stem| stem. to_str ( ) ) . unwrap_or_else ( || {
606- sess. fatal ( "couldn't extract file stem from specified linker" ) ;
607- } ) . to_owned ( ) ;
608-
609- let flavor = if stem == "emcc" {
610- LinkerFlavor :: Em
611- } else if stem == "gcc" || stem. ends_with ( "-gcc" ) {
612- LinkerFlavor :: Gcc
613- } else if stem == "ld" || stem == "ld.lld" || stem. ends_with ( "-ld" ) {
614- LinkerFlavor :: Ld
615- } else if stem == "link" || stem == "lld-link" {
616- LinkerFlavor :: Msvc
617- } else if stem == "lld" || stem == "rust-lld" {
618- LinkerFlavor :: Lld ( sess. target . target . options . lld_flavor )
619- } else {
620- // fall back to the value in the target spec
621- sess. target . target . linker_flavor
622- } ;
623-
624- Some ( ( linker, flavor) )
625- } ,
626- ( None , None ) => None ,
627- }
628- }
629-
630- // linker and linker flavor specified via command line have precedence over what the target
631- // specification specifies
632- if let Some ( ret) = infer_from (
633- sess,
634- sess. opts . cg . linker . clone ( ) ,
635- sess. opts . debugging_opts . linker_flavor ,
636- ) {
637- return ret;
638- }
639-
640- if let Some ( ret) = infer_from (
641- sess,
642- sess. target . target . options . linker . clone ( ) . map ( PathBuf :: from) ,
643- Some ( sess. target . target . linker_flavor ) ,
644- ) {
645- return ret;
646- }
647-
648- bug ! ( "Not enough information provided to determine how to invoke the linker" ) ;
649- }
650-
651474// Create a dynamic library or executable
652475//
653476// This will invoke the system linker/cc to create the resulting file. This
654477// links to all upstream files as well.
655478fn link_natively ( sess : & Session ,
656479 crate_type : config:: CrateType ,
657480 out_filename : & Path ,
658- codegen_results : & CodegenResults ,
481+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
659482 tmpdir : & Path ) {
660483 info ! ( "preparing {:?} to {:?}" , crate_type, out_filename) ;
661484 let ( linker, flavor) = linker_and_flavor ( sess) ;
@@ -1030,7 +853,7 @@ fn link_args(cmd: &mut dyn Linker,
1030853 crate_type : config:: CrateType ,
1031854 tmpdir : & Path ,
1032855 out_filename : & Path ,
1033- codegen_results : & CodegenResults ) {
856+ codegen_results : & CodegenResults < LlvmCodegenBackend > ) {
1034857
1035858 // Linker plugins should be specified early in the list of arguments
1036859 cmd. cross_lang_lto ( ) ;
@@ -1242,7 +1065,7 @@ fn link_args(cmd: &mut dyn Linker,
12421065// may have their native library pulled in above.
12431066fn add_local_native_libraries ( cmd : & mut dyn Linker ,
12441067 sess : & Session ,
1245- codegen_results : & CodegenResults ) {
1068+ codegen_results : & CodegenResults < LlvmCodegenBackend > ) {
12461069 sess. target_filesearch ( PathKind :: All ) . for_each_lib_search_path ( |path, k| {
12471070 match k {
12481071 PathKind :: Framework => { cmd. framework_path ( path) ; }
@@ -1277,7 +1100,7 @@ fn add_local_native_libraries(cmd: &mut dyn Linker,
12771100// the intermediate rlib version)
12781101fn add_upstream_rust_crates ( cmd : & mut dyn Linker ,
12791102 sess : & Session ,
1280- codegen_results : & CodegenResults ,
1103+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
12811104 crate_type : config:: CrateType ,
12821105 tmpdir : & Path ) {
12831106 // All of the heavy lifting has previously been accomplished by the
@@ -1401,7 +1224,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
14011224 // linking it.
14021225 fn link_sanitizer_runtime ( cmd : & mut dyn Linker ,
14031226 sess : & Session ,
1404- codegen_results : & CodegenResults ,
1227+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
14051228 tmpdir : & Path ,
14061229 cnum : CrateNum ) {
14071230 let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
@@ -1470,7 +1293,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
14701293 // we're at the end of the dependency chain.
14711294 fn add_static_crate ( cmd : & mut dyn Linker ,
14721295 sess : & Session ,
1473- codegen_results : & CodegenResults ,
1296+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
14741297 tmpdir : & Path ,
14751298 crate_type : config:: CrateType ,
14761299 cnum : CrateNum ) {
@@ -1610,7 +1433,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
16101433// also be resolved in the target crate.
16111434fn add_upstream_native_libraries ( cmd : & mut dyn Linker ,
16121435 sess : & Session ,
1613- codegen_results : & CodegenResults ,
1436+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
16141437 crate_type : config:: CrateType ) {
16151438 // Be sure to use a topological sorting of crates because there may be
16161439 // interdependencies between native libraries. When passing -nodefaultlibs,
0 commit comments