--- /dev/null
+# 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
# 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
"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]]
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]]
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]]
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]]
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]]
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]]
[[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)",
[[package]]
name = "winapi"
-version = "0.2.6"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
"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"
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());
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);
}
}
+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>) {
}
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());
}
}
// 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
.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")
// 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());
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 {
}
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") {
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
// misc
self.check_linkcheck(stage),
self.check_tidy(stage),
+
+ // can we make the distributables?
+ self.dist(stage),
]);
}
return base
}
#[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);
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={}",
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()
+ }
}
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",
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn test_send() {
let n = list_from(&[1, 2, 3]);
thread::spawn(move || {
}
#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
fn test_box_slice_clone_panics() {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
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") {
// 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]
"alloc 0.0.0",
"core 0.0.0",
"libc 0.0.0",
+ "unwind 0.0.0",
]
[[package]]
"core 0.0.0",
]
+[[package]]
+name = "unwind"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+ "libc 0.0.0",
+]
+
--- /dev/null
+// 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;
+}
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;
use hir::def_id::DefId;
use infer::InferCtxt;
+use hir::map as ast_map;
use hir::pat_util;
use traits::{self, Reveal};
use ty::{self, Ty, AdtKind, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
}
}
+// When hashing a type this ends up affecting properties like symbol names. We
+// want these symbol names to be calculated independent of other factors like
+// what architecture you're compiling *from*.
+//
+// The hashing just uses the standard `Hash` trait, but the implementations of
+// `Hash` for the `usize` and `isize` types are *not* architecture independent
+// (e.g. they has 4 or 8 bytes). As a result we want to avoid `usize` and
+// `isize` completely when hashing. To ensure that these don't leak in we use a
+// custom hasher implementation here which inflates the size of these to a `u64`
+// and `i64`.
+struct WidenUsizeHasher<H> {
+ inner: H,
+}
+
+impl<H> WidenUsizeHasher<H> {
+ fn new(inner: H) -> WidenUsizeHasher<H> {
+ WidenUsizeHasher { inner: inner }
+ }
+}
+
+impl<H: Hasher> Hasher for WidenUsizeHasher<H> {
+ fn write(&mut self, bytes: &[u8]) {
+ self.inner.write(bytes)
+ }
+
+ fn finish(&self) -> u64 {
+ self.inner.finish()
+ }
+
+ fn write_u8(&mut self, i: u8) {
+ self.inner.write_u8(i)
+ }
+ fn write_u16(&mut self, i: u16) {
+ self.inner.write_u16(i)
+ }
+ fn write_u32(&mut self, i: u32) {
+ self.inner.write_u32(i)
+ }
+ fn write_u64(&mut self, i: u64) {
+ self.inner.write_u64(i)
+ }
+ fn write_usize(&mut self, i: usize) {
+ self.inner.write_u64(i as u64)
+ }
+ fn write_i8(&mut self, i: i8) {
+ self.inner.write_i8(i)
+ }
+ fn write_i16(&mut self, i: i16) {
+ self.inner.write_i16(i)
+ }
+ fn write_i32(&mut self, i: i32) {
+ self.inner.write_i32(i)
+ }
+ fn write_i64(&mut self, i: i64) {
+ self.inner.write_i64(i)
+ }
+ fn write_isize(&mut self, i: isize) {
+ self.inner.write_i64(i as i64)
+ }
+}
+
pub struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a, H> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- state: H
+ state: WidenUsizeHasher<H>,
}
impl<'a, 'gcx, 'tcx, H: Hasher> TypeIdHasher<'a, 'gcx, 'tcx, H> {
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, state: H) -> Self {
TypeIdHasher {
tcx: tcx,
- state: state
+ state: WidenUsizeHasher::new(state),
}
}
fn def_id(&mut self, did: DefId) {
// Hash the DefPath corresponding to the DefId, which is independent
// of compiler internal state.
- let tcx = self.tcx;
- let def_path = tcx.def_path(did);
- def_path.deterministic_hash_to(tcx, &mut self.state);
+ let path = self.tcx.def_path(did);
+ self.def_path(&path)
+ }
+
+ pub fn def_path(&mut self, def_path: &ast_map::DefPath) {
+ def_path.deterministic_hash_to(self.tcx, &mut self.state);
}
}
TyInt(i) => self.hash(i),
TyUint(u) => self.hash(u),
TyFloat(f) => self.hash(f),
- TyArray(_, n) => self.hash(n as u64),
+ TyArray(_, n) => self.hash(n),
TyRawPtr(m) |
TyRef(_, m) => self.hash(m.mutbl),
TyClosure(def_id, _) |
self.hash(f.unsafety);
self.hash(f.abi);
self.hash(f.sig.variadic());
- self.hash(f.sig.inputs().skip_binder().len() as u64);
+ self.hash(f.sig.inputs().skip_binder().len());
}
TyTrait(ref data) => {
self.def_id(data.principal.def_id());
self.hash(data.builtin_bounds);
}
TyTuple(tys) => {
- self.hash(tys.len() as u64);
+ self.hash(tys.len());
}
TyParam(p) => {
self.hash(p.idx);
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 {
("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
("x86_64-rumprun-netbsd", x86_64_rumprun_netbsd),
- ("i686_unknown_haiku", i686_unknown_haiku),
- ("x86_64_unknown_haiku", x86_64_unknown_haiku),
+ ("i686-unknown-haiku", i686_unknown_haiku),
+ ("x86_64-unknown-haiku", x86_64_unknown_haiku),
("x86_64-apple-darwin", x86_64_apple_darwin),
("i686-apple-darwin", i686_apple_darwin),
("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.
--- /dev/null
+// 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,
+ })
+}
}
let thread = cfg.spawn(move || {
- io::set_panic(box err);
+ io::set_panic(Some(box err));
f()
});
// 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!();
}
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.
LLVMInitializeSystemZTargetMC,
LLVMInitializeSystemZAsmPrinter,
LLVMInitializeSystemZAsmParser);
+ init_target!(llvm_component = "jsbackend",
+ LLVMInitializeJSBackendTargetInfo,
+ LLVMInitializeJSBackendTarget,
+ LLVMInitializeJSBackendTargetMC);
}
pub fn last_error() -> Option<String> {
let link_meta = self.link_meta;
let is_rustc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro);
let root = self.lazy(&CrateRoot {
- rustc_version: RUSTC_VERSION.to_string(),
+ rustc_version: rustc_version(),
name: link_meta.crate_name.clone(),
triple: tcx.sess.opts.target_triple.clone(),
hash: link_meta.crate_hash,
//! metadata::loader or metadata::creader for all the juicy details!
use cstore::MetadataBlob;
-use schema::{METADATA_HEADER, RUSTC_VERSION};
+use schema::{METADATA_HEADER, rustc_version};
use rustc::hir::svh::Svh;
use rustc::session::Session;
}
if !self.rejected_via_version.is_empty() {
err.help(&format!("please recompile that crate using this compiler ({})",
- RUSTC_VERSION));
+ rustc_version()));
let mismatches = self.rejected_via_version.iter();
for (i, &CrateMismatch { ref path, ref got }) in mismatches.enumerate() {
err.note(&format!("crate `{}` path #{}: {} compiled by {:?}",
fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> {
let root = metadata.get_root();
- if root.rustc_version != RUSTC_VERSION {
+ let rustc_version = rustc_version();
+ if root.rustc_version != rustc_version {
info!("Rejecting via version: expected {} got {}",
- RUSTC_VERSION, root.rustc_version);
+ rustc_version, root.rustc_version);
self.rejected_via_version.push(CrateMismatch {
path: libpath.to_path_buf(),
got: root.rustc_version
use std::marker::PhantomData;
-#[cfg(not(test))]
-pub const RUSTC_VERSION: &'static str = concat!("rustc ", env!("CFG_VERSION"));
-
-#[cfg(test)]
-pub const RUSTC_VERSION: &'static str = "rustc 0.0.0-unit-test";
+pub fn rustc_version() -> String {
+ format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version"))
+}
/// Metadata encoding version.
/// NB: increment this if you change the format of metadata such that
"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))
}
let mut hash_state = scx.symbol_hasher().borrow_mut();
record_time(&tcx.sess.perf_stats.symbol_hash_time, || {
hash_state.reset();
- let mut hasher = Sha256Hasher(&mut hash_state);
+ let hasher = Sha256Hasher(&mut hash_state);
+ let mut hasher = ty::util::TypeIdHasher::new(tcx, hasher);
// the main symbol name is not necessarily unique; hash in the
// compiler's internal def-path, guaranteeing each symbol has a
// truly unique path
- def_path.deterministic_hash_to(tcx, &mut hasher);
+ hasher.def_path(def_path);
// Include the main item-type. Note that, in this case, the
// assertions about `needs_subst` may not hold, but this item-type
// ought to be the same for every reference anyway.
- let mut hasher = ty::util::TypeIdHasher::new(tcx, hasher);
assert!(!item_type.has_erasable_regions());
hasher.visit_ty(item_type);
if num_supplied_types > 0 && num_supplied_types != num_method_types {
if num_method_types == 0 {
- span_err!(self.tcx.sess, self.span, E0035,
- "does not take type parameters");
+ struct_span_err!(self.tcx.sess, self.span, E0035,
+ "does not take type parameters")
+ .span_label(self.span, &"called with unneeded type parameters")
+ .emit();
} else {
- span_err!(self.tcx.sess, self.span, E0036,
+ struct_span_err!(self.tcx.sess, self.span, E0036,
"incorrect number of type parameters given for this method: \
expected {}, found {}",
- num_method_types, num_supplied_types);
+ num_method_types, num_supplied_types)
+ .span_label(self.span,
+ &format!("Passed {} type argument{}, expected {}",
+ num_supplied_types,
+ if num_supplied_types != 1 {
+ "s"
+ } else {
+ ""
+ },
+ num_method_types))
+ .emit();
}
supplied_method_types = vec![self.tcx.types.err; num_method_types];
}
} else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) {
Some(disr)
} else {
- span_err!(tcx.sess, v.span, E0370,
- "enum discriminant overflowed on value after {}; \
- set explicitly via {} = {} if that is desired outcome",
- prev_disr.unwrap(), v.node.name, wrapped_disr);
+ struct_span_err!(tcx.sess, v.span, E0370,
+ "enum discriminant overflowed")
+ .span_label(v.span, &format!("overflowed on value after {}", prev_disr.unwrap()))
+ .note(&format!("explicitly set `{} = {}` if that is desired outcome",
+ v.node.name, wrapped_disr))
+ .emit();
None
}.unwrap_or(wrapped_disr);
prev_disr = Some(disr);
}
}
pub fn is_mod(&self) -> bool {
- ItemType::from(self) == ItemType::Module
+ self.type_() == ItemType::Module
}
pub fn is_trait(&self) -> bool {
- ItemType::from(self) == ItemType::Trait
+ self.type_() == ItemType::Trait
}
pub fn is_struct(&self) -> bool {
- ItemType::from(self) == ItemType::Struct
+ self.type_() == ItemType::Struct
}
pub fn is_enum(&self) -> bool {
- ItemType::from(self) == ItemType::Module
+ self.type_() == ItemType::Module
}
pub fn is_fn(&self) -> bool {
- ItemType::from(self) == ItemType::Function
+ self.type_() == ItemType::Function
}
pub fn is_associated_type(&self) -> bool {
- ItemType::from(self) == ItemType::AssociatedType
+ self.type_() == ItemType::AssociatedType
}
pub fn is_associated_const(&self) -> bool {
- ItemType::from(self) == ItemType::AssociatedConst
+ self.type_() == ItemType::AssociatedConst
}
pub fn is_method(&self) -> bool {
- ItemType::from(self) == ItemType::Method
+ self.type_() == ItemType::Method
}
pub fn is_ty_method(&self) -> bool {
- ItemType::from(self) == ItemType::TyMethod
+ self.type_() == ItemType::TyMethod
}
pub fn is_primitive(&self) -> bool {
- ItemType::from(self) == ItemType::Primitive
+ self.type_() == ItemType::Primitive
}
pub fn is_stripped(&self) -> bool {
match self.inner { StrippedItem(..) => true, _ => false }
pub fn stable_since(&self) -> Option<&str> {
self.stability.as_ref().map(|s| &s.since[..])
}
+
+ /// Returns a documentation-level item type from the item.
+ pub fn type_(&self) -> ItemType {
+ ItemType::from(self)
+ }
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
/// Current hierarchy of components leading down to what's currently being
/// rendered
pub current: Vec<String>,
- /// String representation of how to get back to the root path of the 'doc/'
- /// folder in terms of a relative URL.
- pub root_path: String,
/// The current destination folder of where HTML artifacts should be placed.
/// This changes as the context descends into the module hierarchy.
pub dst: PathBuf,
krate = render_sources(&dst, &mut scx, krate)?;
let cx = Context {
current: Vec::new(),
- root_path: String::new(),
dst: dst,
render_redirect_pages: false,
shared: Arc::new(scx),
for &(did, ref item) in orphan_impl_items {
if let Some(&(ref fqp, _)) = paths.get(&did) {
search_index.push(IndexItem {
- ty: item_type(item),
+ ty: item.type_(),
name: item.name.clone().unwrap(),
path: fqp[..fqp.len() - 1].join("::"),
desc: Escape(&shorter(item.doc_value())).to_string(),
}
}
-/// Returns a documentation-level item type from the item.
-fn item_type(item: &clean::Item) -> ItemType {
- ItemType::from(item)
-}
-
/// Takes a path to a source file and cleans the path to it. This canonicalizes
/// things like ".." to components which preserve the "top down" hierarchy of a
/// static HTML tree. Each component in the cleaned path will be passed as an
// inserted later on when serializing the search-index.
if item.def_id.index != CRATE_DEF_INDEX {
self.search_index.push(IndexItem {
- ty: item_type(&item),
+ ty: item.type_(),
name: s.to_string(),
path: path.join("::").to_string(),
desc: Escape(&shorter(item.doc_value())).to_string(),
self.access_levels.is_public(item.def_id)
{
self.paths.insert(item.def_id,
- (self.stack.clone(), item_type(&item)));
+ (self.stack.clone(), item.type_()));
}
}
// link variants to their parent enum because pages aren't emitted
clean::PrimitiveItem(..) if item.visibility.is_some() => {
self.paths.insert(item.def_id, (self.stack.clone(),
- item_type(&item)));
+ item.type_()));
}
_ => {}
}
impl Context {
+ /// String representation of how to get back to the root path of the 'doc/'
+ /// folder in terms of a relative URL.
+ fn root_path(&self) -> String {
+ repeat("../").take(self.current.len()).collect::<String>()
+ }
+
/// Recurse in the directory structure and change the "root path" to make
/// sure it always points to the top (relatively)
fn recurse<T, F>(&mut self, s: String, f: F) -> T where
}
let prev = self.dst.clone();
self.dst.push(&s);
- self.root_path.push_str("../");
self.current.push(s);
info!("Recursing into {}", self.dst.display());
// Go back to where we were at
self.dst = prev;
- let len = self.root_path.len();
- self.root_path.truncate(len - 3);
self.current.pop().unwrap();
return ret;
title.push_str(it.name.as_ref().unwrap());
}
title.push_str(" - Rust");
- let tyname = item_type(it).css_class();
+ let tyname = it.type_().css_class();
let desc = if it.is_crate() {
format!("API documentation for the Rust `{}` crate.",
self.shared.layout.krate)
let keywords = make_item_keywords(it);
let page = layout::Page {
css_class: tyname,
- root_path: &self.root_path,
+ root_path: &self.root_path(),
title: &title,
description: &desc,
keywords: &keywords,
&Item{ cx: self, item: it },
self.shared.css_file_extension.is_some())?;
} else {
- let mut url = repeat("../").take(self.current.len())
- .collect::<String>();
+ let mut url = self.root_path();
if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
for name in &names[..names.len() - 1] {
url.push_str(name);
// buf will be empty if the item is stripped and there is no redirect for it
if !buf.is_empty() {
let name = item.name.as_ref().unwrap();
- let item_type = item_type(&item);
+ let item_type = item.type_();
let file_name = &item_path(item_type, name);
let joint_dst = self.dst.join(file_name);
try_err!(fs::create_dir_all(&self.dst), &self.dst);
for item in &m.items {
if maybe_ignore_item(item) { continue }
- let short = item_type(item).css_class();
+ let short = item.type_().css_class();
let myname = match item.name {
None => continue,
Some(ref s) => s.to_string(),
}).map(|l| &l.1);
let root = match root {
Some(&Remote(ref s)) => s.to_string(),
- Some(&Local) => self.cx.root_path.clone(),
+ Some(&Local) => self.cx.root_path(),
None | Some(&Unknown) => return None,
};
Some(format!("{root}/{krate}/macro.{name}.html?gotomacrosrc=1",
let path = PathBuf::from(&self.item.source.filename);
self.cx.shared.local_sources.get(&path).map(|path| {
format!("{root}src/{krate}/{path}#{href}",
- root = self.cx.root_path,
+ root = self.cx.root_path(),
krate = self.cx.shared.layout.krate,
path = path,
href = href)
};
let mut path = match cache.extern_locations.get(&self.item.def_id.krate) {
Some(&(_, Remote(ref s))) => s.to_string(),
- Some(&(_, Local)) => self.cx.root_path.clone(),
+ Some(&(_, Local)) => self.cx.root_path(),
Some(&(_, Unknown)) => return None,
None => return None,
};
}
Some(format!("{path}{file}?gotosrc={goto}",
path = path,
- file = item_path(item_type(self.item), external_path.last().unwrap()),
+ file = item_path(self.item.type_(), external_path.last().unwrap()),
goto = self.item.def_id.index.as_usize()))
}
}
}
}
write!(fmt, "<a class='{}' href=''>{}</a>",
- item_type(self.item), self.item.name.as_ref().unwrap())?;
+ self.item.type_(), self.item.name.as_ref().unwrap())?;
write!(fmt, "</span>")?; // in-band
write!(fmt, "<span class='out-of-band'>")?;
}
fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering {
- let ty1 = item_type(i1);
- let ty2 = item_type(i2);
+ let ty1 = i1.type_();
+ let ty2 = i2.type_();
if ty1 != ty2 {
return (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2))
}
continue;
}
- let myty = Some(item_type(myitem));
+ let myty = Some(myitem.type_());
if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) {
// Put `extern crate` and `use` re-exports in the same section.
curty = myty;
name = *myitem.name.as_ref().unwrap(),
stab_docs = stab_docs,
docs = shorter(Some(&Markdown(doc_value).to_string())),
- class = item_type(myitem),
+ class = myitem.type_(),
stab = myitem.stability_class(),
- href = item_path(item_type(myitem), myitem.name.as_ref().unwrap()),
+ href = item_path(myitem.type_(), myitem.name.as_ref().unwrap()),
title = full_path(cx, myitem))?;
}
}
fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::Item)
-> fmt::Result {
let name = m.name.as_ref().unwrap();
- let item_type = item_type(m);
+ let item_type = m.type_();
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "<h3 id='{id}' class='method stab {stab}'>\
let (ref path, _) = cache.external_paths[&it.def_id];
path[..path.len() - 1].join("/")
},
- ty = item_type(it).css_class(),
+ ty = it.type_().css_class(),
name = *it.name.as_ref().unwrap())?;
Ok(())
}
use html::item_type::ItemType::*;
let name = it.name.as_ref().unwrap();
- let ty = match item_type(it) {
+ let ty = match it.type_() {
Typedef | AssociatedType => AssociatedType,
s@_ => s,
};
link: AssocItemLink)
-> fmt::Result {
let name = meth.name.as_ref().unwrap();
- let anchor = format!("#{}.{}", item_type(meth), name);
+ let anchor = format!("#{}.{}", meth.type_(), name);
let href = match link {
AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
AssocItemLink::Anchor(None) => anchor,
link: AssocItemLink, render_mode: RenderMode,
is_default_item: bool, outer_version: Option<&str>,
trait_: Option<&clean::Trait>) -> fmt::Result {
- let item_type = item_type(item);
+ let item_type = item.type_();
let name = item.name.as_ref().unwrap();
let render_method_item: bool = match render_mode {
write!(fmt, "::<wbr>")?;
}
write!(fmt, "<a href='{}index.html'>{}</a>",
- &cx.root_path[..(cx.current.len() - i - 1) * 3],
+ &cx.root_path()[..(cx.current.len() - i - 1) * 3],
*name)?;
}
write!(fmt, "</p>")?;
relpath: '{path}'\
}};</script>",
name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""),
- ty = item_type(it).css_class(),
+ ty = it.type_().css_class(),
path = relpath)?;
if parentlen == 0 {
// there is no sidebar-items.js beyond the crate root path
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
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";
pub const ARCH: &'static str = "asmjs";
}
+#[cfg(target_arch = "wasm32")]
+mod arch {
+ pub const ARCH: &'static str = "wasm32";
+}
+
#[cfg(test)]
mod tests {
use super::*;
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn test_var_big() {
let mut s = "".to_string();
let mut i = 0;
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn test_self_exe_path() {
let path = current_exe();
assert!(path.is_ok());
}
#[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>();
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use io::prelude::*;
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn panic_in_write_doesnt_flush_in_drop() {
static WRITES: AtomicUsize = AtomicUsize::new(0);
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();
}
#[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);
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)
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)
use super::*;
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn panic_doesnt_poison() {
thread::spawn(|| {
let _a = stdin();
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use net::*;
use net::test::{tsa, sa6, sa4};
}
// Tests for this module
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use net::*;
use net::Ipv6MulticastScope::*;
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`].
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use io::ErrorKind;
use io::prelude::*;
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use io::ErrorKind;
use net::*;
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};
::sys::os::exit(code)
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use io::prelude::*;
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn test_os_rng_tasks() {
let mut txs = vec!();
use thread;
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn test_barrier() {
const N: usize = 10;
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn notify_one() {
let m = Arc::new(Mutex::new(()));
let m2 = m.clone();
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn notify_all() {
const N: usize = 10;
}
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn wait_timeout_ms() {
let m = Arc::new(Mutex::new(()));
let m2 = m.clone();
#[test]
#[should_panic]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn two_mutexes() {
let m = Arc::new(Mutex::new(()));
let m2 = m.clone();
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use env;
use super::*;
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod sync_tests {
use env;
use thread;
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use sync::mpsc::channel;
use super::{Queue, Data, Empty, Inconsistent};
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
#[allow(unused_imports)]
mod tests {
use thread;
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use sync::Arc;
use super::Queue;
&guard.__lock.poison
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use sync::mpsc::channel;
use sync::{Arc, Mutex, Condvar};
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use panic;
use sync::mpsc::channel;
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
#![allow(deprecated)] // rand
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
pub mod test {
use path::{Path, PathBuf};
use env;
}
#[bench]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn bench_uninitialized(b: &mut ::test::Bencher) {
b.iter(|| {
let mut lr = repeat(1).take(10000000);
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
use cell::RefCell;
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod test {
use thread;
use io;
}
// 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
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use super::*;
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> {
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);
}
}
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use sync::mpsc::{channel, Sender};
use cell::{Cell, UnsafeCell};
// Tests
////////////////////////////////////////////////////////////////////////////////
-#[cfg(test)]
+#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use any::Any;
use sync::mpsc::{channel, Sender};
}
}
- 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 {
///
/// 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.
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
#[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)]
-Subproject commit 7801978ec1f3637fcda1b564048ebc732bf586af
+Subproject commit 3e03f7374169cd41547d75e62ac2ab8a103a913c
# 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
fn main() {
let x = Test;
x.method::<i32>(); //~ ERROR E0035
+ //~| NOTE called with unneeded type parameters
}
let x = Test;
let v = &[0];
x.method::<i32, i32>(v); //~ ERROR E0036
+ //~| NOTE Passed 2 type arguments, expected 1
}
// 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;
// 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;
enum A {
Ok = i8::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed on value after 127i8; set explicitly via OhNo = -128i8 if that is desired outcome
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 127i8
+ //~| NOTE explicitly set `OhNo = -128i8` if that is desired outcome
}
}
enum A {
Ok = u8::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed on value after 255u8; set explicitly via OhNo = 0u8 if that is desired outcome
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 255u8
+ //~| NOTE explicitly set `OhNo = 0u8` if that is desired outcome
}
}
enum A {
Ok = i16::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 32767i16
+ //~| NOTE explicitly set `OhNo = -32768i16` if that is desired outcome
}
}
enum A {
Ok = u16::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 65535u16
+ //~| NOTE explicitly set `OhNo = 0u16` if that is desired outcome
}
}
enum A {
Ok = i32::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 2147483647i32
+ //~| NOTE explicitly set `OhNo = -2147483648i32` if that is desired outcome
}
}
enum A {
Ok = u32::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 4294967295u32
+ //~| NOTE explicitly set `OhNo = 0u32` if that is desired outcome
}
}
enum A {
Ok = i64::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 9223372036854775807i64
+ //~| NOTE explicitly set `OhNo = -9223372036854775808i64` if that is desired outcome
}
}
enum A {
Ok = u64::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 18446744073709551615u64
+ //~| NOTE explicitly set `OhNo = 0u64` if that is desired outcome
}
}
enum A {
Ok = i8::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed on value after 127i8; set explicitly via OhNo = -128i8 if that is desired outcome
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 127i8
+ //~| NOTE explicitly set `OhNo = -128i8` if that is desired outcome
}
let x = A::Ok;
enum A {
Ok = u8::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed on value after 255u8; set explicitly via OhNo = 0u8 if that is desired outcome
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 255u8
+ //~| NOTE explicitly set `OhNo = 0u8` if that is desired outcome
}
let x = A::Ok;
enum A {
Ok = i16::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| NOTE overflowed on value after 32767i16
+ //~| NOTE explicitly set `OhNo = -32768i16` if that is desired outcome
}
let x = A::Ok;
enum A {
Ok = u16::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| overflowed on value after 65535u16
+ //~| NOTE explicitly set `OhNo = 0u16` if that is desired outcome
}
let x = A::Ok;
enum A {
Ok = i32::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| overflowed on value after 2147483647i32
+ //~| NOTE explicitly set `OhNo = -2147483648i32` if that is desired outcome
}
let x = A::Ok;
enum A {
Ok = u32::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| overflowed on value after 4294967295u32
+ //~| NOTE explicitly set `OhNo = 0u32` if that is desired outcome
}
let x = A::Ok;
enum A {
Ok = i64::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| overflowed on value after 9223372036854775807i64
+ //~| NOTE explicitly set `OhNo = -9223372036854775808i64` if that is desired outcome
}
let x = A::Ok;
enum A {
Ok = u64::MAX - 1,
Ok2,
- OhNo, //~ ERROR enum discriminant overflowed
+ OhNo, //~ ERROR enum discriminant overflowed [E0370]
+ //~| overflowed on value after 18446744073709551615u64
+ //~| NOTE explicitly set `OhNo = 0u64` if that is desired outcome
}
let x = A::Ok;
// except according to those terms.
// error-pattern:thread '<unnamed>' panicked at 'test'
+// ignore-emscripten Needs threads
use std::thread;
// except according to those terms.
// error-pattern:thread 'owned name' panicked at 'test'
+// ignore-emscripten Needs threads.
use std::thread::Builder;
// except according to those terms.
// error-pattern:Ensure that the child thread runs by panicking
+// ignore-emscripten Needs threads.
use std::thread;
// error-pattern:thread 'test_foo' panicked at
// compile-flags: --test
// ignore-pretty: does not work well with `--test`
+// ignore-emscripten
#[test]
fn test_foo() {
// 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")]
// compile-flags: --test
// exec-env:RUST_TEST_THREADS=foo
// ignore-pretty: does not work well with `--test`
+// ignore-emscripten
#[test]
fn do_nothing() {}
// no-prefer-dynamic
// aux-build:allocator-dummy.rs
+// ignore-emscripten
#![feature(test)]
// pretty-expanded FIXME #23616
// ignore-msvc
+// ignore-emscripten
struct TwoU8s {
one: u8,
// 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]
// <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;
// <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;
// 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;
// compile-flags:-C panic=abort
// no-prefer-dynamic
+// ignore-emscripten Function not implemented.
use std::process::Command;
use std::env;
// compile-flags:-C lto -C panic=abort
// no-prefer-dynamic
+// ignore-emscripten Function not implemented.
use std::process::Command;
use std::env;
// compile-flags:-C lto -C panic=unwind
// no-prefer-dynamic
+// ignore-emscripten Function not implemented.
use std::process::Command;
use std::env;
// <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;
// <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)]
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());
pub cflags: String,
pub llvm_components: String,
pub llvm_cxxflags: String,
+ pub nodejs: Option<String>,
}
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();
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"),
}
}
}
};
+ // 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),
"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(),
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);
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();
("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 {