diff --git a/mk/cfg/wasm32-unknown-emscripten.mk b/mk/cfg/wasm32-unknown-emscripten.mk new file mode 100644 index 0000000000000..997bdfbf03ab1 --- /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/mk/main.mk b/mk/main.mk index cc843add50d1b..e68a8f3005561 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -300,7 +300,7 @@ endif # LLVM macros ###################################################################### -LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz +LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \ interpreter instrumentation diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 36b94e4ebea32..babbb6a16bae0 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -5,16 +5,16 @@ dependencies = [ "build_helper 0.1.0", "cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)", + "gcc 0.3.35 (git+https://github.com/alexcrichton/gcc-rs)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -34,7 +34,7 @@ name = "cmake" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -42,17 +42,17 @@ name = "filetime" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "gcc" -version = "0.3.31" -source = "git+https://github.com/alexcrichton/gcc-rs#b8e2400883f1a2749b323354dad372cdd1c838c7" +version = "0.3.35" +source = "git+https://github.com/alexcrichton/gcc-rs#8ff5360b6e0dc4f3c9d3f71036f1ff403c68469d" [[package]] name = "gcc" -version = "0.3.31" +version = "0.3.35" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -65,13 +65,13 @@ name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libc" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -84,15 +84,15 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num_cpus" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -123,7 +123,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -136,7 +136,7 @@ dependencies = [ [[package]] name = "toml" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -149,7 +149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -161,20 +161,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9" "checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" -"checksum gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)" = "" -"checksum gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "cfe877476e53690ebb0ce7325d0bf43e198d9500291b54b3c65e518de5039b07" +"checksum gcc 0.3.35 (git+https://github.com/alexcrichton/gcc-rs)" = "" +"checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "55f3730be7e803cf350d32061958171731c2395831fbd67a61083782808183e0" +"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2" "checksum md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5539a8dee9b4ae308c9c406a379838b435a8f2c84cf9fedc6d5a576be9888db" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" -"checksum num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "51fedae97a05f7353612fe017ab705a37e6db8f4d67c5c6fe739a9e70d6eed09" +"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3" "checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2" "checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199" "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d" -"checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6" +"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" -"checksum winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfaaa8fbdaa618fa6914b59b2769d690dd7521920a18d84b42d254678dd5fd4" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 2b9d717cbd48d..b8417218a2231 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -108,6 +108,10 @@ pub fn compiletest(build: &Build, cmd.arg("--host").arg(compiler.host); cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build)); + if let Some(nodejs) = build.config.nodejs.as_ref() { + cmd.arg("--nodejs").arg(nodejs); + } + let mut flags = vec!["-Crpath".to_string()]; if build.config.rust_optimize_tests { flags.push("-O".to_string()); @@ -323,6 +327,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("emscripten") { + build.run(cargo.arg("--no-run")); + krate_emscripten(build, compiler, target, mode); } else { cargo.args(&build.flags.args); build.run(&mut cargo); @@ -371,6 +378,35 @@ fn krate_android(build: &Build, } } +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); + find_tests(&out_dir.join("deps"), target, &mut tests); + + for test in tests { + let test_file_name = test.to_string_lossy().into_owned(); + println!("running {}", test_file_name); + let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured"); + let status = Command::new(nodejs) + .arg(&test_file_name) + .stderr(::std::process::Stdio::inherit()) + .status(); + match status { + Ok(status) => { + if !status.success() { + panic!("some tests failed"); + } + } + Err(e) => panic!(format!("failed to execute command: {}", e)), + }; + } + } + + fn find_tests(dir: &Path, target: &str, dst: &mut Vec) { @@ -381,7 +417,8 @@ fn find_tests(dir: &Path, } let filename = e.file_name().into_string().unwrap(); if (target.contains("windows") && filename.ends_with(".exe")) || - (!target.contains("windows") && !filename.contains(".")) { + (!target.contains("windows") && !filename.contains(".")) || + (target.contains("emscripten") && filename.contains(".js")){ dst.push(e.path()); } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 3d1cf47cb7e90..033cefb8dea36 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -975,7 +975,8 @@ impl Build { // than an entry here. let mut base = Vec::new(); - if target != self.config.build && !target.contains("msvc") { + if target != self.config.build && !target.contains("msvc") && + !target.contains("emscripten") { base.push(format!("-Clinker={}", self.cc(target).display())); } return base diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index df6408e5fe1c8..63fc59e43286e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -65,7 +65,7 @@ pub fn llvm(build: &Build, target: &str) { .out_dir(&dst) .profile(if build.config.llvm_optimize {"Release"} else {"Debug"}) .define("LLVM_ENABLE_ASSERTIONS", assertions) - .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;SystemZ") + .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend") .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 962d0666f69f1..c4e6399c2c36d 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -95,6 +95,13 @@ pub fn check(build: &mut Build) { // We're gonna build some custom C code here and there, host triples // also build some C++ shims for LLVM so we need a C++ compiler. for target in build.config.target.iter() { + // On emscripten we don't actually need the C compiler to just + // build the target artifacts, only for testing. For the sake + // of easier bot configuration, just skip detection. + if target.contains("emscripten") { + continue; + } + need_cmd(build.cc(target).as_ref()); if let Some(ar) = build.ar(target) { need_cmd(ar.as_ref()); @@ -104,6 +111,14 @@ pub fn check(build: &mut Build) { need_cmd(build.cxx(host).as_ref()); } + // The msvc hosts don't use jemalloc, turn it off globally to + // avoid packaging the dummy liballoc_jemalloc on that platform. + for host in build.config.host.iter() { + if host.contains("msvc") { + build.config.use_jemalloc = false; + } + } + // Externally configured LLVM requires FileCheck to exist let filecheck = build.llvm_filecheck(&build.config.build); if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { @@ -111,15 +126,6 @@ pub fn check(build: &mut Build) { } for target in build.config.target.iter() { - // Either can't build or don't want to run jemalloc on these targets - if target.contains("rumprun") || - target.contains("bitrig") || - target.contains("openbsd") || - target.contains("msvc") || - target.contains("emscripten") { - build.config.use_jemalloc = false; - } - // Can't compile for iOS unless we're on OSX if target.contains("apple-ios") && !build.config.build.contains("apple-darwin") { diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 4b5a26d205af7..8a96cd1b4d239 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -418,7 +418,6 @@ impl<'a> Step<'a> { self.check_crate_std(compiler), self.check_crate_test(compiler), self.check_debuginfo(compiler), - self.dist(stage), ]; // If we're testing the build triple, then we know we can @@ -463,6 +462,9 @@ impl<'a> Step<'a> { // misc self.check_linkcheck(stage), self.check_tidy(stage), + + // can we make the distributables? + self.dist(stage), ]); } return base diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index e3c92fc1aa830..29e18781ce2a5 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -1000,6 +1000,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn manually_share_arc() { let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let arc_v = Arc::new(v); diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 8b31c5a557747..028d742cc832e 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -27,6 +27,24 @@ fn main() { let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let src_dir = env::current_dir().unwrap(); + // FIXME: This is a hack to support building targets that don't + // support jemalloc alongside hosts that do. The jemalloc build is + // controlled by a feature of the std crate, and if that feature + // changes between targets, it invalidates the fingerprint of + // std's build script (this is a cargo bug); so we must ensure + // that the feature set used by std is the same across all + // targets, which means we have to build the alloc_jemalloc crate + // for targets like emscripten, even if we don't use it. + if target.contains("rumprun") || + target.contains("bitrig") || + target.contains("openbsd") || + target.contains("msvc") || + target.contains("emscripten") + { + println!("cargo:rustc-cfg=dummy_jemalloc"); + return; + } + if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") { let jemalloc = PathBuf::from(jemalloc); println!("cargo:rustc-link-search=native={}", diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index 5bbf1c35e0dd4..21e45f9c4b20c 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -23,124 +23,170 @@ extern crate libc; -use libc::{c_int, c_void, size_t}; +pub use imp::*; -// Linkage directives to pull in jemalloc and its dependencies. -// -// On some platforms we need to be sure to link in `pthread` which jemalloc -// depends on, and specifically on android we need to also link to libgcc. -// Currently jemalloc is compiled with gcc which will generate calls to -// intrinsics that are libgcc specific (e.g. those intrinsics aren't present in -// libcompiler-rt), so link that in to get that support. -#[link(name = "jemalloc", kind = "static")] -#[cfg_attr(target_os = "android", link(name = "gcc"))] -#[cfg_attr(all(not(windows), - not(target_os = "android"), - not(target_env = "musl")), - link(name = "pthread"))] -#[cfg(not(cargobuild))] -extern "C" {} - -// Note that the symbols here are prefixed by default on OSX and Windows (we -// don't explicitly request it), and on Android and DragonFly we explicitly -// request it as unprefixing cause segfaults (mismatches in allocators). -extern "C" { - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows"), - link_name = "je_mallocx")] - fn mallocx(size: size_t, flags: c_int) -> *mut c_void; - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows"), - link_name = "je_rallocx")] - fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows"), - link_name = "je_xallocx")] - fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows"), - link_name = "je_sdallocx")] - fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); - #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", - target_os = "dragonfly", target_os = "windows"), - link_name = "je_nallocx")] - fn nallocx(size: size_t, flags: c_int) -> size_t; -} +// See comments in build.rs for why we sometimes build a crate that does nothing +#[cfg(not(dummy_jemalloc))] +mod imp { + use libc::{c_int, c_void, size_t}; -// The minimum alignment guaranteed by the architecture. This value is used to -// add fast paths for low alignment values. In practice, the alignment is a -// constant at the call site and the branch will be optimized out. -#[cfg(all(any(target_arch = "arm", - target_arch = "mips", - target_arch = "powerpc")))] -const MIN_ALIGN: usize = 8; -#[cfg(all(any(target_arch = "x86", - target_arch = "x86_64", - target_arch = "aarch64", - target_arch = "powerpc64", - target_arch = "mips64", - target_arch = "s390x")))] -const MIN_ALIGN: usize = 16; - -// MALLOCX_ALIGN(a) macro -fn mallocx_align(a: usize) -> c_int { - a.trailing_zeros() as c_int -} + // Linkage directives to pull in jemalloc and its dependencies. + // + // On some platforms we need to be sure to link in `pthread` which jemalloc + // depends on, and specifically on android we need to also link to libgcc. + // Currently jemalloc is compiled with gcc which will generate calls to + // intrinsics that are libgcc specific (e.g. those intrinsics aren't present in + // libcompiler-rt), so link that in to get that support. + #[link(name = "jemalloc", kind = "static")] + #[cfg_attr(target_os = "android", link(name = "gcc"))] + #[cfg_attr(all(not(windows), + not(target_os = "android"), + not(target_env = "musl")), + link(name = "pthread"))] + #[cfg(not(cargobuild))] + extern "C" {} + + // Note that the symbols here are prefixed by default on OSX and Windows (we + // don't explicitly request it), and on Android and DragonFly we explicitly + // request it as unprefixing cause segfaults (mismatches in allocators). + extern "C" { + #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", + target_os = "dragonfly", target_os = "windows"), + link_name = "je_mallocx")] + fn mallocx(size: size_t, flags: c_int) -> *mut c_void; + #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", + target_os = "dragonfly", target_os = "windows"), + link_name = "je_rallocx")] + fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; + #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", + target_os = "dragonfly", target_os = "windows"), + link_name = "je_xallocx")] + fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; + #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", + target_os = "dragonfly", target_os = "windows"), + link_name = "je_sdallocx")] + fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); + #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios", + target_os = "dragonfly", target_os = "windows"), + link_name = "je_nallocx")] + fn nallocx(size: size_t, flags: c_int) -> size_t; + } + + // The minimum alignment guaranteed by the architecture. This value is used to + // add fast paths for low alignment values. In practice, the alignment is a + // constant at the call site and the branch will be optimized out. + #[cfg(all(any(target_arch = "arm", + target_arch = "mips", + target_arch = "powerpc")))] + const MIN_ALIGN: usize = 8; + #[cfg(all(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "powerpc64", + target_arch = "mips64", + target_arch = "s390x")))] + const MIN_ALIGN: usize = 16; + + // MALLOCX_ALIGN(a) macro + fn mallocx_align(a: usize) -> c_int { + a.trailing_zeros() as c_int + } + + fn align_to_flags(align: usize) -> c_int { + if align <= MIN_ALIGN { + 0 + } else { + mallocx_align(align) + } + } + + #[no_mangle] + pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 { + let flags = align_to_flags(align); + unsafe { mallocx(size as size_t, flags) as *mut u8 } + } + + #[no_mangle] + pub extern "C" fn __rust_reallocate(ptr: *mut u8, + _old_size: usize, + size: usize, + align: usize) + -> *mut u8 { + let flags = align_to_flags(align); + unsafe { rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 } + } + + #[no_mangle] + pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8, + _old_size: usize, + size: usize, + align: usize) + -> usize { + let flags = align_to_flags(align); + unsafe { xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize } + } -fn align_to_flags(align: usize) -> c_int { - if align <= MIN_ALIGN { + #[no_mangle] + pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { + let flags = align_to_flags(align); + unsafe { sdallocx(ptr as *mut c_void, old_size as size_t, flags) } + } + + #[no_mangle] + pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { + let flags = align_to_flags(align); + unsafe { nallocx(size as size_t, flags) as usize } + } + + // These symbols are used by jemalloc on android but the really old android + // we're building on doesn't have them defined, so just make sure the symbols + // are available. + #[no_mangle] + #[cfg(target_os = "android")] + pub extern "C" fn pthread_atfork(_prefork: *mut u8, + _postfork_parent: *mut u8, + _postfork_child: *mut u8) + -> i32 { 0 - } else { - mallocx_align(align) } } -#[no_mangle] -pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 { - let flags = align_to_flags(align); - unsafe { mallocx(size as size_t, flags) as *mut u8 } -} +#[cfg(dummy_jemalloc)] +mod imp { + fn bogus() -> ! { + panic!("jemalloc is not implemented for this platform"); + } -#[no_mangle] -pub extern "C" fn __rust_reallocate(ptr: *mut u8, - _old_size: usize, - size: usize, - align: usize) - -> *mut u8 { - let flags = align_to_flags(align); - unsafe { rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 } -} + #[no_mangle] + pub extern "C" fn __rust_allocate(_size: usize, _align: usize) -> *mut u8 { + bogus() + } -#[no_mangle] -pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8, - _old_size: usize, - size: usize, - align: usize) - -> usize { - let flags = align_to_flags(align); - unsafe { xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize } -} + #[no_mangle] + pub extern "C" fn __rust_reallocate(_ptr: *mut u8, + _old_size: usize, + _size: usize, + _align: usize) + -> *mut u8 { + bogus() + } -#[no_mangle] -pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { - let flags = align_to_flags(align); - unsafe { sdallocx(ptr as *mut c_void, old_size as size_t, flags) } -} + #[no_mangle] + pub extern "C" fn __rust_reallocate_inplace(_ptr: *mut u8, + _old_size: usize, + _size: usize, + _align: usize) + -> usize { + bogus() + } -#[no_mangle] -pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { - let flags = align_to_flags(align); - unsafe { nallocx(size as size_t, flags) as usize } -} + #[no_mangle] + pub extern "C" fn __rust_deallocate(_ptr: *mut u8, _old_size: usize, _align: usize) { + bogus() + } -// These symbols are used by jemalloc on android but the really old android -// we're building on doesn't have them defined, so just make sure the symbols -// are available. -#[no_mangle] -#[cfg(target_os = "android")] -pub extern "C" fn pthread_atfork(_prefork: *mut u8, - _postfork_parent: *mut u8, - _postfork_child: *mut u8) - -> i32 { - 0 + #[no_mangle] + pub extern "C" fn __rust_usable_size(_size: usize, _align: usize) -> usize { + bogus() + } } diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 01407d1acd2ec..dacafe771edc2 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/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 690c4f4af3589..67f3708a62b91 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -1294,6 +1294,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn test_send() { let n = list_from(&[1, 2, 3]); thread::spawn(move || { diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 5b341ab62d097..9580714075ad7 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -1116,6 +1116,7 @@ fn test_box_slice_clone() { } #[test] +#[cfg_attr(target_os = "emscripten", ignore)] fn test_box_slice_clone_panics() { use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/src/libcompiler_builtins/build.rs b/src/libcompiler_builtins/build.rs index 66c683333b985..acbd39bb1630c 100644 --- a/src/libcompiler_builtins/build.rs +++ b/src/libcompiler_builtins/build.rs @@ -73,6 +73,12 @@ impl Sources { fn main() { let target = env::var("TARGET").expect("TARGET was not set"); + + // Emscripten's runtime includes all the builtins + if target.contains("emscripten") { + return; + } + let cfg = &mut gcc::Config::new(); if target.contains("msvc") { diff --git a/src/libcoretest/num/flt2dec/estimator.rs b/src/libcoretest/num/flt2dec/estimator.rs index 857aae72c8a5b..0bca616ea9abc 100644 --- a/src/libcoretest/num/flt2dec/estimator.rs +++ b/src/libcoretest/num/flt2dec/estimator.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME https://github.com/kripken/emscripten/issues/4563 +// NB we have to actually not compile this test to avoid +// an undefined symbol error +#![cfg(not(target_os = "emscripten"))] + use core::num::flt2dec::estimator::*; #[test] diff --git a/src/libpanic_unwind/Cargo.lock b/src/libpanic_unwind/Cargo.lock index 20d826d4a470e..0cf75c941508b 100644 --- a/src/libpanic_unwind/Cargo.lock +++ b/src/libpanic_unwind/Cargo.lock @@ -5,6 +5,7 @@ dependencies = [ "alloc 0.0.0", "core 0.0.0", "libc 0.0.0", + "unwind 0.0.0", ] [[package]] @@ -25,3 +26,11 @@ dependencies = [ "core 0.0.0", ] +[[package]] +name = "unwind" +version = "0.0.0" +dependencies = [ + "core 0.0.0", + "libc 0.0.0", +] + diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs new file mode 100644 index 0000000000000..b3ab1117674ca --- /dev/null +++ b/src/libpanic_unwind/emcc.rs @@ -0,0 +1,78 @@ +// Copyright 2016 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. + +//! Unwinding for emscripten +//! +//! Whereas Rust's usual unwinding implementation for Unix platforms +//! calls into the libunwind APIs directly, on emscripten we instead +//! call into the C++ unwinding APIs. This is just an expedience since +//! emscripten's runtime always implements those APIs and does not +//! implement libunwind. + +#![allow(private_no_mangle_fns)] + +use core::any::Any; +use core::ptr; +use alloc::boxed::Box; +use libc::{self, c_int}; +use unwind as uw; +use core::mem; + +pub fn payload() -> *mut u8 { + ptr::null_mut() +} + +pub unsafe fn cleanup(ptr: *mut u8) -> Box { + assert!(!ptr.is_null()); + let ex = ptr::read(ptr as *mut _); + __cxa_free_exception(ptr as *mut _); + ex +} + +pub unsafe fn panic(data: Box) -> u32 { + let sz = mem::size_of_val(&data); + let exception = __cxa_allocate_exception(sz); + if exception == ptr::null_mut() { + return uw::_URC_FATAL_PHASE1_ERROR as u32; + } + let exception = exception as *mut Box; + ptr::write(exception, data); + __cxa_throw(exception as *mut _, ptr::null_mut(), ptr::null_mut()); + + unreachable!() +} + +#[lang = "eh_personality"] +#[no_mangle] +unsafe extern "C" fn rust_eh_personality(version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + exception_object: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code { + __gxx_personality_v0(version, actions, + exception_class, + exception_object, + context) +} + +extern { + fn __cxa_allocate_exception(thrown_size: libc::size_t) -> *mut libc::c_void; + fn __cxa_free_exception(thrown_exception: *mut libc::c_void); + fn __cxa_throw(thrown_exception: *mut libc::c_void, + tinfo: *mut libc::c_void, + dest: *mut libc::c_void); + fn __gxx_personality_v0(version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + exception_object: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code; +} diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 11dd9befe0a82..ff483fa823e0c 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -68,10 +68,16 @@ mod imp; mod imp; // i686-pc-windows-gnu and all others -#[cfg(any(unix, all(windows, target_arch = "x86", target_env = "gnu")))] +#[cfg(any(all(unix, not(target_os = "emscripten")), + all(windows, target_arch = "x86", target_env = "gnu")))] #[path = "gcc.rs"] mod imp; +// emscripten +#[cfg(target_os = "emscripten")] +#[path = "emcc.rs"] +mod imp; + mod dwarf; mod windows; diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs index 9ccfdbb129c73..667f7cf2c214a 100644 --- a/src/librustc_back/target/asmjs_unknown_emscripten.rs +++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs @@ -22,6 +22,7 @@ pub fn target() -> Result { allow_asm: false, obj_is_bitcode: true, max_atomic_width: 32, + post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], .. Default::default() }; Ok(Target { diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 3eddd911749e5..6e2f7b1bf5313 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 0000000000000..2923f2eb92e45 --- /dev/null +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -0,0 +1,42 @@ +// 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(), + "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=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_driver/lib.rs b/src/librustc_driver/lib.rs index 5ac4512fe3900..492165e2f2a8e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1075,7 +1075,7 @@ pub fn monitor(f: F) { } let thread = cfg.spawn(move || { - io::set_panic(box err); + io::set_panic(Some(box err)); f() }); @@ -1121,7 +1121,7 @@ fn exit_on_err() -> ! { // Panic so the process returns a failure code, but don't pollute the // output with some unnecessary panic messages, we've already // printed everything that we needed to. - io::set_panic(box io::sink()); + io::set_panic(Some(box io::sink())); panic!(); } diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 3f551476e2b46..5257575a94e8b 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -66,7 +66,8 @@ fn main() { let host = env::var("HOST").expect("HOST was not set"); let is_crossed = target != host; - let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz"]; + let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", + "jsbackend"]; // FIXME: surely we don't need all these components, right? Stuff like mcjit // or interpreter the compiler itself never uses. diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index eb45d3d25c5c0..3946b44ead578 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -434,6 +434,10 @@ pub fn initialize_available_targets() { LLVMInitializeSystemZTargetMC, LLVMInitializeSystemZAsmPrinter, LLVMInitializeSystemZAsmParser); + init_target!(llvm_component = "jsbackend", + LLVMInitializeJSBackendTargetInfo, + LLVMInitializeJSBackendTarget, + LLVMInitializeJSBackendTargetMC); } pub fn last_error() -> Option { diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index b82c5629f9da1..0a5b013c79ac2 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/librustdoc/test.rs b/src/librustdoc/test.rs index 1ab86cf7e8920..02f0916de0ef3 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -228,7 +228,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, let codemap = Rc::new(CodeMap::new()); let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()), Some(codemap.clone())); - let old = io::set_panic(box Sink(data.clone())); + let old = io::set_panic(Some(box Sink(data.clone()))); let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout())); // Compile the code diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 5171fbdf03e80..76a2f93c162e7 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::*; @@ -1017,6 +1033,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn test_var_big() { let mut s = "".to_string(); let mut i = 0; @@ -1030,6 +1047,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn test_self_exe_path() { let path = current_exe(); assert!(path.is_ok()); @@ -1040,6 +1058,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn test_env_set_get_huge() { let n = make_rand_name(); let s = repeat("x").take(10000).collect::(); diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 576198564dbd4..2f2969b110db1 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1686,7 +1686,7 @@ impl AsInnerMut for DirBuilder { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use io::prelude::*; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 4ff8c6ac128bd..21a0cc1fb3b13 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -1107,6 +1107,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn panic_in_write_doesnt_flush_in_drop() { static WRITES: AtomicUsize = AtomicUsize::new(0); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 0de02cbf19c9f..2ba2e8de71b54 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1761,6 +1761,7 @@ mod tests { use super::repeat; #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn read_until() { let mut buf = Cursor::new(&b"12"[..]); let mut v = Vec::new(); @@ -1971,6 +1972,7 @@ mod tests { } #[bench] + #[cfg_attr(target_os = "emscripten", ignore)] fn bench_read_to_end(b: &mut test::Bencher) { b.iter(|| { let mut lr = repeat(1).take(10000000); diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 9a782e95f6e5f..6421595a009a7 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -593,11 +593,11 @@ impl<'a> Write for StderrLock<'a> { with a more general mechanism", issue = "0")] #[doc(hidden)] -pub fn set_panic(sink: Box) -> Option> { +pub fn set_panic(sink: Option>) -> Option> { use panicking::LOCAL_STDERR; use mem; LOCAL_STDERR.with(move |slot| { - mem::replace(&mut *slot.borrow_mut(), Some(sink)) + mem::replace(&mut *slot.borrow_mut(), sink) }).and_then(|mut s| { let _ = s.flush(); Some(s) @@ -617,10 +617,10 @@ pub fn set_panic(sink: Box) -> Option> { with a more general mechanism", issue = "0")] #[doc(hidden)] -pub fn set_print(sink: Box) -> Option> { +pub fn set_print(sink: Option>) -> Option> { use mem; LOCAL_STDOUT.with(move |slot| { - mem::replace(&mut *slot.borrow_mut(), Some(sink)) + mem::replace(&mut *slot.borrow_mut(), sink) }).and_then(|mut s| { let _ = s.flush(); Some(s) @@ -668,6 +668,7 @@ mod tests { use super::*; #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn panic_doesnt_poison() { thread::spawn(|| { let _a = stdin(); diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index d0b59b42c1798..58daa7dbf8dc4 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -519,7 +519,7 @@ impl<'a, T: ToSocketAddrs + ?Sized> ToSocketAddrs for &'a T { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use net::*; use net::test::{tsa, sa6, sa4}; diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 05ef559422f33..ba2cd70e0d777 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -669,7 +669,7 @@ impl From<[u8; 16]> for Ipv6Addr { } // Tests for this module -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use net::*; use net::Ipv6MulticastScope::*; diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index ad2fe3c1c0dbc..7dd0e30df0368 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -31,7 +31,8 @@ mod addr; mod tcp; mod udp; mod parser; -#[cfg(test)] mod test; +#[cfg(all(test, not(target_os = "emscripten")))] +mod test; /// Possible values which can be passed to the [`shutdown`] method of /// [`TcpStream`]. diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 3c5f07c3e33a6..0e7c5b06713fb 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -428,7 +428,7 @@ impl fmt::Debug for TcpListener { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use io::ErrorKind; use io::prelude::*; diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 781f026c12c77..c03ac496adbb2 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -353,7 +353,7 @@ impl fmt::Debug for UdpSocket { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use io::ErrorKind; use net::*; diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs index 1c19e58818d74..e6a95bc831ffb 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/libstd/process.rs b/src/libstd/process.rs index f0c4443070074..9434815577981 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -807,7 +807,7 @@ pub fn exit(code: i32) -> ! { ::sys::os::exit(code) } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use io::prelude::*; diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 3f14fcd239f1d..69cd37651d5c2 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -242,6 +242,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn test_os_rng_tasks() { let mut txs = vec!(); diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index ac0f400379e3c..f46eab6848463 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -118,6 +118,7 @@ mod tests { use thread; #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn test_barrier() { const N: usize = 10; diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 3db8b05b954c3..a983ae716a481 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -270,6 +270,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn notify_one() { let m = Arc::new(Mutex::new(())); let m2 = m.clone(); @@ -286,6 +287,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn notify_all() { const N: usize = 10; @@ -322,6 +324,7 @@ mod tests { } #[test] + #[cfg_attr(target_os = "emscripten", ignore)] fn wait_timeout_ms() { let m = Arc::new(Mutex::new(())); let m2 = m.clone(); @@ -343,6 +346,7 @@ mod tests { #[test] #[should_panic] + #[cfg_attr(target_os = "emscripten", ignore)] fn two_mutexes() { let m = Arc::new(Mutex::new(())); let m2 = m.clone(); diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 3d9f81413dc73..d9c14ef2f771e 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1268,7 +1268,7 @@ impl error::Error for TryRecvError { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use env; use super::*; @@ -1942,7 +1942,7 @@ mod tests { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod sync_tests { use env; use thread; diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs index d926043fbbcd0..8d80f942ff75c 100644 --- a/src/libstd/sync/mpsc/mpsc_queue.rs +++ b/src/libstd/sync/mpsc/mpsc_queue.rs @@ -146,7 +146,7 @@ impl Drop for Queue { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use sync::mpsc::channel; use super::{Queue, Data, Empty, Inconsistent}; diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 51b08bd75c4bc..91896e1ab85dc 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -366,7 +366,7 @@ impl<'rx, T:Send+'rx> fmt::Debug for Handle<'rx, T> { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] #[allow(unused_imports)] mod tests { use thread; diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index 724d7b1be730d..5858e4b6ddb1f 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -231,7 +231,7 @@ impl Drop for Queue { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use sync::Arc; use super::Queue; diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 098a3e44258c7..812724c7a167e 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -352,7 +352,7 @@ pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Fla &guard.__lock.poison } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use sync::mpsc::channel; use sync::{Arc, Mutex, Condvar}; diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 86d2986959c99..ad9d0b3754422 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -367,7 +367,7 @@ impl OnceState { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use panic; use sync::mpsc::channel; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 7f053c6704b56..48ecae185f95c 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -380,7 +380,7 @@ impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { #![allow(deprecated)] // rand diff --git a/src/libstd/sys/common/io.rs b/src/libstd/sys/common/io.rs index 3cd70eddb858c..47cec4ef5c276 100644 --- a/src/libstd/sys/common/io.rs +++ b/src/libstd/sys/common/io.rs @@ -50,7 +50,7 @@ pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec) -> io:: } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] pub mod test { use path::{Path, PathBuf}; use env; @@ -165,6 +165,7 @@ mod tests { } #[bench] + #[cfg_attr(target_os = "emscripten", ignore)] fn bench_uninitialized(b: &mut ::test::Bencher) { b.iter(|| { let mut lr = repeat(1).take(10000000); diff --git a/src/libstd/sys/common/remutex.rs b/src/libstd/sys/common/remutex.rs index cbdeaad7f6bd3..4d0407ccf6c89 100644 --- a/src/libstd/sys/common/remutex.rs +++ b/src/libstd/sys/common/remutex.rs @@ -156,7 +156,7 @@ impl<'a, T> Drop for ReentrantMutexGuard<'a, T> { } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use cell::RefCell; diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 3f93fce193561..40fe24cf10e28 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -786,7 +786,7 @@ impl IntoRawFd for UnixDatagram { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod test { use thread; use io; diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 50014f51f6cf4..dafc11d9cc8e9 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -369,7 +369,7 @@ impl Command { } // NaCl has no signal support. - if cfg!(not(target_os = "nacl")) { + if cfg!(not(any(target_os = "nacl", target_os = "emscripten"))) { // Reset signal handling so the child process starts in a // standardized state. libstd ignores SIGPIPE, and signal-handling // libraries often set a mask. Child processes inherit ignored @@ -589,7 +589,7 @@ impl Process { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use super::*; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 980ef01f549c3..1e879117f73ab 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -29,6 +29,20 @@ pub struct Thread { unsafe impl Send for Thread {} unsafe impl Sync for Thread {} +// The pthread_attr_setstacksize symbol doesn't exist in the emscripten libc, +// so we have to not link to it to satisfy emcc's ERROR_ON_UNDEFINED_SYMBOLS. +#[cfg(not(target_os = "emscripten"))] +unsafe fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t, + stack_size: libc::size_t) -> libc::c_int { + libc::pthread_attr_setstacksize(attr, stack_size) +} + +#[cfg(target_os = "emscripten")] +unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t, + _stack_size: libc::size_t) -> libc::c_int { + panic!() +} + impl Thread { pub unsafe fn new<'a>(stack: usize, p: Box) -> io::Result { @@ -38,8 +52,8 @@ impl Thread { assert_eq!(libc::pthread_attr_init(&mut attr), 0); let stack_size = cmp::max(stack, min_stack_size(&attr)); - match libc::pthread_attr_setstacksize(&mut attr, - stack_size as libc::size_t) { + match pthread_attr_setstacksize(&mut attr, + stack_size as libc::size_t) { 0 => {} n => { assert_eq!(n, libc::EINVAL); diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index c44dee49f14a6..a333a7d967d24 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -524,7 +524,7 @@ pub mod os { } } -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use sync::mpsc::{channel, Sender}; use cell::{Cell, UnsafeCell}; diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index d8e021bb04ff9..775dfababc680 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -741,7 +741,7 @@ fn _assert_sync_and_send() { // Tests //////////////////////////////////////////////////////////////////////////////// -#[cfg(test)] +#[cfg(all(test, not(target_os = "emscripten")))] mod tests { use any::Any; use sync::mpsc::{channel, Sender}; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index dcfd3f754c720..5949afe0ff167 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1182,26 +1182,59 @@ pub fn run_test(opts: &TestOpts, } } - thread::spawn(move || { - let data = Arc::new(Mutex::new(Vec::new())); - let data2 = data.clone(); - let cfg = thread::Builder::new().name(match desc.name { - DynTestName(ref name) => name.clone(), - StaticTestName(name) => name.to_owned(), + // If the platform is single-threaded we're just going to run + // the test synchronously, regardless of the concurrency + // level. + let supports_threads = !cfg!(target_os = "emscripten"); + + // Buffer for capturing standard I/O + let data = Arc::new(Mutex::new(Vec::new())); + let data2 = data.clone(); + + if supports_threads { + thread::spawn(move || { + let cfg = thread::Builder::new().name(match desc.name { + DynTestName(ref name) => name.clone(), + StaticTestName(name) => name.to_owned(), + }); + + let result_guard = cfg.spawn(move || { + if !nocapture { + io::set_print(Some(box Sink(data2.clone()))); + io::set_panic(Some(box Sink(data2))); + } + testfn() + }) + .unwrap(); + let test_result = calc_result(&desc, result_guard.join()); + let stdout = data.lock().unwrap().to_vec(); + monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); }); + } else { + let oldio = if !nocapture { + Some(( + io::set_print(Some(box Sink(data2.clone()))), + io::set_panic(Some(box Sink(data2))) + )) + } else { + None + }; - let result_guard = cfg.spawn(move || { - if !nocapture { - io::set_print(box Sink(data2.clone())); - io::set_panic(box Sink(data2)); - } - testfn() - }) - .unwrap(); - let test_result = calc_result(&desc, result_guard.join()); + use std::panic::{catch_unwind, AssertUnwindSafe}; + + let result = catch_unwind(AssertUnwindSafe(|| { + testfn() + })); + + if let Some((printio, panicio)) = oldio { + io::set_print(printio); + io::set_panic(panicio); + }; + + let test_result = calc_result(&desc, result); let stdout = data.lock().unwrap().to_vec(); monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); - }); + } } match testfn { @@ -1291,7 +1324,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 +1332,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 30de859f1501a..c2edf754e49c1 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(target_os = "emscripten")] pub const unwinder_private_data_size: usize = 20; #[repr(C)] diff --git a/src/llvm b/src/llvm index 7801978ec1f36..3e03f7374169c 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 7801978ec1f3637fcda1b564048ebc732bf586af +Subproject commit 3e03f7374169cd41547d75e62ac2ab8a103a913c diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index ea8d59290df2e..979f5f07abea1 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2016-09-17 +2016-09-25 diff --git a/src/test/compile-fail/allocator-dylib-is-system.rs b/src/test/compile-fail/allocator-dylib-is-system.rs index db7f304227f01..4c576de22021c 100644 --- a/src/test/compile-fail/allocator-dylib-is-system.rs +++ b/src/test/compile-fail/allocator-dylib-is-system.rs @@ -18,6 +18,8 @@ // system allocator. Do this by linking in jemalloc and making sure that we get // an error. +// ignore-emscripten FIXME: What "other allocator" should we use for emcc? + #![feature(alloc_jemalloc)] extern crate allocator_dylib; diff --git a/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs b/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs index 46ad226d25564..02c271ab24da3 100644 --- a/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs +++ b/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs @@ -16,6 +16,8 @@ // Ensure that rust dynamic libraries use jemalloc as their allocator, verifying // by linking in the system allocator here and ensuring that we get a complaint. +// ignore-emscripten FIXME: What "other allocator" is correct for emscripten? + #![feature(alloc_system)] extern crate allocator_dylib2; diff --git a/src/test/run-fail/panic-task-name-none.rs b/src/test/run-fail/panic-task-name-none.rs index ab50503830534..36e2a4b86aa39 100644 --- a/src/test/run-fail/panic-task-name-none.rs +++ b/src/test/run-fail/panic-task-name-none.rs @@ -9,6 +9,7 @@ // except according to those terms. // error-pattern:thread '' panicked at 'test' +// ignore-emscripten Needs threads use std::thread; diff --git a/src/test/run-fail/panic-task-name-owned.rs b/src/test/run-fail/panic-task-name-owned.rs index 2d2371f5ce77c..4da40c3158b84 100644 --- a/src/test/run-fail/panic-task-name-owned.rs +++ b/src/test/run-fail/panic-task-name-owned.rs @@ -9,6 +9,7 @@ // except according to those terms. // error-pattern:thread 'owned name' panicked at 'test' +// ignore-emscripten Needs threads. use std::thread::Builder; diff --git a/src/test/run-fail/task-spawn-barefn.rs b/src/test/run-fail/task-spawn-barefn.rs index ede055acd61ff..108430848b9b2 100644 --- a/src/test/run-fail/task-spawn-barefn.rs +++ b/src/test/run-fail/task-spawn-barefn.rs @@ -9,6 +9,7 @@ // except according to those terms. // error-pattern:Ensure that the child thread runs by panicking +// ignore-emscripten Needs threads. use std::thread; diff --git a/src/test/run-fail/test-panic.rs b/src/test/run-fail/test-panic.rs index fa360570253b0..21ced01d9d69e 100644 --- a/src/test/run-fail/test-panic.rs +++ b/src/test/run-fail/test-panic.rs @@ -12,6 +12,7 @@ // error-pattern:thread 'test_foo' panicked at // compile-flags: --test // ignore-pretty: does not work well with `--test` +// ignore-emscripten #[test] fn test_foo() { diff --git a/src/test/run-fail/test-should-fail-bad-message.rs b/src/test/run-fail/test-should-fail-bad-message.rs index e18c5d9631a70..74b5f17bcf9ba 100644 --- a/src/test/run-fail/test-should-fail-bad-message.rs +++ b/src/test/run-fail/test-should-fail-bad-message.rs @@ -12,6 +12,7 @@ // error-pattern:thread 'test_foo' panicked at // compile-flags: --test // ignore-pretty: does not work well with `--test` +// ignore-emscripten #[test] #[should_panic(expected = "foobar")] diff --git a/src/test/run-fail/test-tasks-invalid-value.rs b/src/test/run-fail/test-tasks-invalid-value.rs index 94ed641c79c93..b5c222764d243 100644 --- a/src/test/run-fail/test-tasks-invalid-value.rs +++ b/src/test/run-fail/test-tasks-invalid-value.rs @@ -15,6 +15,7 @@ // compile-flags: --test // exec-env:RUST_TEST_THREADS=foo // ignore-pretty: does not work well with `--test` +// ignore-emscripten #[test] fn do_nothing() {} diff --git a/src/test/run-pass/allocator-override.rs b/src/test/run-pass/allocator-override.rs index d7a8e79bfbee8..ca2dbdf2b3de3 100644 --- a/src/test/run-pass/allocator-override.rs +++ b/src/test/run-pass/allocator-override.rs @@ -10,6 +10,7 @@ // no-prefer-dynamic // aux-build:allocator-dummy.rs +// ignore-emscripten #![feature(test)] diff --git a/src/test/run-pass/extern-pass-empty.rs b/src/test/run-pass/extern-pass-empty.rs index 21948d2e5ad23..801a3c40ab47d 100644 --- a/src/test/run-pass/extern-pass-empty.rs +++ b/src/test/run-pass/extern-pass-empty.rs @@ -12,6 +12,7 @@ // pretty-expanded FIXME #23616 // ignore-msvc +// ignore-emscripten struct TwoU8s { one: u8, diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs index 62d54da56b2ec..1b9b4ab32ca40 100644 --- a/src/test/run-pass/format-no-std.rs +++ b/src/test/run-pass/format-no-std.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten missing rust_begin_unwind + #![feature(lang_items, start, collections)] #![no_std] diff --git a/src/test/run-pass/packed-struct-layout.rs b/src/test/run-pass/packed-struct-layout.rs index 92308c9fc3e4e..d1e05e5a0184c 100644 --- a/src/test/run-pass/packed-struct-layout.rs +++ b/src/test/run-pass/packed-struct-layout.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten Not sure what's happening here. use std::mem; diff --git a/src/test/run-pass/packed-tuple-struct-layout.rs b/src/test/run-pass/packed-tuple-struct-layout.rs index 411c1807a16b7..ee4eb86ed0de3 100644 --- a/src/test/run-pass/packed-tuple-struct-layout.rs +++ b/src/test/run-pass/packed-tuple-struct-layout.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten use std::mem; diff --git a/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs b/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs index 71c1a61062d10..1c273fcba02da 100644 --- a/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs +++ b/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs @@ -11,6 +11,7 @@ // compile-flags:-C panic=abort // aux-build:exit-success-if-unwind.rs // no-prefer-dynamic +// ignore-emscripten Function not implemented extern crate exit_success_if_unwind; diff --git a/src/test/run-pass/panic-runtime/abort.rs b/src/test/run-pass/panic-runtime/abort.rs index 2fc9d6cfd04a1..be38f6ea3643a 100644 --- a/src/test/run-pass/panic-runtime/abort.rs +++ b/src/test/run-pass/panic-runtime/abort.rs @@ -10,6 +10,7 @@ // compile-flags:-C panic=abort // no-prefer-dynamic +// ignore-emscripten Function not implemented. use std::process::Command; use std::env; diff --git a/src/test/run-pass/panic-runtime/lto-abort.rs b/src/test/run-pass/panic-runtime/lto-abort.rs index 09e33b88189fe..e4cd4e809a4c6 100644 --- a/src/test/run-pass/panic-runtime/lto-abort.rs +++ b/src/test/run-pass/panic-runtime/lto-abort.rs @@ -10,6 +10,7 @@ // compile-flags:-C lto -C panic=abort // no-prefer-dynamic +// ignore-emscripten Function not implemented. use std::process::Command; use std::env; diff --git a/src/test/run-pass/panic-runtime/lto-unwind.rs b/src/test/run-pass/panic-runtime/lto-unwind.rs index 10e633b3775b3..768b88fd09e0b 100644 --- a/src/test/run-pass/panic-runtime/lto-unwind.rs +++ b/src/test/run-pass/panic-runtime/lto-unwind.rs @@ -10,6 +10,7 @@ // compile-flags:-C lto -C panic=unwind // no-prefer-dynamic +// ignore-emscripten Function not implemented. use std::process::Command; use std::env; diff --git a/src/test/run-pass/process-status-inherits-stdin.rs b/src/test/run-pass/process-status-inherits-stdin.rs index 2ad47c4f116ae..ff389bec899ef 100644 --- a/src/test/run-pass/process-status-inherits-stdin.rs +++ b/src/test/run-pass/process-status-inherits-stdin.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten Function not implemented. use std::env; use std::io; diff --git a/src/test/run-pass/simd-intrinsic-generic-cast.rs b/src/test/run-pass/simd-intrinsic-generic-cast.rs index 2efd9333999b2..d32fa01c7b945 100644 --- a/src/test/run-pass/simd-intrinsic-generic-cast.rs +++ b/src/test/run-pass/simd-intrinsic-generic-cast.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten linking with emcc failed #![feature(repr_simd, platform_intrinsics, concat_idents, test)] #![allow(non_camel_case_types)] diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs index 1f64f40c5255b..13d5cc989e94d 100644 --- a/src/test/run-pass/task-stderr.rs +++ b/src/test/run-pass/task-stderr.rs @@ -30,7 +30,7 @@ fn main() { let data = Arc::new(Mutex::new(Vec::new())); let sink = Sink(data.clone()); let res = thread::Builder::new().spawn(move|| -> () { - io::set_panic(Box::new(sink)); + io::set_panic(Some(Box::new(sink))); panic!("Hello, world!") }).unwrap().join(); assert!(res.is_err()); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 5d522736089ea..81cb927f26b02 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -183,4 +183,5 @@ pub struct Config { pub cflags: String, pub llvm_components: String, pub llvm_cxxflags: String, + pub nodejs: Option, } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 114cfaf7972ea..ff91ab7c70b3e 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -109,6 +109,7 @@ pub fn parse_config(args: Vec ) -> Config { reqopt("", "cflags", "flags for the C compiler", "FLAGS"), reqopt("", "llvm-components", "list of LLVM components built in", "LIST"), reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS"), + optopt("", "nodejs", "the name of nodejs", "PATH"), optflag("h", "help", "show this message")); let (argv0, args_) = args.split_first().unwrap(); @@ -190,6 +191,7 @@ pub fn parse_config(args: Vec ) -> Config { cflags: matches.opt_str("cflags").unwrap(), llvm_components: matches.opt_str("llvm-components").unwrap(), llvm_cxxflags: matches.opt_str("llvm-cxxflags").unwrap(), + nodejs: matches.opt_str("nodejs"), } } @@ -431,10 +433,17 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn } }; + // Debugging emscripten code doesn't make sense today + let mut ignore = early_props.ignore; + if (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && + config.target.contains("emscripten") { + ignore = true; + } + test::TestDescAndFn { desc: test::TestDesc { name: make_test_name(config, testpaths), - ignore: early_props.ignore, + ignore: ignore, should_panic: should_panic, }, testfn: make_test_closure(config, testpaths), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8fdb882164af8..35b93392baf2c 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,9 @@ 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") { + let nodejs = self.config.nodejs.clone().unwrap_or("nodejs".to_string()); + args.push(nodejs); } let exe_file = self.make_exe_name(); diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 428bbcfe5761d..cad71c59f0a4a 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 {