From b8b50f0eda08e19e7c96377681f82ac17c76775d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 6 Sep 2016 00:41:50 +0000 Subject: [PATCH] Preliminary wasm32 support --- mk/cfg/wasm32-unknown-emscripten.mk | 24 +++++++++++ src/bootstrap/check.rs | 12 +++--- src/liballoc_system/lib.rs | 3 +- src/libpanic_unwind/gcc.rs | 4 ++ src/librustc_back/target/mod.rs | 3 +- .../target/wasm32_unknown_emscripten.rs | 41 +++++++++++++++++++ src/librustc_trans/abi.rs | 1 + src/libstd/env.rs | 18 +++++++- src/libstd/os/linux/raw.rs | 3 +- src/libtest/lib.rs | 4 +- src/libunwind/libunwind.rs | 2 +- src/tools/compiletest/src/runtest.rs | 7 ++-- src/tools/compiletest/src/util.rs | 3 +- 13 files changed, 107 insertions(+), 18 deletions(-) create mode 100644 mk/cfg/wasm32-unknown-emscripten.mk create mode 100644 src/librustc_back/target/wasm32_unknown_emscripten.rs diff --git a/mk/cfg/wasm32-unknown-emscripten.mk b/mk/cfg/wasm32-unknown-emscripten.mk new file mode 100644 index 00000000000..997bdfbf03a --- /dev/null +++ b/mk/cfg/wasm32-unknown-emscripten.mk @@ -0,0 +1,24 @@ +# wasm32-unknown-emscripten configuration +CC_wasm32-unknown-emscripten=emcc +CXX_wasm32-unknown-emscripten=em++ +CPP_wasm32-unknown-emscripten=$(CPP) +AR_wasm32-unknown-emscripten=emar +CFG_LIB_NAME_wasm32-unknown-emscripten=lib$(1).so +CFG_STATIC_LIB_NAME_wasm32-unknown-emscripten=lib$(1).a +CFG_LIB_GLOB_wasm32-unknown-emscripten=lib$(1)-*.so +CFG_LIB_DSYM_GLOB_wasm32-unknown-emscripten=lib$(1)-*.dylib.dSYM +CFG_JEMALLOC_CFLAGS_wasm32-unknown-emscripten := -m32 $(CFLAGS) +CFG_GCCISH_CFLAGS_wasm32-unknown-emscripten := -g -fPIC -m32 -s BINARYEN=1 $(CFLAGS) +CFG_GCCISH_CXXFLAGS_wasm32-unknown-emscripten := -fno-rtti -s BINARYEN=1 $(CXXFLAGS) +CFG_GCCISH_LINK_FLAGS_wasm32-unknown-emscripten := -shared -fPIC -ldl -pthread -lrt -g -m32 -s BINARYEN=1 +CFG_GCCISH_DEF_FLAG_wasm32-unknown-emscripten := -Wl,--export-dynamic,--dynamic-list= +CFG_LLC_FLAGS_wasm32-unknown-emscripten := +CFG_INSTALL_NAME_wasm32-unknown-emscripten = +CFG_EXE_SUFFIX_wasm32-unknown-emscripten = +CFG_WINDOWSY_wasm32-unknown-emscripten := +CFG_UNIXY_wasm32-unknown-emscripten := 1 +CFG_LDPATH_wasm32-unknown-emscripten := +CFG_RUN_wasm32-unknown-emscripten=$(2) +CFG_RUN_TARG_wasm32-unknown-emscripten=$(call CFG_RUN_wasm32-unknown-emscripten,,$(2)) +CFG_GNU_TRIPLE_wasm32-unknown-emscripten := wasm32-unknown-emscripten +CFG_DISABLE_JEMALLOC_wasm32-unknown-emscripten := 1 diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 8a844f71031..c839e405353 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -323,9 +323,9 @@ pub fn krate(build: &Build, if target.contains("android") { build.run(cargo.arg("--no-run")); krate_android(build, compiler, target, mode); - } else if target.contains("asmjs") { + } else if target.contains("emscripten") { build.run(cargo.arg("--no-run")); - krate_asmjs(build, compiler, target, mode); + krate_emscripten(build, compiler, target, mode); } else { cargo.args(&build.flags.args); build.run(&mut cargo); @@ -374,10 +374,10 @@ fn krate_android(build: &Build, } } -fn krate_asmjs(build: &Build, - compiler: &Compiler, - target: &str, - mode: Mode) { +fn krate_emscripten(build: &Build, + compiler: &Compiler, + target: &str, + mode: Mode) { let mut tests = Vec::new(); let out_dir = build.cargo_out(compiler, mode, target); find_tests(&out_dir, target, &mut tests); diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 01407d1acd2..dacafe771ed 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -29,7 +29,8 @@ target_arch = "mips", target_arch = "powerpc", target_arch = "powerpc64", - target_arch = "asmjs")))] + target_arch = "asmjs", + target_arch = "wasm32")))] const MIN_ALIGN: usize = 8; #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64", diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index e4730a73204..5bfa77cba7a 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -139,6 +139,10 @@ const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7 #[cfg(target_arch = "asmjs")] const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX +// FIXME: Ditto the above +#[cfg(target_arch = "wasm32")] +const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX + // The following code is based on GCC's C and C++ personality routines. For reference, see: // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 3eddd911749..6e2f7b1bf53 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -190,7 +190,8 @@ supported_targets! { ("i586-pc-windows-msvc", i586_pc_windows_msvc), ("le32-unknown-nacl", le32_unknown_nacl), - ("asmjs-unknown-emscripten", asmjs_unknown_emscripten) + ("asmjs-unknown-emscripten", asmjs_unknown_emscripten), + ("wasm32-unknown-emscripten", wasm32_unknown_emscripten) } /// Everything `rustc` knows about how to compile for a specific target. diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs new file mode 100644 index 00000000000..412fb868086 --- /dev/null +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -0,0 +1,41 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::{Target, TargetOptions}; + +pub fn target() -> Result { + let opts = TargetOptions { + linker: "emcc".to_string(), + ar: "emar".to_string(), + + dynamic_linking: false, + executables: true, + // Today emcc emits two files - a .js file to bootstrap and + // possibly interpret the wasm, and a .wasm file + exe_suffix: ".js".to_string(), + linker_is_gnu: true, + allow_asm: false, + obj_is_bitcode: true, + max_atomic_width: 32, + post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string()], + .. Default::default() + }; + Ok(Target { + llvm_target: "asmjs-unknown-emscripten".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_os: "emscripten".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), + arch: "wasm32".to_string(), + options: opts, + }) +} diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index b82c5629f9d..0a5b013c79a 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -519,6 +519,7 @@ impl FnType { "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, self), "s390x" => cabi_s390x::compute_abi_info(ccx, self), "asmjs" => cabi_asmjs::compute_abi_info(ccx, self), + "wasm32" => cabi_asmjs::compute_abi_info(ccx, self), a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 5171fbdf03e..5da6e5a8b80 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -892,7 +892,18 @@ mod os { pub const EXE_EXTENSION: &'static str = "pexe"; } -#[cfg(target_os = "emscripten")] +#[cfg(all(target_os = "emscripten", target_arch = "asmjs"))] +mod os { + pub const FAMILY: &'static str = "unix"; + pub const OS: &'static str = "emscripten"; + pub const DLL_PREFIX: &'static str = "lib"; + pub const DLL_SUFFIX: &'static str = ".so"; + pub const DLL_EXTENSION: &'static str = "so"; + pub const EXE_SUFFIX: &'static str = ".js"; + pub const EXE_EXTENSION: &'static str = "js"; +} + +#[cfg(all(target_os = "emscripten", target_arch = "wasm32"))] mod os { pub const FAMILY: &'static str = "unix"; pub const OS: &'static str = "emscripten"; @@ -969,6 +980,11 @@ mod arch { pub const ARCH: &'static str = "asmjs"; } +#[cfg(target_arch = "wasm32")] +mod arch { + pub const ARCH: &'static str = "wasm32"; +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs index 1c19e58818d..e6a95bc831f 100644 --- a/src/libstd/os/linux/raw.rs +++ b/src/libstd/os/linux/raw.rs @@ -34,7 +34,8 @@ pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t}; target_arch = "le32", target_arch = "powerpc", target_arch = "arm", - target_arch = "asmjs"))] + target_arch = "asmjs", + target_arch = "wasm32"))] mod arch { use os::raw::{c_long, c_short, c_uint}; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index dcfd3f754c7..12dd8e615e8 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1291,7 +1291,7 @@ impl MetricMap { /// /// This function is a no-op, and does not even read from `dummy`. #[cfg(not(any(all(target_os = "nacl", target_arch = "le32"), - target_arch = "asmjs")))] + target_arch = "asmjs", target_arch = "wasm32")))] pub fn black_box(dummy: T) -> T { // we need to "use" the argument in some way LLVM can't // introspect. @@ -1299,7 +1299,7 @@ pub fn black_box(dummy: T) -> T { dummy } #[cfg(any(all(target_os = "nacl", target_arch = "le32"), - target_arch = "asmjs"))] + target_arch = "asmjs", target_arch = "wasm32"))] #[inline(never)] pub fn black_box(dummy: T) -> T { dummy diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index 30de859f150..5d69a95da82 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -65,7 +65,7 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(target_arch = "s390x")] pub const unwinder_private_data_size: usize = 2; -#[cfg(target_arch = "asmjs")] +#[cfg(any(target_arch = "asmjs", target_arch = "wasm32"))] pub const unwinder_private_data_size: usize = 20; #[repr(C)] diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8fdb882164a..5885e464b4f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1168,7 +1168,6 @@ actual:\n\ "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => { self._arm_exec_compiled_test(env) } - _=> { let aux_dir = self.aux_output_dir_name(); self.compose_and_run(self.make_run_args(), @@ -1421,7 +1420,7 @@ actual:\n\ fn make_exe_name(&self) -> PathBuf { let mut f = self.output_base_name(); // FIXME: This is using the host architecture exe suffix, not target! - if self.config.target == "asmjs-unknown-emscripten" { + if self.config.target.contains("emscripten") { let mut fname = f.file_name().unwrap().to_os_string(); fname.push(".js"); f.set_file_name(&fname); @@ -1439,8 +1438,8 @@ actual:\n\ let mut args = self.split_maybe_args(&self.config.runtool); // If this is emscripten, then run tests under nodejs - if self.config.target == "asmjs-unknown-emscripten" { - args.push("nodejs".to_owned()); + if self.config.target.contains("emscripten") { + args.push("node".to_owned()); } let exe_file = self.make_exe_name(); diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 428bbcfe576..cad71c59f0a 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -43,7 +43,8 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[("aarch64", "aarch ("sparc", "sparc"), ("x86_64", "x86_64"), ("xcore", "xcore"), - ("asmjs", "asmjs")]; + ("asmjs", "asmjs"), + ("wasm32", "wasm32")]; pub fn get_os(triple: &str) -> &'static str { for &(triple_os, os) in OS_TABLE {