Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for wasm32-wali-linux-musl Tier-3 target #135651

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions compiler/rustc_target/src/spec/base/linux_wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//! This target is a confluence of Linux and Wasm models, inheriting most
//! aspects from their respective base targets

use crate::spec::{
Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel,
add_link_args, crt_objects, cvs,
};

pub(crate) fn opts() -> TargetOptions {
macro_rules! args {
($prefix:literal) => {
&[
// By default LLD only gives us one page of stack (64k) which is a
// little small. Default to a larger stack closer to other PC platforms
// (1MB) and users can always inject their own link-args to override this.
concat!($prefix, "-z"),
concat!($prefix, "stack-size=1048576"),
// By default LLD's memory layout is:
//
// 1. First, a blank page
// 2. Next, all static data
// 3. Finally, the main stack (which grows down)
//
// This has the unfortunate consequence that on stack overflows you
// corrupt static data and can cause some exceedingly weird bugs. To
// help detect this a little sooner we instead request that the stack is
// placed before static data.
//
// This means that we'll generate slightly larger binaries as references
// to static data will take more bytes in the ULEB128 encoding, but
// stack overflow will be guaranteed to trap as it underflows instead of
// corrupting static data.
concat!($prefix, "--stack-first"),
// FIXME we probably shouldn't pass this but instead pass an explicit list
// of symbols we'll allow to be undefined. We don't currently have a
// mechanism of knowing, however, which symbols are intended to be imported
// from the environment and which are intended to be imported from other
// objects linked elsewhere. This is a coarse approximation but is sure to
// hide some bugs and frustrate someone at some point, so we should ideally
// work towards a world where we can explicitly list symbols that are
// supposed to be imported and have all other symbols generate errors if
// they remain undefined.
concat!($prefix, "--allow-undefined"),
// LLD only implements C++-like demangling, which doesn't match our own
// mangling scheme. Tell LLD to not demangle anything and leave it up to
// us to demangle these symbols later. Currently rustc does not perform
// further demangling, but tools like twiggy and wasm-bindgen are intended
// to do so.
concat!($prefix, "--no-demangle"),
]
};
}

let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!(""));
add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,"));

TargetOptions {
is_like_wasm: true,
families: cvs!["wasm", "unix"],
os: "linux".into(),
env: "musl".into(),

// we allow dynamic linking, but only cdylibs. Basically we allow a
// final library artifact that exports some symbols (a wasm module) but
// we don't allow intermediate `dylib` crate types
dynamic_linking: true,
only_cdylib: true,

// relatively self-explanatory!
exe_suffix: ".wasm".into(),
dll_prefix: "".into(),
dll_suffix: ".wasm".into(),
eh_frame_header: false,

max_atomic_width: Some(64),

// Unwinding doesn't work right now, so the whole target unconditionally
// defaults to panic=abort. Note that this is guaranteed to change in
// the future once unwinding is implemented. Don't rely on this as we're
// basically guaranteed to change it once WebAssembly supports
// exceptions.
panic_strategy: PanicStrategy::Abort,

// Symbol visibility takes care of this for the WebAssembly.
// Additionally the only known linker, LLD, doesn't support the script
// arguments just yet
limit_rdylib_exports: false,

// we use the LLD shipped with the Rust toolchain by default
linker: Some("rust-lld".into()),
linker_flavor: LinkerFlavor::WasmLld(Cc::No),

pre_link_args,

// FIXME: Figure out cases in which WASM needs to link with a native toolchain.
//
// rust-lang/rust#104137: cannot blindly remove this without putting in
// some other way to compensate for lack of `-nostartfiles` in linker
// invocation.
link_self_contained: LinkSelfContainedDefault::True,
pre_link_objects_self_contained: crt_objects::pre_wasi_self_contained(),
post_link_objects_self_contained: crt_objects::post_wasi_self_contained(),

// This has no effect in LLVM 8 or prior, but in LLVM 9 and later when
// PIC code is implemented this has quite a drastic effect if it stays
// at the default, `pic`. In an effort to keep wasm binaries as minimal
// as possible we're defaulting to `static` for now, but the hope is
// that eventually we can ship a `pic`-compatible standard library which
// works with `static` as well (or works with some method of generating
// non-relative calls and such later on).
relocation_model: RelocModel::Static,

// When the atomics feature is activated then these two keys matter,
// otherwise they're basically ignored by the standard library. In this
// mode, however, the `#[thread_local]` attribute works (i.e.
// `has_thread_local`) and we need to get it to work by specifying
// `local-exec` as that's all that's implemented in LLVM today for wasm.
has_thread_local: true,
tls_model: TlsModel::LocalExec,

// Supporting Linux requires multithreading supported by Wasm's thread
// proposal
singlethread: false,

// gdb scripts don't work on wasm blobs
emit_debug_gdb_scripts: false,

// There's more discussion of this at
// https://bugs.llvm.org/show_bug.cgi?id=52442 but the general result is
// that this isn't useful for wasm and has tricky issues with
// representation, so this is disabled.
generate_arange_section: false,

// Right now this is a bit of a workaround but we're currently saying that
// the target by default has a static crt which we're taking as a signal
// for "use the bundled crt". If that's turned off then the system's crt
// will be used, but this means that default usage of this target doesn't
// need an external compiler but it's still interoperable with an external
// compiler if configured correctly.
crt_static_default: true,
crt_static_respected: true,

// Allow `+crt-static` to create a "cdylib" output which is just a wasm file
// without a main function.
crt_static_allows_dylibs: true,

// Wasm start ignores arguments -- relies on API call from interface.
main_needs_argc_argv: false,

// Wasm toolchains mangle the name of "main" to distinguish between different
// signatures.
entry_name: "__main_void".into(),

// Wasm Feature flags for supporting Linux
features: "+atomics,+bulk-memory,+mutable-globals,+sign-ext".into(),

..Default::default()
}
}
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/base/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub(crate) mod linux_gnu;
pub(crate) mod linux_musl;
pub(crate) mod linux_ohos;
pub(crate) mod linux_uclibc;
pub(crate) mod linux_wasm;
pub(crate) mod msvc;
pub(crate) mod netbsd;
pub(crate) mod nto_qnx;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,7 @@ supported_targets! {
("wasm32-wasip1", wasm32_wasip1),
("wasm32-wasip2", wasm32_wasip2),
("wasm32-wasip1-threads", wasm32_wasip1_threads),
("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
("wasm64-unknown-unknown", wasm64_unknown_unknown),

("thumbv6m-none-eabi", thumbv6m_none_eabi),
Expand Down
29 changes: 29 additions & 0 deletions compiler/rustc_target/src/spec/targets/wasm32_wali_linux_musl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! The `wasm32-wali-linux-musl` target is a wasm32 target compliant with the
//! [WebAssembly Linux Interface](https://github.com/arjunr2/WALI).

use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};

pub(crate) fn target() -> Target {
let mut options = base::linux_wasm::opts();

options
.add_pre_link_args(LinkerFlavor::WasmLld(Cc::No), &["--export-memory", "--shared-memory"]);
options.add_pre_link_args(
LinkerFlavor::WasmLld(Cc::Yes),
&["--target=wasm32-wasi-threads", "-Wl,--export-memory,", "-Wl,--shared-memory"],
);

Target {
llvm_target: "wasm32-wasi".into(),
metadata: TargetMetadata {
description: Some("WebAssembly Linux Interface with musl-libc".into()),
tier: Some(3),
host_tools: Some(false),
std: None,
},
pointer_width: 32,
data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(),
arch: "wasm32".into(),
options,
}
}
5 changes: 4 additions & 1 deletion library/core/src/ffi/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ mod c_char_definition {

mod c_long_definition {
cfg_if! {
if #[cfg(all(target_pointer_width = "64", not(windows)))] {
if #[cfg(any(
all(target_pointer_width = "64", not(windows)),
// wasm32 Linux ABI uses 64-bit long
all(target_arch = "wasm32", target_os = "linux")))] {
pub(super) type c_long = i64;
pub(super) type c_ulong = u64;
} else {
Expand Down
3 changes: 3 additions & 0 deletions library/unwind/src/libunwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ pub const unwinder_private_data_size: usize = 35;
#[cfg(target_arch = "loongarch64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "wasm32")]
pub const unwinder_private_data_size: usize = 2;

#[repr(C)]
pub struct _Unwind_Exception {
pub exception_class: _Unwind_Exception_Class,
Expand Down
5 changes: 5 additions & 0 deletions src/bootstrap/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,11 @@ def v(*args):
"target.loongarch64-unknown-linux-musl.musl-root",
"loongarch64-unknown-linux-musl install directory",
)
v(
"musl-root-wali-wasm32",
"target.wasm32-wali-linux-musl.musl-root",
"wasm32-wali-linux-musl install directory",
)
v(
"qemu-armhf-rootfs",
"target.arm-unknown-linux-gnueabihf.qemu-rootfs",
Expand Down
48 changes: 31 additions & 17 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,24 +390,38 @@ fn copy_self_contained_objects(
let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
});
for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
copy_and_stamp(
builder,
&libdir_self_contained,
&srcdir,
obj,
&mut target_deps,
DependencyType::TargetSelfContained,
);
}
let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
let src = crt_path.join(obj);
let target = libdir_self_contained.join(obj);
builder.copy_link(&src, &target);
target_deps.push((target, DependencyType::TargetSelfContained));
if !target.starts_with("wasm32") {
for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
copy_and_stamp(
builder,
&libdir_self_contained,
&srcdir,
obj,
&mut target_deps,
DependencyType::TargetSelfContained,
);
}
let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
let src = crt_path.join(obj);
let target = libdir_self_contained.join(obj);
builder.copy_link(&src, &target);
target_deps.push((target, DependencyType::TargetSelfContained));
}
} else {
// For wasm32 targets, we need to copy the libc.a and crt1-command.o files from the
// musl-libdir, but we don't need the other files.
for &obj in &["libc.a", "crt1-command.o"] {
copy_and_stamp(
builder,
&libdir_self_contained,
&srcdir,
obj,
&mut target_deps,
DependencyType::TargetSelfContained,
);
}
}

if !target.starts_with("s390x") {
let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/src/core/sanity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub struct Finder {
// Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
const STAGE0_MISSING_TARGETS: &[&str] = &[
// just a dummy comment so the list doesn't get onelined
"wasm32-wali-linux-musl",
];

/// Minimum version threshold for libstdc++ required when using prebuilt LLVM
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
- [wasm32-wasip1](platform-support/wasm32-wasip1.md)
- [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md)
- [wasm32-wasip2](platform-support/wasm32-wasip2.md)
- [wasm32-wali-linux-musl](platform-support/wasm32-wali-linux.md)
- [wasm32-unknown-emscripten](platform-support/wasm32-unknown-emscripten.md)
- [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
- [wasm32v1-none](platform-support/wasm32v1-none.md)
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ target | std | host | notes
[`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX
[`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX, hardfloat
[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly
[`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI)
[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ? | | 64-bit x86 Cygwin |
Expand Down
Loading
Loading