From 273cc30fb24cafef9bee3163b6f53fad60880b62 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 21 Dec 2016 10:58:46 -0800 Subject: [PATCH 01/30] Clarify phrasing of MSYS2 dependencies in README.md. Fixes https://github.com/rust-lang/rust/issues/36115. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2133b17de0fb..c1218e9c600c 100644 --- a/README.md +++ b/README.md @@ -82,8 +82,9 @@ build. # Install build tools needed for Rust. If you're building a 32-bit compiler, # then replace "x86_64" below with "i686". If you've already got git, python, # or CMake installed and in PATH you can remove them from this list. Note - # that it is important that the `python2` and `cmake` packages **not** used. - # The build has historically been known to fail with these packages. + # that it is important that you do **not** use the 'python2' and 'cmake' + # packages from the 'msys2' subsystem. The build has historically been known + # to fail with these packages. $ pacman -S git \ make \ diffutils \ From 292d36febdf2ceaa73c41e2e46b41a5719394c2f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 20 Dec 2016 11:03:11 +0100 Subject: [PATCH 02/30] Add missing doc examples for Builder --- src/libstd/thread/mod.rs | 61 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 2a3fb5ec43f2..fed6b31cee87 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -216,6 +216,20 @@ pub use self::local::{LocalKey, LocalKeyState}; /// Thread configuration. Provides detailed control over the properties /// and behavior of new threads. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// +/// let builder = thread::Builder::new(); +/// +/// let handler = builder.spawn(|| { +/// // thread code +/// }).unwrap(); +/// +/// handler.join().unwrap(); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Builder { @@ -228,6 +242,22 @@ pub struct Builder { impl Builder { /// Generates the base configuration for spawning a thread, from which /// configuration methods can be chained. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new() + /// .name("foo".into()) + /// .stack_size(10); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> Builder { Builder { @@ -241,7 +271,7 @@ impl Builder { /// /// # Examples /// - /// ```rust + /// ``` /// use std::thread; /// /// let builder = thread::Builder::new() @@ -260,6 +290,14 @@ impl Builder { } /// Sets the size of the stack for the new thread. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new().stack_size(10); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stack_size(mut self, size: usize) -> Builder { self.stack_size = Some(size); @@ -275,9 +313,26 @@ impl Builder { /// /// # Errors /// - /// Unlike the `spawn` free function, this method yields an - /// `io::Result` to capture any failure to create the thread at + /// Unlike the [`spawn`] free function, this method yields an + /// [`io::Result`] to capture any failure to create the thread at /// the OS level. + /// + /// [`spawn`]: ../../std/thread/fn.spawn.html + /// [`io::Result`]: ../../std/io/type.Result.html + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// + /// let builder = thread::Builder::new(); + /// + /// let handler = builder.spawn(|| { + /// // thread code + /// }).unwrap(); + /// + /// handler.join().unwrap(); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn spawn(self, f: F) -> io::Result> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static From f4bd94f779f3e3815ba9d68dd1d39a224cce8760 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Dec 2016 10:51:46 +0100 Subject: [PATCH 03/30] Add missing urls in Arc docs --- src/liballoc/arc.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 1cad8f7f4078..e1a240a0d2eb 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -55,24 +55,24 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. /// /// `Arc` uses atomic operations for reference counting, so `Arc`s can be -/// sent between threads. In other words, `Arc` implements [`Send`][send] -/// as long as `T` implements `Send` and [`Sync`][sync]. The disadvantage is +/// sent between threads. In other words, `Arc` implements [`Send`] +/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is /// that atomic operations are more expensive than ordinary memory accesses. /// If you are not sharing reference-counted values between threads, consider -/// using [`rc::Rc`][rc] for lower overhead. `Rc` is a safe default, because -/// the compiler will catch any attempt to send an `Rc` between threads. +/// using [`rc::Rc`] for lower overhead. [`Rc`] is a safe default, because +/// the compiler will catch any attempt to send an [`Rc`] between threads. /// However, a library might choose `Arc` in order to give library consumers /// more flexibility. /// /// The [`downgrade`][downgrade] method can be used to create a non-owning -/// [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d -/// to an `Arc`, but this will return [`None`][option] if the value has -/// already been dropped. +/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d +/// to an `Arc`, but this will return [`None`] if the value has already been +/// dropped. /// /// A cycle between `Arc` pointers will never be deallocated. For this reason, -/// `Weak` is used to break cycles. For example, a tree could have strong -/// `Arc` pointers from parent nodes to children, and `Weak` pointers from -/// children back to their parents. +/// [`Weak`][weak] is used to break cycles. For example, a tree could have +/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak] +/// pointers from children back to their parents. /// /// `Arc` automatically dereferences to `T` (via the [`Deref`][deref] trait), /// so you can call `T`'s methods on a value of type `Arc`. To avoid name @@ -86,22 +86,22 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// Arc::downgrade(&my_arc); /// ``` /// -/// `Weak` does not auto-dereference to `T`, because the value may have +/// [`Weak`][weak] does not auto-dereference to `T`, because the value may have /// already been destroyed. /// /// [arc]: struct.Arc.html /// [weak]: struct.Weak.html -/// [rc]: ../../std/rc/struct.Rc.html +/// [`Rc`]: ../../std/rc/struct.Rc.html /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone /// [mutex]: ../../std/sync/struct.Mutex.html /// [rwlock]: ../../std/sync/struct.RwLock.html /// [atomic]: ../../std/sync/atomic/index.html -/// [send]: ../../std/marker/trait.Send.html +/// [`Send`]: ../../std/marker/trait.Send.html /// [sync]: ../../std/marker/trait.Sync.html /// [deref]: ../../std/ops/trait.Deref.html /// [downgrade]: struct.Arc.html#method.downgrade /// [upgrade]: struct.Weak.html#method.upgrade -/// [option]: ../../std/option/enum.Option.html +/// [`None`]: ../../std/option/enum.Option.html#variant.None /// [assoc]: ../../book/method-syntax.html#associated-functions /// /// # Examples @@ -127,7 +127,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// } /// ``` /// -/// Sharing a mutable `AtomicUsize`: +/// Sharing a mutable [`AtomicUsize`]: +/// +/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html /// /// ```no_run /// use std::sync::Arc; From 67cc77ccde95da116610d753e1a93af44d93eb90 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 25 Dec 2016 21:56:07 -0800 Subject: [PATCH 04/30] travis: Don't use -9 on gzip I timed this locally and plain old `gzip` took 2m06s while `gzip -9` took a whopping 6m23s to save a mere 4MB out of 1.2GB. Let's shave a few minutes off the Android builder by turning down the compression level. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ea8c94af80b7..47bcbe94432c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,7 +76,7 @@ before_cache: - docker history -q rust-ci | grep -v missing | xargs docker save | - gzip -9 > $HOME/docker/rust-ci.tar.gz + gzip > $HOME/docker/rust-ci.tar.gz before_install: - zcat $HOME/docker/rust-ci.tar.gz | docker load || true From 3907b93c57c599de1864eea51e42f6b8f24c0255 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Dec 2016 10:51:25 +0100 Subject: [PATCH 05/30] Add missing urls in AtomicBool docs --- src/libcore/sync/atomic.rs | 48 +++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 198db0e7c0aa..4ed31d892c5a 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -237,11 +237,16 @@ impl AtomicBool { /// Loads a value from the bool. /// - /// `load` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `load` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. /// /// # Panics /// - /// Panics if `order` is `Release` or `AcqRel`. + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.Release /// /// # Examples /// @@ -260,7 +265,10 @@ impl AtomicBool { /// Stores a value into the bool. /// - /// `store` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `store` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -286,7 +294,10 @@ impl AtomicBool { /// Stores a value into the bool, returning the old value. /// - /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `swap` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -309,8 +320,10 @@ impl AtomicBool { /// The return value is always the previous value. If it is equal to `current`, then the value /// was updated. /// - /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of - /// this operation. + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -339,10 +352,15 @@ impl AtomicBool { /// The return value is a result indicating whether the new value was written and containing /// the previous value. On success this value is guaranteed to be equal to `current`. /// - /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this - /// operation. The first describes the required ordering if the operation succeeds while the - /// second describes the required ordering when the operation fails. The failure ordering can't - /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering. + /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. The first describes the required ordering if the + /// operation succeeds while the second describes the required ordering when the + /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must + /// be equivalent or weaker than the success ordering. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.Release /// /// # Examples /// @@ -387,11 +405,15 @@ impl AtomicBool { /// return value is a result indicating whether the new value was written and containing the /// previous value. /// - /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory + /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. The first describes the required ordering if the operation /// succeeds while the second describes the required ordering when the operation fails. The - /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the - /// success ordering. + /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or + /// weaker than the success ordering. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.Release /// /// # Examples /// From 917a9affc114b68ef4985511bdee106429bbf2ac Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 25 Dec 2016 21:57:32 -0800 Subject: [PATCH 06/30] std: Clamp max read/write sizes on Unix Turns out that even though all these functions take a `size_t` they don't actually work that well with anything larger than the maximum value of `ssize_t`, the return value. Furthermore it looks like OSX rejects any read/write requests larger than `INT_MAX - 1`. Handle all these cases by just clamping the maximum size of a read/write on Unix to a platform-specific value. Closes #38590 --- src/libstd/sys/unix/fd.rs | 27 ++++++++++++++++++++++----- src/libstd/sys/windows/handle.rs | 9 ++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 2384d959881a..dcab30aad838 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -10,8 +10,9 @@ #![unstable(reason = "not public", issue = "0", feature = "fd")] +use cmp; use io::{self, Read}; -use libc::{self, c_int, c_void}; +use libc::{self, c_int, c_void, ssize_t}; use mem; use sync::atomic::{AtomicBool, Ordering}; use sys::cvt; @@ -23,6 +24,22 @@ pub struct FileDesc { fd: c_int, } +fn max_len() -> usize { + // The maximum read limit on most posix-like systems is `SSIZE_MAX`, + // with the man page quoting that if the count of bytes to read is + // greater than `SSIZE_MAX` the result is "unspecified". + // + // On OSX, however, apparently the 64-bit libc is either buggy or + // intentionally showing odd behavior by rejecting any read with a size + // larger than or equal to INT_MAX. To handle both of these the read + // size is capped on both platforms. + if cfg!(target_os = "macos") { + ::max_value() as usize - 1 + } else { + ::max_value() as usize + } +} + impl FileDesc { pub fn new(fd: c_int) -> FileDesc { FileDesc { fd: fd } @@ -41,7 +58,7 @@ impl FileDesc { let ret = cvt(unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, - buf.len()) + cmp::min(buf.len(), max_len())) })?; Ok(ret as usize) } @@ -69,7 +86,7 @@ impl FileDesc { unsafe { cvt_pread64(self.fd, buf.as_mut_ptr() as *mut c_void, - buf.len(), + cmp::min(buf.len(), max_len()), offset as i64) .map(|n| n as usize) } @@ -79,7 +96,7 @@ impl FileDesc { let ret = cvt(unsafe { libc::write(self.fd, buf.as_ptr() as *const c_void, - buf.len()) + cmp::min(buf.len(), max_len())) })?; Ok(ret as usize) } @@ -102,7 +119,7 @@ impl FileDesc { unsafe { cvt_pwrite64(self.fd, buf.as_ptr() as *const c_void, - buf.len(), + cmp::min(buf.len(), max_len()), offset as i64) .map(|n| n as usize) } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 10b86ba44bc7..fdb9483fe1c8 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -19,7 +19,6 @@ use ptr; use sys::c; use sys::cvt; use sys_common::io::read_to_end_uninitialized; -use u32; /// An owned container for `HANDLE` object, closing them on Drop. /// @@ -83,9 +82,7 @@ impl RawHandle { pub fn read(&self, buf: &mut [u8]) -> io::Result { let mut read = 0; - // ReadFile takes a DWORD (u32) for the length so it only supports - // reading u32::MAX bytes at a time. - let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD; + let len = cmp::min(buf.len(), ::max_value() as usize) as c::DWORD; let res = cvt(unsafe { c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, ptr::null_mut()) @@ -181,9 +178,7 @@ impl RawHandle { pub fn write(&self, buf: &[u8]) -> io::Result { let mut amt = 0; - // WriteFile takes a DWORD (u32) for the length so it only supports - // writing u32::MAX bytes at a time. - let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD; + let len = cmp::min(buf.len(), ::max_value() as usize) as c::DWORD; cvt(unsafe { c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, ptr::null_mut()) From 20abf050e7f5698cd1012de00295ec805143735a Mon Sep 17 00:00:00 2001 From: kellerkindt Date: Tue, 27 Dec 2016 02:26:30 +0100 Subject: [PATCH 07/30] And suddenly a german word :O "verboten" is german for "forbidden" --- src/doc/book/variable-bindings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/variable-bindings.md b/src/doc/book/variable-bindings.md index 37b6c0513fc9..e1947310a9a2 100644 --- a/src/doc/book/variable-bindings.md +++ b/src/doc/book/variable-bindings.md @@ -102,7 +102,7 @@ mutation, then the solution is quite easy: add `mut`. There are other good reasons to avoid mutable state when possible, but they’re out of the scope of this guide. In general, you can often avoid explicit mutation, and so it is preferable in Rust. That said, sometimes, mutation is -what you need, so it’s not verboten. +what you need, so it’s not forbidden. # Initializing bindings From 18d49288d546efaceab7c4c6d71a868b575bd00f Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 22 Dec 2016 16:24:29 -0500 Subject: [PATCH 08/30] PTX support - `--emit=asm --target=nvptx64-nvidia-cuda` can be used to turn a crate into a PTX module (a `.s` file). - intrinsics like `__syncthreads` and `blockIdx.x` are exposed as `"platform-intrinsics"`. - "cabi" has been implemented for the nvptx and nvptx64 architectures. i.e. `extern "C"` works. - a new ABI, `"ptx-kernel"`. That can be used to generate "global" functions. Example: `extern "ptx-kernel" fn kernel() { .. }`. All other functions are "device" functions. --- src/bootstrap/native.rs | 2 +- src/etc/platform-intrinsics/nvptx/cuda.json | 13 +++ src/etc/platform-intrinsics/nvptx/info.json | 7 ++ src/etc/platform-intrinsics/nvptx/sreg.json | 90 ++++++++++++++++++++ src/librustc_llvm/build.rs | 2 +- src/librustc_llvm/ffi.rs | 1 + src/librustc_llvm/lib.rs | 5 ++ src/librustc_platform_intrinsics/lib.rs | 3 + src/librustc_platform_intrinsics/nvptx.rs | 92 +++++++++++++++++++++ src/librustc_trans/abi.rs | 5 ++ src/librustc_trans/cabi_nvptx.rs | 53 ++++++++++++ src/librustc_trans/cabi_nvptx64.rs | 53 ++++++++++++ src/librustc_trans/lib.rs | 2 + src/libsyntax/abi.rs | 2 + src/libsyntax/feature_gate.rs | 17 +++- 15 files changed, 344 insertions(+), 3 deletions(-) create mode 100644 src/etc/platform-intrinsics/nvptx/cuda.json create mode 100644 src/etc/platform-intrinsics/nvptx/info.json create mode 100644 src/etc/platform-intrinsics/nvptx/sreg.json create mode 100644 src/librustc_platform_intrinsics/nvptx.rs create mode 100644 src/librustc_trans/cabi_nvptx.rs create mode 100644 src/librustc_trans/cabi_nvptx64.rs diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 09dbd9f8220b..80f27a5ab673 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -81,7 +81,7 @@ pub fn llvm(build: &Build, target: &str) { .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) .define("LLVM_TARGETS_TO_BUILD", - "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc") + "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX") .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") diff --git a/src/etc/platform-intrinsics/nvptx/cuda.json b/src/etc/platform-intrinsics/nvptx/cuda.json new file mode 100644 index 000000000000..1beaaeb5d871 --- /dev/null +++ b/src/etc/platform-intrinsics/nvptx/cuda.json @@ -0,0 +1,13 @@ +{ + "intrinsic_prefix": "_", + "llvm_prefix": "llvm.cuda.", + "intrinsics": [ + { + "intrinsic": "syncthreads", + "width": ["0"], + "llvm": "syncthreads", + "ret": "V", + "args": [] + } + ] +} diff --git a/src/etc/platform-intrinsics/nvptx/info.json b/src/etc/platform-intrinsics/nvptx/info.json new file mode 100644 index 000000000000..80332c54e041 --- /dev/null +++ b/src/etc/platform-intrinsics/nvptx/info.json @@ -0,0 +1,7 @@ +{ + "platform": "nvptx", + "number_info": { + "signed": {} + }, + "width_info": {} +} diff --git a/src/etc/platform-intrinsics/nvptx/sreg.json b/src/etc/platform-intrinsics/nvptx/sreg.json new file mode 100644 index 000000000000..33d97f269469 --- /dev/null +++ b/src/etc/platform-intrinsics/nvptx/sreg.json @@ -0,0 +1,90 @@ +{ + "intrinsic_prefix": "_", + "llvm_prefix": "llvm.nvvm.read.ptx.sreg.", + "intrinsics": [ + { + "intrinsic": "block_dim_x", + "width": ["0"], + "llvm": "ntid.x", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_dim_y", + "width": ["0"], + "llvm": "ntid.y", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_dim_z", + "width": ["0"], + "llvm": "ntid.z", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_idx_x", + "width": ["0"], + "llvm": "ctaid.x", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_idx_y", + "width": ["0"], + "llvm": "ctaid.y", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_idx_z", + "width": ["0"], + "llvm": "ctaid.z", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "grid_dim_x", + "width": ["0"], + "llvm": "nctaid.x", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "grid_dim_y", + "width": ["0"], + "llvm": "nctaid.y", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "grid_dim_z", + "width": ["0"], + "llvm": "nctaid.z", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "thread_idx_x", + "width": ["0"], + "llvm": "tid.x", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "thread_idx_y", + "width": ["0"], + "llvm": "tid.y", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "thread_idx_z", + "width": ["0"], + "llvm": "tid.z", + "ret": "S32", + "args": [] + } + ] +} diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index e681a81cf0c3..2ee4cc494356 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -96,7 +96,7 @@ fn main() { let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430", - "sparc"]; + "sparc", "nvptx"]; // FIXME: surely we don't need all these components, right? Stuff like mcjit // or interpreter the compiler itself never uses. diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index f3dbac7ce682..334a1dbdec16 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -42,6 +42,7 @@ pub enum CallConv { X86StdcallCallConv = 64, X86FastcallCallConv = 65, ArmAapcsCallConv = 67, + PtxKernel = 71, X86_64_SysV = 78, X86_64_Win64 = 79, X86_VectorCall = 80, diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 69709f72b8b4..679e9c17a8b9 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -377,6 +377,11 @@ pub fn initialize_available_targets() { LLVMInitializeSparcTargetMC, LLVMInitializeSparcAsmPrinter, LLVMInitializeSparcAsmParser); + init_target!(llvm_component = "nvptx", + LLVMInitializeNVPTXTargetInfo, + LLVMInitializeNVPTXTarget, + LLVMInitializeNVPTXTargetMC, + LLVMInitializeNVPTXAsmPrinter); } pub fn last_error() -> Option { diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs index 6fe1f0c2b9cc..e814050e9609 100644 --- a/src/librustc_platform_intrinsics/lib.rs +++ b/src/librustc_platform_intrinsics/lib.rs @@ -95,6 +95,7 @@ static VOID: Type = Type::Void; mod x86; mod arm; mod aarch64; +mod nvptx; impl Intrinsic { pub fn find(name: &str) -> Option { @@ -104,6 +105,8 @@ impl Intrinsic { arm::find(name) } else if name.starts_with("aarch64_") { aarch64::find(name) + } else if name.starts_with("nvptx_") { + nvptx::find(name) } else { None } diff --git a/src/librustc_platform_intrinsics/nvptx.rs b/src/librustc_platform_intrinsics/nvptx.rs new file mode 100644 index 000000000000..82408723ebe6 --- /dev/null +++ b/src/librustc_platform_intrinsics/nvptx.rs @@ -0,0 +1,92 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// DO NOT EDIT: autogenerated by etc/platform-intrinsics/generator.py +// ignore-tidy-linelength + +#![allow(unused_imports)] + +use {Intrinsic, Type}; +use IntrinsicDef::Named; + +// The default inlining settings trigger a pathological behaviour in +// LLVM, which causes makes compilation very slow. See #28273. +#[inline(never)] +pub fn find(name: &str) -> Option { + if !name.starts_with("nvptx") { return None } + Some(match &name["nvptx".len()..] { + "_syncthreads" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::VOID, + definition: Named("llvm.cuda.syncthreads") + }, + "_block_dim_x" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.ntid.x") + }, + "_block_dim_y" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.ntid.y") + }, + "_block_dim_z" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.ntid.z") + }, + "_block_idx_x" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.x") + }, + "_block_idx_y" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.y") + }, + "_block_idx_z" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.z") + }, + "_grid_dim_x" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.x") + }, + "_grid_dim_y" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.y") + }, + "_grid_dim_z" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.z") + }, + "_thread_idx_x" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.tid.x") + }, + "_thread_idx_y" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.tid.y") + }, + "_thread_idx_z" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS }, + output: &::I32, + definition: Named("llvm.nvvm.read.ptx.sreg.tid.z") + }, + _ => return None, + }) +} diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 9c4246e079b7..81e4b4d1f21c 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -25,6 +25,8 @@ use cabi_mips64; use cabi_asmjs; use cabi_msp430; use cabi_sparc; +use cabi_nvptx; +use cabi_nvptx64; use machine::{llalign_of_min, llsize_of, llsize_of_alloc}; use type_::Type; use type_of; @@ -353,6 +355,7 @@ impl FnType { Win64 => llvm::X86_64_Win64, SysV64 => llvm::X86_64_SysV, Aapcs => llvm::ArmAapcsCallConv, + PtxKernel => llvm::PtxKernel, // These API constants ought to be more specific... Cdecl => llvm::CCallConv, @@ -608,6 +611,8 @@ impl FnType { "wasm32" => cabi_asmjs::compute_abi_info(ccx, self), "msp430" => cabi_msp430::compute_abi_info(ccx, self), "sparc" => cabi_sparc::compute_abi_info(ccx, self), + "nvptx" => cabi_nvptx::compute_abi_info(ccx, self), + "nvptx64" => cabi_nvptx64::compute_abi_info(ccx, self), a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_trans/cabi_nvptx.rs b/src/librustc_trans/cabi_nvptx.rs new file mode 100644 index 000000000000..5ece19f764a8 --- /dev/null +++ b/src/librustc_trans/cabi_nvptx.rs @@ -0,0 +1,53 @@ +// 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. + +// Reference: PTX Writer's Guide to Interoperability +// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability + +#![allow(non_upper_case_globals)] + +use llvm::Struct; + +use abi::{self, ArgType, FnType}; +use context::CrateContext; +use type_::Type; + +fn ty_size(ty: Type) -> usize { + abi::ty_size(ty, 4) +} + +fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { + if ret.ty.kind() == Struct && ty_size(ret.ty) > 32 { + ret.make_indirect(ccx); + } else { + ret.extend_integer_width_to(32); + } +} + +fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) { + if arg.ty.kind() == Struct && ty_size(arg.ty) > 32 { + arg.make_indirect(ccx); + } else { + arg.extend_integer_width_to(32); + } +} + +pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { + if !fty.ret.is_ignore() { + classify_ret_ty(ccx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(ccx, arg); + } +} diff --git a/src/librustc_trans/cabi_nvptx64.rs b/src/librustc_trans/cabi_nvptx64.rs new file mode 100644 index 000000000000..880c6cfd7a8a --- /dev/null +++ b/src/librustc_trans/cabi_nvptx64.rs @@ -0,0 +1,53 @@ +// 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. + +// Reference: PTX Writer's Guide to Interoperability +// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability + +#![allow(non_upper_case_globals)] + +use llvm::Struct; + +use abi::{self, ArgType, FnType}; +use context::CrateContext; +use type_::Type; + +fn ty_size(ty: Type) -> usize { + abi::ty_size(ty, 8) +} + +fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { + if ret.ty.kind() == Struct && ty_size(ret.ty) > 64 { + ret.make_indirect(ccx); + } else { + ret.extend_integer_width_to(64); + } +} + +fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) { + if arg.ty.kind() == Struct && ty_size(arg.ty) > 64 { + arg.make_indirect(ccx); + } else { + arg.extend_integer_width_to(64); + } +} + +pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { + if !fty.ret.is_ignore() { + classify_ret_ty(ccx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(ccx, arg); + } +} diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 3a8eef131a29..0d3e1853f011 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -103,6 +103,8 @@ mod cabi_asmjs; mod cabi_mips; mod cabi_mips64; mod cabi_msp430; +mod cabi_nvptx; +mod cabi_nvptx64; mod cabi_powerpc; mod cabi_powerpc64; mod cabi_s390x; diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index a39cac8db991..0cc62fb43a54 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -41,6 +41,7 @@ pub enum Abi { Aapcs, Win64, SysV64, + PtxKernel, // Multiplatform / generic ABIs Rust, @@ -82,6 +83,7 @@ const AbiDatas: &'static [AbiData] = &[ AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false }, AbiData {abi: Abi::Win64, name: "win64", generic: false }, AbiData {abi: Abi::SysV64, name: "sysv64", generic: false }, + AbiData {abi: Abi::PtxKernel, name: "ptx-kernel", generic: false }, // Cross-platform ABIs AbiData {abi: Abi::Rust, name: "Rust", generic: true }, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e04cc11f15e1..625af803458b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -318,6 +318,9 @@ declare_features! ( // Allow safe suggestions for potential type conversions. (active, safe_suggestion, "1.0.0", Some(37384)), + + // `extern "ptx-*" fn()` + (active, abi_ptx, "1.15.0", None), ); declare_features! ( @@ -986,7 +989,19 @@ impl<'a> PostExpansionVisitor<'a> { gate_feature_post!(&self, abi_sysv64, span, "sysv64 ABI is experimental and subject to change"); }, - _ => {} + Abi::PtxKernel => { + gate_feature_post!(&self, abi_ptx, span, + "PTX ABIs are experimental and subject to change"); + } + // Stable + Abi::Cdecl | + Abi::Stdcall | + Abi::Fastcall | + Abi::Aapcs | + Abi::Win64 | + Abi::Rust | + Abi::C | + Abi::System => {} } } } From aac5ff76649a2257e2c04f1d44cf11e999a39442 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 22 Dec 2016 23:27:28 -0500 Subject: [PATCH 09/30] fix ui test --- src/test/ui/codemap_tests/unicode.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr index a748e13ecf10..70fe17888e84 100644 --- a/src/test/ui/codemap_tests/unicode.stderr +++ b/src/test/ui/codemap_tests/unicode.stderr @@ -1,4 +1,4 @@ -error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic], found `路濫狼á́́` +error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, ptx-kernel, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic], found `路濫狼á́́` --> $DIR/unicode.rs:11:8 | 11 | extern "路濫狼á́́" fn foo() {} From fd97f5df1547b263fed8862fce2b188da9d92fb9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 26 Dec 2016 23:03:20 -0800 Subject: [PATCH 10/30] travis: Don't install ccache in containers We no longer use it, we use sccache --- src/ci/docker/arm-android/Dockerfile | 1 - src/ci/docker/cross/Dockerfile | 1 - src/ci/docker/i686-gnu-nopt/Dockerfile | 1 - src/ci/docker/i686-gnu/Dockerfile | 1 - src/ci/docker/x86_64-freebsd/Dockerfile | 1 - src/ci/docker/x86_64-gnu-cargotest/Dockerfile | 1 - src/ci/docker/x86_64-gnu-debug/Dockerfile | 1 - src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile | 1 - src/ci/docker/x86_64-gnu-make/Dockerfile | 1 - src/ci/docker/x86_64-gnu-nopt/Dockerfile | 1 - src/ci/docker/x86_64-gnu/Dockerfile | 1 - src/ci/docker/x86_64-musl/Dockerfile | 1 - 12 files changed, 12 deletions(-) diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile index 8911b4ff0cb8..b3f013c1ef62 100644 --- a/src/ci/docker/arm-android/Dockerfile +++ b/src/ci/docker/arm-android/Dockerfile @@ -11,7 +11,6 @@ RUN dpkg --add-architecture i386 && \ python2.7 \ git \ cmake \ - ccache \ unzip \ expect \ openjdk-9-jre \ diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index 08b436313f63..b9b442500e2a 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ gcc-arm-linux-gnueabi libc6-dev-armel-cross \ diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile index 1da33c94c7b1..ab46fdda1fc5 100644 --- a/src/ci/docker/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/i686-gnu-nopt/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile index 9e5b0e0435e8..33bc80c02bc9 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils diff --git a/src/ci/docker/x86_64-freebsd/Dockerfile b/src/ci/docker/x86_64-freebsd/Dockerfile index 75f3174e2c04..16adda29632b 100644 --- a/src/ci/docker/x86_64-freebsd/Dockerfile +++ b/src/ci/docker/x86_64-freebsd/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ bzip2 \ xz-utils \ diff --git a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile b/src/ci/docker/x86_64-gnu-cargotest/Dockerfile index 2c3db87d9fb1..050b4bfe51f8 100644 --- a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile +++ b/src/ci/docker/x86_64-gnu-cargotest/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ libssl-dev \ sudo \ xz-utils \ diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index eec88442293a..b56f4cc5fb61 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile index 4c9198d88eb2..cf43b68e9c6f 100644 --- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ llvm-3.7-tools \ diff --git a/src/ci/docker/x86_64-gnu-make/Dockerfile b/src/ci/docker/x86_64-gnu-make/Dockerfile index 1c503aea13d5..96a3f4598728 100644 --- a/src/ci/docker/x86_64-gnu-make/Dockerfile +++ b/src/ci/docker/x86_64-gnu-make/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile index 66de6ea13ac6..1fb2fd15d861 100644 --- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index 3d71b7ffb9a3..02ac204547ee 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils diff --git a/src/ci/docker/x86_64-musl/Dockerfile b/src/ci/docker/x86_64-musl/Dockerfile index 96b38067cbb1..ee9a7d8a06db 100644 --- a/src/ci/docker/x86_64-musl/Dockerfile +++ b/src/ci/docker/x86_64-musl/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ xz-utils \ sudo \ gdb From 03d4fc564ea6d357d304f7d83c40551c40a285de Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 26 Dec 2016 23:04:39 -0800 Subject: [PATCH 11/30] travis: Remove extraneous /tmp/obj dirs These are no longer used when running containers and tests. --- src/ci/docker/arm-android/Dockerfile | 2 -- src/ci/docker/cross/Dockerfile | 3 --- src/ci/docker/i686-gnu-nopt/Dockerfile | 2 -- src/ci/docker/i686-gnu/Dockerfile | 2 -- src/ci/docker/x86_64-freebsd/Dockerfile | 2 -- src/ci/docker/x86_64-gnu-cargotest/Dockerfile | 2 -- src/ci/docker/x86_64-gnu-debug/Dockerfile | 2 -- src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile | 2 -- src/ci/docker/x86_64-gnu-make/Dockerfile | 2 -- src/ci/docker/x86_64-gnu-nopt/Dockerfile | 2 -- src/ci/docker/x86_64-gnu/Dockerfile | 2 -- src/ci/docker/x86_64-musl/Dockerfile | 3 --- 12 files changed, 26 deletions(-) diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile index b3f013c1ef62..a40e76839ecc 100644 --- a/src/ci/docker/arm-android/Dockerfile +++ b/src/ci/docker/arm-android/Dockerfile @@ -49,5 +49,3 @@ ENV RUST_CONFIGURE_ARGS \ --i686-linux-android-ndk=/android/ndk-x86-9 \ --aarch64-linux-android-ndk=/android/ndk-aarch64 ENV XPY_CHECK test --target arm-linux-androideabi -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index b9b442500e2a..c5aa323f50cd 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -69,6 +69,3 @@ ENV AR_s390x_unknown_linux_gnu=s390x-linux-gnu-ar \ # FIXME(rust-lang/rust#36150): powerpc unfortunately aborts right now ENV NO_LLVM_ASSERTIONS=1 - -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile index ab46fdda1fc5..1ffb24981c59 100644 --- a/src/ci/docker/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/i686-gnu-nopt/Dockerfile @@ -24,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile index 33bc80c02bc9..e4310232d78c 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -24,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-freebsd/Dockerfile b/src/ci/docker/x86_64-freebsd/Dockerfile index 16adda29632b..86efa74ba3b6 100644 --- a/src/ci/docker/x86_64-freebsd/Dockerfile +++ b/src/ci/docker/x86_64-freebsd/Dockerfile @@ -32,5 +32,3 @@ ENV \ ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-freebsd ENV RUST_CHECK_TARGET "" -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile b/src/ci/docker/x86_64-gnu-cargotest/Dockerfile index 050b4bfe51f8..1be11cb24f2f 100644 --- a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile +++ b/src/ci/docker/x86_64-gnu-cargotest/Dockerfile @@ -26,5 +26,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu ENV RUST_CHECK_TARGET check-cargotest ENV NO_VENDOR 1 -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index b56f4cc5fb61..9ec8c6059ec3 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -27,5 +27,3 @@ ENV RUST_CONFIGURE_ARGS \ --enable-debug \ --enable-optimize ENV RUST_CHECK_TARGET "" -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile index cf43b68e9c6f..aabfc0cd1bd8 100644 --- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile @@ -29,5 +29,3 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-3.7 ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu-make/Dockerfile b/src/ci/docker/x86_64-gnu-make/Dockerfile index 96a3f4598728..c6071d704f5f 100644 --- a/src/ci/docker/x86_64-gnu-make/Dockerfile +++ b/src/ci/docker/x86_64-gnu-make/Dockerfile @@ -24,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile index 1fb2fd15d861..d28dc3de1b49 100644 --- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile @@ -24,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index 02ac204547ee..9d8b75c80c7f 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -24,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-musl/Dockerfile b/src/ci/docker/x86_64-musl/Dockerfile index ee9a7d8a06db..49954157ec02 100644 --- a/src/ci/docker/x86_64-musl/Dockerfile +++ b/src/ci/docker/x86_64-musl/Dockerfile @@ -32,6 +32,3 @@ ENV RUST_CONFIGURE_ARGS \ ENV RUST_CHECK_TARGET check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu ENV PATH=$PATH:/musl-x86_64/bin ENV XPY_CHECK test --target x86_64-unknown-linux-musl - -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj From 5cdf128410e465fd5c0338daa48366ea5200bc32 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 26 Dec 2016 21:45:01 -0800 Subject: [PATCH 12/30] Document foreign variadic functions in TRPL and the reference. Fixes https://github.com/rust-lang/rust/issues/38485. --- src/doc/book/ffi.md | 25 +++++++++++++++++++++++++ src/doc/reference.md | 9 +++++++++ 2 files changed, 34 insertions(+) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index b53af694428d..41457ee67a5f 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -574,6 +574,31 @@ The [`libc` crate on crates.io][libc] includes type aliases and function definitions for the C standard library in the `libc` module, and Rust links against `libc` and `libm` by default. +# Variadic functions + +In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can +be achieved in Rust by specifying `...` within the argument list of a foreign function declaration: + +```no_run +extern { + fn foo(x: i32, ...); +} + +fn main() { + unsafe { + foo(10, 20, 30, 40, 50); + } +} +``` + +Normal Rust functions can *not* be variadic: + +```ignore +// This will not compile + +fn foo(x: i32, ...) { } +``` + # The "nullable pointer optimization" Certain Rust types are defined to never be `null`. This includes references (`&T`, diff --git a/src/doc/reference.md b/src/doc/reference.md index b5a91a170d8e..9898c31282c3 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1657,6 +1657,15 @@ Functions within external blocks may be called by Rust code, just like functions defined in Rust. The Rust compiler automatically translates between the Rust ABI and the foreign ABI. +Functions within external blocks may be variadic by specifying `...` after one +or more named arguments in the argument list: + +```ignore +extern { + fn foo(x: i32, ...); +} +``` + A number of [attributes](#ffi-attributes) control the behavior of external blocks. By default external blocks assume that the library they are calling uses the From f26e52efa56946c04c3751509a001c91c477e77b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 27 Dec 2016 23:26:50 -0800 Subject: [PATCH 13/30] compiletest: Don't limit all suites on Android On Android we only have one test thread for supposed problems with concurrency and the remote debugger. Not all of our suites require one concurrency, however, and suites like compile-fail or pretty can be much faster if they're parallelized on Travis. This commit only sets the test threads to one on Android for suites which actually run code, and other suites aren't tampered with. --- src/tools/compiletest/src/main.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index e4d9836c5629..f04e308d62fb 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -261,7 +261,24 @@ pub fn run_tests(config: &Config) { // android debug-info test uses remote debugger // so, we test 1 thread at once. // also trying to isolate problems with adb_run_wrapper.sh ilooping - env::set_var("RUST_TEST_THREADS","1"); + match config.mode { + // These tests don't actually run code or don't run for android, so + // we don't need to limit ourselves there + Mode::Ui | + Mode::CompileFail | + Mode::ParseFail | + Mode::RunMake | + Mode::Codegen | + Mode::CodegenUnits | + Mode::Pretty | + Mode::Rustdoc | + Mode::Incremental => {} + + _ => { + env::set_var("RUST_TEST_THREADS", "1"); + } + + } } match config.mode { From 94d58c203ea7d29f0fcefccb15960a493504fa18 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 28 Dec 2016 11:00:53 +0100 Subject: [PATCH 14/30] Add missing urls for atomic_int macros types --- src/libcore/sync/atomic.rs | 53 ++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 198db0e7c0aa..e5fb8a7a73c6 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -913,12 +913,16 @@ macro_rules! atomic_int { /// Loads a value from the atomic integer. /// - /// `load` takes an `Ordering` argument which describes the memory ordering of this + /// `load` takes an [`Ordering`] argument which describes the memory ordering of this /// operation. /// /// # Panics /// - /// Panics if `order` is `Release` or `AcqRel`. + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -937,9 +941,11 @@ macro_rules! atomic_int { /// Stores a value into the atomic integer. /// - /// `store` takes an `Ordering` argument which describes the memory ordering of this + /// `store` takes an [`Ordering`] argument which describes the memory ordering of this /// operation. /// + /// [`Ordering`]: enum.Ordering.html + /// /// # Examples /// /// ``` @@ -962,9 +968,11 @@ macro_rules! atomic_int { /// Stores a value into the atomic integer, returning the old value. /// - /// `swap` takes an `Ordering` argument which describes the memory ordering of this + /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this /// operation. /// + /// [`Ordering`]: enum.Ordering.html + /// /// # Examples /// /// ``` @@ -986,9 +994,11 @@ macro_rules! atomic_int { /// The return value is always the previous value. If it is equal to `current`, then the /// value was updated. /// - /// `compare_and_swap` also takes an `Ordering` argument which describes the memory + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory /// ordering of this operation. /// + /// [`Ordering`]: enum.Ordering.html + /// /// # Examples /// /// ``` @@ -1024,11 +1034,15 @@ macro_rules! atomic_int { /// containing the previous value. On success this value is guaranteed to be equal to /// `current`. /// - /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of - /// this operation. The first describes the required ordering if the operation succeeds - /// while the second describes the required ordering when the operation fails. The - /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker - /// than the success ordering. + /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. The first describes the required ordering if + /// the operation succeeds while the second describes the required ordering when + /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and + /// must be equivalent or weaker than the success ordering. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -1062,16 +1076,21 @@ macro_rules! atomic_int { /// Stores a value into the atomic integer if the current value is the same as the /// `current` value. /// - /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the - /// comparison succeeds, which can result in more efficient code on some platforms. The - /// return value is a result indicating whether the new value was written and containing - /// the previous value. + /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even + /// when the comparison succeeds, which can result in more efficient code on some + /// platforms. The return value is a result indicating whether the new value was + /// written and containing the previous value. /// - /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory + /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. The first describes the required ordering if the /// operation succeeds while the second describes the required ordering when the - /// operation fails. The failure ordering can't be `Release` or `AcqRel` and must be - /// equivalent or weaker than the success ordering. + /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and + /// must be equivalent or weaker than the success ordering. + /// + /// [`compare_exchange`]: #method.compare_exchange + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// From ef8d5e14b12f6dc3e72810fbaa22d23287218ece Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Dec 2016 13:52:30 +0100 Subject: [PATCH 15/30] Add missing urls for AtomicPtr --- src/libcore/sync/atomic.rs | 51 +++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 198db0e7c0aa..f924c9278339 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -619,11 +619,16 @@ impl AtomicPtr { /// Loads a value from the pointer. /// - /// `load` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `load` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. /// /// # Panics /// - /// Panics if `order` is `Release` or `AcqRel`. + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -643,7 +648,10 @@ impl AtomicPtr { /// Stores a value into the pointer. /// - /// `store` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `store` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -671,7 +679,10 @@ impl AtomicPtr { /// Stores a value into the pointer, returning the old value. /// - /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `swap` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -696,8 +707,10 @@ impl AtomicPtr { /// The return value is always the previous value. If it is equal to `current`, then the value /// was updated. /// - /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of - /// this operation. + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -726,10 +739,15 @@ impl AtomicPtr { /// The return value is a result indicating whether the new value was written and containing /// the previous value. On success this value is guaranteed to be equal to `current`. /// - /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this - /// operation. The first describes the required ordering if the operation succeeds while the - /// second describes the required ordering when the operation fails. The failure ordering can't - /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering. + /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. The first describes the required ordering if + /// the operation succeeds while the second describes the required ordering when + /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] + /// and must be equivalent or weaker than the success ordering. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -768,16 +786,21 @@ impl AtomicPtr { /// Stores a value into the pointer if the current value is the same as the `current` value. /// - /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the + /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the /// comparison succeeds, which can result in more efficient code on some platforms. The /// return value is a result indicating whether the new value was written and containing the /// previous value. /// - /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory + /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. The first describes the required ordering if the operation /// succeeds while the second describes the required ordering when the operation fails. The - /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the - /// success ordering. + /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or + /// weaker than the success ordering. + /// + /// [`compare_exchange`]: #method.compare_exchange + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// From 88429dc5751fa134b87a78977ce938c61900f059 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 28 Dec 2016 09:29:14 -0800 Subject: [PATCH 16/30] travis: Use `&&` intead of `;` Show errors sooner and try not to hide them behind lots of other walls of text. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3a9635a86180..bbe11e18472e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,10 +66,10 @@ script: if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then echo skipping, not a full build; elif [ "$TRAVIS_OS_NAME" = "osx" ]; then - git submodule update --init; + git submodule update --init && src/ci/run.sh; else - git submodule update --init; + git submodule update --init && src/ci/docker/run.sh $IMAGE; fi From 0f8e931475b1f7864504f509b389d28e1ffbc93a Mon Sep 17 00:00:00 2001 From: Wang Xuerui Date: Thu, 29 Dec 2016 02:23:38 +0800 Subject: [PATCH 17/30] rustbuild: allow overriding list of LLVM targets to build A new option is introduced under the `[llvm]` section of `config.toml`, `targets`, for overriding the list of LLVM targets to build support for. The option is passed through to LLVM configure script. Also notes are added about the implications of (ab)using the option; since the default is not changed, and users of the option are expected to know what they're doing anyway (as every porter should), the impact should be minimal. Fixes #38200. --- src/bootstrap/config.rs | 3 +++ src/bootstrap/config.toml.example | 11 +++++++++++ src/bootstrap/native.rs | 9 +++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 6b86e537b7d2..7e576175c354 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -54,6 +54,7 @@ pub struct Config { pub llvm_version_check: bool, pub llvm_static_stdcpp: bool, pub llvm_link_shared: bool, + pub llvm_targets: Option, // rust codegen options pub rust_optimize: bool, @@ -152,6 +153,7 @@ struct Llvm { release_debuginfo: Option, version_check: Option, static_libstdcpp: Option, + targets: Option, } #[derive(RustcDecodable)] @@ -285,6 +287,7 @@ impl Config { set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo); set(&mut config.llvm_version_check, llvm.version_check); set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); + config.llvm_targets = llvm.targets.clone(); } if let Some(ref rust) = toml.rust { diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 5fc095137c79..25f668f6e473 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -42,6 +42,17 @@ # example. #ninja = false +# LLVM targets to build support for. +# Note: this is NOT related to Rust compilation targets. However, as Rust is +# dependent on LLVM for code generation, turning targets off here WILL lead to +# the resulting rustc being unable to compile for the disabled architectures. +# Also worth pointing out is that, in case support for new targets are added to +# LLVM, enabling them here doesn't mean Rust is automatically gaining said +# support. You'll need to write a target specification at least, and most +# likely, teach rustc about the C ABI of the target. Get in touch with the +# Rust team and file an issue if you need assistance in porting! +#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc" + # ============================================================================= # General build configuration options # ============================================================================= diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 09dbd9f8220b..d3fa54e417ac 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -75,13 +75,18 @@ pub fn llvm(build: &Build, target: &str) { (true, true) => "RelWithDebInfo", }; + // NOTE: remember to also update `config.toml.example` when changing the defaults! + let llvm_targets = match build.config.llvm_targets { + Some(ref s) => s, + None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc", + }; + cfg.target(target) .host(&build.config.build) .out_dir(&dst) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) - .define("LLVM_TARGETS_TO_BUILD", - "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc") + .define("LLVM_TARGETS_TO_BUILD", llvm_targets) .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") From ee2abe85a6ed9dacd03c4113445053b9bde1ccaf Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Wed, 28 Dec 2016 11:11:17 -0800 Subject: [PATCH 18/30] Add missing apostrophe. (Minor typo fix.) The "support" in this case is possessed by the "programmer", and that ownership should be indicated by an apostrophe. --- src/doc/book/lifetimes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 140e27d19248..546e66fc8ac0 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -128,7 +128,7 @@ _descriptive_, not _prescriptive_. This means that how long a reference is valid is determined by the code, not by the annotations. The annotations, however, give information about lifetimes to the compiler that uses them to check the validity of references. The compiler can do so without annotations in simple -cases, but needs the programmers support in complex scenarios. +cases, but needs the programmer's support in complex scenarios. [traits]: traits.html From 1825f80fab649f0a5647239c58bcfbc58f378947 Mon Sep 17 00:00:00 2001 From: Martijn Vermaat Date: Wed, 28 Dec 2016 14:40:00 -0500 Subject: [PATCH 19/30] Fix default terminfo code for reset (sg0 -> sgr0) Resetting the terminal should first try `sgr0` (as per the comment), not `sg0` which I believe to be a typo. This will at least fix rustc output in Emacs terminals (e.g., ansi-term) with `TERM=eterm-color` which does not provide the next fallback `sgr`. In such a terminal, the final fallback `op` (`\e[39;49`) is used which resets only colors, not all attributes. This causes all text to be printed in bold from the first string printed in bold by rustc onwards, including the terminal prompt and the output from all following commands. The typo seems to have been introduced by #29999 --- src/libterm/terminfo/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index 395d966b9f25..68cfc7033ef5 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -190,7 +190,7 @@ impl Terminal for TerminfoTerminal { fn reset(&mut self) -> io::Result { // are there any terminals that have color/attrs and not sgr0? // Try falling back to sgr, then op - let cmd = match ["sg0", "sgr", "op"] + let cmd = match ["sgr0", "sgr", "op"] .iter() .filter_map(|cap| self.ti.strings.get(*cap)) .next() { From 57b53fdd9ef34bf4015b4fd7a202dfa485773c96 Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Wed, 28 Dec 2016 12:57:50 -0800 Subject: [PATCH 20/30] Use "an" before "i32" (Minor typo fix.) Since the word `i32` starts with a vowel, the indefinite article should use "an", not "a" \[[1](http://www.dictionary.com/browse/an)\]. (Previously there was one instance of "an i32" and two instances of "a i32", so at least something is wrong!) Since I believe that "an" is the correct form, I aligned everything with that. --- src/doc/book/closures.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index a3c7333c6bec..115fe1f76623 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -283,7 +283,7 @@ fn call_with_one(some_closure: F) -> i32 # some_closure(1) } ``` -We take one parameter, and it has the type `F`. We also return a `i32`. This part +We take one parameter, and it has the type `F`. We also return an `i32`. This part isn’t interesting. The next part is: ```rust @@ -293,7 +293,7 @@ isn’t interesting. The next part is: ``` Because `Fn` is a trait, we can use it as a bound for our generic type. In -this case, our closure takes a `i32` as an argument and returns an `i32`, and +this case, our closure takes an `i32` as an argument and returns an `i32`, and so the generic bound we use is `Fn(i32) -> i32`. There’s one other key point here: because we’re bounding a generic with a From 7046fea5be39110f4d4354b7fe5466903f606d8e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 25 Dec 2016 15:20:33 -0800 Subject: [PATCH 21/30] rustbuild: Compile rustc twice, not thrice This commit switches the rustbuild build system to compiling the compiler twice for a normal bootstrap rather than the historical three times. Rust is a bootstrapped language which means that a previous version of the compiler is used to build the next version of the compiler. Over time, however, we change many parts of compiler artifacts such as the metadata format, symbol names, etc. These changes make artifacts from one compiler incompatible from another compiler. Consequently if a compiler wants to be able to use some artifacts then it itself must have compiled the artifacts. Historically the rustc build system has achieved this by compiling the compiler three times: * An older compiler (stage0) is downloaded to kick off the chain. * This compiler now compiles a new compiler (stage1) * The stage1 compiler then compiles another compiler (stage2) * Finally, the stage2 compiler needs libraries to link against, so it compiles all the libraries again. This entire process amounts in compiling the compiler three times. Additionally, this process always guarantees that the Rust source tree can compile itself because the stage2 compiler (created by a freshly created compiler) would successfully compile itself again. This property, ensuring Rust can compile itself, is quite important! In general, though, this third compilation is not required for general purpose development on the compiler. The third compiler (stage2) can reuse the libraries that were created during the second compile. In other words, the second compilation can produce both a compiler and the libraries that compiler will use. These artifacts *must* be compatible due to the way plugins work today anyway, and they were created by the same source code so they *should* be compatible as well. So given all that, this commit switches the default build process to only compile the compiler three times, avoiding this third compilation by copying artifacts from the previous one. Along the way a new entry in the Travis matrix was also added to ensure that our full bootstrap can succeed. This entry does not run tests, though, as it should not be necessary. To restore the old behavior of a full bootstrap (three compiles) you can either pass: ./configure --enable-full-bootstrap or if you're using config.toml: [build] full-bootstrap = true Overall this will hopefully be an easy 33% win in build times of the compiler. If we do 33% less work we should be 33% faster! This in turn should affect cycle times and such on Travis and AppVeyor positively as well as making it easier to work on the compiler itself. --- .travis.yml | 1 + configure | 1 + src/bootstrap/check.rs | 18 +- src/bootstrap/compile.rs | 92 +++++---- src/bootstrap/config.rs | 4 + src/bootstrap/config.toml.example | 7 + src/bootstrap/doc.rs | 15 ++ src/bootstrap/lib.rs | 28 ++- src/bootstrap/step.rs | 181 ++++++++++++------ .../x86_64-gnu-full-bootstrap/Dockerfile | 28 +++ 10 files changed, 262 insertions(+), 113 deletions(-) create mode 100644 src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile diff --git a/.travis.yml b/.travis.yml index ea8c94af80b7..dd5fe7cd0432 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ matrix: - env: IMAGE=i686-gnu-nopt - env: IMAGE=x86_64-freebsd - env: IMAGE=x86_64-gnu + - env: IMAGE=x86_64-gnu-full-bootstrap - env: IMAGE=x86_64-gnu-cargotest - env: IMAGE=x86_64-gnu-debug - env: IMAGE=x86_64-gnu-nopt diff --git a/configure b/configure index 4f1e8f656ae2..5094e5a764bd 100755 --- a/configure +++ b/configure @@ -693,6 +693,7 @@ opt_nosave manage-submodules 1 "let the build manage the git submodules" opt_nosave clang 0 "prefer clang to gcc for building the runtime" opt_nosave jemalloc 1 "build liballoc with jemalloc" opt elf-tls 1 "elf thread local storage on platforms where supported" +opt full-bootstrap 0 "build three compilers instead of two" valopt_nosave prefix "/usr/local" "set installation prefix" valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary" diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index e7b0afeb8ce6..ec0243908eda 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -341,12 +341,22 @@ pub fn krate(build: &Build, println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage, compiler.host, target); + // If we're not doing a full bootstrap but we're testing a stage2 version of + // libstd, then what we're actually testing is the libstd produced in + // stage1. Reflect that here by updating the compiler that we're working + // with automatically. + let compiler = if build.force_use_stage1(compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler.clone() + }; + // Build up the base `cargo test` command. // // Pass in some standard flags then iterate over the graph we've discovered // in `cargo metadata` with the maps above and figure out what `-p` // arguments need to get passed. - let mut cargo = build.cargo(compiler, mode, target, test_kind.subcommand()); + let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand()); cargo.arg("--manifest-path") .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); @@ -380,7 +390,7 @@ pub fn krate(build: &Build, // Note that to run the compiler we need to run with the *host* libraries, // but our wrapper scripts arrange for that to be the case anyway. let mut dylib_path = dylib_path(); - dylib_path.insert(0, build.sysroot_libdir(compiler, target)); + dylib_path.insert(0, build.sysroot_libdir(&compiler, target)); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); if target.contains("android") { @@ -399,10 +409,10 @@ pub fn krate(build: &Build, if target.contains("android") { build.run(&mut cargo); - krate_android(build, compiler, target, mode); + krate_android(build, &compiler, target, mode); } else if target.contains("emscripten") { build.run(&mut cargo); - krate_emscripten(build, compiler, target, mode); + krate_emscripten(build, &compiler, target, mode); } else { cargo.args(&build.flags.cmd.test_args()); build.run(&mut cargo); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b268686ca6c3..24e29225c6e0 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -33,14 +33,14 @@ use {Build, Compiler, Mode}; /// This will build the standard library for a particular stage of the build /// using the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. -pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { - println!("Building stage{} std artifacts ({} -> {})", compiler.stage, - compiler.host, target); - +pub fn std(build: &Build, target: &str, compiler: &Compiler) { let libdir = build.sysroot_libdir(compiler, target); let _ = fs::remove_dir_all(&libdir); t!(fs::create_dir_all(&libdir)); + println!("Building stage{} std artifacts ({} -> {})", compiler.stage, + compiler.host, target); + // Some platforms have startup objects that may be required to produce the // libstd dynamic library, for example. build_startup_objects(build, target, &libdir); @@ -65,29 +65,30 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { build.run(&mut cargo); update_mtime(&libstd_stamp(build, &compiler, target)); - std_link(build, target, compiler.stage, compiler.host); } /// Link all libstd rlibs/dylibs into the sysroot location. /// -/// Links those artifacts generated in the given `stage` for `target` produced -/// by `compiler` into `host`'s sysroot. +/// Links those artifacts generated by `compiler` to a the `stage` compiler's +/// sysroot for the specified `host` and `target`. +/// +/// Note that this assumes that `compiler` has already generated the libstd +/// libraries for `target`, and this method will find them in the relevant +/// output directory. pub fn std_link(build: &Build, - target: &str, - stage: u32, - host: &str) { - let compiler = Compiler::new(stage, &build.config.build); - let target_compiler = Compiler::new(compiler.stage, host); + compiler: &Compiler, + target_compiler: &Compiler, + target: &str) { + println!("Copying stage{} std from stage{} ({} -> {} / {})", + target_compiler.stage, + compiler.stage, + compiler.host, + target_compiler.host, + target); let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(&compiler, Mode::Libstd, target); - // If we're linking one compiler host's output into another, then we weren't - // called from the `std` method above. In that case we clean out what's - // already there. - if host != compiler.host { - let _ = fs::remove_dir_all(&libdir); - t!(fs::create_dir_all(&libdir)); - } + t!(fs::create_dir_all(&libdir)); add_to_sysroot(&out_dir, &libdir); if target.contains("musl") && !target.contains("mips") { @@ -137,7 +138,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) { /// This will build libtest and supporting libraries for a particular stage of /// the build using the `compiler` targeting the `target` architecture. The /// artifacts created will also be linked into the sysroot directory. -pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { +pub fn test(build: &Build, target: &str, compiler: &Compiler) { println!("Building stage{} test artifacts ({} -> {})", compiler.stage, compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Libtest, target); @@ -147,19 +148,13 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { .arg(build.src.join("src/rustc/test_shim/Cargo.toml")); build.run(&mut cargo); update_mtime(&libtest_stamp(build, compiler, target)); - test_link(build, target, compiler.stage, compiler.host); } -/// Link all libtest rlibs/dylibs into the sysroot location. -/// -/// Links those artifacts generated in the given `stage` for `target` produced -/// by `compiler` into `host`'s sysroot. +/// Same as `std_link`, only for libtest pub fn test_link(build: &Build, - target: &str, - stage: u32, - host: &str) { - let compiler = Compiler::new(stage, &build.config.build); - let target_compiler = Compiler::new(compiler.stage, host); + compiler: &Compiler, + target_compiler: &Compiler, + target: &str) { let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(&compiler, Mode::Libtest, target); add_to_sysroot(&out_dir, &libdir); @@ -170,7 +165,7 @@ pub fn test_link(build: &Build, /// This will build the compiler for a particular stage of the build using /// the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. -pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { +pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { println!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, compiler.host, target); @@ -222,20 +217,13 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { cargo.env("CFG_DEFAULT_AR", s); } build.run(&mut cargo); - - rustc_link(build, target, compiler.stage, compiler.host); } -/// Link all librustc rlibs/dylibs into the sysroot location. -/// -/// Links those artifacts generated in the given `stage` for `target` produced -/// by `compiler` into `host`'s sysroot. +/// Same as `std_link`, only for librustc pub fn rustc_link(build: &Build, - target: &str, - stage: u32, - host: &str) { - let compiler = Compiler::new(stage, &build.config.build); - let target_compiler = Compiler::new(compiler.stage, host); + compiler: &Compiler, + target_compiler: &Compiler, + target: &str) { let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(&compiler, Mode::Librustc, target); add_to_sysroot(&out_dir, &libdir); @@ -259,6 +247,17 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { PathBuf::from(out.trim()) } +pub fn create_sysroot(build: &Build, compiler: &Compiler) { + // nothing to do in stage0 + if compiler.stage == 0 { + return + } + + let sysroot = build.sysroot(compiler); + let _ = fs::remove_dir_all(&sysroot); + t!(fs::create_dir_all(&sysroot)); +} + /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler @@ -269,18 +268,17 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { if stage == 0 { return } + + println!("Copying stage{} compiler ({})", stage, host); + // The compiler that we're assembling let target_compiler = Compiler::new(stage, host); // The compiler that compiled the compiler we're assembling let build_compiler = Compiler::new(stage - 1, &build.config.build); - // Clear out old files - let sysroot = build.sysroot(&target_compiler); - let _ = fs::remove_dir_all(&sysroot); - t!(fs::create_dir_all(&sysroot)); - // Link in all dylibs to the libdir + let sysroot = build.sysroot(&target_compiler); let sysroot_libdir = sysroot.join(libdir(host)); t!(fs::create_dir_all(&sysroot_libdir)); let src_libdir = build.sysroot_libdir(&build_compiler, host); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 6b86e537b7d2..93fe39ab41b5 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -46,6 +46,7 @@ pub struct Config { pub docs: bool, pub vendor: bool, pub target_config: HashMap, + pub full_bootstrap: bool, // llvm codegen options pub llvm_assertions: bool, @@ -134,6 +135,7 @@ struct Build { vendor: Option, nodejs: Option, python: Option, + full_bootstrap: Option, } /// TOML representation of various global install decisions. @@ -264,6 +266,7 @@ impl Config { set(&mut config.docs, build.docs); set(&mut config.submodules, build.submodules); set(&mut config.vendor, build.vendor); + set(&mut config.full_bootstrap, build.full_bootstrap); if let Some(ref install) = toml.install { config.prefix = install.prefix.clone(); @@ -393,6 +396,7 @@ impl Config { ("NINJA", self.ninja), ("CODEGEN_TESTS", self.codegen_tests), ("VENDOR", self.vendor), + ("FULL_BOOTSTRAP", self.full_bootstrap), } match key { diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 5fc095137c79..7c8d3870e923 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -100,6 +100,13 @@ # Indicate whether the vendored sources are used for Rust dependencies or not #vendor = false +# Typically the build system will build the rust compiler twice. The second +# compiler, however, will simply use its own libraries to link against. If you +# would rather to perform a full bootstrap, compiling the compiler three times, +# then you can set this option to true. You shouldn't ever need to set this +# option to true. +#full-bootstrap = false + # ============================================================================= # General install configuration options # ============================================================================= diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 30c7fefad874..4c4462bf1220 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -137,6 +137,11 @@ pub fn std(build: &Build, stage: u32, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; let out_dir = build.stage_out(&compiler, Mode::Libstd) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); @@ -160,6 +165,11 @@ pub fn test(build: &Build, stage: u32, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; let out_dir = build.stage_out(&compiler, Mode::Libtest) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); @@ -182,6 +192,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; let out_dir = build.stage_out(&compiler, Mode::Librustc) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 665e0c67b7f6..49eaed4c67ac 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -572,9 +572,7 @@ impl Build { let mut cmd = Command::new(self.tool(&compiler, tool)); let host = compiler.host; let mut paths = vec![ - self.cargo_out(compiler, Mode::Libstd, host).join("deps"), - self.cargo_out(compiler, Mode::Libtest, host).join("deps"), - self.cargo_out(compiler, Mode::Librustc, host).join("deps"), + self.sysroot_libdir(compiler, compiler.host), self.cargo_out(compiler, Mode::Tool, host).join("deps"), ]; @@ -880,6 +878,30 @@ impl Build { fn python(&self) -> &Path { self.config.python.as_ref().unwrap() } + + /// Tests whether the `compiler` compiling for `target` should be forced to + /// use a stage1 compiler instead. + /// + /// Currently, by default, the build system does not perform a "full + /// bootstrap" by default where we compile the compiler three times. + /// Instead, we compile the compiler two times. The final stage (stage2) + /// just copies the libraries from the previous stage, which is what this + /// method detects. + /// + /// Here we return `true` if: + /// + /// * The build isn't performing a full bootstrap + /// * The `compiler` is in the final stage, 2 + /// * We're not cross-compiling, so the artifacts are already available in + /// stage1 + /// + /// When all of these conditions are met the build will lift artifacts from + /// the previous stage forward. + fn force_use_stage1(&self, compiler: &Compiler, target: &str) -> bool { + !self.config.full_bootstrap && + compiler.stage >= 2 && + self.config.host.iter().any(|h| h == target) + } } impl<'a> Compiler<'a> { diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index c5898c1119a6..ad188897387f 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -44,7 +44,7 @@ pub fn run(build: &Build) { rules.run(&steps); } -pub fn build_rules(build: &Build) -> Rules { +pub fn build_rules<'a>(build: &'a Build) -> Rules { let mut rules = Rules::new(build); // This is the first rule that we're going to define for rustbuild, which is @@ -117,6 +117,7 @@ pub fn build_rules(build: &Build) -> Rules { // the compiler with no target libraries ready to go rules.build("rustc", "src/rustc") + .dep(|s| s.name("create-sysroot").target(s.host)) .dep(move |s| { if s.stage == 0 { Step::noop() @@ -151,69 +152,131 @@ pub fn build_rules(build: &Build) -> Rules { // Crate compilations // // Tools used during the build system but not shipped + rules.build("create-sysroot", "path/to/nowhere") + .run(move |s| compile::create_sysroot(build, &s.compiler())); + + // These rules are "pseudo rules" that don't actually do any work + // themselves, but represent a complete sysroot with the relevant compiler + // linked into place. + // + // That is, depending on "libstd" means that when the rule is completed then + // the `stage` sysroot for the compiler `host` will be available with a + // standard library built for `target` linked in place. Not all rules need + // the compiler itself to be available, just the standard library, so + // there's a distinction between the two. rules.build("libstd", "src/libstd") - .dep(|s| s.name("build-crate-std_shim")); + .dep(|s| s.name("rustc").target(s.host)) + .dep(|s| s.name("libstd-link")); rules.build("libtest", "src/libtest") - .dep(|s| s.name("build-crate-test_shim")); + .dep(|s| s.name("libstd")) + .dep(|s| s.name("libtest-link")) + .default(true); rules.build("librustc", "src/librustc") - .dep(|s| s.name("build-crate-rustc-main")); + .dep(|s| s.name("libtest")) + .dep(|s| s.name("librustc-link")) + .host(true) + .default(true); + + // Helper method to define the rules to link a crate into its place in the + // sysroot. + // + // The logic here is a little subtle as there's a few cases to consider. + // Not all combinations of (stage, host, target) actually require something + // to be compiled, but rather libraries could get propagated from a + // different location. For example: + // + // * Any crate with a `host` that's not the build triple will not actually + // compile something. A different `host` means that the build triple will + // actually compile the libraries, and then we'll copy them over from the + // build triple to the `host` directory. + // + // * Some crates aren't even compiled by the build triple, but may be copied + // from previous stages. For example if we're not doing a full bootstrap + // then we may just depend on the stage1 versions of libraries to be + // available to get linked forward. + // + // * Finally, there are some cases, however, which do indeed comiple crates + // and link them into place afterwards. + // + // The rule definition below mirrors these three cases. The `dep` method + // calculates the correct dependency which either comes from stage1, a + // different compiler, or from actually building the crate itself (the `dep` + // rule). The `run` rule then mirrors these three cases and links the cases + // forward into the compiler sysroot specified from the correct location. + fn crate_rule<'a, 'b>(build: &'a Build, + rules: &'b mut Rules<'a>, + krate: &'a str, + dep: &'a str, + link: fn(&Build, &Compiler, &Compiler, &str)) + -> RuleBuilder<'a, 'b> { + let mut rule = rules.build(&krate, "path/to/nowhere"); + rule.dep(move |s| { + if build.force_use_stage1(&s.compiler(), s.target) { + s.host(&build.config.build).stage(1) + } else if s.host == build.config.build { + s.name(dep) + } else { + s.host(&build.config.build) + } + }) + .run(move |s| { + if build.force_use_stage1(&s.compiler(), s.target) { + link(build, + &s.stage(1).host(&build.config.build).compiler(), + &s.compiler(), + s.target) + } else if s.host == build.config.build { + link(build, &s.compiler(), &s.compiler(), s.target) + } else { + link(build, + &s.host(&build.config.build).compiler(), + &s.compiler(), + s.target) + } + }); + return rule + } + + // Similar to the `libstd`, `libtest`, and `librustc` rules above, except + // these rules only represent the libraries being available in the sysroot, + // not the compiler itself. This is done as not all rules need a compiler in + // the sysroot, but may just need the libraries. + // + // All of these rules use the helper definition above. + crate_rule(build, + &mut rules, + "libstd-link", + "build-crate-std_shim", + compile::std_link) + .dep(|s| s.name("create-sysroot").target(s.host)); + crate_rule(build, + &mut rules, + "libtest-link", + "build-crate-test_shim", + compile::test_link) + .dep(|s| s.name("libstd-link")); + crate_rule(build, + &mut rules, + "librustc-link", + "build-crate-rustc-main", + compile::rustc_link) + .dep(|s| s.name("libtest-link")); + for (krate, path, _default) in krates("std_shim") { rules.build(&krate.build_step, path) .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host)) - .dep(move |s| { - if s.host == build.config.build { - Step::noop() - } else { - s.host(&build.config.build) - } - }) - .run(move |s| { - if s.host == build.config.build { - compile::std(build, s.target, &s.compiler()) - } else { - compile::std_link(build, s.target, s.stage, s.host) - } - }); + .run(move |s| compile::std(build, s.target, &s.compiler())); } - for (krate, path, default) in krates("test_shim") { + for (krate, path, _default) in krates("test_shim") { rules.build(&krate.build_step, path) - .dep(|s| s.name("libstd")) - .dep(move |s| { - if s.host == build.config.build { - Step::noop() - } else { - s.host(&build.config.build) - } - }) - .default(default) - .run(move |s| { - if s.host == build.config.build { - compile::test(build, s.target, &s.compiler()) - } else { - compile::test_link(build, s.target, s.stage, s.host) - } - }); + .dep(|s| s.name("libstd-link")) + .run(move |s| compile::test(build, s.target, &s.compiler())); } - for (krate, path, default) in krates("rustc-main") { + for (krate, path, _default) in krates("rustc-main") { rules.build(&krate.build_step, path) - .dep(|s| s.name("libtest")) + .dep(|s| s.name("libtest-link")) .dep(move |s| s.name("llvm").host(&build.config.build).stage(0)) - .dep(move |s| { - if s.host == build.config.build { - Step::noop() - } else { - s.host(&build.config.build) - } - }) - .host(true) - .default(default) - .run(move |s| { - if s.host == build.config.build { - compile::rustc(build, s.target, &s.compiler()) - } else { - compile::rustc_link(build, s.target, s.stage, s.host) - } - }); + .run(move |s| compile::rustc(build, s.target, &s.compiler())); } // ======================================================================== @@ -444,25 +507,25 @@ pub fn build_rules(build: &Build) -> Rules { .run(move |s| doc::standalone(build, s.stage, s.target)); rules.doc("doc-error-index", "src/tools/error_index_generator") .dep(move |s| s.name("tool-error-index").target(&build.config.build)) - .dep(move |s| s.name("librustc")) + .dep(move |s| s.name("librustc-link")) .default(build.config.docs) .host(true) .run(move |s| doc::error_index(build, s.stage, s.target)); for (krate, path, default) in krates("std_shim") { rules.doc(&krate.doc_step, path) - .dep(|s| s.name("libstd")) + .dep(|s| s.name("libstd-link")) .default(default && build.config.docs) .run(move |s| doc::std(build, s.stage, s.target)); } for (krate, path, default) in krates("test_shim") { rules.doc(&krate.doc_step, path) - .dep(|s| s.name("libtest")) + .dep(|s| s.name("libtest-link")) .default(default && build.config.compiler_docs) .run(move |s| doc::test(build, s.stage, s.target)); } for (krate, path, default) in krates("rustc-main") { rules.doc(&krate.doc_step, path) - .dep(|s| s.name("librustc")) + .dep(|s| s.name("librustc-link")) .host(true) .default(default && build.config.compiler_docs) .run(move |s| doc::rustc(build, s.stage, s.target)); @@ -481,9 +544,9 @@ pub fn build_rules(build: &Build) -> Rules { // for the `rust-std` package, so if this is a host target we // depend on librustc and otherwise we just depend on libtest. if build.config.host.iter().any(|t| t == s.target) { - s.name("librustc") + s.name("librustc-link") } else { - s.name("libtest") + s.name("libtest-link") } }) .default(true) diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile new file mode 100644 index 000000000000..7c079e45751c --- /dev/null +++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile @@ -0,0 +1,28 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +ENV RUST_CONFIGURE_ARGS \ + --build=x86_64-unknown-linux-gnu \ + --enable-full-bootstrap +ENV RUST_CHECK_TARGET "" From fc3e49b1f1c77fbda732573aa5d6b3c11f4f7bcc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 28 Dec 2016 15:05:17 -0800 Subject: [PATCH 22/30] rustbuild: Move pretty test suites to host-only In an ongoing effort to optimize the runtime of the Android cross builder this commit updates the pretty test suites to run only for host platforms, not for target platforms as well. This means we'll still keep running all the suites but we'll only run them for configured hosts, not for configured targets. This notably means that we won't be running these suites on Android or musl targets, for example. --- src/bootstrap/step.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index c5898c1119a6..5f4ee061888a 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -254,13 +254,6 @@ pub fn build_rules(build: &Build) -> Rules { suite("check-incremental", "src/test/incremental", "incremental", "incremental"); suite("check-ui", "src/test/ui", "ui", "ui"); - suite("check-pretty", "src/test/pretty", "pretty", "pretty"); - suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", - "run-pass"); - suite("check-pretty-rfail", "src/test/run-pass/pretty", "pretty", - "run-fail"); - suite("check-pretty-valgrind", "src/test/run-pass-valgrind", "pretty", - "run-pass-valgrind"); } if build.config.build.contains("msvc") { @@ -307,6 +300,13 @@ pub fn build_rules(build: &Build) -> Rules { "compile-fail", "compile-fail-fulldeps"); suite("check-rmake", "src/test/run-make", "run-make", "run-make"); suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc"); + suite("check-pretty", "src/test/pretty", "pretty", "pretty"); + suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", + "run-pass"); + suite("check-pretty-rfail", "src/test/run-pass/pretty", "pretty", + "run-fail"); + suite("check-pretty-valgrind", "src/test/run-pass-valgrind", "pretty", + "run-pass-valgrind"); suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps", "pretty", "run-pass-fulldeps"); suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps", From b9038c8e9f4df04093fcca5fb4870796c3a29b75 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Thu, 29 Dec 2016 02:23:49 +0000 Subject: [PATCH 23/30] rustdoc: Fix broken CSS for trait items --- src/librustdoc/html/render.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d66adb5ecfa3..ff7133f5d0c9 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2057,10 +2057,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, let item_type = m.type_(); let id = derive_id(format!("{}.{}", item_type, name)); let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); - write!(w, "

\ + write!(w, "

\