diff --git a/Cargo.lock b/Cargo.lock index 5e6bde1db7cd5..ff289ab163f84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -819,7 +819,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "fortanix-sgx-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2216,6 +2216,7 @@ dependencies = [ name = "rustc-main" version = "0.0.0" dependencies = [ + "jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_codegen_ssa 0.0.0", "rustc_driver 0.0.0", "rustc_target 0.0.0", @@ -2402,7 +2403,6 @@ dependencies = [ "arena 0.0.0", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2892,7 +2892,7 @@ dependencies = [ "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "dlmalloc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fortanix-sgx-abi 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "panic_abort 0.0.0", "panic_unwind 0.0.0", @@ -3449,7 +3449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fortanix-sgx-abi 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "26105e20b4c3f7a319db1376b54ac9a46e5761e949405553375095d05a0cee4d" +"checksum fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3f8cbee5e872cf7db61a999a041f9bc4706ca7bf7df4cb914f53fabb1c1bc550" "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" "checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" "checksum fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d94485a00b1827b861dd9d1a2cc9764f9044d4c535514c0760a5a2012ef3399f" diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 84e7c40e4559e..5d486c04b427e 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -48,7 +48,6 @@ impl Step for Std { builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, - vec![], &libstd_stamp(builder, compiler, target), true); @@ -95,7 +94,6 @@ impl Step for Rustc { builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, - vec![], &librustc_stamp(builder, compiler, target), true); @@ -146,7 +144,6 @@ impl Step for CodegenBackend { let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage)); run_cargo(builder, &mut cargo, - vec![], &codegen_backend_stamp(builder, compiler, target, backend), true); } @@ -184,7 +181,6 @@ impl Step for Test { builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, - vec![], &libtest_stamp(builder, compiler, target), true); @@ -232,7 +228,6 @@ impl Step for Rustdoc { println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target); run_cargo(builder, &mut cargo, - vec![], &rustdoc_stamp(builder, compiler, target), true); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 61a04b9720602..366df4b0ad5cc 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -29,6 +29,7 @@ use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use serde_json; +use crate::dist; use crate::util::{exe, libdir, is_dylib}; use crate::{Compiler, Mode, GitRepo}; use crate::native; @@ -114,7 +115,6 @@ impl Step for Std { &compiler.host, target)); run_cargo(builder, &mut cargo, - vec![], &libstd_stamp(builder, compiler, target), false); @@ -375,7 +375,6 @@ impl Step for Test { &compiler.host, target)); run_cargo(builder, &mut cargo, - vec![], &libtest_stamp(builder, compiler, target), false); @@ -503,7 +502,6 @@ impl Step for Rustc { compiler.stage, &compiler.host, target)); run_cargo(builder, &mut cargo, - vec![], &librustc_stamp(builder, compiler, target), false); @@ -646,47 +644,18 @@ impl Step for CodegenBackend { let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); - let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "rustc"); + let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build"); cargo.arg("--manifest-path") .arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); rustc_cargo_env(builder, &mut cargo); let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); - let mut cargo_tails_args = vec![]; - - if builder.config.llvm_thin_lto { - cargo_tails_args.push("--".to_string()); - - let num_jobs = builder.jobs(); - - if !target.contains("msvc") { - // Here we assume that the linker is clang. If it's not, there'll - // be linker errors. - cargo_tails_args.push("-Clink-arg=-fuse-ld=lld".to_string()); - cargo_tails_args.push("-Clink-arg=-flto=thin".to_string()); - - if builder.config.llvm_optimize { - cargo_tails_args.push("-Clink-arg=-O2".to_string()); - } - - // Let's make LLD respect the `-j` option. - let num_jobs_arg = format!("-Clink-arg=-Wl,--thinlto-jobs={}", num_jobs); - cargo_tails_args.push(num_jobs_arg); - } else { - // Here we assume that the linker is lld-link.exe. lld-link.exe - // does not need the extra arguments except for num_jobs - let num_jobs_arg = format!("-Clink-arg=/opt:lldltojobs={}", num_jobs); - cargo_tails_args.push(num_jobs_arg); - } - } - let tmp_stamp = out_dir.join(".tmp.stamp"); let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage)); let files = run_cargo(builder, cargo.arg("--features").arg(features), - cargo_tails_args, &tmp_stamp, false); if builder.config.dry_run { @@ -759,7 +728,9 @@ pub fn build_codegen_backend(builder: &Builder, "libstdc++.a"); cargo.env("LLVM_STATIC_STDCPP", file); } - if builder.config.llvm_link_shared { + if builder.config.llvm_link_shared || + (builder.config.llvm_thin_lto && backend != "emscripten") + { cargo.env("LLVM_LINK_SHARED", "1"); } } @@ -999,6 +970,8 @@ impl Step for Assemble { copy_lld_to_sysroot(builder, target_compiler, &lld_install); } + dist::maybe_install_llvm_dylib(builder, target_compiler.host, &sysroot); + // Link the compiler binary itself into place let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host); let rustc = out_dir.join(exe("rustc_binary", &*host)); @@ -1025,7 +998,6 @@ pub fn add_to_sysroot(builder: &Builder, sysroot_dst: &Path, stamp: &Path) { pub fn run_cargo(builder: &Builder, cargo: &mut Command, - tail_args: Vec, stamp: &Path, is_check: bool) -> Vec @@ -1048,7 +1020,7 @@ pub fn run_cargo(builder: &Builder, // files we need to probe for later. let mut deps = Vec::new(); let mut toplevel = Vec::new(); - let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| { + let ok = stream_cargo(builder, cargo, &mut |msg| { let filenames = match msg { CargoMessage::CompilerArtifact { filenames, .. } => filenames, _ => return, @@ -1173,7 +1145,6 @@ pub fn run_cargo(builder: &Builder, pub fn stream_cargo( builder: &Builder, cargo: &mut Command, - tail_args: Vec, cb: &mut dyn FnMut(CargoMessage), ) -> bool { if builder.config.dry_run { @@ -1184,10 +1155,6 @@ pub fn stream_cargo( cargo.arg("--message-format").arg("json") .stdout(Stdio::piped()); - for arg in tail_args { - cargo.arg(arg); - } - builder.verbose(&format!("running: {:?}", cargo)); let mut child = match cargo.spawn() { Ok(child) => child, diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 927f9bf8ddbca..55ec4af0382b0 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1888,13 +1888,13 @@ impl Step for HashSign { // LLVM tools are linked dynamically. // Note: This function does no yet support Windows but we also don't support // linking LLVM tools dynamically on Windows yet. -fn maybe_install_llvm_dylib(builder: &Builder, - target: Interned, - image: &Path) { +pub fn maybe_install_llvm_dylib(builder: &Builder, + target: Interned, + sysroot: &Path) { let src_libdir = builder .llvm_out(target) .join("lib"); - let dst_libdir = image.join("lib/rustlib").join(&*target).join("lib"); + let dst_libdir = sysroot.join("lib/rustlib").join(&*target).join("lib"); t!(fs::create_dir_all(&dst_libdir)); if target.contains("apple-darwin") { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 4335359e11589..d2fc26e5812c2 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -87,7 +87,7 @@ impl Step for ToolBuild { let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool)); builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| { + let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { | "rls" diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile index 10aedf6a60e10..24e2dea4ca773 100644 --- a/src/ci/docker/mingw-check/Dockerfile +++ b/src/ci/docker/mingw-check/Dockerfile @@ -21,4 +21,5 @@ RUN sh /scripts/sccache.sh ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ - python2.7 ../x.py build --stage 0 src/tools/build-manifest + python2.7 ../x.py build --stage 0 src/tools/build-manifest && \ + python2.7 ../x.py test --stage 0 src/tools/compiletest diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 7438f3e6c9df5..859749780b472 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -443,6 +443,18 @@ impl Hasher for Box { #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Box { + /// Converts a generic type `T` into a `Box` + /// + /// The conversion allocates on the heap and moves `t` + /// from the stack into it. + /// + /// # Examples + /// ```rust + /// let x = 5; + /// let boxed = Box::new(5); + /// + /// assert_eq!(Box::from(x), boxed); + /// ``` fn from(t: T) -> Self { Box::new(t) } @@ -450,6 +462,9 @@ impl From for Box { #[stable(feature = "pin", since = "1.33.0")] impl From> for Pin> { + /// Converts a `Box` into a `Pin>` + /// + /// This conversion does not allocate on the heap and happens in place. fn from(boxed: Box) -> Self { // It's not possible to move or replace the insides of a `Pin>` // when `T: !Unpin`, so it's safe to pin it directly without any @@ -460,6 +475,19 @@ impl From> for Pin> { #[stable(feature = "box_from_slice", since = "1.17.0")] impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { + /// Converts a `&[T]` into a `Box<[T]>` + /// + /// This conversion allocates on the heap + /// and performs a copy of `slice`. + /// + /// # Examples + /// ```rust + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice: Box<[u8]> = Box::from(slice); + /// + /// println!("{:?}", boxed_slice); + /// ``` fn from(slice: &'a [T]) -> Box<[T]> { let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; boxed.copy_from_slice(slice); @@ -469,6 +497,16 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { #[stable(feature = "box_from_slice", since = "1.17.0")] impl<'a> From<&'a str> for Box { + /// Converts a `&str` into a `Box` + /// + /// This conversion allocates on the heap + /// and performs a copy of `s`. + /// + /// # Examples + /// ```rust + /// let boxed: Box = Box::from("hello"); + /// println!("{}", boxed); + /// ``` #[inline] fn from(s: &'a str) -> Box { unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } @@ -477,6 +515,22 @@ impl<'a> From<&'a str> for Box { #[stable(feature = "boxed_str_conv", since = "1.19.0")] impl From> for Box<[u8]> { + /// Converts a `Box>` into a `Box<[u8]>` + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// # Examples + /// ```rust + /// // create a Box which will be used to create a Box<[u8]> + /// let boxed: Box = Box::from("hello"); + /// let boxed_str: Box<[u8]> = Box::from(boxed); + /// + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice = Box::from(slice); + /// + /// assert_eq!(boxed_slice, boxed_str); + /// ``` #[inline] fn from(s: Box) -> Self { unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) } diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index f77d8eb6f7c55..c1dcfcb7985c4 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -162,7 +162,7 @@ pub trait Iterator { /// That said, the implementation should provide a correct estimation, /// because otherwise it would be a violation of the trait's protocol. /// - /// The default implementation returns `(0, None)` which is correct for any + /// The default implementation returns `(0, `[`None`]`)` which is correct for any /// iterator. /// /// [`usize`]: ../../std/primitive.usize.html diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index b58d80e24857d..8bb3fc1295205 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1271,8 +1271,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "set the MIR optimization level (0-3, default: 1)"), mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes on LLVM >= 6)"), - arg_align_attributes: bool = (false, parse_bool, [TRACKED], - "emit align metadata for reference arguments"), dump_mir: Option = (None, parse_opt_string, [UNTRACKED], "dump MIR state to file. `val` is used to select which passes and functions to dump. For example: diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index b8954dee794f7..8c4f7a58dab40 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -456,6 +456,9 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { let linux_s390x = target.target_os == "linux" && target.arch == "s390x" && target.target_env == "gnu"; + let linux_sparc64 = target.target_os == "linux" + && target.arch == "sparc64" + && target.target_env == "gnu"; let rust_abi = match sig.abi { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true, _ => false @@ -489,12 +492,6 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { attrs.pointee_size = pointee.size; attrs.pointee_align = Some(pointee.align); - // HACK(eddyb) LLVM inserts `llvm.assume` calls when inlining functions - // with align attributes, and those calls later block optimizations. - if !is_return && !cx.tcx.sess.opts.debugging_opts.arg_align_attributes { - attrs.pointee_align = None; - } - // `Box` pointer parameters never alias because ownership is transferred // `&mut` pointer parameters never alias other parameters, // or mutable global data @@ -526,8 +523,9 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { if arg.layout.is_zst() { // For some forsaken reason, x86_64-pc-windows-gnu // doesn't ignore zero-sized struct arguments. - // The same is true for s390x-unknown-linux-gnu. - if is_return || rust_abi || (!win_x64_gnu && !linux_s390x) { + // The same is true for s390x-unknown-linux-gnu + // and sparc64-unknown-linux-gnu. + if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) { arg.mode = PassMode::Ignore; } } diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 82b1d7e8b40e4..090ff83ecc1a8 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -74,6 +74,10 @@ unsafe fn configure_llvm(sess: &Session) { add("-mergefunc-use-aliases"); } + // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes + // during inlining. Unfortunately these may block other optimizations. + add("-preserve-alignment-assumptions-during-inlining=false"); + for arg in &sess.opts.cg.llvm_args { add(&(*arg)); } diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index d0cdb8924dfff..43198937e3db6 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -24,6 +24,8 @@ #![allow(dead_code)] #![feature(quote)] +#![recursion_limit="256"] + //! This crate contains codegen code that is used by all codegen backends (LLVM and others). //! The backend-agnostic functions of this crate use functions defined in various traits that //! have to be implemented by each backends. diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 0356cc9bd545f..8bcda409e6663 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -38,8 +38,3 @@ syntax = { path = "../libsyntax" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } - -[dependencies.jemalloc-sys] -version = '0.1.8' -optional = true -features = ['unprefixed_malloc_on_supported_platforms'] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 5527c0ad38787..b56ae61227c85 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -63,14 +63,6 @@ extern crate syntax; extern crate syntax_ext; extern crate syntax_pos; -// Note that the linkage here should be all that we need, on Linux we're not -// prefixing the symbols here so this should naturally override our default -// allocator. On OSX it should override via the zone allocator. We shouldn't -// enable this by default on other platforms, so other platforms aren't handled -// here yet. -#[cfg(feature = "jemalloc-sys")] -extern crate jemalloc_sys; - use driver::CompileController; use pretty::{PpMode, UserIdentifiedItem}; @@ -218,14 +210,7 @@ pub fn run(run_compiler: F) -> isize } fn load_backend_from_dylib(path: &Path) -> fn() -> Box { - // Note that we're specifically using `open_global_now` here rather than - // `open`, namely we want the behavior on Unix of RTLD_GLOBAL and RTLD_NOW, - // where NOW means "bind everything right now" because we don't want - // surprises later on and RTLD_GLOBAL allows the symbols to be made - // available for future dynamic libraries opened. This is currently used by - // loading LLVM and then making its symbols available for other dynamic - // libraries. - let lib = DynamicLibrary::open_global_now(path).unwrap_or_else(|err| { + let lib = DynamicLibrary::open(Some(path)).unwrap_or_else(|err| { let err = format!("couldn't load codegen backend {:?}: {:?}", path, err); early_error(ErrorOutputType::default(), &err); }); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 9dbc9cbc43bc2..921be95c6a29f 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -30,6 +30,8 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] +#![recursion_limit="256"] + #[macro_use] extern crate syntax; #[macro_use] diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index ce482087bbae5..1b6453893375e 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -142,6 +142,10 @@ fn main() { continue; } + if flag.starts_with("-flto") { + continue; + } + // -Wdate-time is not supported by the netbsd cross compiler if is_crossed && target.contains("netbsd") && flag.contains("date-time") { continue; diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index f1c7b2be6fb86..c44339775686d 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -262,7 +262,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Scalar::Ptr(ptr) => { // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. - let align = self.check_bounds_ptr_maybe_dead(ptr)?; + let align = self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead)?; (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { @@ -297,17 +297,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end /// of an allocation (i.e., at the first *inaccessible* location) *is* considered /// in-bounds! This follows C's/LLVM's rules. - /// This function also works for deallocated allocations. - /// Use `.get(ptr.alloc_id)?.check_bounds_ptr(ptr)` if you want to force the allocation - /// to still be live. /// If you want to check bounds before doing a memory access, better first obtain /// an `Allocation` and call `check_bounds`. - pub fn check_bounds_ptr_maybe_dead( + pub fn check_bounds_ptr( &self, ptr: Pointer, + liveness: InboundsCheck, ) -> EvalResult<'tcx, Align> { - let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id); - ptr.check_in_alloc(allocation_size, InboundsCheck::MaybeDead)?; + let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id, liveness)?; + ptr.check_in_alloc(allocation_size, liveness)?; Ok(align) } } @@ -429,27 +427,37 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } - pub fn get_size_and_align(&self, id: AllocId) -> (Size, Align) { + /// Obtain the size and alignment of an allocation, even if that allocation has been deallocated + /// + /// If `liveness` is `InboundsCheck::Dead`, this function always returns `Ok` + pub fn get_size_and_align( + &self, + id: AllocId, + liveness: InboundsCheck, + ) -> EvalResult<'static, (Size, Align)> { if let Ok(alloc) = self.get(id) { - return (Size::from_bytes(alloc.bytes.len() as u64), alloc.align); + return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)); } // Could also be a fn ptr or extern static match self.tcx.alloc_map.lock().get(id) { - Some(AllocKind::Function(..)) => (Size::ZERO, Align::from_bytes(1).unwrap()), + Some(AllocKind::Function(..)) => Ok((Size::ZERO, Align::from_bytes(1).unwrap())), Some(AllocKind::Static(did)) => { // The only way `get` couldn't have worked here is if this is an extern static assert!(self.tcx.is_foreign_item(did)); // Use size and align of the type let ty = self.tcx.type_of(did); let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); - (layout.size, layout.align.abi) - } - _ => { - // Must be a deallocated pointer - *self.dead_alloc_map.get(&id).expect( - "allocation missing in dead_alloc_map" - ) + Ok((layout.size, layout.align.abi)) } + _ => match liveness { + InboundsCheck::MaybeDead => { + // Must be a deallocated pointer + Ok(*self.dead_alloc_map.get(&id).expect( + "allocation missing in dead_alloc_map" + )) + }, + InboundsCheck::Live => err!(DanglingPointerDeref), + }, } } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 7143d66ad9246..2fb9939c2ab54 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -17,7 +17,7 @@ use rustc::mir; use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx}; use rustc::mir::interpret::{ - GlobalId, AllocId, + GlobalId, AllocId, InboundsCheck, ConstValue, Pointer, Scalar, EvalResult, EvalErrorKind, }; @@ -647,7 +647,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => { // The niche must be just 0 (which an inbounds pointer value never is) let ptr_valid = niche_start == 0 && variants_start == variants_end && - self.memory.check_bounds_ptr_maybe_dead(ptr).is_ok(); + self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok(); if !ptr_valid { return err!(InvalidDiscriminant(raw_discr.erase_tag())); } diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index a5d2edbc5d439..81e2a3b3ff541 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -21,6 +21,8 @@ #![feature(nll)] #![feature(rustc_diagnostic_macros)] +#![recursion_limit="256"] + #[macro_use] extern crate rustc; extern crate rustc_mir; diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 2cc3f1efcb5f4..5228d9de65327 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -67,6 +67,8 @@ #![feature(nll)] #![feature(rustc_diagnostic_macros)] +#![recursion_limit="256"] + #[macro_use] extern crate syntax; extern crate rustc; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e543677ef0621..87bbf93777b91 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -18,6 +18,8 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] +#![recursion_limit="256"] + #[macro_use] extern crate bitflags; #[macro_use] diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 9cee00b9c76d0..9e3d9af5ba253 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -40,7 +40,7 @@ rustc_tsan = { path = "../librustc_tsan" } dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] -fortanix-sgx-abi = { version = "0.3.1", features = ['rustc-dep-of-std'] } +fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } [build-dependencies] cc = "1.0" diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 5bede9eafc14d..4a693bffddfc1 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -314,7 +314,7 @@ #![feature(alloc_layout_extra)] #![feature(maybe_uninit)] #![cfg_attr(target_env = "sgx", feature(global_asm, range_contains, slice_index_methods, - decl_macro, coerce_unsized))] + decl_macro, coerce_unsized, sgx_platform))] #![default_lib_allocator] diff --git a/src/libstd/os/fortanix_sgx/mod.rs b/src/libstd/os/fortanix_sgx/mod.rs new file mode 100644 index 0000000000000..825e7f359d64c --- /dev/null +++ b/src/libstd/os/fortanix_sgx/mod.rs @@ -0,0 +1,67 @@ +// Copyright 2018 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. + +//! Functionality specific to the `x86_64-fortanix-unknown-sgx` target. +//! +//! This includes functions to deal with memory isolation, usercalls, and the +//! SGX instruction set. + +#![deny(missing_docs, missing_debug_implementations)] +#![unstable(feature = "sgx_platform", issue = "56975")] + +/// Low-level interfaces to usercalls. See the [ABI documentation] for more +/// information. +/// +/// [ABI documentation]: https://docs.rs/fortanix-sgx-abi/ +pub mod usercalls { + pub use sys::abi::usercalls::*; + + /// Primitives for allocating memory in userspace as well as copying data + /// to and from user memory. + pub mod alloc { + pub use sys::abi::usercalls::alloc; + } + + /// Lowest-level interfaces to usercalls and usercall ABI type definitions. + pub mod raw { + use sys::abi::usercalls::raw::invoke_with_usercalls; + pub use sys::abi::usercalls::raw::do_usercall; + pub use sys::abi::usercalls::raw::{accept_stream, alloc, async_queues, bind_stream, close, + connect_stream, exit, flush, free, insecure_time, + launch_thread, read, read_alloc, send, wait, write}; + + macro_rules! define_usercallnrs { + ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => { + /// Usercall numbers as per the ABI. + #[repr(C)] + #[unstable(feature = "sgx_platform", issue = "56975")] + #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] + #[allow(missing_docs)] + pub enum UsercallNrs { + $($f,)* + } + }; + } + invoke_with_usercalls!(define_usercallnrs); + + // fortanix-sgx-abi re-exports + pub use sys::abi::usercalls::raw::{ByteBuffer, FifoDescriptor, Return, Usercall}; + pub use sys::abi::usercalls::raw::Error; + pub use sys::abi::usercalls::raw::{EV_RETURNQ_NOT_EMPTY, EV_UNPARK, EV_USERCALLQ_NOT_FULL, + FD_STDERR, FD_STDIN, FD_STDOUT, RESULT_SUCCESS, + USERCALL_USER_DEFINED, WAIT_INDEFINITE, WAIT_NO}; + pub use sys::abi::usercalls::raw::{Fd, Result, Tcs}; + } +} + +/// Functions for querying mapping information for pointers. +pub mod mem { + pub use sys::abi::mem::*; +} diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 1cb9799ff3c22..ba5b938ed4ccf 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -29,25 +29,10 @@ cfg_if! { #[doc(cfg(target_os = "linux"))] pub mod linux; - } else { - // If we're not documenting libstd then we just expose everything as we - // otherwise would. - - #[cfg(target_os = "android")] pub mod android; - #[cfg(target_os = "bitrig")] pub mod bitrig; - #[cfg(target_os = "dragonfly")] pub mod dragonfly; - #[cfg(target_os = "freebsd")] pub mod freebsd; - #[cfg(target_os = "haiku")] pub mod haiku; - #[cfg(target_os = "ios")] pub mod ios; - #[cfg(target_os = "macos")] pub mod macos; - #[cfg(target_os = "netbsd")] pub mod netbsd; - #[cfg(target_os = "openbsd")] pub mod openbsd; - #[cfg(target_os = "solaris")] pub mod solaris; - #[cfg(target_os = "emscripten")] pub mod emscripten; - #[cfg(target_os = "fuchsia")] pub mod fuchsia; - #[cfg(target_os = "hermit")] pub mod hermit; + // If we're not documenting libstd then we just expose the main modules + // as we otherwise would. #[cfg(any(target_os = "redox", unix))] #[stable(feature = "rust1", since = "1.0.0")] @@ -63,4 +48,19 @@ cfg_if! { } } +#[cfg(target_os = "android")] pub mod android; +#[cfg(target_os = "bitrig")] pub mod bitrig; +#[cfg(target_os = "dragonfly")] pub mod dragonfly; +#[cfg(target_os = "freebsd")] pub mod freebsd; +#[cfg(target_os = "haiku")] pub mod haiku; +#[cfg(target_os = "ios")] pub mod ios; +#[cfg(target_os = "macos")] pub mod macos; +#[cfg(target_os = "netbsd")] pub mod netbsd; +#[cfg(target_os = "openbsd")] pub mod openbsd; +#[cfg(target_os = "solaris")] pub mod solaris; +#[cfg(target_os = "emscripten")] pub mod emscripten; +#[cfg(target_os = "fuchsia")] pub mod fuchsia; +#[cfg(target_os = "hermit")] pub mod hermit; +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] pub mod fortanix_sgx; + pub mod raw; diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index 04c47aeb8276b..625202e560494 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -65,7 +65,7 @@ cfg_if! { if #[cfg(any(unix, target_os = "redox"))] { // On unix we'll document what's already available pub use self::ext as unix_ext; - } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] { + } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", target_env = "sgx"))] { // On CloudABI and wasm right now the module below doesn't compile // (missing things in `libc` which is empty) so just omit everything // with an empty module @@ -86,7 +86,7 @@ cfg_if! { // On windows we'll just be documenting what's already available #[allow(missing_docs)] pub use self::ext as windows_ext; - } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] { + } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", target_env = "sgx"))] { // On CloudABI and wasm right now the shim below doesn't compile, so // just omit it #[unstable(issue = "0", feature = "std_internals")] diff --git a/src/libstd/sys/sgx/abi/mem.rs b/src/libstd/sys/sgx/abi/mem.rs index bf32c712216bc..11eb64606c43e 100644 --- a/src/libstd/sys/sgx/abi/mem.rs +++ b/src/libstd/sys/sgx/abi/mem.rs @@ -10,13 +10,13 @@ // Do not remove inline: will result in relocation failure #[inline(always)] -pub unsafe fn rel_ptr(offset: u64) -> *const T { +pub(crate) unsafe fn rel_ptr(offset: u64) -> *const T { (image_base() + offset) as *const T } // Do not remove inline: will result in relocation failure #[inline(always)] -pub unsafe fn rel_ptr_mut(offset: u64) -> *mut T { +pub(crate) unsafe fn rel_ptr_mut(offset: u64) -> *mut T { (image_base() + offset) as *mut T } @@ -34,6 +34,17 @@ fn image_base() -> u64 { base } +/// Returns `true` if the specified memory range is in the enclave. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub fn is_enclave_range(p: *const u8, len: usize) -> bool { + let start=p as u64; + let end=start + (len as u64); + start >= image_base() && + end <= image_base() + (unsafe { ENCLAVE_SIZE } as u64) // unsafe ok: link-time constant +} + +/// Returns `true` if the specified memory range is in userspace. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn is_user_range(p: *const u8, len: usize) -> bool { let start=p as u64; let end=start + (len as u64); diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs index 069cca3b98e27..18ba221af5a23 100644 --- a/src/libstd/sys/sgx/abi/mod.rs +++ b/src/libstd/sys/sgx/abi/mod.rs @@ -13,10 +13,10 @@ use io::Write; // runtime features mod reloc; -mod mem; pub(super) mod panic; // library features +pub mod mem; pub mod thread; pub mod tls; #[macro_use] diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs index 64968a9970c48..f1689091eb593 100644 --- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs +++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs @@ -10,7 +10,7 @@ #![allow(unused)] -use ptr; +use ptr::{self, NonNull}; use mem; use cell::UnsafeCell; use slice; @@ -39,39 +39,78 @@ use super::super::mem::is_user_range; /// as vtable pointers) must not be leaked for confidentiality reasons. /// /// Non-exhaustive list of specific requirements for reading from userspace: -/// * Any bit pattern is valid for this type (no `enum`s). There can be no +/// * **Any bit pattern is valid** for this type (no `enum`s). There can be no /// guarantee that the value correctly adheres to the expectations of the /// type, so any value must be valid for this type. /// /// Non-exhaustive list of specific requirements for writing to userspace: -/// * No pointers to enclave memory. Memory addresses of data in enclave memory -/// must not be leaked for confidentiality reasons. -/// * No internal padding. Padding might contain previously-initialized secret -/// data stored at that memory location and must not be leaked for +/// * **No pointers to enclave memory.** Memory addresses of data in enclave +/// memory must not be leaked for confidentiality reasons. +/// * **No internal padding.** Padding might contain previously-initialized +/// secret data stored at that memory location and must not be leaked for /// confidentiality reasons. +#[unstable(feature = "sgx_platform", issue = "56975")] pub unsafe trait UserSafeSized: Copy + Sized {} +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafeSized for u8 {} +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafeSized for FifoDescriptor {} +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafeSized for ByteBuffer {} +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafeSized for Usercall {} +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafeSized for Return {} +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafeSized for [T; 2] {} /// A type that can be represented in memory as one or more `UserSafeSized`s. +#[unstable(feature = "sgx_platform", issue = "56975")] pub unsafe trait UserSafe { - unsafe fn align_of() -> usize; + /// Equivalent to `mem::align_of::`. + fn align_of() -> usize; + /// Construct a pointer to `Self` given a memory range in user space. + /// /// NB. This takes a size, not a length! - unsafe fn from_raw_sized_unchecked(ptr: *const u8, size: usize) -> *const Self; + /// + /// # Safety + /// The caller must ensure the memory range is in user memory, is the + /// correct size and is correctly aligned and points to the right type. + unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self; + /// Construct a pointer to `Self` given a memory range. + /// /// NB. This takes a size, not a length! - unsafe fn from_raw_sized(ptr: *const u8, size: usize) -> *const Self { + /// + /// # Safety + /// The caller must ensure the memory range points to the correct type. + /// + /// # Panics + /// This function panics if: + /// + /// * The pointer is not aligned + /// * The pointer is null + /// * The pointed-to range is not in user memory + unsafe fn from_raw_sized(ptr: *mut u8, size: usize) -> NonNull { let ret = Self::from_raw_sized_unchecked(ptr, size); Self::check_ptr(ret); - ret + NonNull::new_unchecked(ret as _) } + /// Check if a pointer may point to Self in user memory. + /// + /// # Safety + /// The caller must ensure the memory range points to the correct type and + /// length (if this is a slice). + /// + /// # Panics + /// This function panics if: + /// + /// * The pointer is not aligned + /// * The pointer is null + /// * The pointed-to range is not in user memory unsafe fn check_ptr(ptr: *const Self) { let is_aligned = |p| -> bool { 0 == (p as usize) & (Self::align_of() - 1) @@ -83,27 +122,29 @@ pub unsafe trait UserSafe { } } +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafe for T { - unsafe fn align_of() -> usize { + fn align_of() -> usize { mem::align_of::() } - unsafe fn from_raw_sized_unchecked(ptr: *const u8, size: usize) -> *const Self { + unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self { assert_eq!(size, mem::size_of::()); ptr as _ } } +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafe for [T] { - unsafe fn align_of() -> usize { + fn align_of() -> usize { mem::align_of::() } - unsafe fn from_raw_sized_unchecked(ptr: *const u8, size: usize) -> *const Self { + unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self { let elem_size = mem::size_of::(); assert_eq!(size % elem_size, 0); let len = size / elem_size; - slice::from_raw_parts(ptr as _, len) + slice::from_raw_parts_mut(ptr as _, len) } } @@ -111,14 +152,40 @@ unsafe impl UserSafe for [T] { /// to `&T` in enclave memory. Access to the memory is only allowed by copying /// to avoid TOCTTOU issues. After copying, code should make sure to completely /// check the value before use. +/// +/// It is also possible to obtain a mutable reference `&mut UserRef`. Unlike +/// regular mutable references, these are not exclusive. Userspace may always +/// write to the backing memory at any time, so it can't be assumed that there +/// the pointed-to memory is uniquely borrowed. The two different refence types +/// are used solely to indicate intent: a mutable reference is for writing to +/// user memory, an immutable reference for reading from user memory. +#[unstable(feature = "sgx_platform", issue = "56975")] pub struct UserRef(UnsafeCell); /// An owned type in userspace memory. `User` is equivalent to `Box` in /// enclave memory. Access to the memory is only allowed by copying to avoid /// TOCTTOU issues. The user memory will be freed when the value is dropped. /// After copying, code should make sure to completely check the value before /// use. -pub struct User(*mut UserRef); +#[unstable(feature = "sgx_platform", issue = "56975")] +pub struct User(NonNull>); + +trait NewUserRef { + unsafe fn new_userref(v: T) -> Self; +} + +impl NewUserRef<*mut T> for NonNull> { + unsafe fn new_userref(v: *mut T) -> Self { + NonNull::new_unchecked(v as _) + } +} +impl NewUserRef> for NonNull> { + unsafe fn new_userref(v: NonNull) -> Self { + NonNull::new_userref(v.as_ptr()) + } +} + +#[unstable(feature = "sgx_platform", issue = "56975")] impl User where T: UserSafe { // This function returns memory that is practically uninitialized, but is // not considered "unspecified" or "undefined" for purposes of an @@ -127,24 +194,28 @@ impl User where T: UserSafe { fn new_uninit_bytes(size: usize) -> Self { unsafe { let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed"); - User(T::from_raw_sized(ptr as _, size) as _) + User(NonNull::new_userref(T::from_raw_sized(ptr as _, size))) } } + /// Copy `val` into freshly allocated space in user memory. pub fn new_from_enclave(val: &T) -> Self { unsafe { let ret = Self::new_uninit_bytes(mem::size_of_val(val)); ptr::copy( val as *const T as *const u8, - ret.0 as *mut T as *mut u8, + ret.0.as_ptr() as *mut u8, mem::size_of_val(val) ); ret } } - /// Create an owned `User` from a raw pointer. The pointer should be - /// freeable with the `free` usercall and the alignment of `T`. + /// Create an owned `User` from a raw pointer. + /// + /// # Safety + /// The caller must ensure `ptr` points to `T`, is freeable with the `free` + /// usercall and the alignment of `T`, and is uniquely owned. /// /// # Panics /// This function panics if: @@ -154,7 +225,7 @@ impl User where T: UserSafe { /// * The pointed-to range is not in user memory pub unsafe fn from_raw(ptr: *mut T) -> Self { T::check_ptr(ptr); - User(ptr as _) + User(NonNull::new_userref(ptr)) } /// Convert this value into a raw pointer. The value will no longer be @@ -162,24 +233,31 @@ impl User where T: UserSafe { pub fn into_raw(self) -> *mut T { let ret = self.0; mem::forget(self); - ret as _ + ret.as_ptr() as _ } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl User where T: UserSafe { + /// Allocate space for `T` in user memory. pub fn uninitialized() -> Self { Self::new_uninit_bytes(mem::size_of::()) } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl User<[T]> where [T]: UserSafe { + /// Allocate space for a `[T]` of `n` elements in user memory. pub fn uninitialized(n: usize) -> Self { Self::new_uninit_bytes(n * mem::size_of::()) } /// Create an owned `User<[T]>` from a raw thin pointer and a slice length. - /// The pointer should be freeable with the `free` usercall and the - /// alignment of `T`. + /// + /// # Safety + /// The caller must ensure `ptr` points to `len` elements of `T`, is + /// freeable with the `free` usercall and the alignment of `T`, and is + /// uniquely owned. /// /// # Panics /// This function panics if: @@ -188,13 +266,17 @@ impl User<[T]> where [T]: UserSafe { /// * The pointer is null /// * The pointed-to range is not in user memory pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self { - User(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::()) as _) + User(NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::()))) } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl UserRef where T: UserSafe { /// Create a `&UserRef<[T]>` from a raw pointer. /// + /// # Safety + /// The caller must ensure `ptr` points to `T`. + /// /// # Panics /// This function panics if: /// @@ -206,7 +288,11 @@ impl UserRef where T: UserSafe { &*(ptr as *const Self) } - /// Create a `&mut UserRef<[T]>` from a raw pointer. + /// Create a `&mut UserRef<[T]>` from a raw pointer. See the struct + /// documentation for the nuances regarding a `&mut UserRef`. + /// + /// # Safety + /// The caller must ensure `ptr` points to `T`. /// /// # Panics /// This function panics if: @@ -219,6 +305,8 @@ impl UserRef where T: UserSafe { &mut*(ptr as *mut Self) } + /// Copy `val` into user memory. + /// /// # Panics /// This function panics if the destination doesn't have the same size as /// the source. This can happen for dynamically-sized types such as slices. @@ -233,6 +321,8 @@ impl UserRef where T: UserSafe { } } + /// Copy the value from user memory and place it into `dest`. + /// /// # Panics /// This function panics if the destination doesn't have the same size as /// the source. This can happen for dynamically-sized types such as slices. @@ -247,24 +337,32 @@ impl UserRef where T: UserSafe { } } + /// Obtain a raw pointer from this reference. pub fn as_raw_ptr(&self) -> *const T { self as *const _ as _ } + /// Obtain a raw pointer from this reference. pub fn as_raw_mut_ptr(&mut self) -> *mut T { self as *mut _ as _ } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl UserRef where T: UserSafe { + /// Copy the value from user memory into enclave memory. pub fn to_enclave(&self) -> T { unsafe { ptr::read(self.0.get()) } } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl UserRef<[T]> where [T]: UserSafe { /// Create a `&UserRef<[T]>` from a raw thin pointer and a slice length. /// + /// # Safety + /// The caller must ensure `ptr` points to `n` elements of `T`. + /// /// # Panics /// This function panics if: /// @@ -272,10 +370,15 @@ impl UserRef<[T]> where [T]: UserSafe { /// * The pointer is null /// * The pointed-to range is not in user memory pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self { - &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::()) as *const Self) + &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::()).as_ptr() as *const Self) } /// Create a `&mut UserRef<[T]>` from a raw thin pointer and a slice length. + /// See the struct documentation for the nuances regarding a + /// `&mut UserRef`. + /// + /// # Safety + /// The caller must ensure `ptr` points to `n` elements of `T`. /// /// # Panics /// This function panics if: @@ -284,21 +387,30 @@ impl UserRef<[T]> where [T]: UserSafe { /// * The pointer is null /// * The pointed-to range is not in user memory pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self { - &mut*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::()) as *mut Self) + &mut*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::()).as_ptr() as *mut Self) } + /// Obtain a raw pointer to the first element of this user slice. pub fn as_ptr(&self) -> *const T { self.0.get() as _ } + /// Obtain a raw pointer to the first element of this user slice. pub fn as_mut_ptr(&mut self) -> *mut T { self.0.get() as _ } + /// Obtain the number of elements in this user slice. pub fn len(&self) -> usize { unsafe { (*self.0.get()).len() } } + /// Copy the value from user memory and place it into `dest`. Afterwards, + /// `dest` will contain exactly `self.len()` elements. + /// + /// # Panics + /// This function panics if the destination doesn't have the same size as + /// the source. This can happen for dynamically-sized types such as slices. pub fn copy_to_enclave_vec(&self, dest: &mut Vec) { unsafe { if let Some(missing) = self.len().checked_sub(dest.capacity()) { @@ -309,12 +421,14 @@ impl UserRef<[T]> where [T]: UserSafe { } } + /// Copy the value from user memory into a vector in enclave memory. pub fn to_enclave(&self) -> Vec { let mut ret = Vec::with_capacity(self.len()); self.copy_to_enclave_vec(&mut ret); ret } + /// Returns an iterator over the slice. pub fn iter(&self) -> Iter where T: UserSafe // FIXME: should be implied by [T]: UserSafe? { @@ -323,6 +437,7 @@ impl UserRef<[T]> where [T]: UserSafe { } } + /// Returns an iterator that allows modifying each value. pub fn iter_mut(&mut self) -> IterMut where T: UserSafe // FIXME: should be implied by [T]: UserSafe? { @@ -332,8 +447,13 @@ impl UserRef<[T]> where [T]: UserSafe { } } +/// Immutable user slice iterator +/// +/// This struct is created by the `iter` method on `UserRef<[T]>`. +#[unstable(feature = "sgx_platform", issue = "56975")] pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>); +#[unstable(feature = "sgx_platform", issue = "56975")] impl<'a, T: UserSafe> Iterator for Iter<'a, T> { type Item = &'a UserRef; @@ -345,8 +465,13 @@ impl<'a, T: UserSafe> Iterator for Iter<'a, T> { } } +/// Mutable user slice iterator +/// +/// This struct is created by the `iter_mut` method on `UserRef<[T]>`. +#[unstable(feature = "sgx_platform", issue = "56975")] pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>); +#[unstable(feature = "sgx_platform", issue = "56975")] impl<'a, T: UserSafe> Iterator for IterMut<'a, T> { type Item = &'a mut UserRef; @@ -358,31 +483,36 @@ impl<'a, T: UserSafe> Iterator for IterMut<'a, T> { } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl Deref for User where T: UserSafe { type Target = UserRef; fn deref(&self) -> &Self::Target { - unsafe { &*self.0 } + unsafe { &*self.0.as_ptr() } } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl DerefMut for User where T: UserSafe { fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { &mut*self.0 } + unsafe { &mut*self.0.as_ptr() } } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl Drop for User where T: UserSafe { fn drop(&mut self) { unsafe { - let ptr = (*self.0).0.get(); + let ptr = (*self.0.as_ptr()).0.get(); super::free(ptr as _, mem::size_of_val(&mut*ptr), T::align_of()); } } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl, U> CoerceUnsized> for UserRef {} +#[unstable(feature = "sgx_platform", issue = "56975")] impl> Index for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe { type Output = UserRef; @@ -394,6 +524,7 @@ impl> Index for UserRef<[T]> where [T]: UserSafe, I::Ou } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl> IndexMut for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe { #[inline] fn index_mut(&mut self, index: I) -> &mut UserRef { @@ -402,3 +533,21 @@ impl> IndexMut for UserRef<[T]> where [T]: UserSafe, I: } } } + +#[unstable(feature = "sgx_platform", issue = "56975")] +impl UserRef { + /// Copy the user memory range pointed to by the user `ByteBuffer` to + /// enclave memory. + /// + /// # Panics + /// This function panics if: + /// + /// * The pointer in the user `ByteBuffer` is null + /// * The pointed-to range in the user `ByteBuffer` is not in user memory + pub fn copy_user_buffer(&self) -> Vec { + unsafe { + let buf = self.to_enclave(); + User::from_raw_parts(buf.data as _, buf.len).to_enclave() + } + } +} diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index d1d180e48251f..a5066abc14462 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -8,22 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use fortanix_sgx_abi::*; - use io::{Error as IoError, Result as IoResult}; use time::Duration; -pub mod alloc; +pub(crate) mod alloc; #[macro_use] -mod raw; +pub(crate) mod raw; -pub(crate) fn copy_user_buffer(buf: &alloc::UserRef) -> Vec { - unsafe { - let buf = buf.to_enclave(); - alloc::User::from_raw_parts(buf.data as _, buf.len).to_enclave() - } -} +use self::raw::*; +/// Usercall `read`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult { unsafe { let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len()); @@ -33,6 +28,18 @@ pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult { } } +/// Usercall `read_alloc`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub fn read_alloc(fd: Fd) -> IoResult> { + unsafe { + let mut userbuf = alloc::User::::uninitialized(); + raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?; + Ok(userbuf.copy_user_buffer()) + } +} + +/// Usercall `write`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn write(fd: Fd, buf: &[u8]) -> IoResult { unsafe { let userbuf = alloc::User::new_from_enclave(buf); @@ -40,19 +47,25 @@ pub fn write(fd: Fd, buf: &[u8]) -> IoResult { } } +/// Usercall `flush`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn flush(fd: Fd) -> IoResult<()> { unsafe { raw::flush(fd).from_sgx_result() } } +/// Usercall `close`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn close(fd: Fd) { unsafe { raw::close(fd) } } fn string_from_bytebuffer(buf: &alloc::UserRef, usercall: &str, arg: &str) -> String { - String::from_utf8(copy_user_buffer(buf)) + String::from_utf8(buf.copy_user_buffer()) .unwrap_or_else(|_| panic!("Usercall {}: expected {} to be valid UTF-8", usercall, arg)) } +/// Usercall `bind_stream`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn bind_stream(addr: &str) -> IoResult<(Fd, String)> { unsafe { let addr_user = alloc::User::new_from_enclave(addr.as_bytes()); @@ -67,6 +80,8 @@ pub fn bind_stream(addr: &str) -> IoResult<(Fd, String)> { } } +/// Usercall `accept_stream`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn accept_stream(fd: Fd) -> IoResult<(Fd, String, String)> { unsafe { let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized(); @@ -84,6 +99,8 @@ pub fn accept_stream(fd: Fd) -> IoResult<(Fd, String, String)> { } } +/// Usercall `connect_stream`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn connect_stream(addr: &str) -> IoResult<(Fd, String, String)> { unsafe { let addr_user = alloc::User::new_from_enclave(addr.as_bytes()); @@ -103,31 +120,45 @@ pub fn connect_stream(addr: &str) -> IoResult<(Fd, String, String)> { } } -pub fn launch_thread() -> IoResult<()> { - unsafe { raw::launch_thread().from_sgx_result() } +/// Usercall `launch_thread`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub unsafe fn launch_thread() -> IoResult<()> { + raw::launch_thread().from_sgx_result() } +/// Usercall `exit`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn exit(panic: bool) -> ! { unsafe { raw::exit(panic) } } +/// Usercall `wait`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn wait(event_mask: u64, timeout: u64) -> IoResult { unsafe { raw::wait(event_mask, timeout).from_sgx_result() } } +/// Usercall `send`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn send(event_set: u64, tcs: Option) -> IoResult<()> { unsafe { raw::send(event_set, tcs).from_sgx_result() } } +/// Usercall `insecure_time`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn insecure_time() -> Duration { let t = unsafe { raw::insecure_time() }; Duration::new(t / 1_000_000_000, (t % 1_000_000_000) as _) } +/// Usercall `alloc`. See the ABI documentation for more information. +#[unstable(feature = "sgx_platform", issue = "56975")] pub fn alloc(size: usize, alignment: usize) -> IoResult<*mut u8> { unsafe { raw::alloc(size, alignment).from_sgx_result() } } +#[unstable(feature = "sgx_platform", issue = "56975")] +#[doc(inline)] pub use self::raw::free; fn check_os_error(err: Result) -> i32 { diff --git a/src/libstd/sys/sgx/abi/usercalls/raw.rs b/src/libstd/sys/sgx/abi/usercalls/raw.rs index a28d41c1b7458..44b370c44c636 100644 --- a/src/libstd/sys/sgx/abi/usercalls/raw.rs +++ b/src/libstd/sys/sgx/abi/usercalls/raw.rs @@ -10,7 +10,8 @@ #![allow(unused)] -use fortanix_sgx_abi::*; +#[unstable(feature = "sgx_platform", issue = "56975")] +pub use fortanix_sgx_abi::*; use ptr::NonNull; @@ -21,7 +22,16 @@ extern "C" { fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn; } -unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) { +/// Perform the raw usercall operation as defined in the ABI calling convention. +/// +/// # Safety +/// The caller must ensure to pass parameters appropriate for the usercall `nr` +/// and to observe all requirements specified in the ABI. +/// +/// # Panics +/// Panics if `nr` is 0. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) { if nr==0 { panic!("Invalid usercall number {}",nr) } let UsercallReturn(a, b) = usercall(nr,p1,p2,0,p3,p4); (a, b) @@ -169,6 +179,9 @@ impl ReturnValue for (T, U) { macro_rules! enclave_usercalls_internal_define_usercalls { (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => ( + /// This is the raw function definition, see the ABI documentation for + /// more information. + #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( @@ -181,6 +194,9 @@ macro_rules! enclave_usercalls_internal_define_usercalls { } ); (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => ( + /// This is the raw function definition, see the ABI documentation for + /// more information. + #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( @@ -193,6 +209,9 @@ macro_rules! enclave_usercalls_internal_define_usercalls { } ); (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => ( + /// This is the raw function definition, see the ABI documentation for + /// more information. + #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( @@ -204,6 +223,9 @@ macro_rules! enclave_usercalls_internal_define_usercalls { } ); (def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => ( + /// This is the raw function definition, see the ABI documentation for + /// more information. + #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f($n1: $t1) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( @@ -214,6 +236,9 @@ macro_rules! enclave_usercalls_internal_define_usercalls { } ); (def fn $f:ident() -> $r:ty) => ( + /// This is the raw function definition, see the ABI documentation for + /// more information. + #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f() -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( diff --git a/src/libstd/sys/sgx/args.rs b/src/libstd/sys/sgx/args.rs index 8fb35d7ef98bd..50627b8c91302 100644 --- a/src/libstd/sys/sgx/args.rs +++ b/src/libstd/sys/sgx/args.rs @@ -9,7 +9,7 @@ // except according to those terms. use ffi::OsString; -use super::abi::usercalls::{copy_user_buffer, alloc, ByteBuffer}; +use super::abi::usercalls::{alloc, raw::ByteBuffer}; use sync::atomic::{AtomicUsize, Ordering}; use sys::os_str::Buf; use sys_common::FromInner; @@ -22,7 +22,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { if argc != 0 { let args = alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _); let args = args.iter() - .map( |a| OsString::from_inner(Buf { inner: copy_user_buffer(a) }) ) + .map( |a| OsString::from_inner(Buf { inner: a.copy_user_buffer() }) ) .collect::(); ARGS.store(Box::into_raw(Box::new(args)) as _, Ordering::Relaxed); } diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs index 176d230846dc2..9cfe821fe5154 100644 --- a/src/libstd/sys/sgx/net.rs +++ b/src/libstd/sys/sgx/net.rs @@ -29,7 +29,7 @@ struct Socket { } impl Socket { - fn new(fd: usercalls::Fd, local_addr: String) -> Socket { + fn new(fd: usercalls::raw::Fd, local_addr: String) -> Socket { Socket { inner: Arc::new(FileDesc::new(fd)), local_addr } } } diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs index 9f3c4536cb5b6..b8d5b17d8d2d9 100644 --- a/src/libstd/sys/sgx/thread.rs +++ b/src/libstd/sys/sgx/thread.rs @@ -75,7 +75,7 @@ impl Thread { pub fn yield_now() { assert_eq!( - usercalls::wait(0, usercalls::WAIT_NO).unwrap_err().kind(), + usercalls::wait(0, usercalls::raw::WAIT_NO).unwrap_err().kind(), io::ErrorKind::WouldBlock ); } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index c49d577253143..2bbe3a69ce8bb 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -24,6 +24,8 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] +#![recursion_limit="256"] + extern crate fmt_macros; #[macro_use] extern crate syntax; diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml index 32969d09e8567..164a3c6ad0d80 100644 --- a/src/rustc/Cargo.toml +++ b/src/rustc/Cargo.toml @@ -15,5 +15,10 @@ rustc_driver = { path = "../librustc_driver" } # crate is intended to be used by codegen backends, which may not be in-tree. rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } +[dependencies.jemalloc-sys] +version = '0.1.8' +optional = true +features = ['unprefixed_malloc_on_supported_platforms'] + [features] -jemalloc = ['rustc_driver/jemalloc-sys'] +jemalloc = ['jemalloc-sys'] diff --git a/src/rustc/rustc.rs b/src/rustc/rustc.rs index ab5a7c3f747eb..1c1c7b4bb8e32 100644 --- a/src/rustc/rustc.rs +++ b/src/rustc/rustc.rs @@ -23,6 +23,14 @@ extern {} extern crate rustc_driver; +// Note that the linkage here should be all that we need, on Linux we're not +// prefixing the symbols here so this should naturally override our default +// allocator. On OSX it should override via the zone allocator. We shouldn't +// enable this by default on other platforms, so other platforms aren't handled +// here yet. +#[cfg(feature = "jemalloc-sys")] +extern crate jemalloc_sys; + fn main() { rustc_driver::set_sigpipe_handler(); rustc_driver::main() diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 52bdb1b103afd..69632c9c82b70 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -28,37 +28,37 @@ pub fn boolean(x: bool) -> bool { x } -// CHECK: @readonly_borrow(i32* noalias readonly dereferenceable(4) %arg0) +// CHECK: @readonly_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn readonly_borrow(_: &i32) { } -// CHECK: @static_borrow(i32* noalias readonly dereferenceable(4) %arg0) +// CHECK: @static_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) // static borrow may be captured #[no_mangle] pub fn static_borrow(_: &'static i32) { } -// CHECK: @named_borrow(i32* noalias readonly dereferenceable(4) %arg0) +// CHECK: @named_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) // borrow with named lifetime may be captured #[no_mangle] pub fn named_borrow<'r>(_: &'r i32) { } -// CHECK: @unsafe_borrow(i16* dereferenceable(2) %arg0) +// CHECK: @unsafe_borrow(i16* align 2 dereferenceable(2) %arg0) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_borrow(_: &UnsafeInner) { } -// CHECK: @mutable_unsafe_borrow(i16* dereferenceable(2) %arg0) +// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %arg0) // ... unless this is a mutable borrow, those never alias #[no_mangle] pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { } -// CHECK: @mutable_borrow(i32* dereferenceable(4) %arg0) +// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %arg0) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_borrow(_: &mut i32) { @@ -69,13 +69,13 @@ pub fn mutable_borrow(_: &mut i32) { pub fn indirect_struct(_: S) { } -// CHECK: @borrowed_struct(%S* noalias readonly dereferenceable(32) %arg0) +// CHECK: @borrowed_struct(%S* noalias readonly align 4 dereferenceable(32) %arg0) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn borrowed_struct(_: &S) { } -// CHECK: noalias align 4 dereferenceable(4) i32* @_box(i32* noalias dereferenceable(4) %x) +// CHECK: noalias align 4 dereferenceable(4) i32* @_box(i32* noalias align 4 dereferenceable(4) %x) #[no_mangle] pub fn _box(x: Box) -> Box { x @@ -95,48 +95,48 @@ pub fn struct_return() -> S { pub fn helper(_: usize) { } -// CHECK: @slice([0 x i8]* noalias nonnull readonly %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @slice([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn slice(_: &[u8]) { } -// CHECK: @mutable_slice([0 x i8]* nonnull %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %arg0.0, [[USIZE]] %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_slice(_: &mut [u8]) { } -// CHECK: @unsafe_slice([0 x i16]* nonnull %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @unsafe_slice([0 x i16]* nonnull align 2 %arg0.0, [[USIZE]] %arg0.1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_slice(_: &[UnsafeInner]) { } -// CHECK: @str([0 x i8]* noalias nonnull readonly %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @str([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn str(_: &[u8]) { } -// CHECK: @trait_borrow({}* nonnull %arg0.0, [3 x [[USIZE]]]* noalias readonly dereferenceable({{.*}}) %arg0.1) +// CHECK: @trait_borrow({}* nonnull align 1 %arg0.0, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}) %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn trait_borrow(_: &Drop) { } -// CHECK: @trait_box({}* noalias nonnull, [3 x [[USIZE]]]* noalias readonly dereferenceable({{.*}})) +// CHECK: @trait_box({}* noalias nonnull align 1, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}})) #[no_mangle] pub fn trait_box(_: Box) { } -// CHECK: { i8*, i8* } @trait_option(i8* noalias %x.0, i8* %x.1) +// CHECK: { i8*, i8* } @trait_option(i8* noalias align 1 %x.0, i8* %x.1) #[no_mangle] pub fn trait_option(x: Option>) -> Option> { x } -// CHECK: { [0 x i16]*, [[USIZE]] } @return_slice([0 x i16]* noalias nonnull readonly %x.0, [[USIZE]] %x.1) +// CHECK: { [0 x i16]*, [[USIZE]] } @return_slice([0 x i16]* noalias nonnull readonly align 2 %x.0, [[USIZE]] %x.1) #[no_mangle] pub fn return_slice(x: &[u16]) -> &[u16] { x diff --git a/src/test/run-make-fulldeps/llvm-pass/Makefile b/src/test/run-make-fulldeps/llvm-pass/Makefile deleted file mode 100644 index 8a18aadf36a8b..0000000000000 --- a/src/test/run-make-fulldeps/llvm-pass/Makefile +++ /dev/null @@ -1,28 +0,0 @@ --include ../tools.mk - -ifeq ($(UNAME),Darwin) -PLUGIN_FLAGS := -C link-args=-Wl,-undefined,dynamic_lookup -endif - -ifeq ($(findstring stage1,$(RUST_BUILD_STAGE)),stage1) -# ignore stage1 -all: - -else -# Windows doesn't correctly handle include statements with escaping paths, -# so this test will not get run on Windows. -ifdef IS_WINDOWS -all: -else -all: $(call NATIVE_STATICLIB,llvm-function-pass) $(call NATIVE_STATICLIB,llvm-module-pass) - $(RUSTC) plugin.rs -C prefer-dynamic $(PLUGIN_FLAGS) - $(RUSTC) main.rs - -$(TMPDIR)/libllvm-function-pass.o: - $(CXX) $(CFLAGS) $(LLVM_CXXFLAGS) -c llvm-function-pass.so.cc -o $(TMPDIR)/libllvm-function-pass.o - -$(TMPDIR)/libllvm-module-pass.o: - $(CXX) $(CFLAGS) $(LLVM_CXXFLAGS) -c llvm-module-pass.so.cc -o $(TMPDIR)/libllvm-module-pass.o -endif - -endif diff --git a/src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc b/src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc deleted file mode 100644 index c0a17d920cffc..0000000000000 --- a/src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -#include -#include -#include - -#include "llvm/Pass.h" -#include "llvm/IR/Function.h" - -using namespace llvm; - -namespace { - - class TestLLVMPass : public FunctionPass { - - public: - - static char ID; - TestLLVMPass() : FunctionPass(ID) { } - - bool runOnFunction(Function &F) override; - - StringRef getPassName() const override { - return "Some LLVM pass"; - } - - }; - -} - -bool TestLLVMPass::runOnFunction(Function &F) { - // A couple examples of operations that previously caused segmentation faults - // https://github.com/rust-lang/rust/issues/31067 - - for (auto N = F.begin(); N != F.end(); ++N) { - /* code */ - } - - LLVMContext &C = F.getContext(); - IntegerType *Int8Ty = IntegerType::getInt8Ty(C); - PointerType::get(Int8Ty, 0); - return true; -} - -char TestLLVMPass::ID = 0; - -static RegisterPass RegisterAFLPass( - "some-llvm-function-pass", "Some LLVM pass"); diff --git a/src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc b/src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc deleted file mode 100644 index 70051681ab035..0000000000000 --- a/src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -#include -#include -#include - -#include "llvm/IR/Module.h" - -using namespace llvm; - -namespace { - - class TestLLVMPass : public ModulePass { - - public: - - static char ID; - TestLLVMPass() : ModulePass(ID) { } - - bool runOnModule(Module &M) override; - - StringRef getPassName() const override { - return "Some LLVM pass"; - } - - }; - -} - -bool TestLLVMPass::runOnModule(Module &M) { - // A couple examples of operations that previously caused segmentation faults - // https://github.com/rust-lang/rust/issues/31067 - - for (auto F = M.begin(); F != M.end(); ++F) { - /* code */ - } - - LLVMContext &C = M.getContext(); - IntegerType *Int8Ty = IntegerType::getInt8Ty(C); - PointerType::get(Int8Ty, 0); - return true; -} - -char TestLLVMPass::ID = 0; - -static RegisterPass RegisterAFLPass( - "some-llvm-module-pass", "Some LLVM pass"); diff --git a/src/test/run-make-fulldeps/llvm-pass/main.rs b/src/test/run-make-fulldeps/llvm-pass/main.rs deleted file mode 100644 index 5b5ab94bcef02..0000000000000 --- a/src/test/run-make-fulldeps/llvm-pass/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -#![feature(plugin)] -#![plugin(some_plugin)] - -fn main() {} diff --git a/src/test/run-make-fulldeps/llvm-pass/plugin.rs b/src/test/run-make-fulldeps/llvm-pass/plugin.rs deleted file mode 100644 index f77b2fca857a6..0000000000000 --- a/src/test/run-make-fulldeps/llvm-pass/plugin.rs +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -#![feature(plugin_registrar, rustc_private)] -#![crate_type = "dylib"] -#![crate_name = "some_plugin"] - -extern crate rustc; -extern crate rustc_plugin; - -#[link(name = "llvm-function-pass", kind = "static")] -#[link(name = "llvm-module-pass", kind = "static")] -extern {} - -use rustc_plugin::registry::Registry; - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_llvm_pass("some-llvm-function-pass"); - reg.register_llvm_pass("some-llvm-module-pass"); -}