]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #36339 - brson:emscripten-new, r=alexcrichton
authorbors <bors@rust-lang.org>
Sat, 1 Oct 2016 02:00:36 +0000 (19:00 -0700)
committerGitHub <noreply@github.com>
Sat, 1 Oct 2016 02:00:36 +0000 (19:00 -0700)
Working asmjs and wasm targets

This patch set results in a working standard library for the asmjs-unknown-emscripten and wasm32-unknown-emscripten targets. It is based on the work of @badboy and @rschulman.

It does a few things:

- Updates LLVM with the emscripten [fastcomp](https://github.com/rust-lang/llvm/pull/50) patches, which include the pnacl IR legalizer and the asm.js backend. This patch is thought not to have any significant effect on existing targets.
- Teaches rustbuild to correctly link C code with emscripten
- Updates gcc-rs to work correctly with emscripten
- Teaches rustbuild to run crate tests for emscripten with node
- Modifies Thread::new to return an error on emscripten, to facilitate debugging a common failure mode
- Modifies libtest to run in single-threaded mode for emscripten
- Ignores a host of tests that don't work yet, mostly dealing with threads and I/O
- Updates libc with wasm32 definitions (presently the same as asmjs)
- Adds a wasm32-unknown-emscripten target that feeds the output of LLVM's asmjs backend through emcc to generate wasm

Notes and caveats:

- This is only known to work with `--enable-rustbuild`.
- The wasm32 target can't be tested correctly yet because of issues in compiletest and limitations in node https://github.com/kripken/emscripten/issues/4542, but hello.rs does seem to work when run on node via the binaryen interpreter
- This requires an up to date installation of the emscripten sdk from its incoming branch
- Unwinding is very broken
- When enabling the emscripten targets jemalloc is disabled for all targets, which results in test failures for the host

Next steps are to fix the jemalloc issue, start building the two emscripten targets on the auto builders, then start producing nightlies.

https://github.com/rust-lang/rust/issues/36317 tracks work on this.

Fixes https://github.com/rust-lang/rust/issues/36515
Fixes https://github.com/rust-lang/rust/issues/36515
Fixes https://github.com/rust-lang/rust/issues/36356

84 files changed:
mk/cfg/wasm32-unknown-emscripten.mk [new file with mode: 0644]
mk/main.mk
src/bootstrap/Cargo.lock
src/bootstrap/check.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/sanity.rs
src/bootstrap/step.rs
src/liballoc/arc.rs
src/liballoc_jemalloc/build.rs
src/liballoc_jemalloc/lib.rs
src/liballoc_system/lib.rs
src/libcollections/linked_list.rs
src/libcollectionstest/slice.rs
src/libcompiler_builtins/build.rs
src/libcoretest/num/flt2dec/estimator.rs
src/libpanic_unwind/Cargo.lock
src/libpanic_unwind/emcc.rs [new file with mode: 0644]
src/libpanic_unwind/lib.rs
src/librustc_back/target/asmjs_unknown_emscripten.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/wasm32_unknown_emscripten.rs [new file with mode: 0644]
src/librustc_driver/lib.rs
src/librustc_llvm/build.rs
src/librustc_llvm/lib.rs
src/librustc_trans/abi.rs
src/librustdoc/test.rs
src/libstd/env.rs
src/libstd/fs.rs
src/libstd/io/buffered.rs
src/libstd/io/mod.rs
src/libstd/io/stdio.rs
src/libstd/net/addr.rs
src/libstd/net/ip.rs
src/libstd/net/mod.rs
src/libstd/net/tcp.rs
src/libstd/net/udp.rs
src/libstd/os/linux/raw.rs
src/libstd/process.rs
src/libstd/rand/mod.rs
src/libstd/sync/barrier.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/mpsc_queue.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mutex.rs
src/libstd/sync/once.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/common/io.rs
src/libstd/sys/common/remutex.rs
src/libstd/sys/unix/ext/net.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/thread.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libtest/lib.rs
src/libunwind/libunwind.rs
src/llvm
src/rustllvm/llvm-auto-clean-trigger
src/test/compile-fail/allocator-dylib-is-system.rs
src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs
src/test/run-fail/panic-task-name-none.rs
src/test/run-fail/panic-task-name-owned.rs
src/test/run-fail/task-spawn-barefn.rs
src/test/run-fail/test-panic.rs
src/test/run-fail/test-should-fail-bad-message.rs
src/test/run-fail/test-tasks-invalid-value.rs
src/test/run-pass/allocator-override.rs
src/test/run-pass/extern-pass-empty.rs
src/test/run-pass/format-no-std.rs
src/test/run-pass/packed-struct-layout.rs
src/test/run-pass/packed-tuple-struct-layout.rs
src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs
src/test/run-pass/panic-runtime/abort.rs
src/test/run-pass/panic-runtime/lto-abort.rs
src/test/run-pass/panic-runtime/lto-unwind.rs
src/test/run-pass/process-status-inherits-stdin.rs
src/test/run-pass/simd-intrinsic-generic-cast.rs
src/test/run-pass/task-stderr.rs
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs

diff --git a/mk/cfg/wasm32-unknown-emscripten.mk b/mk/cfg/wasm32-unknown-emscripten.mk
new file mode 100644 (file)
index 0000000..997bdfb
--- /dev/null
@@ -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
index cc843add50d1ba55053e5971621214775378f825..e68a8f3005561d56309527c7ac1de40c82e0ae93 100644 (file)
@@ -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
 
index 36b94e4ebea32d4136abc26919eb7f89f4fe0d8d..babbb6a16bae0002e1b4506e13394f6e60986e15 100644 (file)
@@ -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)" = "<none>"
-"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)" = "<none>"
+"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"
index 2b9d717cbd48dbaa3365257cb80916b32a10c393..b8417218a2231e285e3adbefc3b99ba1c01fc77d 100644 (file)
@@ -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<PathBuf>) {
@@ -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());
         }
     }
index 3d1cf47cb7e9037039b88ccdfea749001854801c..033cefb8dea3603e478978728da388bbd5cfe680 100644 (file)
@@ -975,7 +975,8 @@ fn rustc_flags(&self, target: &str) -> Vec<String> {
         // 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
index df6408e5fe1c8ac2010abcfdd3222a6b61b976d5..63fc59e43286e24d987de924f87b57afbf85ee01 100644 (file)
@@ -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")
index 962d0666f69f192f8fbb8a37a54fb7ee40ccad92..c4e6399c2c36d270fc65fed47663379bf92bacff 100644 (file)
@@ -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") {
index 4b5a26d205af7457f7093871145457a996e86af9..8a96cd1b4d23939f5e08e516beaa4a984e5c96fc 100644 (file)
@@ -418,7 +418,6 @@ pub fn deps(&self, build: &'a Build) -> Vec<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 @@ pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
                         // misc
                         self.check_linkcheck(stage),
                         self.check_tidy(stage),
+
+                        // can we make the distributables?
+                        self.dist(stage),
                     ]);
                 }
                 return base
index e3c92fc1aa8301950e1f107d758050e0093ed60d..29e18781ce2a597884333e84f57f5d1938a27948 100644 (file)
@@ -1000,6 +1000,7 @@ fn drop(&mut self) {
     }
 
     #[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);
index 8b31c5a557747765fbdc09967cc9c28ad4cec700..028d742cc832ea7c0a466562075f25c787f629e3 100644 (file)
@@ -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={}",
index 5bbf1c35e0dd41f0b60e6f46d0ec3f0003b050df..21e45f9c4b20c81598c7629da18deeedc31941b4 100644 (file)
 
 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()
+    }
 }
index 01407d1acd2ecda82db51af61f7f50925cc91a22..dacafe771edc2c500264e0d028fcbe6ddfbc5fbd 100644 (file)
@@ -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",
index 690c4f4af35896df5b24cb5be112bfbf279b34e4..67f3708a62b91dbf50e83d6bf98fcb5842f967b0 100644 (file)
@@ -1294,6 +1294,7 @@ fn test_insert_prev() {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_send() {
         let n = list_from(&[1, 2, 3]);
         thread::spawn(move || {
index 5b341ab62d097dd3de59d4ed5150a93e93df8e2b..9580714075ad78260e8c68e50354d8af085319ea 100644 (file)
@@ -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};
index 66c683333b9854812767fc92e16b790c296f391d..acbd39bb1630c483c3a25064c8780eb95c118728 100644 (file)
@@ -73,6 +73,12 @@ fn extend(&mut self, sources: &[&'static str]) {
 
 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") {
index 857aae72c8a5bd5d92a0088a36bbe3c37fc58b37..0bca616ea9abcc99e5fc604ee4d91f2472b2985d 100644 (file)
@@ -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]
index 20d826d4a470ee7c7c14d85b6760caade6f26eef..0cf75c941508b7b378ceeb86cb3105e0c593df5b 100644 (file)
@@ -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 (file)
index 0000000..b3ab111
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Any + Send> {
+    assert!(!ptr.is_null());
+    let ex = ptr::read(ptr as *mut _);
+    __cxa_free_exception(ptr as *mut _);
+    ex
+}
+
+pub unsafe fn panic(data: Box<Any + Send>) -> 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<Any + Send>;
+    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;
+}
index 11dd9befe0a82e940da630f68317591ef960187b..ff483fa823e0cc0c86d7b224474b0ad5ae7266d7 100644 (file)
 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;
 
index 9ccfdbb129c7352bceab72900939f340660c7512..667f7cf2c214a9defc7c7b01c0d0f60addf59e91 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Result<Target, String> {
         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 {
index 3eddd911749e5251b13818b7fb64c58f5af85e3c..6e2f7b1bf5313526b7c6adc34c6f4916742b37f9 100644 (file)
@@ -190,7 +190,8 @@ fn $module() {
     ("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 (file)
index 0000000..2923f2e
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Target, String> {
+    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,
+    })
+}
index 5ac4512fe39004d72386822c36351e960b1d8800..492165e2f2a8e081290d8af025ea390352c5b330 100644 (file)
@@ -1075,7 +1075,7 @@ fn flush(&mut self) -> io::Result<()> {
     }
 
     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!();
 }
 
index 3f551476e2b46b87a6529075e55bd2c6b124f5e5..5257575a94e8b1322a87ce3e0986adc1fa16afb7 100644 (file)
@@ -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.
index eb45d3d25c5c05f5ff71a713d57c039626cac426..3946b44ead5787c69b5e925359cef91f8aed5943 100644 (file)
@@ -434,6 +434,10 @@ fn init() { }
                  LLVMInitializeSystemZTargetMC,
                  LLVMInitializeSystemZAsmPrinter,
                  LLVMInitializeSystemZAsmParser);
+    init_target!(llvm_component = "jsbackend",
+                 LLVMInitializeJSBackendTargetInfo,
+                 LLVMInitializeJSBackendTarget,
+                 LLVMInitializeJSBackendTargetMC);
 }
 
 pub fn last_error() -> Option<String> {
index b82c5629f9da1dcea0d5510caac0f30ce60aa64f..0a5b013c79ac21fbdc979244a6a11a98b8a922c7 100644 (file)
@@ -519,6 +519,7 @@ pub fn adjust_for_abi<'a, 'tcx>(&mut self,
             "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))
         }
 
index 1ab86cf7e8920fc4fe9cef6db4aedab43cd769bc..02f0916de0ef3a970e0cd95c11ba4f0823912912 100644 (file)
@@ -228,7 +228,7 @@ fn drop(&mut self) {
     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
index 5171fbdf03e80702f3b44fda48151af5ba5dba1d..76a2f93c162e7a3f9579fd69388dbc450aa9a109 100644 (file)
@@ -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 @@ fn test_set_var_overwrite() {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_var_big() {
         let mut s = "".to_string();
         let mut i = 0;
@@ -1030,6 +1047,7 @@ fn test_var_big() {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_self_exe_path() {
         let path = current_exe();
         assert!(path.is_ok());
@@ -1040,6 +1058,7 @@ fn test_self_exe_path() {
     }
 
     #[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::<String>();
index 576198564dbd43f7393335460a51c07d06c74195..2f2969b110db17a7687b81802ce6409013526277 100644 (file)
@@ -1686,7 +1686,7 @@ fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::prelude::*;
 
index 4ff8c6ac128bd9872fdc8b546914d2327cc252be..21a0cc1fb3b13e0028014fc916973a9f06ef7775 100644 (file)
@@ -1107,6 +1107,7 @@ fn flush(&mut self) -> io::Result<()> {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn panic_in_write_doesnt_flush_in_drop() {
         static WRITES: AtomicUsize = AtomicUsize::new(0);
 
index e308a2d8e0375486e9669124c38a61e740bf0417..3becc0a0c9ee17ca1886823e0ad87c0cb2c02ce0 100644 (file)
@@ -1757,6 +1757,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();
@@ -1967,6 +1968,7 @@ fn chain_zero_length_read_is_not_eof() {
     }
 
     #[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);
index 9a782e95f6e5f994fd2cabe77cd59512a99ef90f..6421595a009a7124e5635abf580f271b111c5719 100644 (file)
@@ -593,11 +593,11 @@ fn flush(&mut self) -> io::Result<()> {
                      with a more general mechanism",
            issue = "0")]
 #[doc(hidden)]
-pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
+pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
     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<Write + Send>) -> Option<Box<Write + Send>> {
                      with a more general mechanism",
            issue = "0")]
 #[doc(hidden)]
-pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
+pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
     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();
index d0b59b42c1798a73a2ca56e75d553849ea5a9672..58daa7dbf8dc4d843b9b5e49f2da0f860d0e85f8 100644 (file)
@@ -519,7 +519,7 @@ fn to_socket_addrs(&self) -> io::Result<T::Iter> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use net::*;
     use net::test::{tsa, sa6, sa4};
index 05ef559422f33187707e1894c56eef67800945cf..ba2cd70e0d7776a77f0b553b2006eeb95c38d850 100644 (file)
@@ -669,7 +669,7 @@ fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
 }
 
 // Tests for this module
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use net::*;
     use net::Ipv6MulticastScope::*;
index ad2fe3c1c0dbc8874e093328a1c530d6bec47aab..7dd0e30df0368cf5abd3b3dd42facc610096ddf2 100644 (file)
@@ -31,7 +31,8 @@
 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`].
index 3c5f07c3e33a6db25ef7fd9f033d9f3825d080be..0e7c5b06713fb31a58d3977a85f7f4f1aa5e27ac 100644 (file)
@@ -428,7 +428,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::ErrorKind;
     use io::prelude::*;
index 781f026c12c7795e1b2c82fae0506c5b40d8b566..c03ac496adbb27b6f9c4ecef20e412a7f833764e 100644 (file)
@@ -353,7 +353,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::ErrorKind;
     use net::*;
index 1c19e58818d743e5fb67c2da76c45e8c2dbf48e4..e6a95bc831ffbafdbea5df3a14e5610d2c8cb32f 100644 (file)
@@ -34,7 +34,8 @@
           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};
 
index 674b00095370efc6945aaf79ee8c60a223d9f6da..9d21a76e81b9e41f4e39ebe1af7fba669e002aa2 100644 (file)
@@ -825,7 +825,7 @@ pub fn exit(code: i32) -> ! {
     ::sys::os::exit(code)
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::prelude::*;
 
index 3f14fcd239f1d0ceb2d6d36f32da74a3a845c345..69cd37651d5c28bde1bc9d5427975abea94e0133 100644 (file)
@@ -242,6 +242,7 @@ fn test_os_rng() {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_os_rng_tasks() {
 
         let mut txs = vec!();
index ac0f400379e3cabf3504a10b496426774e2c0659..f46eab684846384a9b5245657d11f20bd450d867 100644 (file)
@@ -118,6 +118,7 @@ mod tests {
     use thread;
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_barrier() {
         const N: usize = 10;
 
index 3db8b05b954c3dacf4b157a8edc73f9d83118613..a983ae716a4816d387c75659c4dedafc3a5007e3 100644 (file)
@@ -270,6 +270,7 @@ fn smoke() {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn notify_one() {
         let m = Arc::new(Mutex::new(()));
         let m2 = m.clone();
@@ -286,6 +287,7 @@ fn notify_one() {
     }
 
     #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn notify_all() {
         const N: usize = 10;
 
@@ -322,6 +324,7 @@ fn notify_all() {
     }
 
     #[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 @@ fn wait_timeout_ms() {
 
     #[test]
     #[should_panic]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn two_mutexes() {
         let m = Arc::new(Mutex::new(()));
         let m2 = m.clone();
index 3d9f81413dc734202b1e8a6df174ed35703b2d2b..d9c14ef2f771eb83a81cdb8ea9130704449d66d9 100644 (file)
@@ -1268,7 +1268,7 @@ fn cause(&self) -> Option<&error::Error> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use env;
     use super::*;
@@ -1942,7 +1942,7 @@ fn destroy_upgraded_shared_port_when_sender_still_active() {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod sync_tests {
     use env;
     use thread;
index d926043fbbcd074e37fae9807f07b6a34cbfcce8..8d80f942ff75cb9f50c29919c75d7beaf6a21466 100644 (file)
@@ -146,7 +146,7 @@ fn drop(&mut self) {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sync::mpsc::channel;
     use super::{Queue, Data, Empty, Inconsistent};
index 51b08bd75c4bc3475548171cf9dd1ec018619629..91896e1ab85dca7ccadbfb4f3d980949a4330ec5 100644 (file)
@@ -366,7 +366,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 #[allow(unused_imports)]
 mod tests {
     use thread;
index 724d7b1be730d59953620950ffa5ca20f55b5172..5858e4b6ddb1f2ab35312aaa4a5406baa84ca29c 100644 (file)
@@ -231,7 +231,7 @@ fn drop(&mut self) {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sync::Arc;
     use super::Queue;
index 098a3e44258c77f2d116826b5dffe71560d355e5..812724c7a167eaf13e61801d079dd421222c9315 100644 (file)
@@ -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};
index 86d2986959c999abee5e10c3761f16f4fa0253fc..ad9d0b375442200be9ecf0cf59fb04d64dcfdd44 100644 (file)
@@ -367,7 +367,7 @@ pub fn poisoned(&self) -> bool {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use panic;
     use sync::mpsc::channel;
index 7f053c6704b56dffb09b5b32bf135fbc07345ef9..48ecae185f95c37e9e9a54a3e24c121587bb5fcc 100644 (file)
@@ -380,7 +380,7 @@ fn drop(&mut self) {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     #![allow(deprecated)] // rand
 
index 3cd70eddb858c1d0f8566855ff2fb0aca5fa478c..47cec4ef5c2762a7c6e2601e28f88c84bb728974 100644 (file)
@@ -50,7 +50,7 @@ pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec<u8>) -> io::
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 pub mod test {
     use path::{Path, PathBuf};
     use env;
@@ -165,6 +165,7 @@ fn read_to_end_uninit_good() {
     }
 
     #[bench]
+    #[cfg_attr(target_os = "emscripten", ignore)]
     fn bench_uninitialized(b: &mut ::test::Bencher) {
         b.iter(|| {
             let mut lr = repeat(1).take(10000000);
index cbdeaad7f6bd3acfbff16c2cb7fa25ab688f904a..4d0407ccf6c8903bb20eee0059b492319a94d81f 100644 (file)
@@ -156,7 +156,7 @@ fn drop(&mut self) {
 }
 
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
     use cell::RefCell;
index 3f93fce1935611f236f611d3eb5ed9652617d851..40fe24cf10e281626d97a14e6da9f540bd3a5776 100644 (file)
@@ -786,7 +786,7 @@ fn into_raw_fd(self) -> RawFd {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod test {
     use thread;
     use io;
index 50014f51f6cf46420fbaaa2a3e2e68db15933f3e..dafc11d9cc8e9c7b01b01f1aeb0968d1254b9a3c 100644 (file)
@@ -369,7 +369,7 @@ macro_rules! t {
         }
 
         // 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 @@ pub fn wait(&mut self) -> io::Result<ExitStatus> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use super::*;
 
index 980ef01f549c36b9d10f0a1a49d738f8035c8a7d..1e879117f73abf2e185c0d7b57a05ad38aaed1f3 100644 (file)
@@ -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<FnBox() + 'a>)
                           -> io::Result<Thread> {
@@ -38,8 +52,8 @@ pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
         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);
index c44dee49f14a69373eed7cbcf6952358b701f8e5..a333a7d967d240fa11f757543fe50f068c529cad 100644 (file)
@@ -524,7 +524,7 @@ pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use sync::mpsc::{channel, Sender};
     use cell::{Cell, UnsafeCell};
index a634c8f77a45ca684513a8aa7f55b3ef64534a17..901ff98fcb3c5fa51e23b52a83e42042cbb9d0ca 100644 (file)
@@ -741,7 +741,7 @@ fn _assert_both<T: Send + Sync>() {}
 // Tests
 ////////////////////////////////////////////////////////////////////////////////
 
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use any::Any;
     use sync::mpsc::{channel, Sender};
index dcfd3f754c7203b2860a09e080f6f40b79e61bc3..5949afe0ff167c070710d903c126450d693da163 100644 (file)
@@ -1182,26 +1182,59 @@ fn flush(&mut self) -> io::Result<()> {
             }
         }
 
-        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 @@ pub fn fmt_metrics(&self) -> String {
 ///
 /// 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<T>(dummy: T) -> T {
     // we need to "use" the argument in some way LLVM can't
     // introspect.
@@ -1299,7 +1332,7 @@ pub fn black_box<T>(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<T>(dummy: T) -> T {
     dummy
index 30de859f1501aeee01176cba6daca382bbca09d5..c2edf754e49c18ef38c97ac9fbb1d8b25f8658c6 100644 (file)
@@ -65,7 +65,7 @@ pub enum _Unwind_Reason_Code {
 #[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)]
index 7801978ec1f3637fcda1b564048ebc732bf586af..3e03f7374169cd41547d75e62ac2ab8a103a913c 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 7801978ec1f3637fcda1b564048ebc732bf586af
+Subproject commit 3e03f7374169cd41547d75e62ac2ab8a103a913c
index ea8d59290df2e23415bbe18db4b4ac7f04dfb594..979f5f07abea129a351a1e5e27a26547d0e56fe2 100644 (file)
@@ -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
index db7f304227f01acc9df0d1df50744ac82e3e08c4..4c576de22021ccedf276bec0859bbe85e04f55c1 100644 (file)
@@ -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;
index 46ad226d255645a0df21d8ac19f5179aa6905fe0..02c271ab24da3185a550c14d08775e1aadcba06a 100644 (file)
@@ -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;
index ab50503830534e7546ba0e89dd58807c8e7be3fd..36e2a4b86aa3965fa7d6ade6835e392162e58a55 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // error-pattern:thread '<unnamed>' panicked at 'test'
+// ignore-emscripten Needs threads
 
 use std::thread;
 
index 2d2371f5ce77c6d05fc58e85249b9442bdb580ea..4da40c3158b84c22ef955e8e243d3224b1e1a5cd 100644 (file)
@@ -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;
 
index ede055acd61ffcb7a20a3ff54461b366a2633a12..108430848b9b29673efe9b569fae95650be2bc3b 100644 (file)
@@ -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;
 
index fa360570253b0f0e947eaaf1b2fe669d40704f21..21ced01d9d69efe619f8e23d79a72411bdf72b41 100644 (file)
@@ -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() {
index e18c5d9631a702358a6964b918fe8b2db3bb3267..74b5f17bcf9bad053905f6d917fb3498f63d7b87 100644 (file)
@@ -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")]
index 94ed641c79c9372cabcf34a107356b5e2bc780cc..b5c222764d243ea33060ff3826da71884f908c42 100644 (file)
@@ -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() {}
index d7a8e79bfbee84f5951461887676e2370f5ebc65..ca2dbdf2b3de30a4a3672ecd389dc075889ca29c 100644 (file)
@@ -10,6 +10,7 @@
 
 // no-prefer-dynamic
 // aux-build:allocator-dummy.rs
+// ignore-emscripten
 
 #![feature(test)]
 
index 21948d2e5ad23c04bf3dad6312652456f48ea5bb..801a3c40ab47ddb9a2d0dd73248e521da5f0ab07 100644 (file)
@@ -12,6 +12,7 @@
 
 // pretty-expanded FIXME #23616
 // ignore-msvc
+// ignore-emscripten
 
 struct TwoU8s {
     one: u8,
index 62d54da56b2ec95279eb421f8083b3d9222b1c93..1b9b4ab32ca40cb1cb1f767ef4cf565721470b7e 100644 (file)
@@ -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]
 
index 92308c9fc3e4e0eddebe36707b3cf215c32144fc..d1e05e5a0184c3d1c8cac004726b958bf3b0c5c2 100644 (file)
@@ -7,6 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
index 411c1807a16b71491410c7c4bfedf810985dcd2f..ee4eb86ed0de3d04a6c30d4552810aac53646e26 100644 (file)
@@ -7,6 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+// ignore-emscripten
 
 
 use std::mem;
index 71c1a61062d1085a24bb2e02a065a68731bb07af..1c273fcba02daf77b148b7c9f44dd9779b4d416e 100644 (file)
@@ -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;
 
index 2fc9d6cfd04a13ead3a726200646f7ff118650e9..be38f6ea3643a8857c7c553af3e2df34aa8ac59d 100644 (file)
@@ -10,6 +10,7 @@
 
 // compile-flags:-C panic=abort
 // no-prefer-dynamic
+// ignore-emscripten Function not implemented.
 
 use std::process::Command;
 use std::env;
index 09e33b88189fe8fb691ed1934bea768f41733016..e4cd4e809a4c6bf7684b9346ea325dbca9335c39 100644 (file)
@@ -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;
index 10e633b3775b3530f88d325a4ed703bca6f148fa..768b88fd09e0b3fad9c8aaa33c2b3db88e2fca0e 100644 (file)
@@ -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;
index 2ad47c4f116ae9a34d6dbd22c145ed65391b280c..ff389bec899efba23026791c97f3aaad210e03f6 100644 (file)
@@ -7,6 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
index 2efd9333999b24ca0f83834b7be300b849cb7f19..d32fa01c7b9453fb2e3c1d52705b6d070eb108c5 100644 (file)
@@ -7,6 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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)]
index 1f64f40c5255baead14e2e11b8488ffe4f305466..13d5cc989e94dac4a8dfd332bc55e2abcea5d87b 100644 (file)
@@ -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());
index 5d522736089ea4d2acf1340b99bf5a6cd6c23583..81cb927f26b0210d33ff07695a281f424ba70142 100644 (file)
@@ -183,4 +183,5 @@ pub struct Config {
     pub cflags: String,
     pub llvm_components: String,
     pub llvm_cxxflags: String,
+    pub nodejs: Option<String>,
 }
index 114cfaf7972ea51481a176ebd1800a1bca13185c..ff91ab7c70b3ee97a05f96c7e93e3033c3554b51 100644 (file)
@@ -109,6 +109,7 @@ pub fn parse_config(args: Vec<String> ) -> 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 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         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),
index 8fdb882164af8517d793bb0c6e885e1277fb2751..35b93392baf2c4c96110e961a7a871f714394a01 100644 (file)
@@ -1168,7 +1168,6 @@ fn exec_compiled_test(&self) -> ProcRes {
             "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 @@ fn make_lib_name(&self, auxfile: &Path) -> PathBuf {
     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 @@ fn make_run_args(&self) -> ProcArgs {
         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();
index 428bbcfe5761d6d00acadc632fea0f7c0c5685ef..cad71c59f0a4aef93ccd10d3d75b1022b0bafdc9 100644 (file)
@@ -43,7 +43,8 @@
                                                               ("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 {