|
| 1 | +//! This target is a confluence of Linux and Wasm models, inheriting most |
| 2 | +//! aspects from their respective base targets |
| 3 | +
|
| 4 | +use crate::spec::{ |
| 5 | + Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel, |
| 6 | + add_link_args, crt_objects, cvs, |
| 7 | +}; |
| 8 | + |
| 9 | +pub(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 | +} |
0 commit comments