9
9
// except according to those terms.
10
10
11
11
use back:: wasm;
12
- use cc:: windows_registry;
13
12
use super :: archive:: { ArchiveBuilder , ArchiveConfig } ;
14
13
use 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 ;
15
18
use super :: rpath:: RPathConfig ;
16
19
use super :: rpath;
17
20
use metadata:: METADATA_FILENAME ;
@@ -20,10 +23,9 @@ use rustc::session::config::{RUST_CGU_EXT, Lto};
20
23
use rustc:: session:: filesearch;
21
24
use rustc:: session:: search_paths:: PathKind ;
22
25
use rustc:: session:: Session ;
23
- use rustc:: middle:: cstore:: { NativeLibrary , LibSource , NativeLibraryKind } ;
26
+ use rustc:: middle:: cstore:: { NativeLibrary , NativeLibraryKind } ;
24
27
use rustc:: middle:: dependency_format:: Linkage ;
25
- use rustc_codegen_ssa:: CrateInfo ;
26
- use CodegenResults ;
28
+ use rustc_codegen_ssa:: CodegenResults ;
27
29
use rustc:: util:: common:: time;
28
30
use rustc_fs_util:: fix_windows_verbatim_for_gcc;
29
31
use rustc:: hir:: def_id:: CrateNum ;
@@ -34,6 +36,7 @@ use rustc_codegen_utils::linker::Linker;
34
36
use rustc_codegen_utils:: command:: Command ;
35
37
use context:: get_reloc_model;
36
38
use llvm;
39
+ use LlvmCodegenBackend ;
37
40
38
41
use std:: ascii;
39
42
use std:: char;
@@ -51,77 +54,11 @@ pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default
51
54
invalid_output_for_target, out_filename, check_file_is_writeable,
52
55
filename_for_metadata} ;
53
56
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
- }
120
57
121
58
/// Perform the linkage portion of the compilation phase. This will generate all
122
59
/// of the requested outputs for this compilation session.
123
60
pub ( crate ) fn link_binary ( sess : & Session ,
124
- codegen_results : & CodegenResults ,
61
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
125
62
outputs : & OutputFilenames ,
126
63
crate_name : & str ) -> Vec < PathBuf > {
127
64
let mut out_filenames = Vec :: new ( ) ;
@@ -220,62 +157,8 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
220
157
false
221
158
}
222
159
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
-
277
160
fn link_binary_output ( sess : & Session ,
278
- codegen_results : & CodegenResults ,
161
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
279
162
crate_type : config:: CrateType ,
280
163
outputs : & OutputFilenames ,
281
164
crate_name : & str ) -> Vec < PathBuf > {
@@ -362,8 +245,11 @@ fn archive_config<'a>(sess: &'a Session,
362
245
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
363
246
/// directory being searched for `extern crate` (observing an incomplete file).
364
247
/// 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 {
367
253
let out_filename = tmpdir. path ( ) . join ( METADATA_FILENAME ) ;
368
254
let result = fs:: write ( & out_filename, & codegen_results. metadata . raw_data ) ;
369
255
@@ -386,7 +272,7 @@ enum RlibFlavor {
386
272
// all of the object files from native libraries. This is done by unzipping
387
273
// native libraries and inserting all of the contents into this archive.
388
274
fn link_rlib < ' a > ( sess : & ' a Session ,
389
- codegen_results : & CodegenResults ,
275
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
390
276
flavor : RlibFlavor ,
391
277
out_filename : & Path ,
392
278
tmpdir : & TempDir ) -> ArchiveBuilder < ' a > {
@@ -500,7 +386,7 @@ fn link_rlib<'a>(sess: &'a Session,
500
386
// link in the metadata object file (and also don't prepare the archive with a
501
387
// metadata file).
502
388
fn link_staticlib ( sess : & Session ,
503
- codegen_results : & CodegenResults ,
389
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
504
390
out_filename : & Path ,
505
391
tempdir : & TempDir ) {
506
392
let mut ab = link_rlib ( sess,
@@ -585,77 +471,14 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) {
585
471
}
586
472
}
587
473
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
-
651
474
// Create a dynamic library or executable
652
475
//
653
476
// This will invoke the system linker/cc to create the resulting file. This
654
477
// links to all upstream files as well.
655
478
fn link_natively ( sess : & Session ,
656
479
crate_type : config:: CrateType ,
657
480
out_filename : & Path ,
658
- codegen_results : & CodegenResults ,
481
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
659
482
tmpdir : & Path ) {
660
483
info ! ( "preparing {:?} to {:?}" , crate_type, out_filename) ;
661
484
let ( linker, flavor) = linker_and_flavor ( sess) ;
@@ -1030,7 +853,7 @@ fn link_args(cmd: &mut dyn Linker,
1030
853
crate_type : config:: CrateType ,
1031
854
tmpdir : & Path ,
1032
855
out_filename : & Path ,
1033
- codegen_results : & CodegenResults ) {
856
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ) {
1034
857
1035
858
// Linker plugins should be specified early in the list of arguments
1036
859
cmd. cross_lang_lto ( ) ;
@@ -1242,7 +1065,7 @@ fn link_args(cmd: &mut dyn Linker,
1242
1065
// may have their native library pulled in above.
1243
1066
fn add_local_native_libraries ( cmd : & mut dyn Linker ,
1244
1067
sess : & Session ,
1245
- codegen_results : & CodegenResults ) {
1068
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ) {
1246
1069
sess. target_filesearch ( PathKind :: All ) . for_each_lib_search_path ( |path, k| {
1247
1070
match k {
1248
1071
PathKind :: Framework => { cmd. framework_path ( path) ; }
@@ -1277,7 +1100,7 @@ fn add_local_native_libraries(cmd: &mut dyn Linker,
1277
1100
// the intermediate rlib version)
1278
1101
fn add_upstream_rust_crates ( cmd : & mut dyn Linker ,
1279
1102
sess : & Session ,
1280
- codegen_results : & CodegenResults ,
1103
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
1281
1104
crate_type : config:: CrateType ,
1282
1105
tmpdir : & Path ) {
1283
1106
// All of the heavy lifting has previously been accomplished by the
@@ -1401,7 +1224,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
1401
1224
// linking it.
1402
1225
fn link_sanitizer_runtime ( cmd : & mut dyn Linker ,
1403
1226
sess : & Session ,
1404
- codegen_results : & CodegenResults ,
1227
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
1405
1228
tmpdir : & Path ,
1406
1229
cnum : CrateNum ) {
1407
1230
let src = & codegen_results. crate_info . used_crate_source [ & cnum] ;
@@ -1470,7 +1293,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
1470
1293
// we're at the end of the dependency chain.
1471
1294
fn add_static_crate ( cmd : & mut dyn Linker ,
1472
1295
sess : & Session ,
1473
- codegen_results : & CodegenResults ,
1296
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
1474
1297
tmpdir : & Path ,
1475
1298
crate_type : config:: CrateType ,
1476
1299
cnum : CrateNum ) {
@@ -1610,7 +1433,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
1610
1433
// also be resolved in the target crate.
1611
1434
fn add_upstream_native_libraries ( cmd : & mut dyn Linker ,
1612
1435
sess : & Session ,
1613
- codegen_results : & CodegenResults ,
1436
+ codegen_results : & CodegenResults < LlvmCodegenBackend > ,
1614
1437
crate_type : config:: CrateType ) {
1615
1438
// Be sure to use a topological sorting of crates because there may be
1616
1439
// interdependencies between native libraries. When passing -nodefaultlibs,
0 commit comments