1 use std::collections::BTreeMap;
2 use super::{LldFlavor, TargetOptions, PanicStrategy, LinkerFlavor};
4 pub fn options() -> TargetOptions {
5 let mut lld_args = Vec::new();
6 let mut clang_args = Vec::new();
7 let mut arg = |arg: &str| {
8 lld_args.push(arg.to_string());
9 clang_args.push(format!("-Wl,{}", arg));
12 // There have been reports in the wild (rustwasm/wasm-bindgen#119) of
13 // using threads causing weird hangs and bugs. Disable it entirely as
14 // this isn't yet the bottleneck of compilation at all anyway.
16 // FIXME: we should file an upstream issue with LLD about this
19 // By default LLD only gives us one page of stack (64k) which is a
20 // little small. Default to a larger stack closer to other PC platforms
21 // (1MB) and users can always inject their own link-args to override this.
23 arg("stack-size=1048576");
25 // By default LLD's memory layout is:
27 // 1. First, a blank page
28 // 2. Next, all static data
29 // 3. Finally, the main stack (which grows down)
31 // This has the unfortunate consequence that on stack overflows you
32 // corrupt static data and can cause some exceedingly weird bugs. To
33 // help detect this a little sooner we instead request that the stack is
34 // placed before static data.
36 // This means that we'll generate slightly larger binaries as references
37 // to static data will take more bytes in the ULEB128 encoding, but
38 // stack overflow will be guaranteed to trap as it underflows instead of
39 // corrupting static data.
42 // FIXME we probably shouldn't pass this but instead pass an explicit
43 // whitelist of symbols we'll allow to be undefined. We don't currently have
44 // a mechanism of knowing, however, which symbols are intended to be
45 // imported from the environment and which are intended to be imported from
46 // other objects linked elsewhere. This is a coarse approximation but is
47 // sure to hide some bugs and frustrate someone at some point, so we should
48 // ideally work towards a world where we can explicitly list symbols that
49 // are supposed to be imported and have all other symbols generate errors if
50 // they remain undefined.
51 arg("--allow-undefined");
53 // Rust code should never have warnings, and warnings are often
54 // indicative of bugs, let's prevent them.
55 arg("--fatal-warnings");
57 // LLD only implements C++-like demangling, which doesn't match our own
58 // mangling scheme. Tell LLD to not demangle anything and leave it up to
59 // us to demangle these symbols later. Currently rustc does not perform
60 // further demangling, but tools like twiggy and wasm-bindgen are intended
64 // The symbol visibility story is a bit in flux right now with LLD.
65 // It's... not entirely clear to me what's going on, but this looks to
66 // make everything work when `export_symbols` isn't otherwise called for
67 // things like executables.
69 // This is really only here to get things working. If it can be removed and
70 // basic tests still work, then sounds like it should be removed!
71 arg("--export-dynamic");
73 let mut pre_link_args = BTreeMap::new();
74 pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Wasm), lld_args);
75 pre_link_args.insert(LinkerFlavor::Gcc, clang_args);
78 // we allow dynamic linking, but only cdylibs. Basically we allow a
79 // final library artifact that exports some symbols (a wasm module) but
80 // we don't allow intermediate `dylib` crate types
81 dynamic_linking: true,
84 // This means we'll just embed a `start` function in the wasm module
87 // relatively self-explanatory!
88 exe_suffix: ".wasm".to_string(),
89 dll_prefix: String::new(),
90 dll_suffix: ".wasm".to_string(),
93 max_atomic_width: Some(64),
95 // Unwinding doesn't work right now, so the whole target unconditionally
96 // defaults to panic=abort. Note that this is guaranteed to change in
97 // the future once unwinding is implemented. Don't rely on this as we're
98 // basically guaranteed to change it once WebAssembly supports
100 panic_strategy: PanicStrategy::Abort,
102 // Wasm doesn't have atomics yet, so tell LLVM that we're in a single
103 // threaded model which will legalize atomics to normal operations.
106 // no dynamic linking, no need for default visibility!
107 default_hidden_visibility: true,
109 // Symbol visibility takes care of this for the WebAssembly.
110 // Additionally the only known linker, LLD, doesn't support the script
111 // arguments just yet
112 limit_rdylib_exports: false,
114 // we use the LLD shipped with the Rust toolchain by default
115 linker: Some("rust-lld".to_owned()),
116 lld_flavor: LldFlavor::Wasm,
118 // No need for indirection here, simd types can always be passed by
119 // value as the whole module either has simd or not, which is different
120 // from x86 (for example) where programs can have functions that don't
121 // enable simd features.
122 simd_types_indirect: false,
126 // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when
127 // PIC code is implemented this has quite a drastric effect if it stays
128 // at the default, `pic`. In an effort to keep wasm binaries as minimal
129 // as possible we're defaulting to `static` for now, but the hope is
130 // that eventually we can ship a `pic`-compatible standard library which
131 // works with `static` as well (or works with some method of generating
132 // non-relative calls and such later on).
133 relocation_model: "static".to_string(),
135 // When the atomics feature is activated then these two keys matter,
136 // otherwise they're basically ignored by the standard library. In this
137 // mode, however, the `#[thread_local]` attribute works (i.e.
138 // `has_elf_tls`) and we need to get it to work by specifying
139 // `local-exec` as that's all that's implemented in LLVM today for wasm.
141 tls_model: "local-exec".to_string(),
143 .. Default::default()