rustc_target/spec/base/
linux_wasm.rs

1//! This target is a confluence of Linux and Wasm models, inheriting most
2//! aspects from their respective base targets
3
4use crate::spec::{
5    Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel,
6    add_link_args, crt_objects, cvs,
7};
8
9pub(crate) fn opts() -> TargetOptions {
10    macro_rules! args {
11        ($prefix:literal) => {
12            &[
13                // By default LLD only gives us one page of stack (64k) which is a
14                // little small. Default to a larger stack closer to other PC platforms
15                // (1MB) and users can always inject their own link-args to override this.
16                concat!($prefix, "-z"),
17                concat!($prefix, "stack-size=1048576"),
18                // By default LLD's memory layout is:
19                //
20                // 1. First, a blank page
21                // 2. Next, all static data
22                // 3. Finally, the main stack (which grows down)
23                //
24                // This has the unfortunate consequence that on stack overflows you
25                // corrupt static data and can cause some exceedingly weird bugs. To
26                // help detect this a little sooner we instead request that the stack is
27                // placed before static data.
28                //
29                // This means that we'll generate slightly larger binaries as references
30                // to static data will take more bytes in the ULEB128 encoding, but
31                // stack overflow will be guaranteed to trap as it underflows instead of
32                // corrupting static data.
33                concat!($prefix, "--stack-first"),
34                // FIXME we probably shouldn't pass this but instead pass an explicit list
35                // of symbols we'll allow to be undefined. We don't currently have a
36                // mechanism of knowing, however, which symbols are intended to be imported
37                // from the environment and which are intended to be imported from other
38                // objects linked elsewhere. This is a coarse approximation but is sure to
39                // hide some bugs and frustrate someone at some point, so we should ideally
40                // work towards a world where we can explicitly list symbols that are
41                // supposed to be imported and have all other symbols generate errors if
42                // they remain undefined.
43                concat!($prefix, "--allow-undefined"),
44                // LLD only implements C++-like demangling, which doesn't match our own
45                // mangling scheme. Tell LLD to not demangle anything and leave it up to
46                // us to demangle these symbols later. Currently rustc does not perform
47                // further demangling, but tools like twiggy and wasm-bindgen are intended
48                // to do so.
49                concat!($prefix, "--no-demangle"),
50            ]
51        };
52    }
53
54    let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!(""));
55    add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,"));
56
57    TargetOptions {
58        is_like_wasm: true,
59        families: cvs!["wasm", "unix"],
60        os: "linux".into(),
61        env: "musl".into(),
62
63        // we allow dynamic linking, but only cdylibs. Basically we allow a
64        // final library artifact that exports some symbols (a wasm module) but
65        // we don't allow intermediate `dylib` crate types
66        dynamic_linking: true,
67        only_cdylib: true,
68
69        // relatively self-explanatory!
70        exe_suffix: ".wasm".into(),
71        dll_prefix: "".into(),
72        dll_suffix: ".wasm".into(),
73        eh_frame_header: false,
74
75        max_atomic_width: Some(64),
76
77        // Unwinding doesn't work right now, so the whole target unconditionally
78        // defaults to panic=abort. Note that this is guaranteed to change in
79        // the future once unwinding is implemented. Don't rely on this as we're
80        // basically guaranteed to change it once WebAssembly supports
81        // exceptions.
82        panic_strategy: PanicStrategy::Abort,
83
84        // Symbol visibility takes care of this for the WebAssembly.
85        // Additionally the only known linker, LLD, doesn't support the script
86        // arguments just yet
87        limit_rdylib_exports: false,
88
89        // we use the LLD shipped with the Rust toolchain by default
90        linker: Some("rust-lld".into()),
91        linker_flavor: LinkerFlavor::WasmLld(Cc::No),
92
93        pre_link_args,
94
95        // FIXME: Figure out cases in which WASM needs to link with a native toolchain.
96        //
97        // rust-lang/rust#104137: cannot blindly remove this without putting in
98        // some other way to compensate for lack of `-nostartfiles` in linker
99        // invocation.
100        link_self_contained: LinkSelfContainedDefault::True,
101        pre_link_objects_self_contained: crt_objects::pre_wasi_self_contained(),
102        post_link_objects_self_contained: crt_objects::post_wasi_self_contained(),
103
104        // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when
105        // PIC code is implemented this has quite a drastic effect if it stays
106        // at the default, `pic`. In an effort to keep wasm binaries as minimal
107        // as possible we're defaulting to `static` for now, but the hope is
108        // that eventually we can ship a `pic`-compatible standard library which
109        // works with `static` as well (or works with some method of generating
110        // non-relative calls and such later on).
111        relocation_model: RelocModel::Static,
112
113        // When the atomics feature is activated then these two keys matter,
114        // otherwise they're basically ignored by the standard library. In this
115        // mode, however, the `#[thread_local]` attribute works (i.e.
116        // `has_thread_local`) and we need to get it to work by specifying
117        // `local-exec` as that's all that's implemented in LLVM today for wasm.
118        has_thread_local: true,
119        tls_model: TlsModel::LocalExec,
120
121        // Supporting Linux requires multithreading supported by Wasm's thread
122        // proposal
123        singlethread: false,
124
125        // gdb scripts don't work on wasm blobs
126        emit_debug_gdb_scripts: false,
127
128        // There's more discussion of this at
129        // https://bugs.llvm.org/show_bug.cgi?id=52442 but the general result is
130        // that this isn't useful for wasm and has tricky issues with
131        // representation, so this is disabled.
132        generate_arange_section: false,
133
134        // Right now this is a bit of a workaround but we're currently saying that
135        // the target by default has a static crt which we're taking as a signal
136        // for "use the bundled crt". If that's turned off then the system's crt
137        // will be used, but this means that default usage of this target doesn't
138        // need an external compiler but it's still interoperable with an external
139        // compiler if configured correctly.
140        crt_static_default: true,
141        crt_static_respected: true,
142
143        // Allow `+crt-static` to create a "cdylib" output which is just a wasm file
144        // without a main function.
145        crt_static_allows_dylibs: true,
146
147        // Wasm start ignores arguments -- relies on API call from interface.
148        main_needs_argc_argv: false,
149
150        // Wasm toolchains mangle the name of "main" to distinguish between different
151        // signatures.
152        entry_name: "__main_void".into(),
153
154        // Wasm Feature flags for supporting Linux
155        features: "+atomics,+bulk-memory,+mutable-globals,+sign-ext".into(),
156
157        ..Default::default()
158    }
159}