Skip to content

Commit cf95a4d

Browse files
committed
Target definition for wasm32-wali-linux-musl to support the Wasm Linux
Interface This commit does not patch libc, stdarch, or cc
1 parent fd17dea commit cf95a4d

File tree

14 files changed

+351
-19
lines changed

14 files changed

+351
-19
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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+
}

compiler/rustc_target/src/spec/base/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub(crate) mod linux_gnu;
1818
pub(crate) mod linux_musl;
1919
pub(crate) mod linux_ohos;
2020
pub(crate) mod linux_uclibc;
21+
pub(crate) mod linux_wasm;
2122
pub(crate) mod msvc;
2223
pub(crate) mod netbsd;
2324
pub(crate) mod nto_qnx;

compiler/rustc_target/src/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,7 @@ supported_targets! {
19251925
("wasm32-wasip1", wasm32_wasip1),
19261926
("wasm32-wasip2", wasm32_wasip2),
19271927
("wasm32-wasip1-threads", wasm32_wasip1_threads),
1928+
("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
19281929
("wasm64-unknown-unknown", wasm64_unknown_unknown),
19291930

19301931
("thumbv6m-none-eabi", thumbv6m_none_eabi),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! The `wasm32-wali-linux-musl` target is a wasm32 target compliant with the
2+
//! [WebAssembly Linux Interface](https://github.com/arjunr2/WALI).
3+
4+
use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};
5+
6+
pub(crate) fn target() -> Target {
7+
let mut options = base::linux_wasm::opts();
8+
9+
options
10+
.add_pre_link_args(LinkerFlavor::WasmLld(Cc::No), &["--export-memory", "--shared-memory"]);
11+
options.add_pre_link_args(
12+
LinkerFlavor::WasmLld(Cc::Yes),
13+
&["--target=wasm32-wasi-threads", "-Wl,--export-memory,", "-Wl,--shared-memory"],
14+
);
15+
16+
Target {
17+
llvm_target: "wasm32-wasi".into(),
18+
metadata: TargetMetadata {
19+
description: Some("WebAssembly Linux Interface with musl-libc".into()),
20+
tier: Some(3),
21+
host_tools: Some(false),
22+
std: None,
23+
},
24+
pointer_width: 32,
25+
data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
26+
arch: "wasm32".into(),
27+
options,
28+
}
29+
}

library/core/src/ffi/primitives.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ mod c_char_definition {
129129

130130
mod c_long_definition {
131131
cfg_if! {
132-
if #[cfg(all(target_pointer_width = "64", not(windows)))] {
132+
if #[cfg(any(
133+
all(target_pointer_width = "64", not(windows)),
134+
// wasm32 Linux ABI uses 64-bit long
135+
all(target_arch = "wasm32", target_os = "linux")))] {
133136
pub(super) type c_long = i64;
134137
pub(super) type c_ulong = u64;
135138
} else {

library/unwind/src/libunwind.rs

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ pub const unwinder_private_data_size: usize = 35;
8181
#[cfg(target_arch = "loongarch64")]
8282
pub const unwinder_private_data_size: usize = 2;
8383

84+
#[cfg(target_arch = "wasm32")]
85+
pub const unwinder_private_data_size: usize = 2;
86+
8487
#[repr(C)]
8588
pub struct _Unwind_Exception {
8689
pub exception_class: _Unwind_Exception_Class,

src/bootstrap/configure.py

+5
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ def v(*args):
269269
"target.loongarch64-unknown-linux-musl.musl-root",
270270
"loongarch64-unknown-linux-musl install directory",
271271
)
272+
v(
273+
"musl-root-wali-wasm32",
274+
"target.wasm32-wali-linux-musl.musl-root",
275+
"wasm32-wali-linux-musl install directory",
276+
)
272277
v(
273278
"qemu-armhf-rootfs",
274279
"target.arm-unknown-linux-gnueabihf.qemu-rootfs",

src/bootstrap/src/core/build_steps/compile.rs

+31-17
Original file line numberDiff line numberDiff line change
@@ -390,24 +390,38 @@ fn copy_self_contained_objects(
390390
let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
391391
panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
392392
});
393-
for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
394-
copy_and_stamp(
395-
builder,
396-
&libdir_self_contained,
397-
&srcdir,
398-
obj,
399-
&mut target_deps,
400-
DependencyType::TargetSelfContained,
401-
);
402-
}
403-
let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
404-
for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
405-
let src = crt_path.join(obj);
406-
let target = libdir_self_contained.join(obj);
407-
builder.copy_link(&src, &target);
408-
target_deps.push((target, DependencyType::TargetSelfContained));
393+
if !target.starts_with("wasm32") {
394+
for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
395+
copy_and_stamp(
396+
builder,
397+
&libdir_self_contained,
398+
&srcdir,
399+
obj,
400+
&mut target_deps,
401+
DependencyType::TargetSelfContained,
402+
);
403+
}
404+
let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
405+
for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
406+
let src = crt_path.join(obj);
407+
let target = libdir_self_contained.join(obj);
408+
builder.copy_link(&src, &target);
409+
target_deps.push((target, DependencyType::TargetSelfContained));
410+
}
411+
} else {
412+
// For wasm32 targets, we need to copy the libc.a and crt1-command.o files from the
413+
// musl-libdir, but we don't need the other files.
414+
for &obj in &["libc.a", "crt1-command.o"] {
415+
copy_and_stamp(
416+
builder,
417+
&libdir_self_contained,
418+
&srcdir,
419+
obj,
420+
&mut target_deps,
421+
DependencyType::TargetSelfContained,
422+
);
423+
}
409424
}
410-
411425
if !target.starts_with("s390x") {
412426
let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
413427
target_deps.push((libunwind_path, DependencyType::TargetSelfContained));

src/bootstrap/src/core/sanity.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub struct Finder {
3434
// Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
3535
const STAGE0_MISSING_TARGETS: &[&str] = &[
3636
// just a dummy comment so the list doesn't get onelined
37+
"wasm32-wali-linux-musl",
3738
];
3839

3940
/// Minimum version threshold for libstdc++ required when using prebuilt LLVM

src/doc/rustc/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
- [wasm32-wasip1](platform-support/wasm32-wasip1.md)
9696
- [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md)
9797
- [wasm32-wasip2](platform-support/wasm32-wasip2.md)
98+
- [wasm32-wali-linux-musl](platform-support/wasm32-wali-linux.md)
9899
- [wasm32-unknown-emscripten](platform-support/wasm32-unknown-emscripten.md)
99100
- [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
100101
- [wasm32v1-none](platform-support/wasm32v1-none.md)

src/doc/rustc/src/platform-support.md

+1
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ target | std | host | notes
405405
[`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX
406406
[`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX, hardfloat
407407
[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly
408+
[`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI)
408409
[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS
409410
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
410411
[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ? | | 64-bit x86 Cygwin |

0 commit comments

Comments
 (0)