Skip to content

Commit

Permalink
Add a wasi target
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Mar 12, 2019
1 parent 88f755f commit 87cd55f
Show file tree
Hide file tree
Showing 30 changed files with 2,346 additions and 164 deletions.
126 changes: 63 additions & 63 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,8 @@ rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' }
# here
rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' }

libc = { git = 'https://github.com/alexcrichton/libc', branch = 'wasi' }
#libc = { path = "../libc" }

[patch."https://github.com/rust-lang/rust-clippy"]
clippy_lints = { path = "src/tools/clippy/clippy_lints" }
67 changes: 11 additions & 56 deletions src/librustc_codegen_ssa/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ impl<'a> GccLinker<'a> {
}

fn takes_hints(&self) -> bool {
!self.sess.target.target.options.is_like_osx
!self.sess.target.target.options.is_like_osx &&
self.sess.target.target.arch != "wasm32"
}

// Some platforms take hints about whether a library is static or dynamic.
Expand Down Expand Up @@ -375,6 +376,12 @@ impl<'a> Linker for GccLinker<'a> {
return
}

// Symbol visibility takes care of this. Additionally LLD doesn't
// support the script arguments just yet
if self.sess.target.target.arch == "wasm32" {
return;
}

let mut arg = OsString::new();
let path = tmpdir.join("list");

Expand Down Expand Up @@ -443,13 +450,13 @@ impl<'a> Linker for GccLinker<'a> {
}

fn group_start(&mut self) {
if !self.sess.target.target.options.is_like_osx {
if self.takes_hints() {
self.linker_arg("--start-group");
}
}

fn group_end(&mut self) {
if !self.sess.target.target.options.is_like_osx {
if self.takes_hints() {
self.linker_arg("--end-group");
}
}
Expand Down Expand Up @@ -877,59 +884,7 @@ pub struct WasmLd<'a> {
}

impl<'a> WasmLd<'a> {
fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
// There have been reports in the wild (rustwasm/wasm-bindgen#119) of
// using threads causing weird hangs and bugs. Disable it entirely as
// this isn't yet the bottleneck of compilation at all anyway.
cmd.arg("--no-threads");

// 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.
cmd.arg("-z").arg("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.
cmd.arg("--stack-first");

// FIXME we probably shouldn't pass this but instead pass an explicit
// whitelist of symbols we'll allow to be undefined. Unfortunately
// though we can't handle symbols like `log10` that LLVM injects at a
// super late date without actually parsing object files. For now let's
// stick to this and hopefully fix it before stabilization happens.
cmd.arg("--allow-undefined");

// For now we just never have an entry symbol
cmd.arg("--no-entry");

// Rust code should never have warnings, and warnings are often
// indicative of bugs, let's prevent them.
cmd.arg("--fatal-warnings");

// The symbol visibility story is a bit in flux right now with LLD.
// It's... not entirely clear to me what's going on, but this looks to
// make everything work when `export_symbols` isn't otherwise called for
// things like executables.
cmd.arg("--export-dynamic");

// 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.
cmd.arg("--no-demangle");

fn new(cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
WasmLd { cmd, sess, info }
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_target/abi/call/wasm32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ fn classify_ret_ty<Ty>(ret: &mut ArgType<'_, Ty>) {
}

fn classify_arg_ty<Ty>(arg: &mut ArgType<'_, Ty>) {
arg.extend_integer_width_to(32);
if arg.layout.is_aggregate() {
arg.make_indirect();
} else {
arg.extend_integer_width_to(32);
}
}

pub fn compute_abi_info<Ty>(fty: &mut FnType<'_, Ty>) {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ mod l4re_base;
mod fuchsia_base;
mod redox_base;
mod riscv_base;
mod wasm32_base;

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
RustcEncodable, RustcDecodable)]
Expand Down Expand Up @@ -437,6 +438,7 @@ supported_targets! {
("asmjs-unknown-emscripten", asmjs_unknown_emscripten),
("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
("wasm32-unknown-unknown", wasm32_unknown_unknown),
("wasm32-unknown-wasi", wasm32_unknown_wasi),
("wasm32-experimental-emscripten", wasm32_experimental_emscripten),

("thumbv6m-none-eabi", thumbv6m_none_eabi),
Expand Down
113 changes: 113 additions & 0 deletions src/librustc_target/spec/wasm32_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use std::collections::BTreeMap;
use super::{LldFlavor, TargetOptions, PanicStrategy, LinkerFlavor};

pub fn options() -> TargetOptions {
let mut lld_args = Vec::new();
let mut clang_args = Vec::new();
let mut arg = |arg: &str| {
lld_args.push(arg.to_string());
clang_args.push(format!("-Wl,{}", arg));
};

// There have been reports in the wild (rustwasm/wasm-bindgen#119) of
// using threads causing weird hangs and bugs. Disable it entirely as
// this isn't yet the bottleneck of compilation at all anyway.
arg("--no-threads");

// 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.
arg("-z");
arg("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.
arg("--stack-first");

// FIXME we probably shouldn't pass this but instead pass an explicit
// whitelist of symbols we'll allow to be undefined. Unfortunately
// though we can't handle symbols like `log10` that LLVM injects at a
// super late date without actually parsing object files. For now let's
// stick to this and hopefully fix it before stabilization happens.
arg("--allow-undefined");

// Rust code should never have warnings, and warnings are often
// indicative of bugs, let's prevent them.
arg("--fatal-warnings");

// 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.
arg("--no-demangle");

// The symbol visibility story is a bit in flux right now with LLD.
// It's... not entirely clear to me what's going on, but this looks to
// make everything work when `export_symbols` isn't otherwise called for
// things like executables.
arg("--export-dynamic");

// For now we just never have an entry symbol
lld_args.push("--no-entry".to_string());

let mut pre_link_args = BTreeMap::new();
pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Wasm), lld_args);
pre_link_args.insert(LinkerFlavor::Gcc, clang_args);

TargetOptions {
// 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,

// This means we'll just embed a `start` function in the wasm module
executables: true,

// relatively self-explanatory!
exe_suffix: ".wasm".to_string(),
dll_prefix: String::new(),
dll_suffix: ".wasm".to_string(),
linker_is_gnu: 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.
panic_strategy: PanicStrategy::Abort,

// Wasm doesn't have atomics yet, so tell LLVM that we're in a single
// threaded model which will legalize atomics to normal operations.
singlethread: true,

// no dynamic linking, no need for default visibility!
default_hidden_visibility: true,

// we use the LLD shipped with the Rust toolchain by default
linker: Some("rust-lld".to_owned()),
lld_flavor: LldFlavor::Wasm,

// No need for indirection here, simd types can always be passed by
// value as the whole module either has simd or not, which is different
// from x86 (for example) where programs can have functions that don't
// enable simd features.
simd_types_indirect: false,

pre_link_args,

.. Default::default()
}
}
47 changes: 3 additions & 44 deletions src/librustc_target/spec/wasm32_unknown_unknown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,10 @@
// (aka panic=abort by default), but otherwise this is in general a relatively
// standard target.

use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy};
use super::{LldFlavor, LinkerFlavor, Target};
use super::wasm32_base;

pub fn target() -> Result<Target, String> {
let opts = TargetOptions {
// 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,

// This means we'll just embed a `start` function in the wasm module
executables: true,

// relatively self-explanatory!
exe_suffix: ".wasm".to_string(),
dll_prefix: String::new(),
dll_suffix: ".wasm".to_string(),
linker_is_gnu: 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.
panic_strategy: PanicStrategy::Abort,

// Wasm doesn't have atomics yet, so tell LLVM that we're in a single
// threaded model which will legalize atomics to normal operations.
singlethread: true,

// no dynamic linking, no need for default visibility!
default_hidden_visibility: true,

// we use the LLD shipped with the Rust toolchain by default
linker: Some("rust-lld".to_owned()),
lld_flavor: LldFlavor::Wasm,

// No need for indirection here, simd types can always be passed by
// value as the whole module either has simd or not, which is different
// from x86 (for example) where programs can have functions that don't
// enable simd features.
simd_types_indirect: false,

.. Default::default()
};
Ok(Target {
llvm_target: "wasm32-unknown-unknown".to_string(),
target_endian: "little".to_string(),
Expand All @@ -65,6 +24,6 @@ pub fn target() -> Result<Target, String> {
data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
arch: "wasm32".to_string(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Wasm),
options: opts,
options: wasm32_base::options(),
})
}
25 changes: 25 additions & 0 deletions src/librustc_target/spec/wasm32_unknown_wasi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use super::{LinkerFlavor, Target};
use super::wasm32_base;

pub fn target() -> Result<Target, String> {
let mut options = wasm32_base::options();
options.linker = Some("clang".to_string());
options
.pre_link_args
.entry(LinkerFlavor::Gcc)
.or_insert(Vec::new())
.push("--target=wasm32-unknown-wasi".to_string());
Ok(Target {
llvm_target: "wasm32-unknown-wasi".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(),
target_os: "unknown".to_string(),
target_env: "wasi".to_string(),
target_vendor: "unknown".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
arch: "wasm32".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options,
})
}
1 change: 1 addition & 0 deletions src/libstd/os/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ cfg_if! {
#[cfg(target_os = "emscripten")] pub mod emscripten;
#[cfg(target_os = "fuchsia")] pub mod fuchsia;
#[cfg(target_os = "hermit")] pub mod hermit;
#[cfg(target_env = "wasi")] pub mod wasi;
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] pub mod fortanix_sgx;

pub mod raw;
6 changes: 6 additions & 0 deletions src/libstd/os/wasi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//! WASI-specific definitions
#![stable(feature = "raw_ext", since = "1.1.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::ext::*;
3 changes: 3 additions & 0 deletions src/libstd/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ cfg_if! {
} else if #[cfg(target_os = "redox")] {
mod redox;
pub use self::redox::*;
} else if #[cfg(target_env = "wasi")] {
mod wasi;
pub use self::wasi::*;
} else if #[cfg(target_arch = "wasm32")] {
mod wasm;
pub use self::wasm::*;
Expand Down
Loading

0 comments on commit 87cd55f

Please sign in to comment.