diff --git a/.gitmodules b/.gitmodules index 2802c8d63913f..0a1188e83eae6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -42,3 +42,9 @@ [submodule "src/tools/miri"] path = src/tools/miri url = https://github.com/solson/miri.git +[submodule "src/dlmalloc"] + path = src/dlmalloc + url = https://github.com/alexcrichton/dlmalloc-rs.git +[submodule "src/binaryen"] + path = src/binaryen + url = https://github.com/alexcrichton/binaryen.git diff --git a/src/Cargo.lock b/src/Cargo.lock index bc20304945357..276980699a2f4 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -50,6 +50,7 @@ version = "0.0.0" dependencies = [ "alloc 0.0.0", "core 0.0.0", + "dlmalloc 0.0.0", "libc 0.0.0", ] @@ -372,9 +373,6 @@ version = "0.1.0" [[package]] name = "core" version = "0.0.0" -dependencies = [ - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "core-foundation" @@ -509,6 +507,14 @@ name = "diff" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dlmalloc" +version = "0.0.0" +dependencies = [ + "alloc 0.0.0", + "core 0.0.0", +] + [[package]] name = "docopt" version = "0.8.1" @@ -1608,6 +1614,15 @@ dependencies = [ "syntax 0.0.0", ] +[[package]] +name = "rustc_binaryen" +version = "0.0.0" +dependencies = [ + "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc_borrowck" version = "0.0.0" @@ -1880,6 +1895,7 @@ dependencies = [ "rustc_allocator 0.0.0", "rustc_apfloat 0.0.0", "rustc_back 0.0.0", + "rustc_binaryen 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", diff --git a/src/binaryen b/src/binaryen new file mode 160000 index 0000000000000..1c9bf65aa0e37 --- /dev/null +++ b/src/binaryen @@ -0,0 +1 @@ +Subproject commit 1c9bf65aa0e371b84755a8ddd6e79497fac57171 diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 1401bc80a1ac2..4d69b19c7310f 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1211,7 +1211,8 @@ impl Step for Crate { // ends up messing with various mtime calculations and such. if !name.contains("jemalloc") && *name != *"build_helper" && - !(name.starts_with("rustc_") && name.ends_with("san")) { + !(name.starts_with("rustc_") && name.ends_with("san")) && + name != "dlmalloc" { cargo.arg("-p").arg(&format!("{}:0.0.0", name)); } for dep in build.crates[&name].deps.iter() { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 7bf385301fab5..9f7e3de9dc051 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -672,6 +672,9 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di spath.ends_with(".s")) { return false } + if spath.contains("test/emscripten") || spath.contains("test\\emscripten") { + return false + } let full_path = Path::new(dir).join(path); if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) { @@ -736,6 +739,7 @@ impl Step for Src { // (essentially libstd and all of its path dependencies) let std_src_dirs = [ "src/build_helper", + "src/dlmalloc", "src/liballoc", "src/liballoc_jemalloc", "src/liballoc_system", @@ -754,6 +758,7 @@ impl Step for Src { "src/libunwind", "src/rustc/compiler_builtins_shim", "src/rustc/libc_shim", + "src/rustc/dlmalloc_shim", "src/libtest", "src/libterm", "src/jemalloc", diff --git a/src/dlmalloc b/src/dlmalloc new file mode 160000 index 0000000000000..d3812c3accaee --- /dev/null +++ b/src/dlmalloc @@ -0,0 +1 @@ +Subproject commit d3812c3accaee7ad23068ed4fc089cc05c7a538f diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js new file mode 100644 index 0000000000000..b595cc1205336 --- /dev/null +++ b/src/etc/wasm32-shim.js @@ -0,0 +1,119 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This is a small "shim" program which is used when wasm32 unit tests are run +// in this repository. This program is intended to be run in node.js and will +// load a wasm module into memory, instantiate it with a set of imports, and +// then run it. +// +// There's a bunch of helper functions defined here in `imports.env`, but note +// that most of them aren't actually needed to execute most programs. Many of +// these are just intended for completeness or debugging. Hopefully over time +// nothing here is needed for completeness. + +const fs = require('fs'); +const process = require('process'); +const buffer = fs.readFileSync(process.argv[2]); + +Error.stackTraceLimit = 20; + +let m = new WebAssembly.Module(buffer); + +let memory = null; + +function copystr(a, b) { + if (memory === null) { + return null + } + let view = new Uint8Array(memory.buffer).slice(a, a + b); + return String.fromCharCode.apply(null, view); +} + +let imports = {}; +imports.env = { + // These are generated by LLVM itself for various intrinsic calls. Hopefully + // one day this is not necessary and something will automatically do this. + fmod: function(x, y) { return x % y; }, + exp2: function(x) { return Math.pow(2, x); }, + exp2f: function(x) { return Math.pow(2, x); }, + ldexp: function(x, y) { return x * Math.pow(2, y); }, + ldexpf: function(x, y) { return x * Math.pow(2, y); }, + log10: function(x) { return Math.log10(x); }, + log10f: function(x) { return Math.log10(x); }, + + // These are called in src/libstd/sys/wasm/stdio.rs and are used when + // debugging is enabled. + rust_wasm_write_stdout: function(a, b) { + let s = copystr(a, b); + if (s !== null) { + process.stdout.write(s); + } + }, + rust_wasm_write_stderr: function(a, b) { + let s = copystr(a, b); + if (s !== null) { + process.stderr.write(s); + } + }, + + // These are called in src/libstd/sys/wasm/args.rs and are used when + // debugging is enabled. + rust_wasm_args_count: function() { + if (memory === null) + return 0; + return process.argv.length - 2; + }, + rust_wasm_args_arg_size: function(i) { + return process.argv[i + 2].length; + }, + rust_wasm_args_arg_fill: function(idx, ptr) { + let arg = process.argv[idx + 2]; + let view = new Uint8Array(memory.buffer); + for (var i = 0; i < arg.length; i++) { + view[ptr + i] = arg.charCodeAt(i); + } + }, + + // These are called in src/libstd/sys/wasm/os.rs and are used when + // debugging is enabled. + rust_wasm_getenv_len: function(a, b) { + let key = copystr(a, b); + if (key === null) { + return -1; + } + if (!(key in process.env)) { + return -1; + } + return process.env[key].length; + }, + rust_wasm_getenv_data: function(a, b, ptr) { + let key = copystr(a, b); + let value = process.env[key]; + let view = new Uint8Array(memory.buffer); + for (var i = 0; i < value.length; i++) { + view[ptr + i] = value.charCodeAt(i); + } + }, +}; + +let module_imports = WebAssembly.Module.imports(m); + +for (var i = 0; i < module_imports.length; i++) { + let imp = module_imports[i]; + if (imp.module != 'env') { + continue + } + if (imp.name == 'memory' && imp.kind == 'memory') { + memory = new WebAssembly.Memory({initial: 20}); + imports.env.memory = memory; + } +} + +let instance = new WebAssembly.Instance(m, imports); diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 65e035d4ffdef..a41a04d7cd4f6 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -31,7 +31,7 @@ fn main() { let host = env::var("HOST").expect("HOST was not set"); if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") || target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") || - target.contains("redox") { + target.contains("redox") || target.contains("wasm32") { println!("cargo:rustc-cfg=dummy_jemalloc"); return; } diff --git a/src/liballoc_system/Cargo.toml b/src/liballoc_system/Cargo.toml index a725a8608be29..f9a57f7d97a74 100644 --- a/src/liballoc_system/Cargo.toml +++ b/src/liballoc_system/Cargo.toml @@ -13,3 +13,7 @@ doc = false alloc = { path = "../liballoc" } core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } + +# See comments in the source for what this dependency is +[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] +dlmalloc = { path = "../rustc/dlmalloc_shim" } diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 7aa5f8a9186b0..05cacf6e88195 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -34,12 +34,14 @@ target_arch = "powerpc64", target_arch = "asmjs", target_arch = "wasm32")))] +#[allow(dead_code)] const MIN_ALIGN: usize = 8; #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64")))] +#[allow(dead_code)] const MIN_ALIGN: usize = 16; extern crate alloc; @@ -458,3 +460,91 @@ mod platform { } } } + +// This is an implementation of a global allocator on the wasm32 platform when +// emscripten is not in use. In that situation there's no actual runtime for us +// to lean on for allocation, so instead we provide our own! +// +// The wasm32 instruction set has two instructions for getting the current +// amount of memory and growing the amount of memory. These instructions are the +// foundation on which we're able to build an allocator, so we do so! Note that +// the instructions are also pretty "global" and this is the "global" allocator +// after all! +// +// The current allocator here is the `dlmalloc` crate which we've got included +// in the rust-lang/rust repository as a submodule. The crate is a port of +// dlmalloc.c from C to Rust and is basically just so we can have "pure Rust" +// for now which is currently technically required (can't link with C yet). +// +// The crate itself provides a global allocator which on wasm has no +// synchronization as there are no threads! +#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] +mod platform { + extern crate dlmalloc; + + use alloc::heap::{Alloc, AllocErr, Layout, Excess, CannotReallocInPlace}; + use System; + use self::dlmalloc::GlobalDlmalloc; + + #[unstable(feature = "allocator_api", issue = "32838")] + unsafe impl<'a> Alloc for &'a System { + #[inline] + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + GlobalDlmalloc.alloc(layout) + } + + #[inline] + unsafe fn alloc_zeroed(&mut self, layout: Layout) + -> Result<*mut u8, AllocErr> + { + GlobalDlmalloc.alloc_zeroed(layout) + } + + #[inline] + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + GlobalDlmalloc.dealloc(ptr, layout) + } + + #[inline] + unsafe fn realloc(&mut self, + ptr: *mut u8, + old_layout: Layout, + new_layout: Layout) -> Result<*mut u8, AllocErr> { + GlobalDlmalloc.realloc(ptr, old_layout, new_layout) + } + + #[inline] + fn usable_size(&self, layout: &Layout) -> (usize, usize) { + GlobalDlmalloc.usable_size(layout) + } + + #[inline] + unsafe fn alloc_excess(&mut self, layout: Layout) -> Result { + GlobalDlmalloc.alloc_excess(layout) + } + + #[inline] + unsafe fn realloc_excess(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result { + GlobalDlmalloc.realloc_excess(ptr, layout, new_layout) + } + + #[inline] + unsafe fn grow_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + GlobalDlmalloc.grow_in_place(ptr, layout, new_layout) + } + + #[inline] + unsafe fn shrink_in_place(&mut self, + ptr: *mut u8, + layout: Layout, + new_layout: Layout) -> Result<(), CannotReallocInPlace> { + GlobalDlmalloc.shrink_in_place(ptr, layout, new_layout) + } + } +} diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index d1a0a5f09e0d5..5af63aa970f2c 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -9,9 +9,6 @@ path = "lib.rs" test = false bench = false -[dev-dependencies] -rand = "0.3" - [[test]] name = "coretests" path = "../libcore/tests/lib.rs" diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index afc5de7b0ee35..edf7f44e5925c 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -27,7 +27,6 @@ #![feature(iter_rfind)] #![feature(iter_rfold)] #![feature(nonzero)] -#![feature(rand)] #![feature(raw)] #![feature(refcell_replace_swap)] #![feature(sip_hash_13)] @@ -48,7 +47,6 @@ extern crate core; extern crate test; -extern crate rand; mod any; mod array; diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs index 2720c5c8677af..ef0178815f98b 100644 --- a/src/libcore/tests/num/flt2dec/mod.rs +++ b/src/libcore/tests/num/flt2dec/mod.rs @@ -9,9 +9,7 @@ // except according to those terms. use std::prelude::v1::*; -use std::{str, mem, i16, f32, f64, fmt}; -use rand::{self, Rand, XorShiftRng}; -use rand::distributions::{IndependentSample, Range}; +use std::{str, i16, f32, f64, fmt}; use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; use core::num::flt2dec::{MAX_SIG_DIGITS, round_up, Part, Formatted, Sign}; @@ -463,87 +461,6 @@ pub fn more_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8] exp: 0, inclusive: false} => b"99999999999999999", 17); } -fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), - V: FnMut(usize) -> Decoded { - assert!(k <= 1024); - - let mut npassed = 0; // f(x) = Some(g(x)) - let mut nignored = 0; // f(x) = None - - for i in 0..n { - if (i & 0xfffff) == 0 { - println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})", - i, n, nignored, npassed, i - nignored - npassed); - } - - let decoded = v(i); - let mut buf1 = [0; 1024]; - if let Some((len1, e1)) = f(&decoded, &mut buf1[..k]) { - let mut buf2 = [0; 1024]; - let (len2, e2) = g(&decoded, &mut buf2[..k]); - if e1 == e2 && &buf1[..len1] == &buf2[..len2] { - npassed += 1; - } else { - println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}", - i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1, - str::from_utf8(&buf2[..len2]).unwrap(), e2); - } - } else { - nignored += 1; - } - } - println!("{}({}): done, ignored={} passed={} failed={}", - func, k, nignored, npassed, n - nignored - npassed); - assert!(nignored + npassed == n, - "{}({}): {} out of {} values returns an incorrect value!", - func, k, n - nignored - npassed, n); - (npassed, nignored) -} - -pub fn f32_random_equivalence_test(f: F, g: G, k: usize, n: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); - let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000); - iterate("f32_random_equivalence_test", k, n, f, g, |_| { - let i: u32 = f32_range.ind_sample(&mut rng); - let x: f32 = unsafe {mem::transmute(i)}; - decode_finite(x) - }); -} - -pub fn f64_random_equivalence_test(f: F, g: G, k: usize, n: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); - let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); - iterate("f64_random_equivalence_test", k, n, f, g, |_| { - let i: u64 = f64_range.ind_sample(&mut rng); - let x: f64 = unsafe {mem::transmute(i)}; - decode_finite(x) - }); -} - -pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values, - // so why not simply testing all of them? - // - // this is of course very stressful (and thus should be behind an `#[ignore]` attribute), - // but with `-C opt-level=3 -C lto` this only takes about an hour or so. - - // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges - let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test", - k, 0x7f7f_ffff, f, g, |i: usize| { - let x: f32 = unsafe {mem::transmute(i as u32 + 1)}; - decode_finite(x) - }); - assert_eq!((npassed, nignored), (2121451881, 17643158)); -} - fn to_string_with_parts(mut f: F) -> String where F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a> { let mut buf = [0; 1024]; diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs index 17fb99bcc9224..286b39d8cf3b3 100644 --- a/src/libcore/tests/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::i16; use super::super::*; use core::num::flt2dec::strategy::grisu::*; @@ -46,35 +45,6 @@ fn shortest_sanity_test() { more_shortest_sanity_test(format_shortest); } -#[test] -fn shortest_random_equivalence_test() { - use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); - f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); -} - -#[test] #[ignore] // it is too expensive -fn shortest_f32_exhaustive_equivalence_test() { - // it is hard to directly test the optimality of the output, but we can at least test if - // two different algorithms agree to each other. - // - // this reports the progress and the number of f32 values returned `None`. - // with `--nocapture` (and plenty of time and appropriate rustc flags), this should print: - // `done, ignored=17643158 passed=2121451881 failed=0`. - - use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS); -} - -#[test] #[ignore] // it is too expensive -fn shortest_f64_hard_random_equivalence_test() { - // this again probably has to use appropriate rustc flags. - - use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f64_random_equivalence_test(format_shortest_opt, fallback, - MAX_SIG_DIGITS, 100_000_000); -} - #[test] fn exact_sanity_test() { // See comments in dragon.rs's exact_sanity_test for why this test is @@ -85,24 +55,6 @@ fn exact_sanity_test() { f32_exact_sanity_test(format_exact); } -#[test] -fn exact_f32_random_equivalence_test() { - use core::num::flt2dec::strategy::dragon::format_exact as fallback; - for k in 1..21 { - f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, 1_000); - } -} - -#[test] -fn exact_f64_random_equivalence_test() { - use core::num::flt2dec::strategy::dragon::format_exact as fallback; - for k in 1..21 { - f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, 1_000); - } -} - #[test] fn test_to_shortest_str() { to_shortest_str_test(format_shortest); diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 7835080db1d45..60e4e6d2ff328 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Ordering::{Equal, Greater, Less}; -use core::slice::heapsort; use core::result::Result::{Ok, Err}; -use rand::{Rng, XorShiftRng}; #[test] fn test_binary_search() { @@ -290,68 +287,3 @@ fn test_rotate() { assert_eq!(a[(i+k)%N], i); } } - -#[test] -fn sort_unstable() { - let mut v = [0; 600]; - let mut tmp = [0; 600]; - let mut rng = XorShiftRng::new_unseeded(); - - for len in (2..25).chain(500..510) { - let v = &mut v[0..len]; - let tmp = &mut tmp[0..len]; - - for &modulus in &[5, 10, 100, 1000] { - for _ in 0..100 { - for i in 0..len { - v[i] = rng.gen::() % modulus; - } - - // Sort in default order. - tmp.copy_from_slice(v); - tmp.sort_unstable(); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Sort in ascending order. - tmp.copy_from_slice(v); - tmp.sort_unstable_by(|a, b| a.cmp(b)); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Sort in descending order. - tmp.copy_from_slice(v); - tmp.sort_unstable_by(|a, b| b.cmp(a)); - assert!(tmp.windows(2).all(|w| w[0] >= w[1])); - - // Test heapsort using `<` operator. - tmp.copy_from_slice(v); - heapsort(tmp, |a, b| a < b); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Test heapsort using `>` operator. - tmp.copy_from_slice(v); - heapsort(tmp, |a, b| a > b); - assert!(tmp.windows(2).all(|w| w[0] >= w[1])); - } - } - } - - // Sort using a completely random comparison function. - // This will reorder the elements *somehow*, but won't panic. - for i in 0..v.len() { - v[i] = i as i32; - } - v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap()); - v.sort_unstable(); - for i in 0..v.len() { - assert_eq!(v[i], i as i32); - } - - // Should not panic. - [0i32; 0].sort_unstable(); - [(); 10].sort_unstable(); - [(); 100].sort_unstable(); - - let mut v = [0xDEADBEEFu64]; - v.sort_unstable(); - assert!(v == [0xDEADBEEF]); -} diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 8be6f6470231d..29a9e1aadaf3c 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -20,13 +20,13 @@ html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] #![deny(warnings)] - -#![feature(staged_api)] - #![panic_runtime] +#![allow(unused_features)] + +#![feature(core_intrinsics)] +#![feature(libc)] #![feature(panic_runtime)] -#![cfg_attr(unix, feature(libc))] -#![cfg_attr(any(target_os = "redox", windows), feature(core_intrinsics))] +#![feature(staged_api)] // Rust's "try" function, but if we're aborting on panics we just call the // function as there's nothing else we need to do here. @@ -59,7 +59,9 @@ pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { libc::abort(); } - #[cfg(any(target_os = "redox", windows))] + #[cfg(any(target_os = "redox", + windows, + all(target_arch = "wasm32", not(target_os = "emscripten"))))] unsafe fn abort() -> ! { core::intrinsics::abort(); } @@ -92,7 +94,6 @@ pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { // binaries, but it should never be called as we don't link in an unwinding // runtime at all. pub mod personalities { - #[no_mangle] #[cfg(not(all(target_os = "windows", target_env = "gnu", diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 558286f4ec070..6b8da7a51ceb8 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -34,9 +34,7 @@ #![feature(core_intrinsics)] #![feature(lang_items)] #![feature(libc)] -#![cfg_attr(not(any(target_env = "msvc", - all(windows, target_arch = "x86_64", target_env = "gnu"))), - feature(panic_unwind))] +#![feature(panic_unwind)] #![feature(raw)] #![feature(staged_api)] #![feature(unwind_attributes)] @@ -80,6 +78,10 @@ mod imp; #[path = "emcc.rs"] mod imp; +#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] +#[path = "wasm32.rs"] +mod imp; + mod dwarf; mod windows; diff --git a/src/libpanic_unwind/wasm32.rs b/src/libpanic_unwind/wasm32.rs new file mode 100644 index 0000000000000..8aed61b3c385a --- /dev/null +++ b/src/libpanic_unwind/wasm32.rs @@ -0,0 +1,29 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unwinding for wasm32 +//! +//! Right now we don't support this, so this is just stubs + +use alloc::boxed::Box; +use core::any::Any; +use core::intrinsics; + +pub fn payload() -> *mut u8 { + 0 as *mut u8 +} + +pub unsafe fn cleanup(_ptr: *mut u8) -> Box { + intrinsics::abort() +} + +pub unsafe fn panic(_data: Box) -> u32 { + intrinsics::abort() +} diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 00a91eeb9c18e..9f957cd780829 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -432,7 +432,7 @@ impl Session { self.opts.debugging_opts.borrowck_mir } pub fn lto(&self) -> bool { - self.opts.cg.lto + self.opts.cg.lto || self.target.target.options.requires_lto } /// Returns the panic strategy for this compile session. If the user explicitly selected one /// using '-C panic', use that, otherwise use the panic strategy defined by the target. diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index d67de123415f2..824b553104760 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -84,6 +84,7 @@ macro_rules! linker_flavor { linker_flavor! { (Em, "em"), + (Binaryen, "binaryen"), (Gcc, "gcc"), (Ld, "ld"), (Msvc, "msvc"), diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index d60d6438b4d61..7599a60ba5ada 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -218,6 +218,7 @@ supported_targets! { ("asmjs-unknown-emscripten", asmjs_unknown_emscripten), ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), + ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-experimental-emscripten", wasm32_experimental_emscripten), ("thumbv6m-none-eabi", thumbv6m_none_eabi), @@ -303,6 +304,8 @@ pub struct TargetOptions { pub features: String, /// Whether dynamic linking is available on this target. Defaults to false. pub dynamic_linking: bool, + /// If dynamic linking is available, whether only cdylibs are supported. + pub only_cdylib: bool, /// Whether executables are available on this target. iOS, for example, only allows static /// libraries. Defaults to false. pub executables: bool, @@ -439,6 +442,17 @@ pub struct TargetOptions { /// Whether to generate trap instructions in places where optimization would /// otherwise produce control flow that falls through into unrelated memory. pub trap_unreachable: bool, + + /// This target requires everything to be compiled with LTO to emit a final + /// executable, aka there is no native linker for this target. + pub requires_lto: bool, + + /// This target has no support for threads. + pub singlethread: bool, + + /// Whether library functions call lowering/optimization is disabled in LLVM + /// for this target unconditionally. + pub no_builtins: bool, } impl Default for TargetOptions { @@ -454,6 +468,7 @@ impl Default for TargetOptions { cpu: "generic".to_string(), features: "".to_string(), dynamic_linking: false, + only_cdylib: false, executables: false, relocation_model: "pic".to_string(), code_model: "default".to_string(), @@ -503,6 +518,9 @@ impl Default for TargetOptions { min_global_align: None, default_codegen_units: None, trap_unreachable: true, + requires_lto: false, + singlethread: false, + no_builtins: false, } } } @@ -702,6 +720,7 @@ impl Target { key!(cpu); key!(features); key!(dynamic_linking, bool); + key!(only_cdylib, bool); key!(executables, bool); key!(relocation_model); key!(code_model); @@ -745,6 +764,9 @@ impl Target { key!(min_global_align, Option); key!(default_codegen_units, Option); key!(trap_unreachable, bool); + key!(requires_lto, bool); + key!(singlethread, bool); + key!(no_builtins, bool); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -896,6 +918,7 @@ impl ToJson for Target { target_option_val!(cpu); target_option_val!(features); target_option_val!(dynamic_linking); + target_option_val!(only_cdylib); target_option_val!(executables); target_option_val!(relocation_model); target_option_val!(code_model); @@ -939,6 +962,9 @@ impl ToJson for Target { target_option_val!(min_global_align); target_option_val!(default_codegen_units); target_option_val!(trap_unreachable); + target_option_val!(requires_lto); + target_option_val!(singlethread); + target_option_val!(no_builtins); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() diff --git a/src/librustc_back/target/wasm32_unknown_unknown.rs b/src/librustc_back/target/wasm32_unknown_unknown.rs new file mode 100644 index 0000000000000..7e1011ab8af96 --- /dev/null +++ b/src/librustc_back/target/wasm32_unknown_unknown.rs @@ -0,0 +1,104 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// The wasm32-unknown-unknown target is currently a highly experimental version +// of a wasm-based target which does *not* use the Emscripten toolchain. Instead +// this is a pretty flavorful (aka hacked up) target right now. The definition +// and semantics of this target are likely to change and so this shouldn't be +// relied on just yet. +// +// In general everyone is currently waiting on a linker for wasm code. In the +// meantime we have no means of actually making use of the traditional separate +// compilation model. At a high level this means that assembling Rust programs +// into a WebAssembly program looks like: +// +// 1. All intermediate artifacts are LLVM bytecode. We'll be using LLVM as +// a linker later on. +// 2. For the final artifact we emit one giant assembly file (WebAssembly +// doesn't have an object file format). To do this we force LTO to be turned +// on (`requires_lto` below) to ensure all Rust code is in one module. Any +// "linked" C library is basically just ignored. +// 3. Using LLVM we emit a `foo.s` file (assembly) with some... what I can only +// describe as arcane syntax. From there we need to actually change this +// into a wasm module. For this step we use the `binaryen` project. This +// project is mostly intended as a WebAssembly code generator, but for now +// we're just using its LLVM-assembly-to-wasm-module conversion utilities. +// +// And voila, out comes a web assembly module! There's some various tweaks here +// and there, but that's the high level at least. Note that this will be +// rethought from the ground up once a linker (lld) is available, so this is all +// temporary and should improve in the future. + +use LinkerFlavor; +use super::{Target, TargetOptions, PanicStrategy}; + +pub fn target() -> Result { + let opts = TargetOptions { + linker: "not-used".to_string(), + + // we allow dynamic linking, but only cdylibs. Basically we allow a + // final library artifact that exports some symbols (a wasm module) but + // we don't allow intermediate `dylib` crate types + dynamic_linking: true, + only_cdylib: true, + + // This means we'll just embed a `start` function in the wasm module + executables: true, + + // relatively self-explanatory! + exe_suffix: ".wasm".to_string(), + dll_prefix: "".to_string(), + dll_suffix: ".wasm".to_string(), + linker_is_gnu: false, + + // We're storing bitcode for now in all the rlibs + obj_is_bitcode: true, + + // A bit of a lie, but "eh" + max_atomic_width: Some(32), + + // Unwinding doesn't work right now, so the whole target unconditionally + // defaults to panic=abort. Note that this is guaranteed to change in + // the future once unwinding is implemented. Don't rely on this. + panic_strategy: PanicStrategy::Abort, + + // There's no linker yet so we're forced to use LLVM as a linker. This + // means that we must always enable LTO for final artifacts. + requires_lto: true, + + // Wasm doesn't have atomics yet, so tell LLVM that we're in a single + // threaded model which will legalize atomics to normal operations. + singlethread: true, + + // Because we're always enabling LTO we can't enable builtin lowering as + // otherwise we'll lower the definition of the `memcpy` function to + // memcpy itself. Note that this is specifically because we're + // performing LTO with compiler-builtins. + no_builtins: true, + + .. Default::default() + }; + Ok(Target { + llvm_target: "wasm32-unknown-unknown".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + // This is basically guaranteed to change in the future, don't rely on + // this. Use `not(target_os = "emscripten")` for now. + target_os: "unknown".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + arch: "wasm32".to_string(), + // A bit of a lie, but it gets the job done + linker_flavor: LinkerFlavor::Binaryen, + options: opts, + }) +} diff --git a/src/librustc_binaryen/BinaryenWrapper.cpp b/src/librustc_binaryen/BinaryenWrapper.cpp new file mode 100644 index 0000000000000..d1095a7819d4a --- /dev/null +++ b/src/librustc_binaryen/BinaryenWrapper.cpp @@ -0,0 +1,132 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This is a small C API inserted on top of the Binaryen C++ API which we use +// from Rust. Once we have a real linker for we'll be able to remove all this, +// and otherwise this is just all on a "as we need it" basis for now. + +#include +#include +#include + +#include "s2wasm.h" +#include "wasm-binary.h" +#include "wasm-linker.h" + +using namespace wasm; + +struct BinaryenRustModule { + BufferWithRandomAccess buffer; +}; + +struct BinaryenRustModuleOptions { + uint64_t globalBase; + bool debug; + uint64_t stackAllocation; + uint64_t initialMem; + uint64_t maxMem; + bool importMemory; + bool ignoreUnknownSymbols; + bool debugInfo; + std::string startFunction; + + BinaryenRustModuleOptions() : + globalBase(0), + debug(false), + stackAllocation(0), + initialMem(0), + maxMem(0), + importMemory(false), + ignoreUnknownSymbols(false), + debugInfo(false), + startFunction("") + {} + +}; + +extern "C" BinaryenRustModuleOptions* +BinaryenRustModuleOptionsCreate() { + return new BinaryenRustModuleOptions; +} + +extern "C" void +BinaryenRustModuleOptionsFree(BinaryenRustModuleOptions *options) { + delete options; +} + +extern "C" void +BinaryenRustModuleOptionsSetDebugInfo(BinaryenRustModuleOptions *options, + bool debugInfo) { + options->debugInfo = debugInfo; +} + +extern "C" void +BinaryenRustModuleOptionsSetStart(BinaryenRustModuleOptions *options, + char *start) { + options->startFunction = start; +} + +extern "C" void +BinaryenRustModuleOptionsSetStackAllocation(BinaryenRustModuleOptions *options, + uint64_t stack) { + options->stackAllocation = stack; +} + +extern "C" void +BinaryenRustModuleOptionsSetImportMemory(BinaryenRustModuleOptions *options, + bool import) { + options->importMemory = import; +} + +extern "C" BinaryenRustModule* +BinaryenRustModuleCreate(const BinaryenRustModuleOptions *options, + const char *assembly) { + Linker linker( + options->globalBase, + options->stackAllocation, + options->initialMem, + options->maxMem, + options->importMemory, + options->ignoreUnknownSymbols, + options->startFunction, + options->debug); + + S2WasmBuilder mainbuilder(assembly, options->debug); + linker.linkObject(mainbuilder); + linker.layout(); + + auto ret = make_unique(); + { + WasmBinaryWriter writer(&linker.getOutput().wasm, ret->buffer, options->debug); + writer.setNamesSection(options->debugInfo); + // FIXME: support source maps? + // writer.setSourceMap(sourceMapStream.get(), sourceMapUrl); + + // FIXME: support symbol maps? + // writer.setSymbolMap(symbolMap); + writer.write(); + } + return ret.release(); +} + +extern "C" const uint8_t* +BinaryenRustModulePtr(const BinaryenRustModule *M) { + return M->buffer.data(); +} + +extern "C" size_t +BinaryenRustModuleLen(const BinaryenRustModule *M) { + return M->buffer.size(); +} + +extern "C" void +BinaryenRustModuleFree(BinaryenRustModule *M) { + delete M; +} diff --git a/src/librustc_binaryen/Cargo.toml b/src/librustc_binaryen/Cargo.toml new file mode 100644 index 0000000000000..9573c89471404 --- /dev/null +++ b/src/librustc_binaryen/Cargo.toml @@ -0,0 +1,16 @@ +# Wondering what this crate is? Take a look at the `lib.rs`! + +[package] +name = "rustc_binaryen" +version = "0.0.0" +authors = ["The Rust Project Developers"] + +[lib] +path = "lib.rs" + +[dependencies] +libc = "0.2" + +[build-dependencies] +cmake = "0.1" +cc = "1.0" diff --git a/src/librustc_binaryen/build.rs b/src/librustc_binaryen/build.rs new file mode 100644 index 0000000000000..f23ff3cee555b --- /dev/null +++ b/src/librustc_binaryen/build.rs @@ -0,0 +1,60 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate cc; +extern crate cmake; + +use std::env; + +use cmake::Config; + +fn main() { + let target = env::var("TARGET").unwrap(); + + // Bring in `__emutls_get_address` which is apparently needed for now + if target.contains("pc-windows-gnu") { + println!("cargo:rustc-link-lib=gcc_eh"); + println!("cargo:rustc-link-lib=pthread"); + } + + Config::new("../binaryen") + .define("BUILD_STATIC_LIB", "ON") + .build_target("binaryen") + .build(); + + // I couldn't figure out how to link just one of these, so link everything. + println!("cargo:rustc-link-lib=static=asmjs"); + println!("cargo:rustc-link-lib=static=binaryen"); + println!("cargo:rustc-link-lib=static=cfg"); + println!("cargo:rustc-link-lib=static=emscripten-optimizer"); + println!("cargo:rustc-link-lib=static=ir"); + println!("cargo:rustc-link-lib=static=passes"); + println!("cargo:rustc-link-lib=static=support"); + println!("cargo:rustc-link-lib=static=wasm"); + + let out_dir = env::var("OUT_DIR").unwrap(); + println!("cargo:rustc-link-search=native={}/build/lib", out_dir); + + // Add in our own little shim along with some extra files that weren't + // included in the main build. + let mut cfg = cc::Build::new(); + cfg.file("BinaryenWrapper.cpp") + .file("../binaryen/src/wasm-linker.cpp") + .file("../binaryen/src/wasm-emscripten.cpp") + .include("../binaryen/src") + .cpp_link_stdlib(None) + .warnings(false) + .cpp(true); + + if !target.contains("msvc") { + cfg.flag("-std=c++11"); + } + cfg.compile("binaryen_wrapper"); +} diff --git a/src/librustc_binaryen/lib.rs b/src/librustc_binaryen/lib.rs new file mode 100644 index 0000000000000..6c7feb6a7a9d3 --- /dev/null +++ b/src/librustc_binaryen/lib.rs @@ -0,0 +1,150 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Rustc bindings to the binaryen project. +//! +//! This crate is a small shim around the binaryen project which provides us the +//! ability to take LLVM's output and generate a wasm module. Specifically this +//! only supports one operation, creating a module from LLVM's assembly format +//! and then serializing that module to a wasm module. + +extern crate libc; + +use std::slice; +use std::ffi::{CString, CStr}; + +/// In-memory representation of a serialized wasm module. +pub struct Module { + ptr: *mut BinaryenRustModule, +} + +impl Module { + /// Creates a new wasm module from the LLVM-assembly provided (in a C string + /// format). + /// + /// The actual module creation can be tweaked through the various options in + /// `ModuleOptions` as well. Any errors are just returned as a bland string. + pub fn new(assembly: &CStr, opts: &ModuleOptions) -> Result { + unsafe { + let ptr = BinaryenRustModuleCreate(opts.ptr, assembly.as_ptr()); + if ptr.is_null() { + Err(format!("failed to create binaryen module")) + } else { + Ok(Module { ptr }) + } + } + } + + /// Returns the data of the serialized wasm module. This is a `foo.wasm` + /// file contents. + pub fn data(&self) -> &[u8] { + unsafe { + let ptr = BinaryenRustModulePtr(self.ptr); + let len = BinaryenRustModuleLen(self.ptr); + slice::from_raw_parts(ptr, len) + } + } +} + +impl Drop for Module { + fn drop(&mut self) { + unsafe { + BinaryenRustModuleFree(self.ptr); + } + } +} + +pub struct ModuleOptions { + ptr: *mut BinaryenRustModuleOptions, +} + +impl ModuleOptions { + pub fn new() -> ModuleOptions { + unsafe { + let ptr = BinaryenRustModuleOptionsCreate(); + ModuleOptions { ptr } + } + } + + /// Turns on or off debug info. + /// + /// From what I can tell this just creates a "names" section of the wasm + /// module which contains a table of the original function names. + pub fn debuginfo(&mut self, debug: bool) -> &mut Self { + unsafe { + BinaryenRustModuleOptionsSetDebugInfo(self.ptr, debug); + } + self + } + + /// Configures a `start` function for the module, to be executed when it's + /// loaded. + pub fn start(&mut self, func: &str) -> &mut Self { + let func = CString::new(func).unwrap(); + unsafe { + BinaryenRustModuleOptionsSetStart(self.ptr, func.as_ptr()); + } + self + } + + /// Configures how much stack is initially allocated for the module. 1MB is + /// probably good enough for now. + pub fn stack(&mut self, amt: u64) -> &mut Self { + unsafe { + BinaryenRustModuleOptionsSetStackAllocation(self.ptr, amt); + } + self + } + + /// Flags whether the initial memory should be imported or exported. So far + /// we export it by default. + pub fn import_memory(&mut self, import: bool) -> &mut Self { + unsafe { + BinaryenRustModuleOptionsSetImportMemory(self.ptr, import); + } + self + } +} + +impl Drop for ModuleOptions { + fn drop(&mut self) { + unsafe { + BinaryenRustModuleOptionsFree(self.ptr); + } + } +} + +enum BinaryenRustModule {} +enum BinaryenRustModuleOptions {} + +extern { + fn BinaryenRustModuleCreate(opts: *const BinaryenRustModuleOptions, + assembly: *const libc::c_char) + -> *mut BinaryenRustModule; + fn BinaryenRustModulePtr(module: *const BinaryenRustModule) -> *const u8; + fn BinaryenRustModuleLen(module: *const BinaryenRustModule) -> usize; + fn BinaryenRustModuleFree(module: *mut BinaryenRustModule); + + fn BinaryenRustModuleOptionsCreate() + -> *mut BinaryenRustModuleOptions; + fn BinaryenRustModuleOptionsSetDebugInfo(module: *mut BinaryenRustModuleOptions, + debuginfo: bool); + fn BinaryenRustModuleOptionsSetStart(module: *mut BinaryenRustModuleOptions, + start: *const libc::c_char); + fn BinaryenRustModuleOptionsSetStackAllocation( + module: *mut BinaryenRustModuleOptions, + stack: u64, + ); + fn BinaryenRustModuleOptionsSetImportMemory( + module: *mut BinaryenRustModuleOptions, + import: bool, + ); + fn BinaryenRustModuleOptionsFree(module: *mut BinaryenRustModuleOptions); +} diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 24c3963fbc4b3..cff584c16802e 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -1606,7 +1606,8 @@ extern "C" { PositionIndependentExecutable: bool, FunctionSections: bool, DataSections: bool, - TrapUnreachable: bool) + TrapUnreachable: bool, + Singlethread: bool) -> TargetMachineRef; pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef); pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef); diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index f797464c1f8f1..96102cad3ef5e 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -11,16 +11,17 @@ test = false [dependencies] bitflags = "1.0" -num_cpus = "1.0" flate2 = "0.2" jobserver = "0.1.5" log = "0.3" +num_cpus = "1.0" owning_ref = "0.3.3" -rustc-demangle = "0.1.4" rustc = { path = "../librustc" } +rustc-demangle = "0.1.4" rustc_allocator = { path = "../librustc_allocator" } rustc_apfloat = { path = "../librustc_apfloat" } rustc_back = { path = "../librustc_back" } +rustc_binaryen = { path = "../librustc_binaryen" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 1d2bfd001f1fe..89f182d178b94 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -27,7 +27,7 @@ use rustc::util::common::time; use rustc::util::fs::fix_windows_verbatim_for_gcc; use rustc::hir::def_id::CrateNum; use rustc_back::tempdir::TempDir; -use rustc_back::{PanicStrategy, RelroLevel}; +use rustc_back::{PanicStrategy, RelroLevel, LinkerFlavor}; use context::get_reloc_model; use llvm; @@ -245,12 +245,12 @@ pub fn each_linked_rlib(sess: &Session, /// It's unusual for a crate to not participate in LTO. Typically only /// compiler-specific and unstable crates have a reason to not participate in /// LTO. -pub fn ignored_for_lto(info: &CrateInfo, cnum: CrateNum) -> bool { - // `#![no_builtins]` crates don't participate in LTO because the state - // of builtins gets messed up (our crate isn't tagged with no builtins). - // Similarly `#![compiler_builtins]` doesn't participate because we want - // those builtins! - info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum) +pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool { + // If our target enables builtin function lowering in LLVM then the + // crates providing these functions don't participate in LTO (e.g. + // no_builtins or compiler builtins crates). + !sess.target.target.options.no_builtins && + (info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum)) } fn link_binary_output(sess: &Session, @@ -488,7 +488,7 @@ fn link_staticlib(sess: &Session, }); ab.add_rlib(path, &name.as_str(), - sess.lto() && !ignored_for_lto(&trans.crate_info, cnum), + sess.lto() && !ignored_for_lto(sess, &trans.crate_info, cnum), skip_object_files).unwrap(); all_native_libs.extend(trans.crate_info.native_libraries[&cnum].iter().cloned()); @@ -548,6 +548,11 @@ fn link_natively(sess: &Session, info!("preparing {:?} to {:?}", crate_type, out_filename); let flavor = sess.linker_flavor(); + // The "binaryen linker" is massively special, so skip everything below. + if flavor == LinkerFlavor::Binaryen { + return link_binaryen(sess, crate_type, out_filename, trans, tmpdir); + } + // The invocations of cc share some flags across platforms let (pname, mut cmd, envs) = get_linker(sess); // This will set PATH on windows @@ -1176,7 +1181,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib) }); - if (!sess.lto() || ignored_for_lto(&trans.crate_info, cnum)) && + if (!sess.lto() || ignored_for_lto(sess, &trans.crate_info, cnum)) && crate_type != config::CrateTypeDylib && !skip_native { cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath)); @@ -1229,8 +1234,10 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // file, then we don't need the object file as it's part of the // LTO module. Note that `#![no_builtins]` is excluded from LTO, // though, so we let that object file slide. - let skip_because_lto = sess.lto() && is_rust_object && - !trans.crate_info.is_no_builtins.contains(&cnum); + let skip_because_lto = sess.lto() && + is_rust_object && + (sess.target.target.options.no_builtins || + !trans.crate_info.is_no_builtins.contains(&cnum)); if skip_because_cfg_say_so || skip_because_lto { archive.remove_file(&f); @@ -1345,3 +1352,30 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { None => true, } } + +/// For now "linking with binaryen" is just "move the one module we generated in +/// the backend to the final output" +/// +/// That is, all the heavy lifting happens during the `back::write` phase. Here +/// we just clean up after that. +/// +/// Note that this is super temporary and "will not survive the night", this is +/// guaranteed to get removed as soon as a linker for wasm exists. This should +/// not be used for anything other than wasm. +fn link_binaryen(sess: &Session, + _crate_type: config::CrateType, + out_filename: &Path, + trans: &CrateTranslation, + _tmpdir: &Path) { + assert!(trans.allocator_module.is_none()); + assert_eq!(trans.modules.len(), 1); + + let object = trans.modules[0].object.as_ref().expect("object must exist"); + let res = fs::hard_link(object, out_filename) + .or_else(|_| fs::copy(object, out_filename).map(|_| ())); + if let Err(e) = res { + sess.fatal(&format!("failed to create `{}`: {}", + out_filename.display(), + e)); + } +} diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 51f89110eb4ae..aa29c3cc12058 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -77,6 +77,9 @@ impl LinkerInfo { is_ld: true, }) as Box } + LinkerFlavor::Binaryen => { + panic!("can't instantiate binaryen linker") + } } } } diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 132b8fa7acfb0..fa6fe2e9e93ef 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -21,6 +21,7 @@ use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; use rustc::util::nodemap::FxHashMap; use rustc_allocator::ALLOCATOR_METHODS; +use rustc_back::LinkerFlavor; use syntax::attr; pub type ExportedSymbols = FxHashMap< @@ -154,12 +155,26 @@ pub fn provide_extern(providers: &mut Providers) { let special_runtime_crate = tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum); + // Dealing with compiler-builtins and wasm right now is super janky. + // There's no linker! As a result we need all of the compiler-builtins + // exported symbols to make their way through all the way to the end of + // compilation. We want to make sure that LLVM doesn't remove them as + // well because we may or may not need them in the final output + // artifact. For now just force them to always get exported at the C + // layer, and we'll worry about gc'ing them later. + let compiler_builtins_and_binaryen = + tcx.is_compiler_builtins(cnum) && + tcx.sess.linker_flavor() == LinkerFlavor::Binaryen; + let mut crate_exports: Vec<_> = tcx .exported_symbol_ids(cnum) .iter() .map(|&def_id| { let name = tcx.symbol_name(Instance::mono(tcx, def_id)); - let export_level = if special_runtime_crate { + let export_level = if compiler_builtins_and_binaryen && + tcx.contains_extern_indicator(def_id) { + SymbolExportLevel::C + } else if special_runtime_crate { // We can probably do better here by just ensuring that // it has hidden visibility rather than public // visibility, as this is primarily here to ensure it's diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index e443f13a7a1ca..da67940abcb77 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -22,6 +22,7 @@ use rustc::session::config::{self, OutputFilenames, OutputType, OutputTypes, Pas AllPasses, Sanitizer}; use rustc::session::Session; use rustc::util::nodemap::FxHashMap; +use rustc_back::LinkerFlavor; use time_graph::{self, TimeGraph, Timeline}; use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; @@ -47,7 +48,7 @@ use std::any::Any; use std::ffi::{CString, CStr}; use std::fs::{self, File}; use std::io; -use std::io::Write; +use std::io::{Read, Write}; use std::mem; use std::path::{Path, PathBuf}; use std::str; @@ -186,6 +187,8 @@ pub fn target_machine_factory(sess: &Session) } }; + let singlethread = sess.target.target.options.singlethread; + let triple = &sess.target.target.llvm_target; let triple = CString::new(triple.as_bytes()).unwrap(); @@ -210,6 +213,7 @@ pub fn target_machine_factory(sess: &Session) ffunction_sections, fdata_sections, trap_unreachable, + singlethread, ) }; @@ -287,7 +291,7 @@ impl ModuleConfig { fn set_flags(&mut self, sess: &Session, no_builtins: bool) { self.no_verify = sess.no_verify(); self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes; - self.no_builtins = no_builtins; + self.no_builtins = no_builtins || sess.target.target.options.no_builtins; self.time_passes = sess.time_passes(); self.inline_threshold = sess.opts.cg.inline_threshold; self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode; @@ -330,6 +334,9 @@ pub struct CodegenContext { pub tm_factory: Arc Result + Send + Sync>, pub msvc_imps_needed: bool, pub target_pointer_width: String, + binaryen_linker: bool, + debuginfo: config::DebugInfoLevel, + wasm_import_memory: bool, // Number of cgus excluding the allocator/metadata modules pub total_cgus: usize, @@ -625,14 +632,21 @@ unsafe fn codegen(cgcx: &CodegenContext, f(cpm) } + // If we're going to generate wasm code from the assembly that llvm + // generates then we'll be transitively affecting a ton of options below. + // This only happens on the wasm target now. + let asm2wasm = cgcx.binaryen_linker && + !cgcx.crate_types.contains(&config::CrateTypeRlib) && + mtrans.kind == ModuleKind::Regular; + // Change what we write and cleanup based on whether obj files are // just llvm bitcode. In that case write bitcode, and possibly // delete the bitcode if it wasn't requested. Don't generate the // machine code, instead copy the .o file from the .bc - let write_bc = config.emit_bc || config.obj_is_bitcode; - let rm_bc = !config.emit_bc && config.obj_is_bitcode; - let write_obj = config.emit_obj && !config.obj_is_bitcode; - let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; + let write_bc = config.emit_bc || (config.obj_is_bitcode && !asm2wasm); + let rm_bc = !config.emit_bc && config.obj_is_bitcode && !asm2wasm; + let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm2wasm; + let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode && !asm2wasm; let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); @@ -711,7 +725,7 @@ unsafe fn codegen(cgcx: &CodegenContext, timeline.record("ir"); } - if config.emit_asm { + if config.emit_asm || (asm2wasm && config.emit_obj) { let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); // We can't use the same module for asm and binary output, because that triggers @@ -732,7 +746,15 @@ unsafe fn codegen(cgcx: &CodegenContext, timeline.record("asm"); } - if write_obj { + if asm2wasm && config.emit_obj { + let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + binaryen_assemble(cgcx, diag_handler, &assembly, &obj_out); + timeline.record("binaryen"); + + if !config.emit_asm { + drop(fs::remove_file(&assembly)); + } + } else if write_obj { with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(diag_handler, tm, cpm, llmod, &obj_out, llvm::FileType::ObjectFile) @@ -764,6 +786,44 @@ unsafe fn codegen(cgcx: &CodegenContext, &cgcx.output_filenames)) } +/// Translates the LLVM-generated `assembly` on the filesystem into a wasm +/// module using binaryen, placing the output at `object`. +/// +/// In this case the "object" is actually a full and complete wasm module. We +/// won't actually be doing anything else to the output for now. This is all +/// pretty janky and will get removed as soon as a linker for wasm exists. +fn binaryen_assemble(cgcx: &CodegenContext, + handler: &Handler, + assembly: &Path, + object: &Path) { + use rustc_binaryen::{Module, ModuleOptions}; + + let input = File::open(&assembly).and_then(|mut f| { + let mut contents = Vec::new(); + f.read_to_end(&mut contents)?; + Ok(CString::new(contents)?) + }); + let mut options = ModuleOptions::new(); + if cgcx.debuginfo != config::NoDebugInfo { + options.debuginfo(true); + } + if cgcx.crate_types.contains(&config::CrateTypeExecutable) { + options.start("main"); + } + options.stack(1024 * 1024); + options.import_memory(cgcx.wasm_import_memory); + let assembled = input.and_then(|input| { + Module::new(&input, &options) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) + }); + let err = assembled.and_then(|binary| { + File::create(&object).and_then(|mut f| f.write_all(binary.data())) + }); + if let Err(e) = err { + handler.err(&format!("failed to run binaryen assembler: {}", e)); + } +} + pub struct CompiledModules { pub modules: Vec, pub metadata_module: CompiledModule, @@ -1318,17 +1378,33 @@ fn start_executing_work(tcx: TyCtxt, let mut each_linked_rlib_for_lto = Vec::new(); drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| { - if link::ignored_for_lto(crate_info, cnum) { + if link::ignored_for_lto(sess, crate_info, cnum) { return } each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); })); + let crate_types = sess.crate_types.borrow(); + let only_rlib = crate_types.len() == 1 && + crate_types[0] == config::CrateTypeRlib; + + let wasm_import_memory = + attr::contains_name(&tcx.hir.krate().attrs, "wasm_import_memory"); + let cgcx = CodegenContext { crate_types: sess.crate_types.borrow().clone(), each_linked_rlib_for_lto, - lto: sess.lto(), - thinlto: sess.opts.debugging_opts.thinlto, + // If we're only building an rlibc then allow the LTO flag to be passed + // but don't actually do anything, the full LTO will happen later + lto: sess.lto() && !only_rlib, + + // Enable ThinLTO if requested, but only if the target we're compiling + // for doesn't require full LTO. Some targets require one LLVM module + // (they effectively don't have a linker) so it's up to us to use LTO to + // link everything together. + thinlto: sess.opts.debugging_opts.thinlto && + !sess.target.target.options.requires_lto, + no_landing_pads: sess.no_landing_pads(), save_temps: sess.opts.cg.save_temps, opts: Arc::new(sess.opts.clone()), @@ -1349,6 +1425,9 @@ fn start_executing_work(tcx: TyCtxt, total_cgus, msvc_imps_needed: msvc_imps_needed(tcx), target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(), + binaryen_linker: tcx.sess.linker_flavor() == LinkerFlavor::Binaryen, + debuginfo: tcx.sess.opts.debuginfo, + wasm_import_memory: wasm_import_memory, }; // This is the "main loop" of parallel work happening for parallel codegen. diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 96e11d366423a..ae25e7d94bffa 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -43,18 +43,19 @@ extern crate flate2; extern crate libc; extern crate owning_ref; #[macro_use] extern crate rustc; +extern crate jobserver; +extern crate num_cpus; extern crate rustc_allocator; extern crate rustc_apfloat; extern crate rustc_back; +extern crate rustc_binaryen; +extern crate rustc_const_math; extern crate rustc_data_structures; +extern crate rustc_demangle; extern crate rustc_incremental; extern crate rustc_llvm as llvm; extern crate rustc_platform_intrinsics as intrinsics; -extern crate rustc_const_math; extern crate rustc_trans_utils; -extern crate rustc_demangle; -extern crate jobserver; -extern crate num_cpus; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs index 47484488fb8e8..c1e670cc7caf5 100644 --- a/src/librustc_trans_utils/link.rs +++ b/src/librustc_trans_utils/link.rs @@ -163,15 +163,30 @@ pub fn default_output_for_target(sess: &Session) -> config::CrateType { /// Checks if target supports crate_type as output pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType) -> bool { - match (sess.target.target.options.dynamic_linking, - sess.target.target.options.executables, crate_type) { - (false, _, config::CrateTypeCdylib) | - (false, _, config::CrateTypeDylib) | - (false, _, config::CrateTypeProcMacro) => true, - (true, _, config::CrateTypeCdylib) | - (true, _, config::CrateTypeDylib) => sess.crt_static() && - !sess.target.target.options.crt_static_allows_dylibs, - (_, false, config::CrateTypeExecutable) => true, - _ => false + match crate_type { + config::CrateTypeCdylib | + config::CrateTypeDylib | + config::CrateTypeProcMacro => { + if !sess.target.target.options.dynamic_linking { + return true + } + if sess.crt_static() && !sess.target.target.options.crt_static_allows_dylibs { + return true + } + } + _ => {} } + if sess.target.target.options.only_cdylib { + match crate_type { + config::CrateTypeProcMacro | config::CrateTypeDylib => return true, + _ => {} + } + } + if !sess.target.target.options.executables { + if crate_type == config::CrateTypeExecutable { + return true + } + } + + false } diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 0e6214ea04fc0..06f11c8deb458 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -19,8 +19,12 @@ use build_helper::{run, native_lib_boilerplate, BuildExpectation}; fn main() { let target = env::var("TARGET").expect("TARGET was not set"); let host = env::var("HOST").expect("HOST was not set"); - if cfg!(feature = "backtrace") && !target.contains("msvc") && - !target.contains("emscripten") && !target.contains("fuchsia") { + if cfg!(feature = "backtrace") && + !target.contains("msvc") && + !target.contains("emscripten") && + !target.contains("fuchsia") && + !target.contains("wasm32") + { let _ = build_libbacktrace(&host, &target); } diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 7ec6124dfa462..14f0edc369058 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -26,7 +26,6 @@ use num::FpCategory; #[cfg(not(test))] use sys::cmath; - #[stable(feature = "rust1", since = "1.0.0")] pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 6318e2e40875f..9d0373404aaa7 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -663,3 +663,39 @@ pub mod builtin { #[macro_export] macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) } } + +/// A macro for defining #[cfg] if-else statements. +/// +/// This is similar to the `if/elif` C preprocessor macro by allowing definition +/// of a cascade of `#[cfg]` cases, emitting the implementation which matches +/// first. +/// +/// This allows you to conveniently provide a long list #[cfg]'d blocks of code +/// without having to rewrite each clause multiple times. +macro_rules! cfg_if { + ($( + if #[cfg($($meta:meta),*)] { $($it:item)* } + ) else * else { + $($it2:item)* + }) => { + __cfg_if_items! { + () ; + $( ( ($($meta),*) ($($it)*) ), )* + ( () ($($it2)*) ), + } + } +} + +macro_rules! __cfg_if_items { + (($($not:meta,)*) ; ) => {}; + (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { + __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* } + __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } + } +} + +macro_rules! __cfg_if_apply { + ($m:meta, $($it:item)*) => { + $(#[$m] $it)* + } +} diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index d91c2073a23a8..27d6433b329bb 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -46,6 +46,9 @@ mod imp; #[path = "redox/mod.rs"] mod imp; +#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] +#[path = "wasm/mod.rs"] +mod imp; // Import essential modules from both platforms when documenting. diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs new file mode 100644 index 0000000000000..d2a4a7b19d548 --- /dev/null +++ b/src/libstd/sys/wasm/args.rs @@ -0,0 +1,90 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi::OsString; +use marker::PhantomData; +use mem; +use vec; + +pub unsafe fn init(_argc: isize, _argv: *const *const u8) { + // On wasm these should always be null, so there's nothing for us to do here +} + +pub unsafe fn cleanup() { +} + +pub fn args() -> Args { + // When the runtime debugging is enabled we'll link to some extra runtime + // functions to actually implement this. These are for now just implemented + // in a node.js script but they're off by default as they're sort of weird + // in a web-wasm world. + if !super::DEBUG { + return Args { + iter: Vec::new().into_iter(), + _dont_send_or_sync_me: PhantomData, + } + } + + // You'll find the definitions of these in `src/etc/wasm32-shim.js`. These + // are just meant for debugging and should not be relied on. + extern { + fn rust_wasm_args_count() -> usize; + fn rust_wasm_args_arg_size(a: usize) -> usize; + fn rust_wasm_args_arg_fill(a: usize, ptr: *mut u8); + } + + unsafe { + let cnt = rust_wasm_args_count(); + let mut v = Vec::with_capacity(cnt); + for i in 0..cnt { + let n = rust_wasm_args_arg_size(i); + let mut data = vec![0; n]; + rust_wasm_args_arg_fill(i, data.as_mut_ptr()); + v.push(mem::transmute::, OsString>(data)); + } + Args { + iter: v.into_iter(), + _dont_send_or_sync_me: PhantomData, + } + } +} + +pub struct Args { + iter: vec::IntoIter, + _dont_send_or_sync_me: PhantomData<*mut ()>, +} + +impl Args { + pub fn inner_debug(&self) -> &[OsString] { + self.iter.as_slice() + } +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl ExactSizeIterator for Args { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} diff --git a/src/libstd/sys/wasm/backtrace.rs b/src/libstd/sys/wasm/backtrace.rs new file mode 100644 index 0000000000000..9a8c48ff29fc7 --- /dev/null +++ b/src/libstd/sys/wasm/backtrace.rs @@ -0,0 +1,37 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use io; +use sys::unsupported; +use sys_common::backtrace::Frame; + +pub struct BacktraceContext; + +pub fn unwind_backtrace(_frames: &mut [Frame]) + -> io::Result<(usize, BacktraceContext)> +{ + unsupported() +} + +pub fn resolve_symname(_frame: Frame, + _callback: F, + _: &BacktraceContext) -> io::Result<()> + where F: FnOnce(Option<&str>) -> io::Result<()> +{ + unsupported() +} + +pub fn foreach_symbol_fileline(_: Frame, + _: F, + _: &BacktraceContext) -> io::Result + where F: FnMut(&[u8], u32) -> io::Result<()> +{ + unsupported() +} diff --git a/src/libstd/sys/wasm/cmath.rs b/src/libstd/sys/wasm/cmath.rs new file mode 100644 index 0000000000000..87ac2091cad41 --- /dev/null +++ b/src/libstd/sys/wasm/cmath.rs @@ -0,0 +1,119 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[inline] +pub unsafe fn cbrtf(n: f32) -> f32 { + f64::cbrt(n as f64) as f32 +} + +#[inline] +pub unsafe fn expm1f(n: f32) -> f32 { + f64::exp_m1(n as f64) as f32 +} + +#[inline] +#[allow(deprecated)] +pub unsafe fn fdimf(a: f32, b: f32) -> f32 { + f64::abs_sub(a as f64, b as f64) as f32 +} + +#[inline] +pub unsafe fn log1pf(n: f32) -> f32 { + f64::ln_1p(n as f64) as f32 +} + +#[inline] +pub unsafe fn hypotf(x: f32, y: f32) -> f32 { + f64::hypot(x as f64, y as f64) as f32 +} + +#[inline] +pub unsafe fn acosf(n: f32) -> f32 { + f64::acos(n as f64) as f32 +} + +#[inline] +pub unsafe fn asinf(n: f32) -> f32 { + f64::asin(n as f64) as f32 +} + +#[inline] +pub unsafe fn atan2f(n: f32, b: f32) -> f32 { + f64::atan2(n as f64, b as f64) as f32 +} + +#[inline] +pub unsafe fn atanf(n: f32) -> f32 { + f64::atan(n as f64) as f32 +} + +#[inline] +pub unsafe fn coshf(n: f32) -> f32 { + f64::cosh(n as f64) as f32 +} + +#[inline] +pub unsafe fn sinhf(n: f32) -> f32 { + f64::sinh(n as f64) as f32 +} + +#[inline] +pub unsafe fn tanf(n: f32) -> f32 { + f64::tan(n as f64) as f32 +} + +#[inline] +pub unsafe fn tanhf(n: f32) -> f32 { + f64::tanh(n as f64) as f32 +} + +// Right now all these functions, the f64 version of the functions above, all +// shell out to random names. These names aren't actually defined anywhere, per +// se, but we need this to compile somehow. +// +// The idea with this is that when you're using wasm then, for now, we have no +// way of providing an implementation of these which delegates to a "correct" +// implementation. For example most wasm applications probably just want to +// delegate to the javascript `Math` object and its related functions, but wasm +// doesn't currently have the ability to seamlessly do that (when you +// instantiate a module you have to set that up). +// +// As a result these are just defined here with "hopefully helpful" names. The +// symbols won't ever be needed or show up unless these functions are called, +// and hopefully when they're called the errors are self-explanatory enough to +// figure out what's going on. + +extern { + #[link_name = "Math_acos"] + pub fn acos(n: f64) -> f64; + #[link_name = "Math_asin"] + pub fn asin(n: f64) -> f64; + #[link_name = "Math_atan"] + pub fn atan(n: f64) -> f64; + #[link_name = "Math_atan2"] + pub fn atan2(a: f64, b: f64) -> f64; + #[link_name = "Math_cbrt"] + pub fn cbrt(n: f64) -> f64; + #[link_name = "Math_cosh"] + pub fn cosh(n: f64) -> f64; + #[link_name = "Math_expm1"] + pub fn expm1(n: f64) -> f64; + pub fn fdim(a: f64, b: f64) -> f64; + #[link_name = "Math_log1p"] + pub fn log1p(n: f64) -> f64; + #[link_name = "Math_sinh"] + pub fn sinh(n: f64) -> f64; + #[link_name = "Math_tan"] + pub fn tan(n: f64) -> f64; + #[link_name = "Math_tanh"] + pub fn tanh(n: f64) -> f64; + #[link_name = "Math_hypot"] + pub fn hypot(x: f64, y: f64) -> f64; +} diff --git a/src/libstd/sys/wasm/condvar.rs b/src/libstd/sys/wasm/condvar.rs new file mode 100644 index 0000000000000..afa7afeef5988 --- /dev/null +++ b/src/libstd/sys/wasm/condvar.rs @@ -0,0 +1,43 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use sys::mutex::Mutex; +use time::Duration; + +pub struct Condvar { } + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { } + } + + #[inline] + pub unsafe fn init(&mut self) {} + + #[inline] + pub unsafe fn notify_one(&self) { + } + + #[inline] + pub unsafe fn notify_all(&self) { + } + + pub unsafe fn wait(&self, _mutex: &Mutex) { + panic!("can't block with web assembly") + } + + pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + panic!("can't block with web assembly"); + } + + #[inline] + pub unsafe fn destroy(&self) { + } +} diff --git a/src/libstd/sys/wasm/env.rs b/src/libstd/sys/wasm/env.rs new file mode 100644 index 0000000000000..1422042bd0228 --- /dev/null +++ b/src/libstd/sys/wasm/env.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod os { + pub const FAMILY: &'static str = ""; + pub const OS: &'static str = ""; + pub const DLL_PREFIX: &'static str = ""; + pub const DLL_SUFFIX: &'static str = ".wasm"; + pub const DLL_EXTENSION: &'static str = "wasm"; + pub const EXE_SUFFIX: &'static str = ".wasm"; + pub const EXE_EXTENSION: &'static str = "wasm"; +} diff --git a/src/libstd/sys/wasm/fs.rs b/src/libstd/sys/wasm/fs.rs new file mode 100644 index 0000000000000..b3c70a6685a6c --- /dev/null +++ b/src/libstd/sys/wasm/fs.rs @@ -0,0 +1,304 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi::OsString; +use fmt; +use hash::{Hash, Hasher}; +use io::{self, SeekFrom}; +use path::{Path, PathBuf}; +use sys::time::SystemTime; +use sys::{unsupported, Void}; + +pub struct File(Void); + +pub struct FileAttr(Void); + +pub struct ReadDir(Void); + +pub struct DirEntry(Void); + +#[derive(Clone, Debug)] +pub struct OpenOptions { } + +pub struct FilePermissions(Void); + +pub struct FileType(Void); + +#[derive(Debug)] +pub struct DirBuilder { } + +impl FileAttr { + pub fn size(&self) -> u64 { + match self.0 {} + } + + pub fn perm(&self) -> FilePermissions { + match self.0 {} + } + + pub fn file_type(&self) -> FileType { + match self.0 {} + } + + pub fn modified(&self) -> io::Result { + match self.0 {} + } + + pub fn accessed(&self) -> io::Result { + match self.0 {} + } + + pub fn created(&self) -> io::Result { + match self.0 {} + } +} + +impl Clone for FileAttr { + fn clone(&self) -> FileAttr { + match self.0 {} + } +} + +impl FilePermissions { + pub fn readonly(&self) -> bool { + match self.0 {} + } + + pub fn set_readonly(&mut self, _readonly: bool) { + match self.0 {} + } +} + +impl Clone for FilePermissions { + fn clone(&self) -> FilePermissions { + match self.0 {} + } +} + +impl PartialEq for FilePermissions { + fn eq(&self, _other: &FilePermissions) -> bool { + match self.0 {} + } +} + +impl Eq for FilePermissions { +} + +impl fmt::Debug for FilePermissions { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +impl FileType { + pub fn is_dir(&self) -> bool { + match self.0 {} + } + + pub fn is_file(&self) -> bool { + match self.0 {} + } + + pub fn is_symlink(&self) -> bool { + match self.0 {} + } +} + +impl Clone for FileType { + fn clone(&self) -> FileType { + match self.0 {} + } +} + +impl Copy for FileType {} + +impl PartialEq for FileType { + fn eq(&self, _other: &FileType) -> bool { + match self.0 {} + } +} + +impl Eq for FileType { +} + +impl Hash for FileType { + fn hash(&self, _h: &mut H) { + match self.0 {} + } +} + +impl fmt::Debug for FileType { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +impl fmt::Debug for ReadDir { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +impl Iterator for ReadDir { + type Item = io::Result; + + fn next(&mut self) -> Option> { + match self.0 {} + } +} + +impl DirEntry { + pub fn path(&self) -> PathBuf { + match self.0 {} + } + + pub fn file_name(&self) -> OsString { + match self.0 {} + } + + pub fn metadata(&self) -> io::Result { + match self.0 {} + } + + pub fn file_type(&self) -> io::Result { + match self.0 {} + } +} + +impl OpenOptions { + pub fn new() -> OpenOptions { + OpenOptions { } + } + + pub fn read(&mut self, _read: bool) { } + pub fn write(&mut self, _write: bool) { } + pub fn append(&mut self, _append: bool) { } + pub fn truncate(&mut self, _truncate: bool) { } + pub fn create(&mut self, _create: bool) { } + pub fn create_new(&mut self, _create_new: bool) { } +} + +impl File { + pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result { + unsupported() + } + + pub fn file_attr(&self) -> io::Result { + match self.0 {} + } + + pub fn fsync(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn datasync(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn truncate(&self, _size: u64) -> io::Result<()> { + match self.0 {} + } + + pub fn read(&self, _buf: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn write(&self, _buf: &[u8]) -> io::Result { + match self.0 {} + } + + pub fn flush(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn seek(&self, _pos: SeekFrom) -> io::Result { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result { + match self.0 {} + } + + pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { + match self.0 {} + } + + pub fn diverge(&self) -> ! { + match self.0 {} + } +} + +impl DirBuilder { + pub fn new() -> DirBuilder { + DirBuilder { } + } + + pub fn mkdir(&self, _p: &Path) -> io::Result<()> { + unsupported() + } +} + +impl fmt::Debug for File { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub fn readdir(_p: &Path) -> io::Result { + unsupported() +} + +pub fn unlink(_p: &Path) -> io::Result<()> { + unsupported() +} + +pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { + unsupported() +} + +pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> { + match perm.0 {} +} + +pub fn rmdir(_p: &Path) -> io::Result<()> { + unsupported() +} + +pub fn remove_dir_all(_path: &Path) -> io::Result<()> { + unsupported() +} + +pub fn readlink(_p: &Path) -> io::Result { + unsupported() +} + +pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { + unsupported() +} + +pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { + unsupported() +} + +pub fn stat(_p: &Path) -> io::Result { + unsupported() +} + +pub fn lstat(_p: &Path) -> io::Result { + unsupported() +} + +pub fn canonicalize(_p: &Path) -> io::Result { + unsupported() +} + +pub fn copy(_from: &Path, _to: &Path) -> io::Result { + unsupported() +} diff --git a/src/libstd/sys/wasm/memchr.rs b/src/libstd/sys/wasm/memchr.rs new file mode 100644 index 0000000000000..e611d94af30b1 --- /dev/null +++ b/src/libstd/sys/wasm/memchr.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use sys_common::memchr::fallback::{memchr, memrchr}; diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs new file mode 100644 index 0000000000000..b838dbafd6f0c --- /dev/null +++ b/src/libstd/sys/wasm/mod.rs @@ -0,0 +1,104 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! System bindings for the wasm/web platform +//! +//! This module contains the facade (aka platform-specific) implementations of +//! OS level functionality for wasm. Note that this wasm is *not* the emscripten +//! wasm, so we have no runtime here. +//! +//! This is all super highly experimental and not actually intended for +//! wide/production use yet, it's still all in the experimental category. This +//! will likely change over time. +//! +//! Currently all functions here are basically stubs that immediately return +//! errors. The hope is that with a portability lint we can turn actually just +//! remove all this and just omit parts of the standard library if we're +//! compiling for wasm. That way it's a compile time error for something that's +//! guaranteed to be a runtime error! + +use io; +use os::raw::c_char; + +// Right now the wasm backend doesn't even have the ability to print to the +// console by default. Wasm can't import anything from JS! (you have to +// explicitly provide it). +// +// Sometimes that's a real bummer, though, so this flag can be set to `true` to +// enable calling various shims defined in `src/etc/wasm32-shim.js` which should +// help receive debug output and see what's going on. In general this flag +// currently controls "will we call out to our own defined shims in node.js", +// and this flag should always be `false` for release builds. +const DEBUG: bool = false; + +pub mod args; +pub mod backtrace; +pub mod cmath; +pub mod condvar; +pub mod env; +pub mod fs; +pub mod memchr; +pub mod mutex; +pub mod net; +pub mod os; +pub mod os_str; +pub mod path; +pub mod pipe; +pub mod process; +pub mod rwlock; +pub mod stack_overflow; +pub mod thread; +pub mod thread_local; +pub mod time; +pub mod stdio; + +#[cfg(not(test))] +pub fn init() { +} + +pub fn unsupported() -> io::Result { + Err(unsupported_err()) +} + +pub fn unsupported_err() -> io::Error { + io::Error::new(io::ErrorKind::Other, + "operation not supported on wasm yet") +} + +pub fn decode_error_kind(_code: i32) -> io::ErrorKind { + io::ErrorKind::Other +} + +// This enum is used as the storage for a bunch of types which can't actually +// exist. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub enum Void {} + +pub unsafe fn strlen(mut s: *const c_char) -> usize { + let mut n = 0; + while *s != 0 { + n += 1; + s = s.offset(1); + } + return n +} + +pub unsafe fn abort_internal() -> ! { + ::intrinsics::abort(); +} + +// We don't have randomness yet, but I totally used a random number generator to +// generate these numbers. +// +// More seriously though this is just for DOS protection in hash maps. It's ok +// if we don't do that on wasm just yet. +pub fn hashmap_random_keys() -> (u64, u64) { + (1, 2) +} diff --git a/src/libstd/sys/wasm/mutex.rs b/src/libstd/sys/wasm/mutex.rs new file mode 100644 index 0000000000000..4197bdcc80839 --- /dev/null +++ b/src/libstd/sys/wasm/mutex.rs @@ -0,0 +1,79 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cell::UnsafeCell; + +pub struct Mutex { + locked: UnsafeCell, +} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} // no threads on wasm + +impl Mutex { + pub const fn new() -> Mutex { + Mutex { locked: UnsafeCell::new(false) } + } + + #[inline] + pub unsafe fn init(&mut self) { + } + + #[inline] + pub unsafe fn lock(&self) { + let locked = self.locked.get(); + assert!(!*locked, "cannot recursively acquire mutex"); + *locked = true; + } + + #[inline] + pub unsafe fn unlock(&self) { + *self.locked.get() = false; + } + + #[inline] + pub unsafe fn try_lock(&self) -> bool { + let locked = self.locked.get(); + if *locked { + false + } else { + *locked = true; + true + } + } + + #[inline] + pub unsafe fn destroy(&self) { + } +} + +// All empty stubs because wasm has no threads yet, so lock acquisition always +// succeeds. +pub struct ReentrantMutex { +} + +impl ReentrantMutex { + pub unsafe fn uninitialized() -> ReentrantMutex { + ReentrantMutex { } + } + + pub unsafe fn init(&mut self) {} + + pub unsafe fn lock(&self) {} + + #[inline] + pub unsafe fn try_lock(&self) -> bool { + true + } + + pub unsafe fn unlock(&self) {} + + pub unsafe fn destroy(&self) {} +} diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs new file mode 100644 index 0000000000000..e7476ab37f7c8 --- /dev/null +++ b/src/libstd/sys/wasm/net.rs @@ -0,0 +1,337 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use fmt; +use io; +use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr}; +use time::Duration; +use sys::{unsupported, Void}; + +pub struct TcpStream(Void); + +impl TcpStream { + pub fn connect(_: &SocketAddr) -> io::Result { + unsupported() + } + + pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result { + unsupported() + } + + pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { + match self.0 {} + } + + pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { + match self.0 {} + } + + pub fn read_timeout(&self) -> io::Result> { + match self.0 {} + } + + pub fn write_timeout(&self) -> io::Result> { + match self.0 {} + } + + pub fn peek(&self, _: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn read(&self, _: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn write(&self, _: &[u8]) -> io::Result { + match self.0 {} + } + + pub fn peer_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn socket_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result { + match self.0 {} + } + + pub fn set_nodelay(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn nodelay(&self) -> io::Result { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for TcpStream { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub struct TcpListener(Void); + +impl TcpListener { + pub fn bind(_: &SocketAddr) -> io::Result { + unsupported() + } + + pub fn socket_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result { + match self.0 {} + } + + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn only_v6(&self) -> io::Result { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for TcpListener { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub struct UdpSocket(Void); + +impl UdpSocket { + pub fn bind(_: &SocketAddr) -> io::Result { + unsupported() + } + + pub fn socket_addr(&self) -> io::Result { + match self.0 {} + } + + pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + match self.0 {} + } + + pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + match self.0 {} + } + + pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result { + match self.0 {} + } + + pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { + match self.0 {} + } + + pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { + match self.0 {} + } + + pub fn read_timeout(&self) -> io::Result> { + match self.0 {} + } + + pub fn write_timeout(&self) -> io::Result> { + match self.0 {} + } + + pub fn set_broadcast(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn broadcast(&self) -> io::Result { + match self.0 {} + } + + pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_loop_v4(&self) -> io::Result { + match self.0 {} + } + + pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_ttl_v4(&self) -> io::Result { + match self.0 {} + } + + pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_loop_v6(&self) -> io::Result { + match self.0 {} + } + + pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) + -> io::Result<()> { + match self.0 {} + } + + pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) + -> io::Result<()> { + match self.0 {} + } + + pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) + -> io::Result<()> { + match self.0 {} + } + + pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) + -> io::Result<()> { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn recv(&self, _: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn peek(&self, _: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn send(&self, _: &[u8]) -> io::Result { + match self.0 {} + } + + pub fn connect(&self, _: &SocketAddr) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for UdpSocket { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub struct LookupHost(Void); + +impl Iterator for LookupHost { + type Item = SocketAddr; + fn next(&mut self) -> Option { + match self.0 {} + } +} + +pub fn lookup_host(_: &str) -> io::Result { + unsupported() +} + +#[allow(bad_style)] +pub mod netc { + pub const AF_INET: u8 = 0; + pub const AF_INET6: u8 = 1; + pub type sa_family_t = u8; + + #[derive(Copy, Clone)] + pub struct in_addr { + pub s_addr: u32, + } + + #[derive(Copy, Clone)] + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: u16, + pub sin_addr: in_addr, + } + + #[derive(Copy, Clone)] + pub struct in6_addr { + pub s6_addr: [u8; 16], + } + + #[derive(Copy, Clone)] + pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: u16, + pub sin6_addr: in6_addr, + pub sin6_flowinfo: u32, + pub sin6_scope_id: u32, + } + + #[derive(Copy, Clone)] + pub struct sockaddr { + } + + pub type socklen_t = usize; +} diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs new file mode 100644 index 0000000000000..c98030f7ebf53 --- /dev/null +++ b/src/libstd/sys/wasm/os.rs @@ -0,0 +1,136 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::intrinsics; + +use error::Error as StdError; +use ffi::{OsString, OsStr}; +use fmt; +use io; +use mem; +use path::{self, PathBuf}; +use str; +use sys::{unsupported, Void}; + +pub fn errno() -> i32 { + 0 +} + +pub fn error_string(_errno: i32) -> String { + format!("operation successful") +} + +pub fn getcwd() -> io::Result { + unsupported() +} + +pub fn chdir(_: &path::Path) -> io::Result<()> { + unsupported() +} + +pub struct SplitPaths<'a>(&'a Void); + +pub fn split_paths(_unparsed: &OsStr) -> SplitPaths { + panic!("unsupported") +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = PathBuf; + fn next(&mut self) -> Option { + match *self.0 {} + } +} + +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths(_paths: I) -> Result + where I: Iterator, T: AsRef +{ + Err(JoinPathsError) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "not supported on wasm yet".fmt(f) + } +} + +impl StdError for JoinPathsError { + fn description(&self) -> &str { + "not supported on wasm yet" + } +} + +pub fn current_exe() -> io::Result { + unsupported() +} + +pub struct Env(Void); + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + match self.0 {} + } +} + +pub fn env() -> Env { + panic!("not supported on web assembly") +} + +pub fn getenv(k: &OsStr) -> io::Result> { + // If we're debugging the runtime then we actually probe node.js to ask for + // the value of environment variables to help provide inputs to programs. + // The `extern` shims here are defined in `src/etc/wasm32-shim.js` and are + // intended for debugging only, you should not rely on them. + if !super::DEBUG { + return Ok(None) + } + + extern { + fn rust_wasm_getenv_len(k: *const u8, kl: usize) -> isize; + fn rust_wasm_getenv_data(k: *const u8, kl: usize, v: *mut u8); + } + unsafe { + let k: &[u8] = mem::transmute(k); + let n = rust_wasm_getenv_len(k.as_ptr(), k.len()); + if n == -1 { + return Ok(None) + } + let mut data = vec![0; n as usize]; + rust_wasm_getenv_data(k.as_ptr(), k.len(), data.as_mut_ptr()); + Ok(Some(mem::transmute(data))) + } +} + +pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> { + unsupported() +} + +pub fn unsetenv(_n: &OsStr) -> io::Result<()> { + unsupported() +} + +pub fn temp_dir() -> PathBuf { + panic!("no filesystem on wasm") +} + +pub fn home_dir() -> Option { + None +} + +pub fn exit(_code: i32) -> ! { + unsafe { intrinsics::abort() } +} + +pub fn getpid() -> u32 { + panic!("no pids on wasm") +} diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs new file mode 100644 index 0000000000000..c5908a7a8dc22 --- /dev/null +++ b/src/libstd/sys/wasm/os_str.rs @@ -0,0 +1,159 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// The underlying OsString/OsStr implementation on Unix systems: just +/// a `Vec`/`[u8]`. + +use borrow::Cow; +use fmt; +use str; +use mem; +use sys_common::{AsInner, IntoInner}; +use std_unicode::lossy::Utf8Lossy; + +#[derive(Clone, Hash)] +pub struct Buf { + pub inner: Vec +} + +pub struct Slice { + pub inner: [u8] +} + +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) + } +} + +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) + } +} + +impl IntoInner> for Buf { + fn into_inner(self) -> Vec { + self.inner + } +} + +impl AsInner<[u8]> for Buf { + fn as_inner(&self) -> &[u8] { + &self.inner + } +} + + +impl Buf { + pub fn from_string(s: String) -> Buf { + Buf { inner: s.into_bytes() } + } + + #[inline] + pub fn with_capacity(capacity: usize) -> Buf { + Buf { + inner: Vec::with_capacity(capacity) + } + } + + #[inline] + pub fn clear(&mut self) { + self.inner.clear() + } + + #[inline] + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.inner.reserve(additional) + } + + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.inner.reserve_exact(additional) + } + + #[inline] + pub fn shrink_to_fit(&mut self) { + self.inner.shrink_to_fit() + } + + pub fn as_slice(&self) -> &Slice { + unsafe { mem::transmute(&*self.inner) } + } + + pub fn into_string(self) -> Result { + String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } ) + } + + pub fn push_slice(&mut self, s: &Slice) { + self.inner.extend_from_slice(&s.inner) + } + + #[inline] + pub fn into_box(self) -> Box { + unsafe { mem::transmute(self.inner.into_boxed_slice()) } + } + + #[inline] + pub fn from_box(boxed: Box) -> Buf { + let inner: Box<[u8]> = unsafe { mem::transmute(boxed) }; + Buf { inner: inner.into_vec() } + } +} + +impl Slice { + fn from_u8_slice(s: &[u8]) -> &Slice { + unsafe { mem::transmute(s) } + } + + pub fn from_str(s: &str) -> &Slice { + Slice::from_u8_slice(s.as_bytes()) + } + + pub fn to_str(&self) -> Option<&str> { + str::from_utf8(&self.inner).ok() + } + + pub fn to_string_lossy(&self) -> Cow { + String::from_utf8_lossy(&self.inner) + } + + pub fn to_owned(&self) -> Buf { + Buf { inner: self.inner.to_vec() } + } + + #[inline] + pub fn into_box(&self) -> Box { + let boxed: Box<[u8]> = self.inner.into(); + unsafe { mem::transmute(boxed) } + } + + pub fn empty_box() -> Box { + let boxed: Box<[u8]> = Default::default(); + unsafe { mem::transmute(boxed) } + } +} diff --git a/src/libstd/sys/wasm/path.rs b/src/libstd/sys/wasm/path.rs new file mode 100644 index 0000000000000..395b8c1e40e98 --- /dev/null +++ b/src/libstd/sys/wasm/path.rs @@ -0,0 +1,29 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use path::Prefix; +use ffi::OsStr; + +#[inline] +pub fn is_sep_byte(b: u8) -> bool { + b == b'/' +} + +#[inline] +pub fn is_verbatim_sep(b: u8) -> bool { + b == b'/' +} + +pub fn parse_prefix(_: &OsStr) -> Option { + None +} + +pub const MAIN_SEP_STR: &'static str = "/"; +pub const MAIN_SEP: char = '/'; diff --git a/src/libstd/sys/wasm/pipe.rs b/src/libstd/sys/wasm/pipe.rs new file mode 100644 index 0000000000000..992e1ac409cfb --- /dev/null +++ b/src/libstd/sys/wasm/pipe.rs @@ -0,0 +1,35 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use io; +use sys::Void; + +pub struct AnonPipe(Void); + +impl AnonPipe { + pub fn read(&self, _buf: &mut [u8]) -> io::Result { + match self.0 {} + } + + pub fn write(&self, _buf: &[u8]) -> io::Result { + match self.0 {} + } + + pub fn diverge(&self) -> ! { + match self.0 {} + } +} + +pub fn read2(p1: AnonPipe, + _v1: &mut Vec, + _p2: AnonPipe, + _v2: &mut Vec) -> io::Result<()> { + match p1.0 {} +} diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs new file mode 100644 index 0000000000000..4febe8a146382 --- /dev/null +++ b/src/libstd/sys/wasm/process.rs @@ -0,0 +1,151 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi::OsStr; +use fmt; +use io; +use sys::fs::File; +use sys::pipe::AnonPipe; +use sys::{unsupported, Void}; + +//////////////////////////////////////////////////////////////////////////////// +// Command +//////////////////////////////////////////////////////////////////////////////// + +pub struct Command { +} + +// passed back to std::process with the pipes connected to the child, if any +// were requested +pub struct StdioPipes { + pub stdin: Option, + pub stdout: Option, + pub stderr: Option, +} + +pub enum Stdio { + Inherit, + Null, + MakePipe, +} + +impl Command { + pub fn new(_program: &OsStr) -> Command { + Command {} + } + + pub fn arg(&mut self, _arg: &OsStr) { + } + + pub fn env(&mut self, _key: &OsStr, _val: &OsStr) { + } + + pub fn env_remove(&mut self, _key: &OsStr) { + } + + pub fn env_clear(&mut self) { + } + + pub fn cwd(&mut self, _dir: &OsStr) { + } + + pub fn stdin(&mut self, _stdin: Stdio) { + } + + pub fn stdout(&mut self, _stdout: Stdio) { + } + + pub fn stderr(&mut self, _stderr: Stdio) { + } + + pub fn spawn(&mut self, _default: Stdio, _needs_stdin: bool) + -> io::Result<(Process, StdioPipes)> { + unsupported() + } +} + +impl From for Stdio { + fn from(pipe: AnonPipe) -> Stdio { + pipe.diverge() + } +} + +impl From for Stdio { + fn from(file: File) -> Stdio { + file.diverge() + } +} + +impl fmt::Debug for Command { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } +} + +pub struct ExitStatus(Void); + +impl ExitStatus { + pub fn success(&self) -> bool { + match self.0 {} + } + + pub fn code(&self) -> Option { + match self.0 {} + } +} + +impl Clone for ExitStatus { + fn clone(&self) -> ExitStatus { + match self.0 {} + } +} + +impl Copy for ExitStatus {} + +impl PartialEq for ExitStatus { + fn eq(&self, _other: &ExitStatus) -> bool { + match self.0 {} + } +} + +impl Eq for ExitStatus { +} + +impl fmt::Debug for ExitStatus { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +impl fmt::Display for ExitStatus { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub struct Process(Void); + +impl Process { + pub fn id(&self) -> u32 { + match self.0 {} + } + + pub fn kill(&mut self) -> io::Result<()> { + match self.0 {} + } + + pub fn wait(&mut self) -> io::Result { + match self.0 {} + } + + pub fn try_wait(&mut self) -> io::Result> { + match self.0 {} + } +} diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/wasm/rwlock.rs new file mode 100644 index 0000000000000..8b06f54167487 --- /dev/null +++ b/src/libstd/sys/wasm/rwlock.rs @@ -0,0 +1,82 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cell::UnsafeCell; + +pub struct RWLock { + mode: UnsafeCell, +} + +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} // no threads on wasm + +impl RWLock { + pub const fn new() -> RWLock { + RWLock { + mode: UnsafeCell::new(0), + } + } + + #[inline] + pub unsafe fn read(&self) { + let mode = self.mode.get(); + if *mode >= 0 { + *mode += 1; + } else { + panic!("rwlock locked for writing"); + } + } + + #[inline] + pub unsafe fn try_read(&self) -> bool { + let mode = self.mode.get(); + if *mode >= 0 { + *mode += 1; + true + } else { + false + } + } + + #[inline] + pub unsafe fn write(&self) { + let mode = self.mode.get(); + if *mode == 0 { + *mode = -1; + } else { + panic!("rwlock locked for reading") + } + } + + #[inline] + pub unsafe fn try_write(&self) -> bool { + let mode = self.mode.get(); + if *mode == 0 { + *mode = -1; + true + } else { + false + } + } + + #[inline] + pub unsafe fn read_unlock(&self) { + *self.mode.get() -= 1; + } + + #[inline] + pub unsafe fn write_unlock(&self) { + *self.mode.get() += 1; + } + + #[inline] + pub unsafe fn destroy(&self) { + } +} diff --git a/src/libstd/sys/wasm/stack_overflow.rs b/src/libstd/sys/wasm/stack_overflow.rs new file mode 100644 index 0000000000000..bed274142f1ce --- /dev/null +++ b/src/libstd/sys/wasm/stack_overflow.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct Handler; + +impl Handler { + pub unsafe fn new() -> Handler { + Handler + } +} + +pub unsafe fn init() { +} + +pub unsafe fn cleanup() { +} diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs new file mode 100644 index 0000000000000..0f75f24025183 --- /dev/null +++ b/src/libstd/sys/wasm/stdio.rs @@ -0,0 +1,92 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use io; +use sys::{Void, unsupported}; + +pub struct Stdin(Void); +pub struct Stdout; +pub struct Stderr; + +impl Stdin { + pub fn new() -> io::Result { + unsupported() + } + + pub fn read(&self, _data: &mut [u8]) -> io::Result { + match self.0 {} + } +} + +impl Stdout { + pub fn new() -> io::Result { + Ok(Stdout) + } + + pub fn write(&self, data: &[u8]) -> io::Result { + // If runtime debugging is enabled at compile time we'll invoke some + // runtime functions that are defined in our src/etc/wasm32-shim.js + // debugging script. Note that this ffi function call is intended + // *purely* for debugging only and should not be relied upon. + if !super::DEBUG { + return unsupported() + } + extern { + fn rust_wasm_write_stdout(data: *const u8, len: usize); + } + unsafe { + rust_wasm_write_stdout(data.as_ptr(), data.len()) + } + Ok(data.len()) + } + + pub fn flush(&self) -> io::Result<()> { + Ok(()) + } +} + +impl Stderr { + pub fn new() -> io::Result { + Ok(Stderr) + } + + pub fn write(&self, data: &[u8]) -> io::Result { + // See comments in stdout for what's going on here. + if !super::DEBUG { + return unsupported() + } + extern { + fn rust_wasm_write_stderr(data: *const u8, len: usize); + } + unsafe { + rust_wasm_write_stderr(data.as_ptr(), data.len()) + } + Ok(data.len()) + } + + pub fn flush(&self) -> io::Result<()> { + Ok(()) + } +} + +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result { + (&*self).write(data) + } + fn flush(&mut self) -> io::Result<()> { + (&*self).flush() + } +} + +pub const STDIN_BUF_SIZE: usize = 0; + +pub fn is_ebadf(_err: &io::Error) -> bool { + true +} diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs new file mode 100644 index 0000000000000..13980e0cc19d1 --- /dev/null +++ b/src/libstd/sys/wasm/thread.rs @@ -0,0 +1,48 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use alloc::boxed::FnBox; +use ffi::CStr; +use io; +use sys::{unsupported, Void}; +use time::Duration; + +pub struct Thread(Void); + +pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; + +impl Thread { + pub unsafe fn new<'a>(_stack: usize, _p: Box) + -> io::Result + { + unsupported() + } + + pub fn yield_now() { + // do nothing + } + + pub fn set_name(_name: &CStr) { + // nope + } + + pub fn sleep(_dur: Duration) { + panic!("can't sleep"); + } + + pub fn join(self) { + match self.0 {} + } +} + +pub mod guard { + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } +} diff --git a/src/libstd/sys/wasm/thread_local.rs b/src/libstd/sys/wasm/thread_local.rs new file mode 100644 index 0000000000000..442dd3302a058 --- /dev/null +++ b/src/libstd/sys/wasm/thread_local.rs @@ -0,0 +1,50 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use boxed::Box; +use ptr; + +pub type Key = usize; + +struct Allocated { + value: *mut u8, + dtor: Option, +} + +#[inline] +pub unsafe fn create(dtor: Option) -> Key { + Box::into_raw(Box::new(Allocated { + value: ptr::null_mut(), + dtor, + })) as usize +} + +#[inline] +pub unsafe fn set(key: Key, value: *mut u8) { + (*(key as *mut Allocated)).value = value; +} + +#[inline] +pub unsafe fn get(key: Key) -> *mut u8 { + (*(key as *mut Allocated)).value +} + +#[inline] +pub unsafe fn destroy(key: Key) { + let key = Box::from_raw(key as *mut Allocated); + if let Some(f) = key.dtor { + f(key.value); + } +} + +#[inline] +pub fn requires_synchronized_create() -> bool { + false +} diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs new file mode 100644 index 0000000000000..7907720e4dac6 --- /dev/null +++ b/src/libstd/sys/wasm/time.rs @@ -0,0 +1,63 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use fmt; +use time::Duration; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct Instant; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct SystemTime; + +pub const UNIX_EPOCH: SystemTime = SystemTime; + +impl Instant { + pub fn now() -> Instant { + panic!("not supported on web assembly"); + } + + pub fn sub_instant(&self, _other: &Instant) -> Duration { + panic!("can't sub yet"); + } + + pub fn add_duration(&self, _other: &Duration) -> Instant { + panic!("can't add yet"); + } + + pub fn sub_duration(&self, _other: &Duration) -> Instant { + panic!("can't sub yet"); + } +} + +impl SystemTime { + pub fn now() -> SystemTime { + panic!("not supported on web assembly"); + } + + pub fn sub_time(&self, _other: &SystemTime) + -> Result { + panic!() + } + + pub fn add_duration(&self, _other: &Duration) -> SystemTime { + panic!() + } + + pub fn sub_duration(&self, _other: &Duration) -> SystemTime { + panic!() + } +} + +impl fmt::Debug for SystemTime { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + panic!() + } +} diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index d7654ce9300b3..14e5697b94e57 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -44,11 +44,15 @@ pub mod thread_local; pub mod util; pub mod wtf8; -#[cfg(any(target_os = "redox", target_os = "l4re"))] -pub use sys::net; - -#[cfg(not(any(target_os = "redox", target_os = "l4re")))] -pub mod net; +cfg_if! { + if #[cfg(any(target_os = "redox", target_os = "l4re"))] { + pub use sys::net; + } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { + pub use sys::net; + } else { + pub mod net; + } +} #[cfg(feature = "backtrace")] #[cfg(any(all(unix, not(target_os = "emscripten")), diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index c19424f295226..f1379b6ec6375 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use env; use alloc::boxed::FnBox; +use env; use sync::atomic::{self, Ordering}; use sys::stack_overflow; use sys::thread as imp; +#[allow(dead_code)] pub unsafe fn start_thread(main: *mut u8) { // Next, set up our stack overflow handler which may get triggered if we run // out of stack. diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 97eec3a21e9d1..ebe7853b8abdb 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -415,6 +415,9 @@ declare_features! ( // Allow trait methods with arbitrary self types (active, arbitrary_self_types, "1.23.0", Some(44874)), + + // #![wasm_import_memory] attribute + (active, wasm_import_memory, "1.22.0", None), ); declare_features! ( @@ -928,6 +931,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG never be stable", cfg_fn!(rustc_attrs))), + ("wasm_import_memory", Whitelisted, Gated(Stability::Unstable, + "wasm_import_memory", + "wasm_import_memory attribute is currently unstable", + cfg_fn!(wasm_import_memory))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 76abcb83edc53..ef08b877262fc 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -434,7 +434,8 @@ Test Attributes: // Parses command line arguments into test options pub fn parse_opts(args: &[String]) -> Option { let opts = optgroups(); - let matches = match opts.parse(&args[1..]) { + let args = args.get(1..).unwrap_or(args); + let matches = match opts.parse(args) { Ok(m) => m, Err(f) => return Some(Err(f.to_string())), }; @@ -1034,6 +1035,10 @@ fn stdout_isatty() -> bool { // FIXME: Implement isatty on Redox false } +#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] +fn stdout_isatty() -> bool { + false +} #[cfg(unix)] fn stdout_isatty() -> bool { unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } @@ -1132,45 +1137,47 @@ pub fn run_tests(opts: &TestOpts, tests: Vec, mut callback: F) }}) }; - while pending > 0 || !remaining.is_empty() { - while pending < concurrency && !remaining.is_empty() { + if concurrency == 1 { + while !remaining.is_empty() { let test = remaining.pop().unwrap(); - if concurrency == 1 { - // We are doing one test at a time so we can print the name - // of the test before we run it. Useful for debugging tests - // that hang forever. - callback(TeWait(test.desc.clone(), test.testfn.padding()))?; - } - let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S); - running_tests.insert(test.desc.clone(), timeout); + callback(TeWait(test.desc.clone(), test.testfn.padding()))?; run_test(opts, !opts.run_tests, test, tx.clone()); - pending += 1; + let (test, result, stdout) = rx.recv().unwrap(); + callback(TeResult(test, result, stdout))?; } + } else { + while pending > 0 || !remaining.is_empty() { + while pending < concurrency && !remaining.is_empty() { + let test = remaining.pop().unwrap(); + let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S); + running_tests.insert(test.desc.clone(), timeout); + run_test(opts, !opts.run_tests, test, tx.clone()); + pending += 1; + } - let mut res; - loop { - if let Some(timeout) = calc_timeout(&running_tests) { - res = rx.recv_timeout(timeout); - for test in get_timed_out_tests(&mut running_tests) { - callback(TeTimeout(test))?; - } - if res != Err(RecvTimeoutError::Timeout) { + let mut res; + loop { + if let Some(timeout) = calc_timeout(&running_tests) { + res = rx.recv_timeout(timeout); + for test in get_timed_out_tests(&mut running_tests) { + callback(TeTimeout(test))?; + } + if res != Err(RecvTimeoutError::Timeout) { + break; + } + } else { + res = rx.recv().map_err(|_| RecvTimeoutError::Disconnected); break; } - } else { - res = rx.recv().map_err(|_| RecvTimeoutError::Disconnected); - break; } - } - let (desc, result, stdout) = res.unwrap(); - running_tests.remove(&desc); + let (desc, result, stdout) = res.unwrap(); + running_tests.remove(&desc); - if concurrency != 1 { callback(TeWait(desc.clone(), PadNone))?; + callback(TeResult(desc, result, stdout))?; + pending -= 1; } - callback(TeResult(desc, result, stdout))?; - pending -= 1; } if opts.bench_benchmarks { @@ -1235,6 +1242,11 @@ fn get_concurrency() -> usize { 1 } + #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] + fn num_cpus() -> usize { + 1 + } + #[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", @@ -1393,7 +1405,12 @@ pub fn run_test(opts: &TestOpts, let TestDescAndFn {desc, testfn} = test; - if force_ignore || desc.ignore { + let ignore_because_panic_abort = + cfg!(target_arch = "wasm32") && + !cfg!(target_os = "emscripten") && + desc.should_panic != ShouldPanic::No; + + if force_ignore || desc.ignore || ignore_because_panic_abort { monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap(); return; } @@ -1445,7 +1462,9 @@ pub fn run_test(opts: &TestOpts, // 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"); + let supports_threads = + !cfg!(target_os = "emscripten") && + !cfg!(target_arch = "wasm32"); if supports_threads { let cfg = thread::Builder::new().name(match name { DynTestName(ref name) => name.clone(), diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index 461b49aa363b4..5bb1eb96dcfad 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -20,13 +20,20 @@ #![cfg_attr(not(target_env = "msvc"), feature(libc))] -#[cfg(not(target_env = "msvc"))] -extern crate libc; +#[macro_use] +mod macros; -#[cfg(not(target_env = "msvc"))] -mod libunwind; -#[cfg(not(target_env = "msvc"))] -pub use libunwind::*; +cfg_if! { + if #[cfg(target_env = "msvc")] { + // no extra unwinder support needed + } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { + // no unwinder on the system! + } else { + extern crate libc; + mod libunwind; + pub use libunwind::*; + } +} #[cfg(all(target_env = "musl", not(target_arch = "mips")))] #[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))] diff --git a/src/libunwind/macros.rs b/src/libunwind/macros.rs new file mode 100644 index 0000000000000..26376a3733f4f --- /dev/null +++ b/src/libunwind/macros.rs @@ -0,0 +1,45 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// A macro for defining #[cfg] if-else statements. +/// +/// This is similar to the `if/elif` C preprocessor macro by allowing definition +/// of a cascade of `#[cfg]` cases, emitting the implementation which matches +/// first. +/// +/// This allows you to conveniently provide a long list #[cfg]'d blocks of code +/// without having to rewrite each clause multiple times. +macro_rules! cfg_if { + ($( + if #[cfg($($meta:meta),*)] { $($it:item)* } + ) else * else { + $($it2:item)* + }) => { + __cfg_if_items! { + () ; + $( ( ($($meta),*) ($($it)*) ), )* + ( () ($($it2)*) ), + } + } +} + +macro_rules! __cfg_if_items { + (($($not:meta,)*) ; ) => {}; + (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { + __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* } + __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } + } +} + +macro_rules! __cfg_if_apply { + ($m:meta, $($it:item)*) => { + $(#[$m] $it)* + } +} diff --git a/src/rustc/dlmalloc_shim/Cargo.toml b/src/rustc/dlmalloc_shim/Cargo.toml new file mode 100644 index 0000000000000..cf8440c40da1a --- /dev/null +++ b/src/rustc/dlmalloc_shim/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "dlmalloc" +version = "0.0.0" +authors = ["The Rust Project Developers"] + +[lib] +path = "../../dlmalloc/src/lib.rs" +test = false +bench = false +doc = false + +[dependencies] +core = { path = "../../libcore" } +alloc = { path = "../../liballoc" } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index b4116c96ba130..d0c042e6451c7 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -366,7 +366,9 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc, LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, bool PositionIndependentExecutable, bool FunctionSections, - bool DataSections, bool TrapUnreachable) { + bool DataSections, + bool TrapUnreachable, + bool Singlethread) { auto CM = fromRust(RustCM); auto OptLevel = fromRust(RustOptLevel); @@ -406,6 +408,10 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.TrapUnreachable = true; } + if (Singlethread) { + Options.ThreadModel = ThreadModel::Single; + } + TargetMachine *TM = TheTarget->createTargetMachine( Trip.getTriple(), RealCPU, Feature, Options, RM, CM, OptLevel); return wrap(TM); diff --git a/src/test/compile-fail/feature-gate-wasm_import_memory.rs b/src/test/compile-fail/feature-gate-wasm_import_memory.rs new file mode 100644 index 0000000000000..a010ebb3551d0 --- /dev/null +++ b/src/test/compile-fail/feature-gate-wasm_import_memory.rs @@ -0,0 +1,14 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![wasm_import_memory] //~ ERROR: currently unstable + +fn main() {} + diff --git a/src/test/run-pass-fulldeps/flt2dec.rs b/src/test/run-pass-fulldeps/flt2dec.rs new file mode 100644 index 0000000000000..3db0644d1ef3c --- /dev/null +++ b/src/test/run-pass-fulldeps/flt2dec.rs @@ -0,0 +1,163 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:--test + +#![feature(rustc_private, flt2dec)] + +extern crate core; +extern crate rand; + +use std::i16; +use std::mem; +use std::str; + +use core::num::flt2dec::MAX_SIG_DIGITS; +use core::num::flt2dec::strategy::grisu::format_exact_opt; +use core::num::flt2dec::strategy::grisu::format_shortest_opt; +use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; + +use rand::{Rand, XorShiftRng}; +use rand::distributions::{IndependentSample, Range}; +pub fn decode_finite(v: T) -> Decoded { + match decode(v).1 { + FullDecoded::Finite(decoded) => decoded, + full_decoded => panic!("expected finite, got {:?} instead", full_decoded) + } +} + + +fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize) + where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), + V: FnMut(usize) -> Decoded { + assert!(k <= 1024); + + let mut npassed = 0; // f(x) = Some(g(x)) + let mut nignored = 0; // f(x) = None + + for i in 0..n { + if (i & 0xfffff) == 0 { + println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})", + i, n, nignored, npassed, i - nignored - npassed); + } + + let decoded = v(i); + let mut buf1 = [0; 1024]; + if let Some((len1, e1)) = f(&decoded, &mut buf1[..k]) { + let mut buf2 = [0; 1024]; + let (len2, e2) = g(&decoded, &mut buf2[..k]); + if e1 == e2 && &buf1[..len1] == &buf2[..len2] { + npassed += 1; + } else { + println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}", + i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1, + str::from_utf8(&buf2[..len2]).unwrap(), e2); + } + } else { + nignored += 1; + } + } + println!("{}({}): done, ignored={} passed={} failed={}", + func, k, nignored, npassed, n - nignored - npassed); + assert!(nignored + npassed == n, + "{}({}): {} out of {} values returns an incorrect value!", + func, k, n - nignored - npassed, n); + (npassed, nignored) +} + +pub fn f32_random_equivalence_test(f: F, g: G, k: usize, n: usize) + where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { + let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); + let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000); + iterate("f32_random_equivalence_test", k, n, f, g, |_| { + let i: u32 = f32_range.ind_sample(&mut rng); + let x: f32 = unsafe {mem::transmute(i)}; + decode_finite(x) + }); +} + +pub fn f64_random_equivalence_test(f: F, g: G, k: usize, n: usize) + where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { + let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); + let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); + iterate("f64_random_equivalence_test", k, n, f, g, |_| { + let i: u64 = f64_range.ind_sample(&mut rng); + let x: f64 = unsafe {mem::transmute(i)}; + decode_finite(x) + }); +} + +pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) + where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { + // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values, + // so why not simply testing all of them? + // + // this is of course very stressful (and thus should be behind an `#[ignore]` attribute), + // but with `-C opt-level=3 -C lto` this only takes about an hour or so. + + // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges + let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test", + k, 0x7f7f_ffff, f, g, |i: usize| { + let x: f32 = unsafe {mem::transmute(i as u32 + 1)}; + decode_finite(x) + }); + assert_eq!((npassed, nignored), (2121451881, 17643158)); +} + +#[test] +fn shortest_random_equivalence_test() { + use core::num::flt2dec::strategy::dragon::format_shortest as fallback; + f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); + f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); +} + +#[test] #[ignore] // it is too expensive +fn shortest_f32_exhaustive_equivalence_test() { + // it is hard to directly test the optimality of the output, but we can at least test if + // two different algorithms agree to each other. + // + // this reports the progress and the number of f32 values returned `None`. + // with `--nocapture` (and plenty of time and appropriate rustc flags), this should print: + // `done, ignored=17643158 passed=2121451881 failed=0`. + + use core::num::flt2dec::strategy::dragon::format_shortest as fallback; + f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS); +} + +#[test] #[ignore] // it is too expensive +fn shortest_f64_hard_random_equivalence_test() { + // this again probably has to use appropriate rustc flags. + + use core::num::flt2dec::strategy::dragon::format_shortest as fallback; + f64_random_equivalence_test(format_shortest_opt, fallback, + MAX_SIG_DIGITS, 100_000_000); +} + +#[test] +fn exact_f32_random_equivalence_test() { + use core::num::flt2dec::strategy::dragon::format_exact as fallback; + for k in 1..21 { + f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), + |d, buf| fallback(d, buf, i16::MIN), k, 1_000); + } +} + +#[test] +fn exact_f64_random_equivalence_test() { + use core::num::flt2dec::strategy::dragon::format_exact as fallback; + for k in 1..21 { + f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), + |d, buf| fallback(d, buf, i16::MIN), k, 1_000); + } +} diff --git a/src/test/run-pass-fulldeps/sort-unstable.rs b/src/test/run-pass-fulldeps/sort-unstable.rs new file mode 100644 index 0000000000000..af8a691aa3ec6 --- /dev/null +++ b/src/test/run-pass-fulldeps/sort-unstable.rs @@ -0,0 +1,83 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_private, sort_internals)] + +extern crate core; +extern crate rand; + +use std::cmp::Ordering::{Equal, Greater, Less}; +use core::slice::heapsort; + +use rand::{Rng, XorShiftRng}; + +fn main() { + let mut v = [0; 600]; + let mut tmp = [0; 600]; + let mut rng = XorShiftRng::new_unseeded(); + + for len in (2..25).chain(500..510) { + let v = &mut v[0..len]; + let tmp = &mut tmp[0..len]; + + for &modulus in &[5, 10, 100, 1000] { + for _ in 0..100 { + for i in 0..len { + v[i] = rng.gen::() % modulus; + } + + // Sort in default order. + tmp.copy_from_slice(v); + tmp.sort_unstable(); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Sort in ascending order. + tmp.copy_from_slice(v); + tmp.sort_unstable_by(|a, b| a.cmp(b)); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Sort in descending order. + tmp.copy_from_slice(v); + tmp.sort_unstable_by(|a, b| b.cmp(a)); + assert!(tmp.windows(2).all(|w| w[0] >= w[1])); + + // Test heapsort using `<` operator. + tmp.copy_from_slice(v); + heapsort(tmp, |a, b| a < b); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Test heapsort using `>` operator. + tmp.copy_from_slice(v); + heapsort(tmp, |a, b| a > b); + assert!(tmp.windows(2).all(|w| w[0] >= w[1])); + } + } + } + + // Sort using a completely random comparison function. + // This will reorder the elements *somehow*, but won't panic. + for i in 0..v.len() { + v[i] = i as i32; + } + v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap()); + v.sort_unstable(); + for i in 0..v.len() { + assert_eq!(v[i], i as i32); + } + + // Should not panic. + [0i32; 0].sort_unstable(); + [(); 10].sort_unstable(); + [(); 100].sort_unstable(); + + let mut v = [0xDEADBEEFu64]; + v.sort_unstable(); + assert!(v == [0xDEADBEEF]); +} diff --git a/src/test/run-pass/allocator/custom.rs b/src/test/run-pass/allocator/custom.rs index b46f024b5bff3..22081678fb999 100644 --- a/src/test/run-pass/allocator/custom.rs +++ b/src/test/run-pass/allocator/custom.rs @@ -15,7 +15,6 @@ extern crate helper; -use std::env; use std::heap::{Heap, Alloc, System, Layout, AllocErr}; use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; @@ -39,8 +38,7 @@ unsafe impl<'a> Alloc for &'a A { static GLOBAL: A = A; fn main() { - env::set_var("FOO", "bar"); - drop(env::var("FOO")); + println!("hello!"); let n = HITS.load(Ordering::SeqCst); assert!(n > 0); diff --git a/src/test/run-pass/allocator/xcrate-use.rs b/src/test/run-pass/allocator/xcrate-use.rs index 4b987b9223d6d..04d2ef466e73d 100644 --- a/src/test/run-pass/allocator/xcrate-use.rs +++ b/src/test/run-pass/allocator/xcrate-use.rs @@ -17,7 +17,6 @@ extern crate custom; extern crate helper; -use std::env; use std::heap::{Heap, Alloc, System, Layout}; use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT}; diff --git a/src/test/run-pass/allocator/xcrate-use2.rs b/src/test/run-pass/allocator/xcrate-use2.rs index 7e6cd9fdf4950..155fb5d6c5de9 100644 --- a/src/test/run-pass/allocator/xcrate-use2.rs +++ b/src/test/run-pass/allocator/xcrate-use2.rs @@ -19,7 +19,6 @@ extern crate custom; extern crate custom_as_global; extern crate helper; -use std::env; use std::heap::{Heap, Alloc, System, Layout}; use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT}; diff --git a/src/test/run-pass/anon-extern-mod-cross-crate-2.rs b/src/test/run-pass/anon-extern-mod-cross-crate-2.rs index b40774e2be82f..8c480d7deebd9 100644 --- a/src/test/run-pass/anon-extern-mod-cross-crate-2.rs +++ b/src/test/run-pass/anon-extern-mod-cross-crate-2.rs @@ -10,6 +10,7 @@ // aux-build:anon-extern-mod-cross-crate-1.rs // pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with extern crate anonexternmod; diff --git a/src/test/run-pass/anon-extern-mod.rs b/src/test/run-pass/anon-extern-mod.rs index 208b4df3c3e7e..16ca7bce95b59 100644 --- a/src/test/run-pass/anon-extern-mod.rs +++ b/src/test/run-pass/anon-extern-mod.rs @@ -9,6 +9,7 @@ // except according to those terms. // pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with #![feature(libc)] diff --git a/src/test/run-pass/auxiliary/issue-3012-1.rs b/src/test/run-pass/auxiliary/issue-3012-1.rs index b6199f59ebe06..f34a97519e77d 100644 --- a/src/test/run-pass/auxiliary/issue-3012-1.rs +++ b/src/test/run-pass/auxiliary/issue-3012-1.rs @@ -10,13 +10,10 @@ #![crate_name="socketlib"] #![crate_type = "lib"] -#![feature(libc)] pub mod socket { - extern crate libc; - pub struct socket_handle { - sockfd: libc::c_int, + sockfd: u32, } impl Drop for socket_handle { @@ -25,7 +22,7 @@ pub mod socket { } } - pub fn socket_handle(x: libc::c_int) -> socket_handle { + pub fn socket_handle(x: u32) -> socket_handle { socket_handle { sockfd: x } diff --git a/src/test/run-pass/builtin-clone-unwind.rs b/src/test/run-pass/builtin-clone-unwind.rs index 90a411352869c..7e7c5ee412556 100644 --- a/src/test/run-pass/builtin-clone-unwind.rs +++ b/src/test/run-pass/builtin-clone-unwind.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + // Test that builtin implementations of `Clone` cleanup everything // in case of unwinding. diff --git a/src/test/run-pass/c-stack-as-value.rs b/src/test/run-pass/c-stack-as-value.rs index 5319693405b5d..df4989d89ab5e 100644 --- a/src/test/run-pass/c-stack-as-value.rs +++ b/src/test/run-pass/c-stack-as-value.rs @@ -9,6 +9,7 @@ // except according to those terms. // pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with #![feature(libc)] diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 84f22025a1d7a..46b3fd1f1e746 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +// ignore-wasm32-bare no libc to test with #![feature(libc, std_misc)] diff --git a/src/test/run-pass/cabi-int-widening.rs b/src/test/run-pass/cabi-int-widening.rs index bf94dd178821a..5b1677c184c74 100644 --- a/src/test/run-pass/cabi-int-widening.rs +++ b/src/test/run-pass/cabi-int-widening.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + #[link(name = "rust_test_helpers", kind = "static")] extern { fn rust_int8_to_int32(_: i8) -> i32; diff --git a/src/test/run-pass/catch-unwind-bang.rs b/src/test/run-pass/catch-unwind-bang.rs index df54ec90022ee..849132b8ebfab 100644 --- a/src/test/run-pass/catch-unwind-bang.rs +++ b/src/test/run-pass/catch-unwind-bang.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + fn worker() -> ! { panic!() } diff --git a/src/test/run-pass/cfg-family.rs b/src/test/run-pass/cfg-family.rs index 415607aa72bfc..1797ad1019c3d 100644 --- a/src/test/run-pass/cfg-family.rs +++ b/src/test/run-pass/cfg-family.rs @@ -9,6 +9,7 @@ // except according to those terms. // pretty-expanded FIXME #23616 +// ignore-wasm32-bare no target_family #[cfg(windows)] pub fn main() { diff --git a/src/test/run-pass/cfg-target-family.rs b/src/test/run-pass/cfg-target-family.rs index b6954f7c2eeaf..0b8574e117478 100644 --- a/src/test/run-pass/cfg-target-family.rs +++ b/src/test/run-pass/cfg-target-family.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no target_family + // pretty-expanded FIXME #23616 #[cfg(target_family = "windows")] diff --git a/src/test/run-pass/check-static-recursion-foreign.rs b/src/test/run-pass/check-static-recursion-foreign.rs index 8e718f328ff91..9c87f2ca68203 100644 --- a/src/test/run-pass/check-static-recursion-foreign.rs +++ b/src/test/run-pass/check-static-recursion-foreign.rs @@ -11,6 +11,7 @@ // Static recursion check shouldn't fail when given a foreign item (#18279) // aux-build:check_static_recursion_foreign_helper.rs +// ignore-wasm32-bare no libc to test ffi with // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/const-cast.rs b/src/test/run-pass/const-cast.rs index 411df2b3e0759..e77fd5f71394e 100644 --- a/src/test/run-pass/const-cast.rs +++ b/src/test/run-pass/const-cast.rs @@ -8,21 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(libc)] - -extern crate libc; - struct TestStruct { - x: *const libc::c_void + x: *const u8, } unsafe impl Sync for TestStruct {} extern fn foo() {} const x: extern "C" fn() = foo; -static y: TestStruct = TestStruct { x: x as *const libc::c_void }; +static y: TestStruct = TestStruct { x: x as *const u8 }; pub fn main() { - assert_eq!(x as *const libc::c_void, y.x); + assert_eq!(x as *const u8, y.x); } diff --git a/src/test/run-pass/duplicated-external-mods.rs b/src/test/run-pass/duplicated-external-mods.rs index 91c9887300935..4cb3dbe027a16 100644 --- a/src/test/run-pass/duplicated-external-mods.rs +++ b/src/test/run-pass/duplicated-external-mods.rs @@ -11,6 +11,7 @@ // aux-build:anon-extern-mod-cross-crate-1.rs // aux-build:anon-extern-mod-cross-crate-1.rs // pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with extern crate anonexternmod; diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index 483dbb356ce6a..3310d3a89b92b 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + #![feature(generators, generator_trait, untagged_unions)] use std::cell::{Cell, RefCell}; diff --git a/src/test/run-pass/env-vars.rs b/src/test/run-pass/env-vars.rs index 933d9a728dbe7..af44a6567e405 100644 --- a/src/test/run-pass/env-vars.rs +++ b/src/test/run-pass/env-vars.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no env vars use std::env::*; diff --git a/src/test/run-pass/extern-call-deep.rs b/src/test/run-pass/extern-call-deep.rs index 6a9da767ad6eb..a41ab8da9de11 100644 --- a/src/test/run-pass/extern-call-deep.rs +++ b/src/test/run-pass/extern-call-deep.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + #![feature(libc)] extern crate libc; diff --git a/src/test/run-pass/extern-call-indirect.rs b/src/test/run-pass/extern-call-indirect.rs index 256eedccb8bfa..ba108955c28d6 100644 --- a/src/test/run-pass/extern-call-indirect.rs +++ b/src/test/run-pass/extern-call-indirect.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + #![feature(libc)] extern crate libc; diff --git a/src/test/run-pass/extern-crosscrate.rs b/src/test/run-pass/extern-crosscrate.rs index 7157d0658be34..825b502d95485 100644 --- a/src/test/run-pass/extern-crosscrate.rs +++ b/src/test/run-pass/extern-crosscrate.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//aux-build:extern-crosscrate-source.rs +// aux-build:extern-crosscrate-source.rs +// ignore-wasm32-bare no libc to test ffi with #![feature(libc)] diff --git a/src/test/run-pass/extern-pass-TwoU16s.rs b/src/test/run-pass/extern-pass-TwoU16s.rs index afdd53db775a8..a1aa9b69fadaa 100644 --- a/src/test/run-pass/extern-pass-TwoU16s.rs +++ b/src/test/run-pass/extern-pass-TwoU16s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc for ffi testing + // Test a foreign function that accepts and returns a struct // by value. diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs index 035084ae9bd3a..6442f230d3024 100644 --- a/src/test/run-pass/extern-pass-TwoU32s.rs +++ b/src/test/run-pass/extern-pass-TwoU32s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc for ffi testing + // Test a foreign function that accepts and returns a struct // by value. diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs index cb1a4d278256a..bfb649c3f74ea 100644 --- a/src/test/run-pass/extern-pass-TwoU64s.rs +++ b/src/test/run-pass/extern-pass-TwoU64s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc for ffi testing + // Test a foreign function that accepts and returns a struct // by value. diff --git a/src/test/run-pass/extern-pass-TwoU8s.rs b/src/test/run-pass/extern-pass-TwoU8s.rs index 657348c99aad8..1f90d9c436677 100644 --- a/src/test/run-pass/extern-pass-TwoU8s.rs +++ b/src/test/run-pass/extern-pass-TwoU8s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc for ffi testing + // Test a foreign function that accepts and returns a struct // by value. diff --git a/src/test/run-pass/extern-pass-char.rs b/src/test/run-pass/extern-pass-char.rs index 9042aed6639b8..920e15bf2c119 100644 --- a/src/test/run-pass/extern-pass-char.rs +++ b/src/test/run-pass/extern-pass-char.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc for ffi testing + // Test a function that takes/returns a u8. diff --git a/src/test/run-pass/extern-pass-double.rs b/src/test/run-pass/extern-pass-double.rs index 38d29180fbc8f..9c184477ad340 100644 --- a/src/test/run-pass/extern-pass-double.rs +++ b/src/test/run-pass/extern-pass-double.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc for ffi testing #[link(name = "rust_test_helpers", kind = "static")] extern { diff --git a/src/test/run-pass/extern-pass-u32.rs b/src/test/run-pass/extern-pass-u32.rs index ed254ac46f20b..691bd6295b143 100644 --- a/src/test/run-pass/extern-pass-u32.rs +++ b/src/test/run-pass/extern-pass-u32.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc for ffi testing + // Test a function that takes/returns a u32. diff --git a/src/test/run-pass/extern-pass-u64.rs b/src/test/run-pass/extern-pass-u64.rs index 6fc630e6d7e1a..4b351ed2836cc 100644 --- a/src/test/run-pass/extern-pass-u64.rs +++ b/src/test/run-pass/extern-pass-u64.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc for ffi testing + // Test a call to a function that takes/returns a u64. diff --git a/src/test/run-pass/extern-return-TwoU16s.rs b/src/test/run-pass/extern-return-TwoU16s.rs index ec1c6130e7adc..b9ce3f4588688 100644 --- a/src/test/run-pass/extern-return-TwoU16s.rs +++ b/src/test/run-pass/extern-return-TwoU16s.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with pub struct TwoU16s { one: u16, two: u16 diff --git a/src/test/run-pass/extern-return-TwoU32s.rs b/src/test/run-pass/extern-return-TwoU32s.rs index e829e993052a5..686ff16fe4d6b 100644 --- a/src/test/run-pass/extern-return-TwoU32s.rs +++ b/src/test/run-pass/extern-return-TwoU32s.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with pub struct TwoU32s { one: u32, two: u32 diff --git a/src/test/run-pass/extern-return-TwoU64s.rs b/src/test/run-pass/extern-return-TwoU64s.rs index ef7325b33fe3d..e754674fd1ebd 100644 --- a/src/test/run-pass/extern-return-TwoU64s.rs +++ b/src/test/run-pass/extern-return-TwoU64s.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with pub struct TwoU64s { one: u64, two: u64 diff --git a/src/test/run-pass/extern-return-TwoU8s.rs b/src/test/run-pass/extern-return-TwoU8s.rs index 46f2e81a5564a..68fe3832e90ab 100644 --- a/src/test/run-pass/extern-return-TwoU8s.rs +++ b/src/test/run-pass/extern-return-TwoU8s.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with pub struct TwoU8s { one: u8, two: u8 diff --git a/src/test/run-pass/extern_fat_drop.rs b/src/test/run-pass/extern_fat_drop.rs index 8ce1f744dee17..123458ff97e13 100644 --- a/src/test/run-pass/extern_fat_drop.rs +++ b/src/test/run-pass/extern_fat_drop.rs @@ -14,7 +14,8 @@ extern crate fat_drop; fn main() { unsafe { - let s: &mut fat_drop::S = std::mem::uninitialized(); + let data: &mut [u8] = &mut [0]; + let s: &mut fat_drop::S = std::mem::transmute::<&mut [u8], _>(data); std::ptr::drop_in_place(s); assert!(fat_drop::DROPPED); } diff --git a/src/test/run-pass/fmt-pointer-trait.rs b/src/test/run-pass/fmt-pointer-trait.rs index 96f31891f2f34..4ecb9da4eb9c6 100644 --- a/src/test/run-pass/fmt-pointer-trait.rs +++ b/src/test/run-pass/fmt-pointer-trait.rs @@ -8,14 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc)] -extern crate libc; use std::ptr; use std::rc::Rc; use std::sync::Arc; fn main() { - let p: *const libc::c_void = ptr::null(); + let p: *const u8 = ptr::null(); let rc = Rc::new(1usize); let arc = Arc::new(1usize); let b = Box::new("hi"); diff --git a/src/test/run-pass/foreign-dupe.rs b/src/test/run-pass/foreign-dupe.rs index fb162d8793356..b79e6e98fc056 100644 --- a/src/test/run-pass/foreign-dupe.rs +++ b/src/test/run-pass/foreign-dupe.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:foreign_lib.rs +// ignore-wasm32-bare no libc to test ffi with // Check that we can still call duplicated extern (imported) functions // which were declared in another crate. See issues #32740 and #32783. diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index a9001a3cdcf6e..ab8e4fbedcff7 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +// ignore-wasm32-bare no libc to test ffi with #![feature(std_misc, libc)] diff --git a/src/test/run-pass/foreign-fn-with-byval.rs b/src/test/run-pass/foreign-fn-with-byval.rs index 2d4542540e7a3..65efa571a9b4b 100644 --- a/src/test/run-pass/foreign-fn-with-byval.rs +++ b/src/test/run-pass/foreign-fn-with-byval.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with #[derive(Copy, Clone)] pub struct S { diff --git a/src/test/run-pass/foreign-mod-unused-const.rs b/src/test/run-pass/foreign-mod-unused-const.rs index 70d4801ae3b3c..5e9e529669a01 100644 --- a/src/test/run-pass/foreign-mod-unused-const.rs +++ b/src/test/run-pass/foreign-mod-unused-const.rs @@ -8,18 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // pretty-expanded FIXME #23616 -#![feature(libc)] - -extern crate libc; - mod foo { - use libc::c_int; - extern { - pub static errno: c_int; + pub static errno: u32; } } diff --git a/src/test/run-pass/foreign-no-abi.rs b/src/test/run-pass/foreign-no-abi.rs index 979e57eba9d1a..b516cdf4416b8 100644 --- a/src/test/run-pass/foreign-no-abi.rs +++ b/src/test/run-pass/foreign-no-abi.rs @@ -10,6 +10,7 @@ // ABI is cdecl by default +// ignore-wasm32-bare no libc to test ffi with // pretty-expanded FIXME #23616 #![feature(libc)] diff --git a/src/test/run-pass/foreign2.rs b/src/test/run-pass/foreign2.rs index d83bd940d1978..d69d6976e4a90 100644 --- a/src/test/run-pass/foreign2.rs +++ b/src/test/run-pass/foreign2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +// ignore-wasm32-bare no libc to test ffi with // pretty-expanded FIXME #23616 #![feature(libc)] diff --git a/src/test/run-pass/generator/panic-drops.rs b/src/test/run-pass/generator/panic-drops.rs index 53cd3235d9d0c..36e401a54bcdd 100644 --- a/src/test/run-pass/generator/panic-drops.rs +++ b/src/test/run-pass/generator/panic-drops.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled as panic=abort by default + #![feature(generators, generator_trait)] use std::ops::Generator; diff --git a/src/test/run-pass/generator/panic-safe.rs b/src/test/run-pass/generator/panic-safe.rs index a583f42b93d8c..0d5bae7876bd3 100644 --- a/src/test/run-pass/generator/panic-safe.rs +++ b/src/test/run-pass/generator/panic-safe.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + #![feature(generators, generator_trait)] use std::ops::Generator; diff --git a/src/test/run-pass/generator/resume-after-return.rs b/src/test/run-pass/generator/resume-after-return.rs index b2e2a3e7e9d5b..56511dcd53a6a 100644 --- a/src/test/run-pass/generator/resume-after-return.rs +++ b/src/test/run-pass/generator/resume-after-return.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + #![feature(generators, generator_trait)] use std::ops::{GeneratorState, Generator}; diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index cfae9903a95e5..99edd2550c01b 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare seems not important to test here #![feature(intrinsics, main)] diff --git a/src/test/run-pass/invoke-external-foreign.rs b/src/test/run-pass/invoke-external-foreign.rs index 1aae8131d8008..d01c3b67895e6 100644 --- a/src/test/run-pass/invoke-external-foreign.rs +++ b/src/test/run-pass/invoke-external-foreign.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:foreign_lib.rs +// ignore-wasm32-bare no libc to test ffi with // The purpose of this test is to check that we can // successfully (and safely) invoke external, cdecl diff --git a/src/test/run-pass/issue-1251.rs b/src/test/run-pass/issue-1251.rs index ddd30ed3bb0c0..00e8aa69a8942 100644 --- a/src/test/run-pass/issue-1251.rs +++ b/src/test/run-pass/issue-1251.rs @@ -9,6 +9,7 @@ // except according to those terms. // pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with #![feature(libc)] diff --git a/src/test/run-pass/issue-12699.rs b/src/test/run-pass/issue-12699.rs index 1e9f30bb766b2..4620d982c1ea5 100644 --- a/src/test/run-pass/issue-12699.rs +++ b/src/test/run-pass/issue-12699.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare can't block the thread + use std::thread; fn main() { diff --git a/src/test/run-pass/issue-13507-2.rs b/src/test/run-pass/issue-13507-2.rs index 084b7a166cdd3..75a724e55fb11 100644 --- a/src/test/run-pass/issue-13507-2.rs +++ b/src/test/run-pass/issue-13507-2.rs @@ -10,9 +10,6 @@ // aux-build:issue13507.rs - -#![feature(core)] - extern crate issue13507; use issue13507::testtypes; diff --git a/src/test/run-pass/issue-14875.rs b/src/test/run-pass/issue-14875.rs index ad19a9be76f88..e705539bb4772 100644 --- a/src/test/run-pass/issue-14875.rs +++ b/src/test/run-pass/issue-14875.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare always compiled as panic=abort right now + // Check that values are not leaked when a dtor panics (#14875) use std::panic::{self, UnwindSafe}; @@ -29,7 +31,6 @@ impl Drop for PanicOnDrop { } } - fn main() { let mut set_on_drop = false; { diff --git a/src/test/run-pass/issue-2214.rs b/src/test/run-pass/issue-2214.rs index 316e379e664ae..7b7ecc91484ba 100644 --- a/src/test/run-pass/issue-2214.rs +++ b/src/test/run-pass/issue-2214.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with #![feature(libc)] diff --git a/src/test/run-pass/issue-25185.rs b/src/test/run-pass/issue-25185.rs index d8d2d5078c5e7..9a2dbd1c96e31 100644 --- a/src/test/run-pass/issue-25185.rs +++ b/src/test/run-pass/issue-25185.rs @@ -10,6 +10,7 @@ // aux-build:issue-25185-1.rs // aux-build:issue-25185-2.rs +// ignore-wasm32-bare no libc for ffi testing extern crate issue_25185_2; diff --git a/src/test/run-pass/issue-28676.rs b/src/test/run-pass/issue-28676.rs index 8f83e51f0a02d..a7bee427a813c 100644 --- a/src/test/run-pass/issue-28676.rs +++ b/src/test/run-pass/issue-28676.rs @@ -7,7 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// + +// ignore-wasm32-bare no libc to test ffi with #[derive(Copy, Clone)] pub struct Quad { a: u64, b: u64, c: u64, d: u64 } diff --git a/src/test/run-pass/issue-29948.rs b/src/test/run-pass/issue-29948.rs index 281dde15bd336..3a7e9ba93e190 100644 --- a/src/test/run-pass/issue-29948.rs +++ b/src/test/run-pass/issue-29948.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + use std::panic; impl<'a> panic::UnwindSafe for Foo<'a> {} diff --git a/src/test/run-pass/issue-3012-2.rs b/src/test/run-pass/issue-3012-2.rs index ecce5df0fc200..bcf8a9180918c 100644 --- a/src/test/run-pass/issue-3012-2.rs +++ b/src/test/run-pass/issue-3012-2.rs @@ -12,15 +12,11 @@ // pretty-expanded FIXME #23616 -#![allow(unknown_features)] -#![feature(box_syntax, libc)] - extern crate socketlib; -extern crate libc; use socketlib::socket; pub fn main() { - let fd: libc::c_int = 1 as libc::c_int; - let _sock: Box<_> = box socket::socket_handle(fd); + let fd: u32 = 1 as u32; + let _sock: Box<_> = Box::new(socket::socket_handle(fd)); } diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs index 10930474799c5..c278dcef9dde7 100644 --- a/src/test/run-pass/issue-3656.rs +++ b/src/test/run-pass/issue-3656.rs @@ -13,6 +13,7 @@ // the alignment of elements into account. // pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test with #![feature(libc)] diff --git a/src/test/run-pass/issue-43853.rs b/src/test/run-pass/issue-43853.rs index f55d584ea24fb..e9f8d2744a16a 100644 --- a/src/test/run-pass/issue-43853.rs +++ b/src/test/run-pass/issue-43853.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + use std::panic; fn test() { diff --git a/src/test/run-pass/issue-4735.rs b/src/test/run-pass/issue-4735.rs index 56e69a9f36e78..7eb09e055a292 100644 --- a/src/test/run-pass/issue-4735.rs +++ b/src/test/run-pass/issue-4735.rs @@ -8,28 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // pretty-expanded FIXME #23616 -#![allow(unknown_features)] -#![feature(box_syntax, libc)] - -extern crate libc; - use std::mem::transmute; -use libc::c_void; -struct NonCopyable(*const c_void); +struct NonCopyable(*const u8); impl Drop for NonCopyable { fn drop(&mut self) { let NonCopyable(p) = *self; - let _v = unsafe { transmute::<*const c_void, Box>(p) }; + let _v = unsafe { transmute::<*const u8, Box>(p) }; } } pub fn main() { - let t = box 0; - let p = unsafe { transmute::, *const c_void>(t) }; + let t = Box::new(0); + let p = unsafe { transmute::, *const u8>(t) }; let _z = NonCopyable(p); } diff --git a/src/test/run-pass/issue-5791.rs b/src/test/run-pass/issue-5791.rs index aad90bd4181d9..2e93279f756f0 100644 --- a/src/test/run-pass/issue-5791.rs +++ b/src/test/run-pass/issue-5791.rs @@ -10,15 +10,11 @@ // pretty-expanded FIXME #23616 -#![feature(libc)] - -extern crate libc; - extern { #[link_name = "malloc"] - fn malloc1(len: libc::c_int) -> *const libc::c_void; + fn malloc1(len: i32) -> *const u8; #[link_name = "malloc"] - fn malloc2(len: libc::c_int, foo: libc::c_int) -> *const libc::c_void; + fn malloc2(len: i32, foo: i32) -> *const u8; } pub fn main () {} diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index f1ac96ab63e5c..0fc13319b8734 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -12,8 +12,7 @@ // for completeness since .rs files linked from .rc files support this // notation to specify their module's attributes - -#![feature(custom_attribute, libc)] +#![feature(custom_attribute)] #![allow(unused_attribute)] #![attr1 = "val"] #![attr2 = "val"] @@ -159,13 +158,11 @@ mod test_other_forms { mod test_foreign_items { pub mod rustrt { - extern crate libc; - extern { #![attr] #[attr] - fn rust_get_test_int() -> libc::intptr_t; + fn rust_get_test_int() -> u32; } } } diff --git a/src/test/run-pass/iter-step-overflow-debug.rs b/src/test/run-pass/iter-step-overflow-debug.rs index 5b9b58f028894..c45a10eac52b1 100644 --- a/src/test/run-pass/iter-step-overflow-debug.rs +++ b/src/test/run-pass/iter-step-overflow-debug.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes use std::panic; diff --git a/src/test/run-pass/iter-sum-overflow-debug.rs b/src/test/run-pass/iter-sum-overflow-debug.rs index 6c07afb37b8a0..c640f7cd28045 100644 --- a/src/test/run-pass/iter-sum-overflow-debug.rs +++ b/src/test/run-pass/iter-sum-overflow-debug.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes use std::panic; diff --git a/src/test/run-pass/iter-sum-overflow-overflow-checks.rs b/src/test/run-pass/iter-sum-overflow-overflow-checks.rs index a3a7179fb7112..517cd139cf354 100644 --- a/src/test/run-pass/iter-sum-overflow-overflow-checks.rs +++ b/src/test/run-pass/iter-sum-overflow-overflow-checks.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C overflow-checks use std::panic; diff --git a/src/test/run-pass/lib-defaults.rs b/src/test/run-pass/lib-defaults.rs index 6e5dccae0a07d..fcaeda9a5495b 100644 --- a/src/test/run-pass/lib-defaults.rs +++ b/src/test/run-pass/lib-defaults.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + // compile-flags: -lrust_test_helpers #[link(name = "rust_test_helpers", kind = "static")] diff --git a/src/test/run-pass/mir_calls_to_shims.rs b/src/test/run-pass/mir_calls_to_shims.rs index 7300a322ec4b7..9641ed282936f 100644 --- a/src/test/run-pass/mir_calls_to_shims.rs +++ b/src/test/run-pass/mir_calls_to_shims.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + #![feature(fn_traits)] #![feature(never_type)] diff --git a/src/test/run-pass/mir_drop_order.rs b/src/test/run-pass/mir_drop_order.rs index e7da43597f169..41cb458c0b8b4 100644 --- a/src/test/run-pass/mir_drop_order.rs +++ b/src/test/run-pass/mir_drop_order.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + use std::cell::RefCell; use std::panic; diff --git a/src/test/run-pass/mir_misc_casts.rs b/src/test/run-pass/mir_misc_casts.rs index ae719ac2800ee..81c8b75fb9b6a 100644 --- a/src/test/run-pass/mir_misc_casts.rs +++ b/src/test/run-pass/mir_misc_casts.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc)] - -extern crate libc; - fn func(){} const STR: &'static str = "hello"; @@ -19,7 +15,7 @@ const BSTR: &'static [u8; 5] = b"hello"; fn from_ptr() -> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, *const ()) { - let f = 1_usize as *const libc::FILE; + let f = 1_usize as *const String; let c1 = f as isize; let c2 = f as usize; let c3 = f as i8; @@ -35,7 +31,7 @@ fn from_ptr() } fn from_1() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1 as isize; let c2 = 1 as usize; let c3 = 1 as i8; @@ -48,12 +44,12 @@ fn from_1() let c10 = 1 as u64; let c11 = 1 as f32; let c12 = 1 as f64; - let c13 = 1 as *const libc::FILE; + let c13 = 1 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1usize() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_usize as isize; let c2 = 1_usize as usize; let c3 = 1_usize as i8; @@ -66,12 +62,12 @@ fn from_1usize() let c10 = 1_usize as u64; let c11 = 1_usize as f32; let c12 = 1_usize as f64; - let c13 = 1_usize as *const libc::FILE; + let c13 = 1_usize as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1isize() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_isize as isize; let c2 = 1_isize as usize; let c3 = 1_isize as i8; @@ -84,12 +80,12 @@ fn from_1isize() let c10 = 1_isize as u64; let c11 = 1_isize as f32; let c12 = 1_isize as f64; - let c13 = 1_isize as *const libc::FILE; + let c13 = 1_isize as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1u8() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_u8 as isize; let c2 = 1_u8 as usize; let c3 = 1_u8 as i8; @@ -102,12 +98,12 @@ fn from_1u8() let c10 = 1_u8 as u64; let c11 = 1_u8 as f32; let c12 = 1_u8 as f64; - let c13 = 1_u8 as *const libc::FILE; + let c13 = 1_u8 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1i8() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_i8 as isize; let c2 = 1_i8 as usize; let c3 = 1_i8 as i8; @@ -120,12 +116,12 @@ fn from_1i8() let c10 = 1_i8 as u64; let c11 = 1_i8 as f32; let c12 = 1_i8 as f64; - let c13 = 1_i8 as *const libc::FILE; + let c13 = 1_i8 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1u16() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_u16 as isize; let c2 = 1_u16 as usize; let c3 = 1_u16 as i8; @@ -138,12 +134,12 @@ fn from_1u16() let c10 = 1_u16 as u64; let c11 = 1_u16 as f32; let c12 = 1_u16 as f64; - let c13 = 1_u16 as *const libc::FILE; + let c13 = 1_u16 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1i16() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_i16 as isize; let c2 = 1_i16 as usize; let c3 = 1_i16 as i8; @@ -156,12 +152,12 @@ fn from_1i16() let c10 = 1_i16 as u64; let c11 = 1_i16 as f32; let c12 = 1_i16 as f64; - let c13 = 1_i16 as *const libc::FILE; + let c13 = 1_i16 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1u32() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_u32 as isize; let c2 = 1_u32 as usize; let c3 = 1_u32 as i8; @@ -174,12 +170,12 @@ fn from_1u32() let c10 = 1_u32 as u64; let c11 = 1_u32 as f32; let c12 = 1_u32 as f64; - let c13 = 1_u32 as *const libc::FILE; + let c13 = 1_u32 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1i32() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_i32 as isize; let c2 = 1_i32 as usize; let c3 = 1_i32 as i8; @@ -192,12 +188,12 @@ fn from_1i32() let c10 = 1_i32 as u64; let c11 = 1_i32 as f32; let c12 = 1_i32 as f64; - let c13 = 1_i32 as *const libc::FILE; + let c13 = 1_i32 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1u64() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_u64 as isize; let c2 = 1_u64 as usize; let c3 = 1_u64 as i8; @@ -210,12 +206,12 @@ fn from_1u64() let c10 = 1_u64 as u64; let c11 = 1_u64 as f32; let c12 = 1_u64 as f64; - let c13 = 1_u64 as *const libc::FILE; + let c13 = 1_u64 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } fn from_1i64() --> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) { +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { let c1 = 1_i64 as isize; let c2 = 1_i64 as usize; let c3 = 1_i64 as i8; @@ -228,7 +224,7 @@ fn from_1i64() let c10 = 1_i64 as u64; let c11 = 1_i64 as f32; let c12 = 1_i64 as f64; - let c13 = 1_i64 as *const libc::FILE; + let c13 = 1_i64 as *const String; (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) } @@ -297,9 +293,9 @@ fn other_casts() } pub fn assert_eq_13(l: (isize, usize, i8, i16, i32, i64, u8, - u16, u32, u64, f32, f64, *const libc::FILE), + u16, u32, u64, f32, f64, *const String), r: (isize, usize, i8, i16, i32, i64, u8, - u16, u32, u64, f32, f64, *const libc::FILE)) -> bool { + u16, u32, u64, f32, f64, *const String)) -> bool { let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13) = l; let (r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13) = r; l1 == r1 && l2 == r2 && l3 == r3 && l4 == r4 && l5 == r5 && l6 == r6 && l7 == r7 && @@ -308,7 +304,7 @@ pub fn assert_eq_13(l: (isize, usize, i8, i16, i32, i64, u8, pub fn main() { - let f = 1_usize as *const libc::FILE; + let f = 1_usize as *const String; let t13 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0, f); let t12 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0); assert_eq_13(from_1(), t13); diff --git a/src/test/run-pass/mir_trans_calls_variadic.rs b/src/test/run-pass/mir_trans_calls_variadic.rs index e4d528e80e104..7845c9426e23b 100644 --- a/src/test/run-pass/mir_trans_calls_variadic.rs +++ b/src/test/run-pass/mir_trans_calls_variadic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + #[link(name = "rust_test_helpers", kind = "static")] extern { fn rust_interesting_average(_: i64, ...) -> f64; diff --git a/src/test/run-pass/newtype-struct-with-dtor.rs b/src/test/run-pass/newtype-struct-with-dtor.rs index d1ad5614e3f35..07c76e27284f5 100644 --- a/src/test/run-pass/newtype-struct-with-dtor.rs +++ b/src/test/run-pass/newtype-struct-with-dtor.rs @@ -8,21 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // pretty-expanded FIXME #23616 -#![feature(libc)] - -extern crate libc; -use libc::c_int; +pub struct Fd(u32); -pub struct Fd(c_int); +fn foo(a: u32) {} impl Drop for Fd { fn drop(&mut self) { unsafe { let Fd(s) = *self; - libc::close(s); + foo(s); } } } diff --git a/src/test/run-pass/paths-containing-nul.rs b/src/test/run-pass/paths-containing-nul.rs index 2da3e59e54c58..9f39146e238d6 100644 --- a/src/test/run-pass/paths-containing-nul.rs +++ b/src/test/run-pass/paths-containing-nul.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no files or I/O + use std::fs; use std::io; diff --git a/src/test/run-pass/pub-extern-privacy.rs b/src/test/run-pass/pub-extern-privacy.rs index b9a3f788f9794..1ef804fe8feea 100644 --- a/src/test/run-pass/pub-extern-privacy.rs +++ b/src/test/run-pass/pub-extern-privacy.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + // pretty-expanded FIXME #23616 use std::mem::transmute; diff --git a/src/test/run-pass/reachable-unnameable-items.rs b/src/test/run-pass/reachable-unnameable-items.rs index 75a2e36ffb7a4..d087be6d10cfc 100644 --- a/src/test/run-pass/reachable-unnameable-items.rs +++ b/src/test/run-pass/reachable-unnameable-items.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default // aux-build:reachable-unnameable-items.rs extern crate reachable_unnameable_items; diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index 4863979b3f6c2..d051e05b5f9e7 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare seems unimportant to test + // Issue #2303 #![feature(intrinsics)] diff --git a/src/test/run-pass/regions-mock-trans.rs b/src/test/run-pass/regions-mock-trans.rs index b67612c94b009..8f278a315d1af 100644 --- a/src/test/run-pass/regions-mock-trans.rs +++ b/src/test/run-pass/regions-mock-trans.rs @@ -10,10 +10,9 @@ // pretty-expanded FIXME #23616 -#![feature(libc)] +#![feature(allocator_api)] -extern crate libc; -use std::mem; +use std::heap::{Alloc, Heap, Layout}; struct arena(()); @@ -32,8 +31,9 @@ struct Ccx { fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> { unsafe { - mem::transmute(libc::malloc(mem::size_of::>() - as libc::size_t)) + let ptr = Heap.alloc(Layout::new::()) + .unwrap_or_else(|e| Heap.oom(e)); + &*(ptr as *const _) } } @@ -45,7 +45,7 @@ fn g(fcx : &Fcx) { let bcx = Bcx { fcx: fcx }; let bcx2 = h(&bcx); unsafe { - libc::free(mem::transmute(bcx2)); + Heap.dealloc(bcx2 as *const _ as *mut _, Layout::new::()); } } diff --git a/src/test/run-pass/rfc-1014.rs b/src/test/run-pass/rfc-1014.rs index df969070a2ad4..950c2e0c4dfab 100644 --- a/src/test/run-pass/rfc-1014.rs +++ b/src/test/run-pass/rfc-1014.rs @@ -7,6 +7,9 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + +// ignore-wasm32-bare no libc + #![feature(libc)] extern crate libc; diff --git a/src/test/run-pass/rfc1717/library-override.rs b/src/test/run-pass/rfc1717/library-override.rs index 26713a2554377..c51b33f9c4af6 100644 --- a/src/test/run-pass/rfc1717/library-override.rs +++ b/src/test/run-pass/rfc1717/library-override.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with // compile-flags: -lstatic=wronglibrary:rust_test_helpers #[link(name = "wronglibrary", kind = "dylib")] diff --git a/src/test/run-pass/rfc1857-drop-order.rs b/src/test/run-pass/rfc1857-drop-order.rs index 42f989538c890..b2e5ff62eb86e 100644 --- a/src/test/run-pass/rfc1857-drop-order.rs +++ b/src/test/run-pass/rfc1857-drop-order.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default + #![allow(dead_code, unreachable_code)] use std::cell::RefCell; diff --git a/src/test/run-pass/signal-alternate-stack-cleanup.rs b/src/test/run-pass/signal-alternate-stack-cleanup.rs index 26fa36f0c13d4..73ccd28a3e963 100644 --- a/src/test/run-pass/signal-alternate-stack-cleanup.rs +++ b/src/test/run-pass/signal-alternate-stack-cleanup.rs @@ -13,6 +13,7 @@ // triggers this situation by sending signal from atexit handler. // // ignore-windows +// ignore-wasm32-bare no libc #![feature(libc)] extern crate libc; diff --git a/src/test/run-pass/static-method-xcrate.rs b/src/test/run-pass/static-method-xcrate.rs index 57609cec9f2b0..ab6adcbbffe7a 100644 --- a/src/test/run-pass/static-method-xcrate.rs +++ b/src/test/run-pass/static-method-xcrate.rs @@ -10,7 +10,6 @@ // aux-build:static-methods-crate.rs - extern crate static_methods_crate; use static_methods_crate::read; diff --git a/src/test/run-pass/static-mut-foreign.rs b/src/test/run-pass/static-mut-foreign.rs index 24d58487f061e..2b7fa0166a8ed 100644 --- a/src/test/run-pass/static-mut-foreign.rs +++ b/src/test/run-pass/static-mut-foreign.rs @@ -12,6 +12,7 @@ // statics cannot. This ensures that there's some form of error if this is // attempted. +// ignore-wasm32-bare no libc to test ffi with #![feature(libc)] diff --git a/src/test/run-pass/struct-return.rs b/src/test/run-pass/struct-return.rs index ed618cea98ac0..61a2bcb3a9b75 100644 --- a/src/test/run-pass/struct-return.rs +++ b/src/test/run-pass/struct-return.rs @@ -7,7 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// + +// ignore-wasm32-bare no libc to test ffi with #[repr(C)] #[derive(Copy, Clone)] diff --git a/src/test/run-pass/supported-cast.rs b/src/test/run-pass/supported-cast.rs index a47ae52f5902c..7f92707586b28 100644 --- a/src/test/run-pass/supported-cast.rs +++ b/src/test/run-pass/supported-cast.rs @@ -8,12 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc)] - -extern crate libc; - pub fn main() { - let f = 1_usize as *const libc::FILE; + let f = 1_usize as *const String; println!("{:?}", f as isize); println!("{:?}", f as usize); println!("{:?}", f as i8); @@ -27,7 +23,7 @@ pub fn main() { println!("{:?}", 1 as isize); println!("{:?}", 1 as usize); - println!("{:?}", 1 as *const libc::FILE); + println!("{:?}", 1 as *const String); println!("{:?}", 1 as i8); println!("{:?}", 1 as i16); println!("{:?}", 1 as i32); @@ -41,7 +37,7 @@ pub fn main() { println!("{:?}", 1_usize as isize); println!("{:?}", 1_usize as usize); - println!("{:?}", 1_usize as *const libc::FILE); + println!("{:?}", 1_usize as *const String); println!("{:?}", 1_usize as i8); println!("{:?}", 1_usize as i16); println!("{:?}", 1_usize as i32); @@ -55,7 +51,7 @@ pub fn main() { println!("{:?}", 1i8 as isize); println!("{:?}", 1i8 as usize); - println!("{:?}", 1i8 as *const libc::FILE); + println!("{:?}", 1i8 as *const String); println!("{:?}", 1i8 as i8); println!("{:?}", 1i8 as i16); println!("{:?}", 1i8 as i32); @@ -69,7 +65,7 @@ pub fn main() { println!("{:?}", 1u8 as isize); println!("{:?}", 1u8 as usize); - println!("{:?}", 1u8 as *const libc::FILE); + println!("{:?}", 1u8 as *const String); println!("{:?}", 1u8 as i8); println!("{:?}", 1u8 as i16); println!("{:?}", 1u8 as i32); @@ -83,7 +79,7 @@ pub fn main() { println!("{:?}", 1i16 as isize); println!("{:?}", 1i16 as usize); - println!("{:?}", 1i16 as *const libc::FILE); + println!("{:?}", 1i16 as *const String); println!("{:?}", 1i16 as i8); println!("{:?}", 1i16 as i16); println!("{:?}", 1i16 as i32); @@ -97,7 +93,7 @@ pub fn main() { println!("{:?}", 1u16 as isize); println!("{:?}", 1u16 as usize); - println!("{:?}", 1u16 as *const libc::FILE); + println!("{:?}", 1u16 as *const String); println!("{:?}", 1u16 as i8); println!("{:?}", 1u16 as i16); println!("{:?}", 1u16 as i32); @@ -111,7 +107,7 @@ pub fn main() { println!("{:?}", 1i32 as isize); println!("{:?}", 1i32 as usize); - println!("{:?}", 1i32 as *const libc::FILE); + println!("{:?}", 1i32 as *const String); println!("{:?}", 1i32 as i8); println!("{:?}", 1i32 as i16); println!("{:?}", 1i32 as i32); @@ -125,7 +121,7 @@ pub fn main() { println!("{:?}", 1u32 as isize); println!("{:?}", 1u32 as usize); - println!("{:?}", 1u32 as *const libc::FILE); + println!("{:?}", 1u32 as *const String); println!("{:?}", 1u32 as i8); println!("{:?}", 1u32 as i16); println!("{:?}", 1u32 as i32); @@ -139,7 +135,7 @@ pub fn main() { println!("{:?}", 1i64 as isize); println!("{:?}", 1i64 as usize); - println!("{:?}", 1i64 as *const libc::FILE); + println!("{:?}", 1i64 as *const String); println!("{:?}", 1i64 as i8); println!("{:?}", 1i64 as i16); println!("{:?}", 1i64 as i32); @@ -153,7 +149,7 @@ pub fn main() { println!("{:?}", 1u64 as isize); println!("{:?}", 1u64 as usize); - println!("{:?}", 1u64 as *const libc::FILE); + println!("{:?}", 1u64 as *const String); println!("{:?}", 1u64 as i8); println!("{:?}", 1u64 as i16); println!("{:?}", 1u64 as i32); @@ -167,7 +163,7 @@ pub fn main() { println!("{:?}", 1u64 as isize); println!("{:?}", 1u64 as usize); - println!("{:?}", 1u64 as *const libc::FILE); + println!("{:?}", 1u64 as *const String); println!("{:?}", 1u64 as i8); println!("{:?}", 1u64 as i16); println!("{:?}", 1u64 as i32); diff --git a/src/test/run-pass/sync-send-in-std.rs b/src/test/run-pass/sync-send-in-std.rs index 85ab59a298323..4dadfdf9c756e 100644 --- a/src/test/run-pass/sync-send-in-std.rs +++ b/src/test/run-pass/sync-send-in-std.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare networking not available + #![feature(lookup_host)] use std::net::lookup_host; diff --git a/src/test/run-pass/test-allow-fail-attr.rs b/src/test/run-pass/test-allow-fail-attr.rs index aa9cf76617f69..884633df66b1b 100644 --- a/src/test/run-pass/test-allow-fail-attr.rs +++ b/src/test/run-pass/test-allow-fail-attr.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #![feature(allow_fail)] diff --git a/src/test/run-pass/test-should-fail-good-message.rs b/src/test/run-pass/test-should-fail-good-message.rs index e665fa4fc7b58..360d4952d16aa 100644 --- a/src/test/run-pass/test-should-fail-good-message.rs +++ b/src/test/run-pass/test-should-fail-good-message.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #[test] #[should_panic(expected = "foo")] diff --git a/src/test/run-pass/union/union-c-interop.rs b/src/test/run-pass/union/union-c-interop.rs index b3df7d658b15f..dd16bf2e4a38e 100644 --- a/src/test/run-pass/union/union-c-interop.rs +++ b/src/test/run-pass/union/union-c-interop.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + #[derive(Clone, Copy)] #[repr(C)] struct LARGE_INTEGER_U { diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index ec6261febc54d..2198ead106bb7 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + #[link(name = "rust_test_helpers", kind = "static")] extern { fn rust_interesting_average(_: u64, ...) -> f64; diff --git a/src/test/run-pass/x86stdcall.rs b/src/test/run-pass/x86stdcall.rs index 106bf8ce7dfa4..e2e64ddfa3158 100644 --- a/src/test/run-pass/x86stdcall.rs +++ b/src/test/run-pass/x86stdcall.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32-bare no libc to test ffi with + // GetLastError doesn't seem to work with stack switching #[cfg(windows)] diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index e03d9f89e5d8c..39f41f57d11df 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -531,7 +531,7 @@ impl Config { let name = line[prefix.len()+1 ..].split(&[':', ' '][..]).next().unwrap(); name == "test" || - name == util::get_os(&self.target) || // target + util::matches_os(&self.target, name) || // target name == util::get_arch(&self.target) || // architecture name == util::get_pointer_width(&self.target) || // pointer width name == self.stage_id.split('-').next().unwrap() || // stage diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2ff3eb7678f1a..3e3c56a07962a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1271,6 +1271,7 @@ actual:\n\ let crate_type = if aux_props.no_prefer_dynamic { None } else if (self.config.target.contains("musl") && !aux_props.force_host) || + self.config.target.contains("wasm32") || self.config.target.contains("emscripten") { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible @@ -1431,7 +1432,10 @@ actual:\n\ } } - if !self.props.no_prefer_dynamic { + + if self.config.target == "wasm32-unknown-unknown" { + // rustc.arg("-g"); // get any backtrace at all on errors + } else if !self.props.no_prefer_dynamic { rustc.args(&["-C", "prefer-dynamic"]); } @@ -1472,6 +1476,10 @@ actual:\n\ let mut fname = f.file_name().unwrap().to_os_string(); fname.push(".js"); f.set_file_name(&fname); + } else if self.config.target.contains("wasm32") { + let mut fname = f.file_name().unwrap().to_os_string(); + fname.push(".wasm"); + f.set_file_name(&fname); } else if !env::consts::EXE_SUFFIX.is_empty() { let mut fname = f.file_name().unwrap().to_os_string(); fname.push(env::consts::EXE_SUFFIX); @@ -1494,6 +1502,22 @@ actual:\n\ } } + // If this is otherwise wasm , then run tests under nodejs with our + // shim + if self.config.target.contains("wasm32") { + if let Some(ref p) = self.config.nodejs { + args.push(p.clone()); + } else { + self.fatal("no NodeJS binary found (--nodejs)"); + } + + let src = self.config.src_base + .parent().unwrap() // chop off `run-pass` + .parent().unwrap() // chop off `test` + .parent().unwrap(); // chop off `src` + args.push(src.join("src/etc/wasm32-shim.js").display().to_string()); + } + let exe_file = self.make_exe_name(); // FIXME (#9639): This needs to handle non-utf8 paths diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index bd4044b4df3b4..c00f28eae67af 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -51,10 +51,15 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("wasm32", "wasm32"), ]; -pub fn get_os(triple: &str) -> &'static str { +pub fn matches_os(triple: &str, name: &str) -> bool { + // For the wasm32 bare target we ignore anything also ignored on emscripten + // and then we also recognize `wasm32-bare` as the os for the target + if triple == "wasm32-unknown-unknown" { + return name == "emscripten" || name == "wasm32-bare" + } for &(triple_os, os) in OS_TABLE { if triple.contains(triple_os) { - return os; + return os == name; } } panic!("Cannot determine OS from triple"); diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index c316ec467620a..598620fa29392 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -50,6 +50,8 @@ pub mod unstable_book; fn filter_dirs(path: &Path) -> bool { let skip = [ + "src/binaryen", + "src/dlmalloc", "src/jemalloc", "src/llvm", "src/libbacktrace",