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