From b089e79562aff01cee9b6246f9352ffecef4b3b9 Mon Sep 17 00:00:00 2001 From: daniellimws Date: Mon, 29 Oct 2018 19:15:22 +0800 Subject: [PATCH 01/21] Add documentation for From impls --- src/liballoc/boxed.rs | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f989e701913a5..da4651ca7793b 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -438,6 +438,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) } @@ -445,6 +457,9 @@ impl From for Box { #[unstable(feature = "pin", issue = "49150")] 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 @@ -455,6 +470,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 does not allocate on the heap + /// but 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::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); @@ -464,6 +492,15 @@ 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 does not allocate on the heap and happens in place. + /// + /// # 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())) } @@ -472,6 +509,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]) } From 15334e03b757c13578d15f49c5950eab21956437 Mon Sep 17 00:00:00 2001 From: daniellimws Date: Mon, 29 Oct 2018 19:37:58 +0800 Subject: [PATCH 02/21] Fix documentation for those that allocate on heap --- src/liballoc/boxed.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index da4651ca7793b..8826a836a913a 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -472,8 +472,8 @@ impl From> for Pin> { impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { /// Converts a `&[T]` into a `Box<[T]>` /// - /// This conversion does not allocate on the heap - /// but performs a copy of `slice`. + /// This conversion allocates on the heap + /// and performs a copy of `slice`. /// /// # Examples /// ```rust @@ -494,7 +494,8 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { impl<'a> From<&'a str> for Box { /// Converts a `&str` into a `Box` /// - /// This conversion does not allocate on the heap and happens in place. + /// This conversion allocates on the heap + /// and performs a copy of `s`. /// /// # Examples /// ```rust From 6e099a698699d81eb2d18bf467ca75041a78bf4c Mon Sep 17 00:00:00 2001 From: daniellimws Date: Sat, 17 Nov 2018 00:21:23 +0800 Subject: [PATCH 03/21] Add double quotes to resolve error --- src/liballoc/boxed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 8826a836a913a..1f1a4f249c727 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -481,7 +481,7 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { /// let slice: &[u8] = &[104, 101, 108, 108, 111]; /// let boxed_slice = Box::from(slice); /// - /// println!({:?}, boxed_slice); + /// println!("{:?}", boxed_slice); /// ``` fn from(slice: &'a [T]) -> Box<[T]> { let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; From 1a8f908126151ce9dd93f5a85d12edf3909fb839 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Nov 2018 17:22:56 +0100 Subject: [PATCH 04/21] Add missing link in docs --- src/libcore/iter/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 2903c370df898..6662d56393cad 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -161,7 +161,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 From 5e2bfda19af0f00707ff0c19547127f902d36b97 Mon Sep 17 00:00:00 2001 From: daniellimws Date: Wed, 5 Dec 2018 23:31:35 +0800 Subject: [PATCH 05/21] Fix error in example by adding type annotation --- src/liballoc/boxed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 1f1a4f249c727..c920dbc0c9566 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -479,7 +479,7 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { /// ```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::from(slice); + /// let boxed_slice: Box<[u8]> = Box::from(slice); /// /// println!("{:?}", boxed_slice); /// ``` From bd18a9295cd1bd19daac3369f29776a8f4272016 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 17 Dec 2018 21:10:59 -0800 Subject: [PATCH 06/21] bootstrap: Link LLVM as a dylib with ThinLTO When building a distributed compiler on Linux where we use ThinLTO to create the LLVM shared object this commit switches the compiler to dynamically linking that LLVM artifact instead of statically linking to LLVM. The primary goal here is to reduce CI compile times, avoiding two+ ThinLTO builds of all of LLVM. By linking dynamically to LLVM we'll reuse the one ThinLTO step done by LLVM's build itself. Lots of discussion about this change can be found [here] and down. A perf run will show whether this is worth it or not! [here]: https://github.com/rust-lang/rust/pull/53245#issuecomment-417015334 --- src/bootstrap/check.rs | 5 ---- src/bootstrap/compile.rs | 49 +++++++------------------------------- src/bootstrap/dist.rs | 8 +++---- src/bootstrap/tool.rs | 2 +- src/librustc_llvm/build.rs | 4 ++++ 5 files changed, 17 insertions(+), 51 deletions(-) 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/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; From c383d389f0a8f7b7bd8d8e58f6b10a2a2b4f7fa2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 18 Dec 2018 13:01:23 -0800 Subject: [PATCH 07/21] Avoid using open_global_now --- src/librustc_driver/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 41c9b22afe06f..56a3a0efcd8a6 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -226,7 +226,7 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box { // 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); }); From 1c8d8af316f97e712c40870b0746a2d1ac073c2e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 18 Dec 2018 19:03:12 -0800 Subject: [PATCH 08/21] Remove no longer working test --- src/test/run-make-fulldeps/llvm-pass/Makefile | 28 ---------- .../llvm-pass/llvm-function-pass.so.cc | 56 ------------------- .../llvm-pass/llvm-module-pass.so.cc | 55 ------------------ src/test/run-make-fulldeps/llvm-pass/main.rs | 14 ----- .../run-make-fulldeps/llvm-pass/plugin.rs | 28 ---------- 5 files changed, 181 deletions(-) delete mode 100644 src/test/run-make-fulldeps/llvm-pass/Makefile delete mode 100644 src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc delete mode 100644 src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc delete mode 100644 src/test/run-make-fulldeps/llvm-pass/main.rs delete mode 100644 src/test/run-make-fulldeps/llvm-pass/plugin.rs 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"); -} From 0feb680ac9393fc3db2e6771cf847b3101f21bad Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 18 Dec 2018 20:33:10 -0800 Subject: [PATCH 09/21] Remove now stray comment --- src/librustc_driver/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 56a3a0efcd8a6..77b1c2310ae31 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -219,13 +219,6 @@ 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(Some(path)).unwrap_or_else(|err| { let err = format!("couldn't load codegen backend {:?}: {:?}", path, err); early_error(ErrorOutputType::default(), &err); From f72f28fae217b1329c533be8df00870bb226865d Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 19 Dec 2018 11:53:40 +0530 Subject: [PATCH 10/21] Show platform-specific modules in `std::os` when building those platforms --- src/libstd/os/mod.rs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 1cb9799ff3c22..0ab8fa424e302 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,18 @@ 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; + pub mod raw; From 4358be46c7f04a6cc12ae913c46a635bb1559779 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 19 Dec 2018 12:02:24 +0530 Subject: [PATCH 11/21] SGX target: fix docs build --- src/libstd/sys/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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")] From 38f5c97c3383fb8424fbde6ccdc1aaad4c28ae0f Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 19 Dec 2018 12:16:04 +0530 Subject: [PATCH 12/21] Revert "Remove some dead code from `sgx`" This reverts commit 134661917bf4b086b027a2c58219d50ba57a1453. --- src/libstd/sys/sgx/abi/mem.rs | 7 +++++++ src/libstd/sys/sgx/abi/usercalls/mod.rs | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/src/libstd/sys/sgx/abi/mem.rs b/src/libstd/sys/sgx/abi/mem.rs index bf32c712216bc..508f2ff4d4fa5 100644 --- a/src/libstd/sys/sgx/abi/mem.rs +++ b/src/libstd/sys/sgx/abi/mem.rs @@ -34,6 +34,13 @@ fn image_base() -> u64 { base } +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 +} + 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/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index d1d180e48251f..2bc32c9fefbb7 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -33,6 +33,14 @@ pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult { } } +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(copy_user_buffer(&userbuf)) + } +} + pub fn write(fd: Fd, buf: &[u8]) -> IoResult { unsafe { let userbuf = alloc::User::new_from_enclave(buf); From d8ddb47fcebf2c73e8d92d65925c4ed72d22171f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 19 Dec 2018 16:26:46 +0100 Subject: [PATCH 13/21] Allow testing pointers for inboundedness while forbidding dangling pointers --- src/librustc_mir/interpret/memory.rs | 10 ++++------ src/librustc_mir/interpret/operand.rs | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 420fe26426321..de7ad1651c166 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)?; + ptr.check_in_alloc(allocation_size, liveness)?; Ok(align) } } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 83ceadada65ce..76f851a958c59 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())); } From ba0ed5b13f23dd6e4ff0047a653ee615b84a67f2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 19 Dec 2018 08:27:23 -0800 Subject: [PATCH 14/21] rustc: Move jemalloc from rustc_driver to rustc This commit moves jemalloc to just the rustc binary rather than the rustc_driver shared library, enusring that it's only used for binaries that opt-in to it like rustc rather than other binaries using librustc_driver like rustdoc/rls/etc. This will hopefully address #56980 --- Cargo.lock | 2 +- src/librustc_driver/Cargo.toml | 5 ----- src/librustc_driver/lib.rs | 8 -------- src/rustc/Cargo.toml | 7 ++++++- src/rustc/rustc.rs | 8 ++++++++ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e03474565d85..16376ab71905b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2214,6 +2214,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", @@ -2400,7 +2401,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)", 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 41c9b22afe06f..fcf7331b8ab45 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -64,14 +64,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}; 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() From dcb5db80b25b8e7fe2ce3a382b793673803cbc1a Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 19 Dec 2018 17:26:17 +0530 Subject: [PATCH 15/21] Add `std::os::fortanix_sgx` module --- Cargo.lock | 6 +- src/libstd/Cargo.toml | 2 +- src/libstd/lib.rs | 2 +- src/libstd/os/fortanix_sgx/mod.rs | 67 +++++++ src/libstd/os/mod.rs | 1 + src/libstd/sys/sgx/abi/mem.rs | 8 +- src/libstd/sys/sgx/abi/mod.rs | 2 +- src/libstd/sys/sgx/abi/usercalls/alloc.rs | 211 ++++++++++++++++++---- src/libstd/sys/sgx/abi/usercalls/mod.rs | 51 ++++-- src/libstd/sys/sgx/abi/usercalls/raw.rs | 29 ++- src/libstd/sys/sgx/args.rs | 4 +- src/libstd/sys/sgx/net.rs | 2 +- src/libstd/sys/sgx/thread.rs | 2 +- 13 files changed, 328 insertions(+), 59 deletions(-) create mode 100644 src/libstd/os/fortanix_sgx/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 7e03474565d85..69e0f1e6b4d52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -817,7 +817,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)", @@ -2890,7 +2890,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", @@ -3447,7 +3447,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/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 ead38f2112687..0b7cb41399a64 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 0ab8fa424e302..ba5b938ed4ccf 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -61,5 +61,6 @@ cfg_if! { #[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/sgx/abi/mem.rs b/src/libstd/sys/sgx/abi/mem.rs index 508f2ff4d4fa5..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,8 @@ 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); @@ -41,6 +43,8 @@ pub fn is_enclave_range(p: *const u8, len: usize) -> bool { 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 2bc32c9fefbb7..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,14 +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(copy_user_buffer(&userbuf)) + 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); @@ -48,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()); @@ -75,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(); @@ -92,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()); @@ -111,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 9de12a5e6f154..48adc834eb94e 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 ); } From 2d2435b47e85d461cbc8047801a2df698364892d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 20 Dec 2018 16:03:49 +0100 Subject: [PATCH 16/21] Run compiletest tests on CI I was assuming that https://github.com/rust-lang/rust/pull/56792 would have resulted in compiletest tests being executed in CI. However, I couldn't find any mentions of the unit test names in any CI logs. This adds the compiletest test execution to the checktools.sh script. --- src/ci/docker/x86_64-gnu-tools/checktools.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index d876cb7f37a41..5da97cc9a8480 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -37,6 +37,11 @@ python2.7 "$X_PY" test --no-fail-fast \ src/tools/rls \ src/tools/rustfmt \ src/tools/miri \ + src/tools/compiletest + +# Note that compiletest here is an exception from the other tools. +# We are only executing the unit tests of it. We don't need to track the +# toolstate because it's not distributed as a tool like the other items. set -e From 0493c9977796b22eabeb410f823c38451cc71be4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 20 Dec 2018 16:38:28 +0100 Subject: [PATCH 17/21] Move compiletest test run to mingw-check builder This way, checktools.sh continues to be used only for tools that are published later on. --- src/ci/docker/mingw-check/Dockerfile | 3 ++- src/ci/docker/x86_64-gnu-tools/checktools.sh | 5 ----- 2 files changed, 2 insertions(+), 6 deletions(-) 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/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index 5da97cc9a8480..d876cb7f37a41 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -37,11 +37,6 @@ python2.7 "$X_PY" test --no-fail-fast \ src/tools/rls \ src/tools/rustfmt \ src/tools/miri \ - src/tools/compiletest - -# Note that compiletest here is an exception from the other tools. -# We are only executing the unit tests of it. We don't need to track the -# toolstate because it's not distributed as a tool like the other items. set -e From db24d8e8e25192703eb8f2ad6864207e92979443 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 21 Dec 2018 00:30:35 +0100 Subject: [PATCH 18/21] Enable emission of alignment attrs for pointer params Instead disable creation of assumptions during inlining using an LLVM opt flag. The -Z arg-align-attributes option which previously controlled this behavior is removed. --- src/librustc/session/config.rs | 2 -- src/librustc_codegen_llvm/abi.rs | 6 ----- src/librustc_codegen_llvm/llvm_util.rs | 4 ++++ src/test/codegen/function-arguments.rs | 32 +++++++++++++------------- 4 files changed, 20 insertions(+), 24 deletions(-) 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..71b75525a5aa1 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -489,12 +489,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 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/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 From c8bcac56649b21ae291e9d224c7e1ddb2f5c62a0 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 20 Dec 2018 15:14:25 +0100 Subject: [PATCH 19/21] Reintroduce the original `check_bounds_ptr` checks --- src/librustc_mir/interpret/memory.rs | 32 ++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index de7ad1651c166..e5245c24c8c6a 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -304,7 +304,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { ptr: Pointer, liveness: InboundsCheck, ) -> EvalResult<'tcx, Align> { - let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id); + let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id, liveness)?; ptr.check_in_alloc(allocation_size, liveness)?; Ok(align) } @@ -427,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), + }, } } From 0c4d5511466c9ecde5a1a8fbf2bff942afe586d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 13 Dec 2018 16:57:25 +0100 Subject: [PATCH 20/21] Fix recursion limits --- src/librustc_codegen_ssa/lib.rs | 2 ++ src/librustc_lint/lib.rs | 2 ++ src/librustc_passes/lib.rs | 2 ++ src/librustc_plugin/lib.rs | 2 ++ src/librustc_resolve/lib.rs | 2 ++ src/libsyntax_ext/lib.rs | 2 ++ 6 files changed, 12 insertions(+) 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_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_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 794e5741d62ca..f402aa6ad796b 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/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; From 65dabd6eaf24bbf3b7069a51984411aea2864856 Mon Sep 17 00:00:00 2001 From: Michael Karcher Date: Sun, 23 Dec 2018 20:33:52 +0100 Subject: [PATCH 21/21] librustc_codegen_llvm: Don't eliminate empty structs in C ABI on linux-sparc64 This is in accordance with the SPARC Compliance Definition 2.4.1, Page 3P-12. It says that structs of up to 8 bytes (which applies to empty structs as well) are to be passed in one register. --- src/librustc_codegen_llvm/abi.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index b8954dee794f7..c083137f0850e 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 @@ -526,8 +529,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; } }