]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_ssa/back/linker.rs
Suggest defining type parameter when appropriate
[rust.git] / src / librustc_codegen_ssa / back / linker.rs
1 use super::archive;
2 use super::command::Command;
3 use super::symbol_export;
4
5 use rustc_data_structures::fx::FxHashMap;
6 use std::ffi::{OsStr, OsString};
7 use std::fs::{self, File};
8 use std::io::prelude::*;
9 use std::io::{self, BufWriter};
10 use std::path::{Path, PathBuf};
11
12 use rustc::middle::dependency_format::Linkage;
13 use rustc::session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel};
14 use rustc::session::Session;
15 use rustc::ty::TyCtxt;
16 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
17 use rustc_serialize::{json, Encoder};
18 use rustc_span::symbol::Symbol;
19 use rustc_target::spec::{LinkerFlavor, LldFlavor};
20
21 /// For all the linkers we support, and information they might
22 /// need out of the shared crate context before we get rid of it.
23 #[derive(RustcEncodable, RustcDecodable)]
24 pub struct LinkerInfo {
25     exports: FxHashMap<CrateType, Vec<String>>,
26 }
27
28 impl LinkerInfo {
29     pub fn new(tcx: TyCtxt<'_>) -> LinkerInfo {
30         LinkerInfo {
31             exports: tcx
32                 .sess
33                 .crate_types
34                 .borrow()
35                 .iter()
36                 .map(|&c| (c, exported_symbols(tcx, c)))
37                 .collect(),
38         }
39     }
40
41     pub fn to_linker<'a>(
42         &'a self,
43         cmd: Command,
44         sess: &'a Session,
45         flavor: LinkerFlavor,
46         target_cpu: &'a str,
47     ) -> Box<dyn Linker + 'a> {
48         match flavor {
49             LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
50                 Box::new(MsvcLinker { cmd, sess, info: self }) as Box<dyn Linker>
51             }
52             LinkerFlavor::Em => Box::new(EmLinker { cmd, sess, info: self }) as Box<dyn Linker>,
53             LinkerFlavor::Gcc => Box::new(GccLinker {
54                 cmd,
55                 sess,
56                 info: self,
57                 hinted_static: false,
58                 is_ld: false,
59                 target_cpu,
60             }) as Box<dyn Linker>,
61
62             LinkerFlavor::Lld(LldFlavor::Ld)
63             | LinkerFlavor::Lld(LldFlavor::Ld64)
64             | LinkerFlavor::Ld => Box::new(GccLinker {
65                 cmd,
66                 sess,
67                 info: self,
68                 hinted_static: false,
69                 is_ld: true,
70                 target_cpu,
71             }) as Box<dyn Linker>,
72
73             LinkerFlavor::Lld(LldFlavor::Wasm) => {
74                 Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
75             }
76
77             LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
78         }
79     }
80 }
81
82 /// Linker abstraction used by `back::link` to build up the command to invoke a
83 /// linker.
84 ///
85 /// This trait is the total list of requirements needed by `back::link` and
86 /// represents the meaning of each option being passed down. This trait is then
87 /// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an
88 /// MSVC linker (e.g., `link.exe`) is being used.
89 pub trait Linker {
90     fn link_dylib(&mut self, lib: Symbol);
91     fn link_rust_dylib(&mut self, lib: Symbol, path: &Path);
92     fn link_framework(&mut self, framework: Symbol);
93     fn link_staticlib(&mut self, lib: Symbol);
94     fn link_rlib(&mut self, lib: &Path);
95     fn link_whole_rlib(&mut self, lib: &Path);
96     fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]);
97     fn include_path(&mut self, path: &Path);
98     fn framework_path(&mut self, path: &Path);
99     fn output_filename(&mut self, path: &Path);
100     fn add_object(&mut self, path: &Path);
101     fn gc_sections(&mut self, keep_metadata: bool);
102     fn position_independent_executable(&mut self);
103     fn no_position_independent_executable(&mut self);
104     fn full_relro(&mut self);
105     fn partial_relro(&mut self);
106     fn no_relro(&mut self);
107     fn optimize(&mut self);
108     fn pgo_gen(&mut self);
109     fn debuginfo(&mut self);
110     fn no_default_libraries(&mut self);
111     fn build_dylib(&mut self, out_filename: &Path);
112     fn build_static_executable(&mut self);
113     fn args(&mut self, args: &[String]);
114     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
115     fn subsystem(&mut self, subsystem: &str);
116     fn group_start(&mut self);
117     fn group_end(&mut self);
118     fn linker_plugin_lto(&mut self);
119     // Should have been finalize(self), but we don't support self-by-value on trait objects (yet?).
120     fn finalize(&mut self) -> Command;
121 }
122
123 pub struct GccLinker<'a> {
124     cmd: Command,
125     sess: &'a Session,
126     info: &'a LinkerInfo,
127     hinted_static: bool, // Keeps track of the current hinting mode.
128     // Link as ld
129     is_ld: bool,
130     target_cpu: &'a str,
131 }
132
133 impl<'a> GccLinker<'a> {
134     /// Argument that must be passed *directly* to the linker
135     ///
136     /// These arguments need to be prepended with `-Wl`, when a GCC-style linker is used.
137     fn linker_arg<S>(&mut self, arg: S) -> &mut Self
138     where
139         S: AsRef<OsStr>,
140     {
141         if !self.is_ld {
142             let mut os = OsString::from("-Wl,");
143             os.push(arg.as_ref());
144             self.cmd.arg(os);
145         } else {
146             self.cmd.arg(arg);
147         }
148         self
149     }
150
151     fn takes_hints(&self) -> bool {
152         // Really this function only returns true if the underlying linker
153         // configured for a compiler is binutils `ld.bfd` and `ld.gold`. We
154         // don't really have a foolproof way to detect that, so rule out some
155         // platforms where currently this is guaranteed to *not* be the case:
156         //
157         // * On OSX they have their own linker, not binutils'
158         // * For WebAssembly the only functional linker is LLD, which doesn't
159         //   support hint flags
160         !self.sess.target.target.options.is_like_osx && self.sess.target.target.arch != "wasm32"
161     }
162
163     // Some platforms take hints about whether a library is static or dynamic.
164     // For those that support this, we ensure we pass the option if the library
165     // was flagged "static" (most defaults are dynamic) to ensure that if
166     // libfoo.a and libfoo.so both exist that the right one is chosen.
167     fn hint_static(&mut self) {
168         if !self.takes_hints() {
169             return;
170         }
171         if !self.hinted_static {
172             self.linker_arg("-Bstatic");
173             self.hinted_static = true;
174         }
175     }
176
177     fn hint_dynamic(&mut self) {
178         if !self.takes_hints() {
179             return;
180         }
181         if self.hinted_static {
182             self.linker_arg("-Bdynamic");
183             self.hinted_static = false;
184         }
185     }
186
187     fn push_linker_plugin_lto_args(&mut self, plugin_path: Option<&OsStr>) {
188         if let Some(plugin_path) = plugin_path {
189             let mut arg = OsString::from("-plugin=");
190             arg.push(plugin_path);
191             self.linker_arg(&arg);
192         }
193
194         let opt_level = match self.sess.opts.optimize {
195             config::OptLevel::No => "O0",
196             config::OptLevel::Less => "O1",
197             config::OptLevel::Default => "O2",
198             config::OptLevel::Aggressive => "O3",
199             config::OptLevel::Size => "Os",
200             config::OptLevel::SizeMin => "Oz",
201         };
202
203         self.linker_arg(&format!("-plugin-opt={}", opt_level));
204         let target_cpu = self.target_cpu;
205         self.linker_arg(&format!("-plugin-opt=mcpu={}", target_cpu));
206     }
207 }
208
209 impl<'a> Linker for GccLinker<'a> {
210     fn link_dylib(&mut self, lib: Symbol) {
211         self.hint_dynamic();
212         self.cmd.arg(format!("-l{}", lib));
213     }
214     fn link_staticlib(&mut self, lib: Symbol) {
215         self.hint_static();
216         self.cmd.arg(format!("-l{}", lib));
217     }
218     fn link_rlib(&mut self, lib: &Path) {
219         self.hint_static();
220         self.cmd.arg(lib);
221     }
222     fn include_path(&mut self, path: &Path) {
223         self.cmd.arg("-L").arg(path);
224     }
225     fn framework_path(&mut self, path: &Path) {
226         self.cmd.arg("-F").arg(path);
227     }
228     fn output_filename(&mut self, path: &Path) {
229         self.cmd.arg("-o").arg(path);
230     }
231     fn add_object(&mut self, path: &Path) {
232         self.cmd.arg(path);
233     }
234     fn position_independent_executable(&mut self) {
235         self.cmd.arg("-pie");
236     }
237     fn no_position_independent_executable(&mut self) {
238         self.cmd.arg("-no-pie");
239     }
240     fn full_relro(&mut self) {
241         self.linker_arg("-zrelro");
242         self.linker_arg("-znow");
243     }
244     fn partial_relro(&mut self) {
245         self.linker_arg("-zrelro");
246     }
247     fn no_relro(&mut self) {
248         self.linker_arg("-znorelro");
249     }
250     fn build_static_executable(&mut self) {
251         self.cmd.arg("-static");
252     }
253     fn args(&mut self, args: &[String]) {
254         self.cmd.args(args);
255     }
256
257     fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
258         self.hint_dynamic();
259         self.cmd.arg(format!("-l{}", lib));
260     }
261
262     fn link_framework(&mut self, framework: Symbol) {
263         self.hint_dynamic();
264         self.cmd.arg("-framework").sym_arg(framework);
265     }
266
267     // Here we explicitly ask that the entire archive is included into the
268     // result artifact. For more details see #15460, but the gist is that
269     // the linker will strip away any unused objects in the archive if we
270     // don't otherwise explicitly reference them. This can occur for
271     // libraries which are just providing bindings, libraries with generic
272     // functions, etc.
273     fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]) {
274         self.hint_static();
275         let target = &self.sess.target.target;
276         if !target.options.is_like_osx {
277             self.linker_arg("--whole-archive").cmd.arg(format!("-l{}", lib));
278             self.linker_arg("--no-whole-archive");
279         } else {
280             // -force_load is the macOS equivalent of --whole-archive, but it
281             // involves passing the full path to the library to link.
282             self.linker_arg("-force_load");
283             let lib = archive::find_library(lib, search_path, &self.sess);
284             self.linker_arg(&lib);
285         }
286     }
287
288     fn link_whole_rlib(&mut self, lib: &Path) {
289         self.hint_static();
290         if self.sess.target.target.options.is_like_osx {
291             self.linker_arg("-force_load");
292             self.linker_arg(&lib);
293         } else {
294             self.linker_arg("--whole-archive").cmd.arg(lib);
295             self.linker_arg("--no-whole-archive");
296         }
297     }
298
299     fn gc_sections(&mut self, keep_metadata: bool) {
300         // The dead_strip option to the linker specifies that functions and data
301         // unreachable by the entry point will be removed. This is quite useful
302         // with Rust's compilation model of compiling libraries at a time into
303         // one object file. For example, this brings hello world from 1.7MB to
304         // 458K.
305         //
306         // Note that this is done for both executables and dynamic libraries. We
307         // won't get much benefit from dylibs because LLVM will have already
308         // stripped away as much as it could. This has not been seen to impact
309         // link times negatively.
310         //
311         // -dead_strip can't be part of the pre_link_args because it's also used
312         // for partial linking when using multiple codegen units (-r).  So we
313         // insert it here.
314         if self.sess.target.target.options.is_like_osx {
315             self.linker_arg("-dead_strip");
316         } else if self.sess.target.target.options.is_like_solaris {
317             self.linker_arg("-zignore");
318
319         // If we're building a dylib, we don't use --gc-sections because LLVM
320         // has already done the best it can do, and we also don't want to
321         // eliminate the metadata. If we're building an executable, however,
322         // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
323         // reduction.
324         } else if !keep_metadata {
325             self.linker_arg("--gc-sections");
326         }
327     }
328
329     fn optimize(&mut self) {
330         if !self.sess.target.target.options.linker_is_gnu {
331             return;
332         }
333
334         // GNU-style linkers support optimization with -O. GNU ld doesn't
335         // need a numeric argument, but other linkers do.
336         if self.sess.opts.optimize == config::OptLevel::Default
337             || self.sess.opts.optimize == config::OptLevel::Aggressive
338         {
339             self.linker_arg("-O1");
340         }
341     }
342
343     fn pgo_gen(&mut self) {
344         if !self.sess.target.target.options.linker_is_gnu {
345             return;
346         }
347
348         // If we're doing PGO generation stuff and on a GNU-like linker, use the
349         // "-u" flag to properly pull in the profiler runtime bits.
350         //
351         // This is because LLVM otherwise won't add the needed initialization
352         // for us on Linux (though the extra flag should be harmless if it
353         // does).
354         //
355         // See https://reviews.llvm.org/D14033 and https://reviews.llvm.org/D14030.
356         //
357         // Though it may be worth to try to revert those changes upstream, since
358         // the overhead of the initialization should be minor.
359         self.cmd.arg("-u");
360         self.cmd.arg("__llvm_profile_runtime");
361     }
362
363     fn debuginfo(&mut self) {
364         if let DebugInfo::None = self.sess.opts.debuginfo {
365             // If we are building without debuginfo enabled and we were called with
366             // `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
367             // found when linking to get rid of symbols from libstd.
368             if let Some(true) = self.sess.opts.debugging_opts.strip_debuginfo_if_disabled {
369                 self.linker_arg("-S");
370             }
371         };
372     }
373
374     fn no_default_libraries(&mut self) {
375         if !self.is_ld {
376             self.cmd.arg("-nodefaultlibs");
377         }
378     }
379
380     fn build_dylib(&mut self, out_filename: &Path) {
381         // On mac we need to tell the linker to let this library be rpathed
382         if self.sess.target.target.options.is_like_osx {
383             self.cmd.arg("-dynamiclib");
384             self.linker_arg("-dylib");
385
386             // Note that the `osx_rpath_install_name` option here is a hack
387             // purely to support rustbuild right now, we should get a more
388             // principled solution at some point to force the compiler to pass
389             // the right `-Wl,-install_name` with an `@rpath` in it.
390             if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
391                 self.linker_arg("-install_name");
392                 let mut v = OsString::from("@rpath/");
393                 v.push(out_filename.file_name().unwrap());
394                 self.linker_arg(&v);
395             }
396         } else {
397             self.cmd.arg("-shared");
398             if self.sess.target.target.options.is_like_windows {
399                 // The output filename already contains `dll_suffix` so
400                 // the resulting import library will have a name in the
401                 // form of libfoo.dll.a
402                 let implib_name =
403                     out_filename.file_name().and_then(|file| file.to_str()).map(|file| {
404                         format!(
405                             "{}{}{}",
406                             self.sess.target.target.options.staticlib_prefix,
407                             file,
408                             self.sess.target.target.options.staticlib_suffix
409                         )
410                     });
411                 if let Some(implib_name) = implib_name {
412                     let implib = out_filename.parent().map(|dir| dir.join(&implib_name));
413                     if let Some(implib) = implib {
414                         self.linker_arg(&format!("--out-implib,{}", (*implib).to_str().unwrap()));
415                     }
416                 }
417             }
418         }
419     }
420
421     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
422         // Symbol visibility in object files typically takes care of this.
423         if crate_type == CrateType::Executable
424             && self.sess.target.target.options.override_export_symbols.is_none()
425         {
426             return;
427         }
428
429         // We manually create a list of exported symbols to ensure we don't expose any more.
430         // The object files have far more public symbols than we actually want to export,
431         // so we hide them all here.
432
433         if !self.sess.target.target.options.limit_rdylib_exports {
434             return;
435         }
436
437         if crate_type == CrateType::ProcMacro {
438             return;
439         }
440
441         let mut arg = OsString::new();
442         let path = tmpdir.join("list");
443
444         debug!("EXPORTED SYMBOLS:");
445
446         if self.sess.target.target.options.is_like_osx {
447             // Write a plain, newline-separated list of symbols
448             let res: io::Result<()> = try {
449                 let mut f = BufWriter::new(File::create(&path)?);
450                 for sym in self.info.exports[&crate_type].iter() {
451                     debug!("  _{}", sym);
452                     writeln!(f, "_{}", sym)?;
453                 }
454             };
455             if let Err(e) = res {
456                 self.sess.fatal(&format!("failed to write lib.def file: {}", e));
457             }
458         } else {
459             // Write an LD version script
460             let res: io::Result<()> = try {
461                 let mut f = BufWriter::new(File::create(&path)?);
462                 writeln!(f, "{{")?;
463                 if !self.info.exports[&crate_type].is_empty() {
464                     writeln!(f, "  global:")?;
465                     for sym in self.info.exports[&crate_type].iter() {
466                         debug!("    {};", sym);
467                         writeln!(f, "    {};", sym)?;
468                     }
469                 }
470                 writeln!(f, "\n  local:\n    *;\n}};")?;
471             };
472             if let Err(e) = res {
473                 self.sess.fatal(&format!("failed to write version script: {}", e));
474             }
475         }
476
477         if self.sess.target.target.options.is_like_osx {
478             if !self.is_ld {
479                 arg.push("-Wl,")
480             }
481             arg.push("-exported_symbols_list,");
482         } else if self.sess.target.target.options.is_like_solaris {
483             if !self.is_ld {
484                 arg.push("-Wl,")
485             }
486             arg.push("-M,");
487         } else {
488             if !self.is_ld {
489                 arg.push("-Wl,")
490             }
491             arg.push("--version-script=");
492         }
493
494         arg.push(&path);
495         self.cmd.arg(arg);
496     }
497
498     fn subsystem(&mut self, subsystem: &str) {
499         self.linker_arg("--subsystem");
500         self.linker_arg(&subsystem);
501     }
502
503     fn finalize(&mut self) -> Command {
504         self.hint_dynamic(); // Reset to default before returning the composed command line.
505
506         ::std::mem::replace(&mut self.cmd, Command::new(""))
507     }
508
509     fn group_start(&mut self) {
510         if self.takes_hints() {
511             self.linker_arg("--start-group");
512         }
513     }
514
515     fn group_end(&mut self) {
516         if self.takes_hints() {
517             self.linker_arg("--end-group");
518         }
519     }
520
521     fn linker_plugin_lto(&mut self) {
522         match self.sess.opts.cg.linker_plugin_lto {
523             LinkerPluginLto::Disabled => {
524                 // Nothing to do
525             }
526             LinkerPluginLto::LinkerPluginAuto => {
527                 self.push_linker_plugin_lto_args(None);
528             }
529             LinkerPluginLto::LinkerPlugin(ref path) => {
530                 self.push_linker_plugin_lto_args(Some(path.as_os_str()));
531             }
532         }
533     }
534 }
535
536 pub struct MsvcLinker<'a> {
537     cmd: Command,
538     sess: &'a Session,
539     info: &'a LinkerInfo,
540 }
541
542 impl<'a> Linker for MsvcLinker<'a> {
543     fn link_rlib(&mut self, lib: &Path) {
544         self.cmd.arg(lib);
545     }
546     fn add_object(&mut self, path: &Path) {
547         self.cmd.arg(path);
548     }
549     fn args(&mut self, args: &[String]) {
550         self.cmd.args(args);
551     }
552
553     fn build_dylib(&mut self, out_filename: &Path) {
554         self.cmd.arg("/DLL");
555         let mut arg: OsString = "/IMPLIB:".into();
556         arg.push(out_filename.with_extension("dll.lib"));
557         self.cmd.arg(arg);
558     }
559
560     fn build_static_executable(&mut self) {
561         // noop
562     }
563
564     fn gc_sections(&mut self, _keep_metadata: bool) {
565         // MSVC's ICF (Identical COMDAT Folding) link optimization is
566         // slow for Rust and thus we disable it by default when not in
567         // optimization build.
568         if self.sess.opts.optimize != config::OptLevel::No {
569             self.cmd.arg("/OPT:REF,ICF");
570         } else {
571             // It is necessary to specify NOICF here, because /OPT:REF
572             // implies ICF by default.
573             self.cmd.arg("/OPT:REF,NOICF");
574         }
575     }
576
577     fn link_dylib(&mut self, lib: Symbol) {
578         self.cmd.arg(&format!("{}.lib", lib));
579     }
580
581     fn link_rust_dylib(&mut self, lib: Symbol, path: &Path) {
582         // When producing a dll, the MSVC linker may not actually emit a
583         // `foo.lib` file if the dll doesn't actually export any symbols, so we
584         // check to see if the file is there and just omit linking to it if it's
585         // not present.
586         let name = format!("{}.dll.lib", lib);
587         if fs::metadata(&path.join(&name)).is_ok() {
588             self.cmd.arg(name);
589         }
590     }
591
592     fn link_staticlib(&mut self, lib: Symbol) {
593         self.cmd.arg(&format!("{}.lib", lib));
594     }
595
596     fn position_independent_executable(&mut self) {
597         // noop
598     }
599
600     fn no_position_independent_executable(&mut self) {
601         // noop
602     }
603
604     fn full_relro(&mut self) {
605         // noop
606     }
607
608     fn partial_relro(&mut self) {
609         // noop
610     }
611
612     fn no_relro(&mut self) {
613         // noop
614     }
615
616     fn no_default_libraries(&mut self) {
617         // Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC
618         // as there's been trouble in the past of linking the C++ standard
619         // library required by LLVM. This likely needs to happen one day, but
620         // in general Windows is also a more controlled environment than
621         // Unix, so it's not necessarily as critical that this be implemented.
622         //
623         // Note that there are also some licensing worries about statically
624         // linking some libraries which require a specific agreement, so it may
625         // not ever be possible for us to pass this flag.
626     }
627
628     fn include_path(&mut self, path: &Path) {
629         let mut arg = OsString::from("/LIBPATH:");
630         arg.push(path);
631         self.cmd.arg(&arg);
632     }
633
634     fn output_filename(&mut self, path: &Path) {
635         let mut arg = OsString::from("/OUT:");
636         arg.push(path);
637         self.cmd.arg(&arg);
638     }
639
640     fn framework_path(&mut self, _path: &Path) {
641         bug!("frameworks are not supported on windows")
642     }
643     fn link_framework(&mut self, _framework: Symbol) {
644         bug!("frameworks are not supported on windows")
645     }
646
647     fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
648         // not supported?
649         self.link_staticlib(lib);
650     }
651     fn link_whole_rlib(&mut self, path: &Path) {
652         // not supported?
653         self.link_rlib(path);
654     }
655     fn optimize(&mut self) {
656         // Needs more investigation of `/OPT` arguments
657     }
658
659     fn pgo_gen(&mut self) {
660         // Nothing needed here.
661     }
662
663     fn debuginfo(&mut self) {
664         // This will cause the Microsoft linker to generate a PDB file
665         // from the CodeView line tables in the object files.
666         self.cmd.arg("/DEBUG");
667
668         // This will cause the Microsoft linker to embed .natvis info into the PDB file
669         let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc");
670         if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
671             for entry in natvis_dir {
672                 match entry {
673                     Ok(entry) => {
674                         let path = entry.path();
675                         if path.extension() == Some("natvis".as_ref()) {
676                             let mut arg = OsString::from("/NATVIS:");
677                             arg.push(path);
678                             self.cmd.arg(arg);
679                         }
680                     }
681                     Err(err) => {
682                         self.sess.warn(&format!("error enumerating natvis directory: {}", err));
683                     }
684                 }
685             }
686         }
687     }
688
689     // Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
690     // export symbols from a dynamic library. When building a dynamic library,
691     // however, we're going to want some symbols exported, so this function
692     // generates a DEF file which lists all the symbols.
693     //
694     // The linker will read this `*.def` file and export all the symbols from
695     // the dynamic library. Note that this is not as simple as just exporting
696     // all the symbols in the current crate (as specified by `codegen.reachable`)
697     // but rather we also need to possibly export the symbols of upstream
698     // crates. Upstream rlibs may be linked statically to this dynamic library,
699     // in which case they may continue to transitively be used and hence need
700     // their symbols exported.
701     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
702         // Symbol visibility takes care of this typically
703         if crate_type == CrateType::Executable {
704             return;
705         }
706
707         let path = tmpdir.join("lib.def");
708         let res: io::Result<()> = try {
709             let mut f = BufWriter::new(File::create(&path)?);
710
711             // Start off with the standard module name header and then go
712             // straight to exports.
713             writeln!(f, "LIBRARY")?;
714             writeln!(f, "EXPORTS")?;
715             for symbol in self.info.exports[&crate_type].iter() {
716                 debug!("  _{}", symbol);
717                 writeln!(f, "  {}", symbol)?;
718             }
719         };
720         if let Err(e) = res {
721             self.sess.fatal(&format!("failed to write lib.def file: {}", e));
722         }
723         let mut arg = OsString::from("/DEF:");
724         arg.push(path);
725         self.cmd.arg(&arg);
726     }
727
728     fn subsystem(&mut self, subsystem: &str) {
729         // Note that previous passes of the compiler validated this subsystem,
730         // so we just blindly pass it to the linker.
731         self.cmd.arg(&format!("/SUBSYSTEM:{}", subsystem));
732
733         // Windows has two subsystems we're interested in right now, the console
734         // and windows subsystems. These both implicitly have different entry
735         // points (starting symbols). The console entry point starts with
736         // `mainCRTStartup` and the windows entry point starts with
737         // `WinMainCRTStartup`. These entry points, defined in system libraries,
738         // will then later probe for either `main` or `WinMain`, respectively to
739         // start the application.
740         //
741         // In Rust we just always generate a `main` function so we want control
742         // to always start there, so we force the entry point on the windows
743         // subsystem to be `mainCRTStartup` to get everything booted up
744         // correctly.
745         //
746         // For more information see RFC #1665
747         if subsystem == "windows" {
748             self.cmd.arg("/ENTRY:mainCRTStartup");
749         }
750     }
751
752     fn finalize(&mut self) -> Command {
753         ::std::mem::replace(&mut self.cmd, Command::new(""))
754     }
755
756     // MSVC doesn't need group indicators
757     fn group_start(&mut self) {}
758     fn group_end(&mut self) {}
759
760     fn linker_plugin_lto(&mut self) {
761         // Do nothing
762     }
763 }
764
765 pub struct EmLinker<'a> {
766     cmd: Command,
767     sess: &'a Session,
768     info: &'a LinkerInfo,
769 }
770
771 impl<'a> Linker for EmLinker<'a> {
772     fn include_path(&mut self, path: &Path) {
773         self.cmd.arg("-L").arg(path);
774     }
775
776     fn link_staticlib(&mut self, lib: Symbol) {
777         self.cmd.arg("-l").sym_arg(lib);
778     }
779
780     fn output_filename(&mut self, path: &Path) {
781         self.cmd.arg("-o").arg(path);
782     }
783
784     fn add_object(&mut self, path: &Path) {
785         self.cmd.arg(path);
786     }
787
788     fn link_dylib(&mut self, lib: Symbol) {
789         // Emscripten always links statically
790         self.link_staticlib(lib);
791     }
792
793     fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
794         // not supported?
795         self.link_staticlib(lib);
796     }
797
798     fn link_whole_rlib(&mut self, lib: &Path) {
799         // not supported?
800         self.link_rlib(lib);
801     }
802
803     fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
804         self.link_dylib(lib);
805     }
806
807     fn link_rlib(&mut self, lib: &Path) {
808         self.add_object(lib);
809     }
810
811     fn position_independent_executable(&mut self) {
812         // noop
813     }
814
815     fn no_position_independent_executable(&mut self) {
816         // noop
817     }
818
819     fn full_relro(&mut self) {
820         // noop
821     }
822
823     fn partial_relro(&mut self) {
824         // noop
825     }
826
827     fn no_relro(&mut self) {
828         // noop
829     }
830
831     fn args(&mut self, args: &[String]) {
832         self.cmd.args(args);
833     }
834
835     fn framework_path(&mut self, _path: &Path) {
836         bug!("frameworks are not supported on Emscripten")
837     }
838
839     fn link_framework(&mut self, _framework: Symbol) {
840         bug!("frameworks are not supported on Emscripten")
841     }
842
843     fn gc_sections(&mut self, _keep_metadata: bool) {
844         // noop
845     }
846
847     fn optimize(&mut self) {
848         // Emscripten performs own optimizations
849         self.cmd.arg(match self.sess.opts.optimize {
850             OptLevel::No => "-O0",
851             OptLevel::Less => "-O1",
852             OptLevel::Default => "-O2",
853             OptLevel::Aggressive => "-O3",
854             OptLevel::Size => "-Os",
855             OptLevel::SizeMin => "-Oz",
856         });
857         // Unusable until https://github.com/rust-lang/rust/issues/38454 is resolved
858         self.cmd.args(&["--memory-init-file", "0"]);
859     }
860
861     fn pgo_gen(&mut self) {
862         // noop, but maybe we need something like the gnu linker?
863     }
864
865     fn debuginfo(&mut self) {
866         // Preserve names or generate source maps depending on debug info
867         self.cmd.arg(match self.sess.opts.debuginfo {
868             DebugInfo::None => "-g0",
869             DebugInfo::Limited => "-g3",
870             DebugInfo::Full => "-g4",
871         });
872     }
873
874     fn no_default_libraries(&mut self) {
875         self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
876     }
877
878     fn build_dylib(&mut self, _out_filename: &Path) {
879         bug!("building dynamic library is unsupported on Emscripten")
880     }
881
882     fn build_static_executable(&mut self) {
883         // noop
884     }
885
886     fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
887         let symbols = &self.info.exports[&crate_type];
888
889         debug!("EXPORTED SYMBOLS:");
890
891         self.cmd.arg("-s");
892
893         let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
894         let mut encoded = String::new();
895
896         {
897             let mut encoder = json::Encoder::new(&mut encoded);
898             let res = encoder.emit_seq(symbols.len(), |encoder| {
899                 for (i, sym) in symbols.iter().enumerate() {
900                     encoder.emit_seq_elt(i, |encoder| encoder.emit_str(&("_".to_owned() + sym)))?;
901                 }
902                 Ok(())
903             });
904             if let Err(e) = res {
905                 self.sess.fatal(&format!("failed to encode exported symbols: {}", e));
906             }
907         }
908         debug!("{}", encoded);
909         arg.push(encoded);
910
911         self.cmd.arg(arg);
912     }
913
914     fn subsystem(&mut self, _subsystem: &str) {
915         // noop
916     }
917
918     fn finalize(&mut self) -> Command {
919         ::std::mem::replace(&mut self.cmd, Command::new(""))
920     }
921
922     // Appears not necessary on Emscripten
923     fn group_start(&mut self) {}
924     fn group_end(&mut self) {}
925
926     fn linker_plugin_lto(&mut self) {
927         // Do nothing
928     }
929 }
930
931 pub struct WasmLd<'a> {
932     cmd: Command,
933     sess: &'a Session,
934     info: &'a LinkerInfo,
935 }
936
937 impl<'a> WasmLd<'a> {
938     fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
939         // If the atomics feature is enabled for wasm then we need a whole bunch
940         // of flags:
941         //
942         // * `--shared-memory` - the link won't even succeed without this, flags
943         //   the one linear memory as `shared`
944         //
945         // * `--max-memory=1G` - when specifying a shared memory this must also
946         //   be specified. We conservatively choose 1GB but users should be able
947         //   to override this with `-C link-arg`.
948         //
949         // * `--import-memory` - it doesn't make much sense for memory to be
950         //   exported in a threaded module because typically you're
951         //   sharing memory and instantiating the module multiple times. As a
952         //   result if it were exported then we'd just have no sharing.
953         //
954         // * `--passive-segments` - all memory segments should be passive to
955         //   prevent each module instantiation from reinitializing memory.
956         //
957         // * `--export=__wasm_init_memory` - when using `--passive-segments` the
958         //   linker will synthesize this function, and so we need to make sure
959         //   that our usage of `--export` below won't accidentally cause this
960         //   function to get deleted.
961         //
962         // * `--export=*tls*` - when `#[thread_local]` symbols are used these
963         //   symbols are how the TLS segments are initialized and configured.
964         let atomics = sess.opts.cg.target_feature.contains("+atomics")
965             || sess.target.target.options.features.contains("+atomics");
966         if atomics {
967             cmd.arg("--shared-memory");
968             cmd.arg("--max-memory=1073741824");
969             cmd.arg("--import-memory");
970             cmd.arg("--passive-segments");
971             cmd.arg("--export=__wasm_init_memory");
972             cmd.arg("--export=__wasm_init_tls");
973             cmd.arg("--export=__tls_size");
974             cmd.arg("--export=__tls_align");
975             cmd.arg("--export=__tls_base");
976         }
977         WasmLd { cmd, sess, info }
978     }
979 }
980
981 impl<'a> Linker for WasmLd<'a> {
982     fn link_dylib(&mut self, lib: Symbol) {
983         self.cmd.arg("-l").sym_arg(lib);
984     }
985
986     fn link_staticlib(&mut self, lib: Symbol) {
987         self.cmd.arg("-l").sym_arg(lib);
988     }
989
990     fn link_rlib(&mut self, lib: &Path) {
991         self.cmd.arg(lib);
992     }
993
994     fn include_path(&mut self, path: &Path) {
995         self.cmd.arg("-L").arg(path);
996     }
997
998     fn framework_path(&mut self, _path: &Path) {
999         panic!("frameworks not supported")
1000     }
1001
1002     fn output_filename(&mut self, path: &Path) {
1003         self.cmd.arg("-o").arg(path);
1004     }
1005
1006     fn add_object(&mut self, path: &Path) {
1007         self.cmd.arg(path);
1008     }
1009
1010     fn position_independent_executable(&mut self) {}
1011
1012     fn full_relro(&mut self) {}
1013
1014     fn partial_relro(&mut self) {}
1015
1016     fn no_relro(&mut self) {}
1017
1018     fn build_static_executable(&mut self) {}
1019
1020     fn args(&mut self, args: &[String]) {
1021         self.cmd.args(args);
1022     }
1023
1024     fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
1025         self.cmd.arg("-l").sym_arg(lib);
1026     }
1027
1028     fn link_framework(&mut self, _framework: Symbol) {
1029         panic!("frameworks not supported")
1030     }
1031
1032     fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
1033         self.cmd.arg("-l").sym_arg(lib);
1034     }
1035
1036     fn link_whole_rlib(&mut self, lib: &Path) {
1037         self.cmd.arg(lib);
1038     }
1039
1040     fn gc_sections(&mut self, _keep_metadata: bool) {
1041         self.cmd.arg("--gc-sections");
1042     }
1043
1044     fn optimize(&mut self) {
1045         self.cmd.arg(match self.sess.opts.optimize {
1046             OptLevel::No => "-O0",
1047             OptLevel::Less => "-O1",
1048             OptLevel::Default => "-O2",
1049             OptLevel::Aggressive => "-O3",
1050             // Currently LLD doesn't support `Os` and `Oz`, so pass through `O2`
1051             // instead.
1052             OptLevel::Size => "-O2",
1053             OptLevel::SizeMin => "-O2",
1054         });
1055     }
1056
1057     fn pgo_gen(&mut self) {}
1058
1059     fn debuginfo(&mut self) {}
1060
1061     fn no_default_libraries(&mut self) {}
1062
1063     fn build_dylib(&mut self, _out_filename: &Path) {
1064         self.cmd.arg("--no-entry");
1065     }
1066
1067     fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
1068         for sym in self.info.exports[&crate_type].iter() {
1069             self.cmd.arg("--export").arg(&sym);
1070         }
1071
1072         // LLD will hide these otherwise-internal symbols since our `--export`
1073         // list above is a whitelist of what to export. Various bits and pieces
1074         // of tooling use this, so be sure these symbols make their way out of
1075         // the linker as well.
1076         self.cmd.arg("--export=__heap_base");
1077         self.cmd.arg("--export=__data_end");
1078     }
1079
1080     fn subsystem(&mut self, _subsystem: &str) {}
1081
1082     fn no_position_independent_executable(&mut self) {}
1083
1084     fn finalize(&mut self) -> Command {
1085         ::std::mem::replace(&mut self.cmd, Command::new(""))
1086     }
1087
1088     // Not needed for now with LLD
1089     fn group_start(&mut self) {}
1090     fn group_end(&mut self) {}
1091
1092     fn linker_plugin_lto(&mut self) {
1093         // Do nothing for now
1094     }
1095 }
1096
1097 fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
1098     if let Some(ref exports) = tcx.sess.target.target.options.override_export_symbols {
1099         return exports.clone();
1100     }
1101
1102     let mut symbols = Vec::new();
1103
1104     let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1105     for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
1106         if level.is_below_threshold(export_threshold) {
1107             symbols.push(symbol_export::symbol_name_for_instance_in_crate(
1108                 tcx,
1109                 symbol,
1110                 LOCAL_CRATE,
1111             ));
1112         }
1113     }
1114
1115     let formats = tcx.dependency_formats(LOCAL_CRATE);
1116     let deps = formats
1117         .iter()
1118         .filter_map(|(t, list)| if *t == crate_type { Some(list) } else { None })
1119         .next()
1120         .unwrap();
1121
1122     for (index, dep_format) in deps.iter().enumerate() {
1123         let cnum = CrateNum::new(index + 1);
1124         // For each dependency that we are linking to statically ...
1125         if *dep_format == Linkage::Static {
1126             // ... we add its symbol list to our export list.
1127             for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
1128                 if !level.is_below_threshold(export_threshold) {
1129                     continue;
1130                 }
1131
1132                 symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum));
1133             }
1134         }
1135     }
1136
1137     symbols
1138 }
1139
1140 /// Much simplified and explicit CLI for the NVPTX linker. The linker operates
1141 /// with bitcode and uses LLVM backend to generate a PTX assembly.
1142 pub struct PtxLinker<'a> {
1143     cmd: Command,
1144     sess: &'a Session,
1145 }
1146
1147 impl<'a> Linker for PtxLinker<'a> {
1148     fn link_rlib(&mut self, path: &Path) {
1149         self.cmd.arg("--rlib").arg(path);
1150     }
1151
1152     fn link_whole_rlib(&mut self, path: &Path) {
1153         self.cmd.arg("--rlib").arg(path);
1154     }
1155
1156     fn include_path(&mut self, path: &Path) {
1157         self.cmd.arg("-L").arg(path);
1158     }
1159
1160     fn debuginfo(&mut self) {
1161         self.cmd.arg("--debug");
1162     }
1163
1164     fn add_object(&mut self, path: &Path) {
1165         self.cmd.arg("--bitcode").arg(path);
1166     }
1167
1168     fn args(&mut self, args: &[String]) {
1169         self.cmd.args(args);
1170     }
1171
1172     fn optimize(&mut self) {
1173         match self.sess.lto() {
1174             Lto::Thin | Lto::Fat | Lto::ThinLocal => {
1175                 self.cmd.arg("-Olto");
1176             }
1177
1178             Lto::No => {}
1179         };
1180     }
1181
1182     fn output_filename(&mut self, path: &Path) {
1183         self.cmd.arg("-o").arg(path);
1184     }
1185
1186     fn finalize(&mut self) -> Command {
1187         // Provide the linker with fallback to internal `target-cpu`.
1188         self.cmd.arg("--fallback-arch").arg(match self.sess.opts.cg.target_cpu {
1189             Some(ref s) => s,
1190             None => &self.sess.target.target.options.cpu,
1191         });
1192
1193         ::std::mem::replace(&mut self.cmd, Command::new(""))
1194     }
1195
1196     fn link_dylib(&mut self, _lib: Symbol) {
1197         panic!("external dylibs not supported")
1198     }
1199
1200     fn link_rust_dylib(&mut self, _lib: Symbol, _path: &Path) {
1201         panic!("external dylibs not supported")
1202     }
1203
1204     fn link_staticlib(&mut self, _lib: Symbol) {
1205         panic!("staticlibs not supported")
1206     }
1207
1208     fn link_whole_staticlib(&mut self, _lib: Symbol, _search_path: &[PathBuf]) {
1209         panic!("staticlibs not supported")
1210     }
1211
1212     fn framework_path(&mut self, _path: &Path) {
1213         panic!("frameworks not supported")
1214     }
1215
1216     fn link_framework(&mut self, _framework: Symbol) {
1217         panic!("frameworks not supported")
1218     }
1219
1220     fn position_independent_executable(&mut self) {}
1221
1222     fn full_relro(&mut self) {}
1223
1224     fn partial_relro(&mut self) {}
1225
1226     fn no_relro(&mut self) {}
1227
1228     fn build_static_executable(&mut self) {}
1229
1230     fn gc_sections(&mut self, _keep_metadata: bool) {}
1231
1232     fn pgo_gen(&mut self) {}
1233
1234     fn no_default_libraries(&mut self) {}
1235
1236     fn build_dylib(&mut self, _out_filename: &Path) {}
1237
1238     fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
1239
1240     fn subsystem(&mut self, _subsystem: &str) {}
1241
1242     fn no_position_independent_executable(&mut self) {}
1243
1244     fn group_start(&mut self) {}
1245
1246     fn group_end(&mut self) {}
1247
1248     fn linker_plugin_lto(&mut self) {}
1249 }