Auto merge of #38697 - alexcrichton:rollup, r=alexcrichton

Rollup of 25 pull requests

- Successful merges: #37149, #38491, #38517, #38559, #38587, #38609, #38611, #38622, #38628, #38630, #38631, #38632, #38635, #38647, #38649, #38655, #38659, #38660, #38662, #38665, #38671, #38674, #38676, #38693, #38695
- Failed merges: #38657, #38680
This commit is contained in:
bors 2016-12-30 07:34:19 +00:00
commit 7f2d2afa91
57 changed files with 1022 additions and 300 deletions

View File

@ -19,7 +19,8 @@ matrix:
- env: IMAGE=i686-gnu-nopt - env: IMAGE=i686-gnu-nopt
- env: IMAGE=x86_64-freebsd - env: IMAGE=x86_64-freebsd
- env: IMAGE=x86_64-gnu - env: IMAGE=x86_64-gnu
- env: IMAGE=x86_64-gnu-cargotest - env: IMAGE=x86_64-gnu-full-bootstrap
- env: IMAGE=x86_64-gnu-aux
- env: IMAGE=x86_64-gnu-debug - env: IMAGE=x86_64-gnu-debug
- env: IMAGE=x86_64-gnu-nopt - env: IMAGE=x86_64-gnu-nopt
- env: IMAGE=x86_64-gnu-make - env: IMAGE=x86_64-gnu-make
@ -66,10 +67,10 @@ script:
if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
echo skipping, not a full build; echo skipping, not a full build;
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
git submodule update --init; git submodule update --init &&
src/ci/run.sh; src/ci/run.sh;
else else
git submodule update --init; git submodule update --init &&
src/ci/docker/run.sh $IMAGE; src/ci/docker/run.sh $IMAGE;
fi fi
@ -78,7 +79,7 @@ before_cache:
- docker history -q rust-ci | - docker history -q rust-ci |
grep -v missing | grep -v missing |
xargs docker save | xargs docker save |
gzip -9 > $HOME/docker/rust-ci.tar.gz gzip > $HOME/docker/rust-ci.tar.gz
before_install: before_install:
- zcat $HOME/docker/rust-ci.tar.gz | docker load || true - zcat $HOME/docker/rust-ci.tar.gz | docker load || true

View File

@ -82,8 +82,9 @@ build.
# Install build tools needed for Rust. If you're building a 32-bit compiler, # 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, # 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 # 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. # that it is important that you do **not** use the 'python2' and 'cmake'
# The build has historically been known to fail with these packages. # packages from the 'msys2' subsystem. The build has historically been known
# to fail with these packages.
$ pacman -S git \ $ pacman -S git \
make \ make \
diffutils \ diffutils \

View File

@ -21,7 +21,7 @@ environment:
# MSVC cargotest # MSVC cargotest
- MSYS_BITS: 64 - MSYS_BITS: 64
NO_VENDOR: 1 NO_VENDOR: 1
RUST_CHECK_TARGET: check-cargotest RUST_CHECK_TARGET: check-aux
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
# 32/64-bit MinGW builds. # 32/64-bit MinGW builds.

1
configure vendored
View File

@ -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 clang 0 "prefer clang to gcc for building the runtime"
opt_nosave jemalloc 1 "build liballoc with jemalloc" opt_nosave jemalloc 1 "build liballoc with jemalloc"
opt elf-tls 1 "elf thread local storage on platforms where supported" 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 prefix "/usr/local" "set installation prefix"
valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary" valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary"

View File

@ -341,12 +341,22 @@ pub fn krate(build: &Build,
println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage, println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
compiler.host, target); 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. // Build up the base `cargo test` command.
// //
// Pass in some standard flags then iterate over the graph we've discovered // 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` // in `cargo metadata` with the maps above and figure out what `-p`
// arguments need to get passed. // 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") cargo.arg("--manifest-path")
.arg(build.src.join(path).join("Cargo.toml")) .arg(build.src.join(path).join("Cargo.toml"))
.arg("--features").arg(features); .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, // 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. // but our wrapper scripts arrange for that to be the case anyway.
let mut dylib_path = dylib_path(); 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()); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
if target.contains("android") { if target.contains("android") {
@ -399,10 +409,10 @@ pub fn krate(build: &Build,
if target.contains("android") { if target.contains("android") {
build.run(&mut cargo); build.run(&mut cargo);
krate_android(build, compiler, target, mode); krate_android(build, &compiler, target, mode);
} else if target.contains("emscripten") { } else if target.contains("emscripten") {
build.run(&mut cargo); build.run(&mut cargo);
krate_emscripten(build, compiler, target, mode); krate_emscripten(build, &compiler, target, mode);
} else { } else {
cargo.args(&build.flags.cmd.test_args()); cargo.args(&build.flags.cmd.test_args());
build.run(&mut cargo); build.run(&mut cargo);

View File

@ -33,17 +33,12 @@ use {Build, Compiler, Mode};
/// This will build the standard library for a particular stage of the build /// This will build the standard library for a particular stage of the build
/// using the `compiler` targeting the `target` architecture. The artifacts /// using the `compiler` targeting the `target` architecture. The artifacts
/// created will also be linked into the sysroot directory. /// created will also be linked into the sysroot directory.
pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { pub fn std(build: &Build, target: &str, compiler: &Compiler) {
println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
compiler.host, target);
let libdir = build.sysroot_libdir(compiler, target); let libdir = build.sysroot_libdir(compiler, target);
let _ = fs::remove_dir_all(&libdir);
t!(fs::create_dir_all(&libdir)); t!(fs::create_dir_all(&libdir));
// Some platforms have startup objects that may be required to produce the println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
// libstd dynamic library, for example. compiler.host, target);
build_startup_objects(build, target, &libdir);
let out_dir = build.cargo_out(compiler, Mode::Libstd, target); let out_dir = build.cargo_out(compiler, Mode::Libstd, target);
build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); build.clear_if_dirty(&out_dir, &build.compiler_path(compiler));
@ -65,29 +60,30 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
build.run(&mut cargo); build.run(&mut cargo);
update_mtime(&libstd_stamp(build, &compiler, target)); update_mtime(&libstd_stamp(build, &compiler, target));
std_link(build, target, compiler.stage, compiler.host);
} }
/// Link all libstd rlibs/dylibs into the sysroot location. /// Link all libstd rlibs/dylibs into the sysroot location.
/// ///
/// Links those artifacts generated in the given `stage` for `target` produced /// Links those artifacts generated by `compiler` to a the `stage` compiler's
/// by `compiler` into `host`'s sysroot. /// 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, pub fn std_link(build: &Build,
target: &str, compiler: &Compiler,
stage: u32, target_compiler: &Compiler,
host: &str) { target: &str) {
let compiler = Compiler::new(stage, &build.config.build); println!("Copying stage{} std from stage{} ({} -> {} / {})",
let target_compiler = Compiler::new(compiler.stage, host); target_compiler.stage,
compiler.stage,
compiler.host,
target_compiler.host,
target);
let libdir = build.sysroot_libdir(&target_compiler, target); let libdir = build.sysroot_libdir(&target_compiler, target);
let out_dir = build.cargo_out(&compiler, Mode::Libstd, 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 t!(fs::create_dir_all(&libdir));
// 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));
}
add_to_sysroot(&out_dir, &libdir); add_to_sysroot(&out_dir, &libdir);
if target.contains("musl") && !target.contains("mips") { if target.contains("musl") && !target.contains("mips") {
@ -110,12 +106,15 @@ fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) {
/// They don't require any library support as they're just plain old object /// They don't require any library support as they're just plain old object
/// files, so we just use the nightly snapshot compiler to always build them (as /// files, so we just use the nightly snapshot compiler to always build them (as
/// no other compilers are guaranteed to be available). /// no other compilers are guaranteed to be available).
fn build_startup_objects(build: &Build, target: &str, into: &Path) { pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &str) {
if !target.contains("pc-windows-gnu") { if !target.contains("pc-windows-gnu") {
return return
} }
let compiler = Compiler::new(0, &build.config.build); let compiler = Compiler::new(0, &build.config.build);
let compiler_path = build.compiler_path(&compiler); let compiler_path = build.compiler_path(&compiler);
let into = build.sysroot_libdir(for_compiler, target);
t!(fs::create_dir_all(&into));
for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) { for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) {
let file = t!(file); let file = t!(file);
@ -123,7 +122,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
build.run(cmd.env("RUSTC_BOOTSTRAP", "1") build.run(cmd.env("RUSTC_BOOTSTRAP", "1")
.arg("--target").arg(target) .arg("--target").arg(target)
.arg("--emit=obj") .arg("--emit=obj")
.arg("--out-dir").arg(into) .arg("--out-dir").arg(&into)
.arg(file.path())); .arg(file.path()));
} }
@ -137,7 +136,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
/// This will build libtest and supporting libraries for a particular stage of /// This will build libtest and supporting libraries for a particular stage of
/// the build using the `compiler` targeting the `target` architecture. The /// the build using the `compiler` targeting the `target` architecture. The
/// artifacts created will also be linked into the sysroot directory. /// 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, println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
compiler.host, target); compiler.host, target);
let out_dir = build.cargo_out(compiler, Mode::Libtest, target); let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
@ -147,19 +146,19 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
.arg(build.src.join("src/rustc/test_shim/Cargo.toml")); .arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
build.run(&mut cargo); build.run(&mut cargo);
update_mtime(&libtest_stamp(build, compiler, target)); update_mtime(&libtest_stamp(build, compiler, target));
test_link(build, target, compiler.stage, compiler.host);
} }
/// Link all libtest rlibs/dylibs into the sysroot location. /// Same as `std_link`, only for libtest
///
/// Links those artifacts generated in the given `stage` for `target` produced
/// by `compiler` into `host`'s sysroot.
pub fn test_link(build: &Build, pub fn test_link(build: &Build,
target: &str, compiler: &Compiler,
stage: u32, target_compiler: &Compiler,
host: &str) { target: &str) {
let compiler = Compiler::new(stage, &build.config.build); println!("Copying stage{} test from stage{} ({} -> {} / {})",
let target_compiler = Compiler::new(compiler.stage, host); target_compiler.stage,
compiler.stage,
compiler.host,
target_compiler.host,
target);
let libdir = build.sysroot_libdir(&target_compiler, target); let libdir = build.sysroot_libdir(&target_compiler, target);
let out_dir = build.cargo_out(&compiler, Mode::Libtest, target); let out_dir = build.cargo_out(&compiler, Mode::Libtest, target);
add_to_sysroot(&out_dir, &libdir); add_to_sysroot(&out_dir, &libdir);
@ -170,7 +169,7 @@ pub fn test_link(build: &Build,
/// This will build the compiler for a particular stage of the build using /// This will build the compiler for a particular stage of the build using
/// the `compiler` targeting the `target` architecture. The artifacts /// the `compiler` targeting the `target` architecture. The artifacts
/// created will also be linked into the sysroot directory. /// 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 ({} -> {})", println!("Building stage{} compiler artifacts ({} -> {})",
compiler.stage, compiler.host, target); compiler.stage, compiler.host, target);
@ -222,20 +221,19 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("CFG_DEFAULT_AR", s); cargo.env("CFG_DEFAULT_AR", s);
} }
build.run(&mut cargo); build.run(&mut cargo);
rustc_link(build, target, compiler.stage, compiler.host);
} }
/// Link all librustc rlibs/dylibs into the sysroot location. /// Same as `std_link`, only for librustc
///
/// Links those artifacts generated in the given `stage` for `target` produced
/// by `compiler` into `host`'s sysroot.
pub fn rustc_link(build: &Build, pub fn rustc_link(build: &Build,
target: &str, compiler: &Compiler,
stage: u32, target_compiler: &Compiler,
host: &str) { target: &str) {
let compiler = Compiler::new(stage, &build.config.build); println!("Copying stage{} rustc from stage{} ({} -> {} / {})",
let target_compiler = Compiler::new(compiler.stage, host); target_compiler.stage,
compiler.stage,
compiler.host,
target_compiler.host,
target);
let libdir = build.sysroot_libdir(&target_compiler, target); let libdir = build.sysroot_libdir(&target_compiler, target);
let out_dir = build.cargo_out(&compiler, Mode::Librustc, target); let out_dir = build.cargo_out(&compiler, Mode::Librustc, target);
add_to_sysroot(&out_dir, &libdir); add_to_sysroot(&out_dir, &libdir);
@ -259,6 +257,17 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
PathBuf::from(out.trim()) 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` /// Prepare a new compiler from the artifacts in `stage`
/// ///
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
@ -269,18 +278,17 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
if stage == 0 { if stage == 0 {
return return
} }
println!("Copying stage{} compiler ({})", stage, host);
// The compiler that we're assembling // The compiler that we're assembling
let target_compiler = Compiler::new(stage, host); let target_compiler = Compiler::new(stage, host);
// The compiler that compiled the compiler we're assembling // The compiler that compiled the compiler we're assembling
let build_compiler = Compiler::new(stage - 1, &build.config.build); 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 // Link in all dylibs to the libdir
let sysroot = build.sysroot(&target_compiler);
let sysroot_libdir = sysroot.join(libdir(host)); let sysroot_libdir = sysroot.join(libdir(host));
t!(fs::create_dir_all(&sysroot_libdir)); t!(fs::create_dir_all(&sysroot_libdir));
let src_libdir = build.sysroot_libdir(&build_compiler, host); let src_libdir = build.sysroot_libdir(&build_compiler, host);

View File

@ -46,6 +46,7 @@ pub struct Config {
pub docs: bool, pub docs: bool,
pub vendor: bool, pub vendor: bool,
pub target_config: HashMap<String, Target>, pub target_config: HashMap<String, Target>,
pub full_bootstrap: bool,
// llvm codegen options // llvm codegen options
pub llvm_assertions: bool, pub llvm_assertions: bool,
@ -54,6 +55,7 @@ pub struct Config {
pub llvm_version_check: bool, pub llvm_version_check: bool,
pub llvm_static_stdcpp: bool, pub llvm_static_stdcpp: bool,
pub llvm_link_shared: bool, pub llvm_link_shared: bool,
pub llvm_targets: Option<String>,
// rust codegen options // rust codegen options
pub rust_optimize: bool, pub rust_optimize: bool,
@ -134,6 +136,7 @@ struct Build {
vendor: Option<bool>, vendor: Option<bool>,
nodejs: Option<String>, nodejs: Option<String>,
python: Option<String>, python: Option<String>,
full_bootstrap: Option<bool>,
} }
/// TOML representation of various global install decisions. /// TOML representation of various global install decisions.
@ -152,6 +155,7 @@ struct Llvm {
release_debuginfo: Option<bool>, release_debuginfo: Option<bool>,
version_check: Option<bool>, version_check: Option<bool>,
static_libstdcpp: Option<bool>, static_libstdcpp: Option<bool>,
targets: Option<String>,
} }
#[derive(RustcDecodable)] #[derive(RustcDecodable)]
@ -264,6 +268,7 @@ impl Config {
set(&mut config.docs, build.docs); set(&mut config.docs, build.docs);
set(&mut config.submodules, build.submodules); set(&mut config.submodules, build.submodules);
set(&mut config.vendor, build.vendor); set(&mut config.vendor, build.vendor);
set(&mut config.full_bootstrap, build.full_bootstrap);
if let Some(ref install) = toml.install { if let Some(ref install) = toml.install {
config.prefix = install.prefix.clone(); config.prefix = install.prefix.clone();
@ -285,6 +290,7 @@ impl Config {
set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo); set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
set(&mut config.llvm_version_check, llvm.version_check); set(&mut config.llvm_version_check, llvm.version_check);
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
config.llvm_targets = llvm.targets.clone();
} }
if let Some(ref rust) = toml.rust { if let Some(ref rust) = toml.rust {
@ -393,6 +399,7 @@ impl Config {
("NINJA", self.ninja), ("NINJA", self.ninja),
("CODEGEN_TESTS", self.codegen_tests), ("CODEGEN_TESTS", self.codegen_tests),
("VENDOR", self.vendor), ("VENDOR", self.vendor),
("FULL_BOOTSTRAP", self.full_bootstrap),
} }
match key { match key {

View File

@ -42,6 +42,17 @@
# example. # example.
#ninja = false #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;NVPTX"
# ============================================================================= # =============================================================================
# General build configuration options # General build configuration options
# ============================================================================= # =============================================================================
@ -100,6 +111,13 @@
# Indicate whether the vendored sources are used for Rust dependencies or not # Indicate whether the vendored sources are used for Rust dependencies or not
#vendor = false #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 # General install configuration options
# ============================================================================= # =============================================================================

View File

@ -137,6 +137,11 @@ pub fn std(build: &Build, stage: u32, target: &str) {
let out = build.doc_out(target); let out = build.doc_out(target);
t!(fs::create_dir_all(&out)); t!(fs::create_dir_all(&out));
let compiler = Compiler::new(stage, &build.config.build); 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) let out_dir = build.stage_out(&compiler, Mode::Libstd)
.join(target).join("doc"); .join(target).join("doc");
let rustdoc = build.rustdoc(&compiler); let rustdoc = build.rustdoc(&compiler);
@ -160,6 +165,11 @@ pub fn test(build: &Build, stage: u32, target: &str) {
let out = build.doc_out(target); let out = build.doc_out(target);
t!(fs::create_dir_all(&out)); t!(fs::create_dir_all(&out));
let compiler = Compiler::new(stage, &build.config.build); 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) let out_dir = build.stage_out(&compiler, Mode::Libtest)
.join(target).join("doc"); .join(target).join("doc");
let rustdoc = build.rustdoc(&compiler); let rustdoc = build.rustdoc(&compiler);
@ -182,6 +192,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
let out = build.doc_out(target); let out = build.doc_out(target);
t!(fs::create_dir_all(&out)); t!(fs::create_dir_all(&out));
let compiler = Compiler::new(stage, &build.config.build); 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) let out_dir = build.stage_out(&compiler, Mode::Librustc)
.join(target).join("doc"); .join(target).join("doc");
let rustdoc = build.rustdoc(&compiler); let rustdoc = build.rustdoc(&compiler);

View File

@ -572,9 +572,7 @@ impl Build {
let mut cmd = Command::new(self.tool(&compiler, tool)); let mut cmd = Command::new(self.tool(&compiler, tool));
let host = compiler.host; let host = compiler.host;
let mut paths = vec![ let mut paths = vec![
self.cargo_out(compiler, Mode::Libstd, host).join("deps"), self.sysroot_libdir(compiler, compiler.host),
self.cargo_out(compiler, Mode::Libtest, host).join("deps"),
self.cargo_out(compiler, Mode::Librustc, host).join("deps"),
self.cargo_out(compiler, Mode::Tool, host).join("deps"), self.cargo_out(compiler, Mode::Tool, host).join("deps"),
]; ];
@ -880,6 +878,30 @@ impl Build {
fn python(&self) -> &Path { fn python(&self) -> &Path {
self.config.python.as_ref().unwrap() 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> { impl<'a> Compiler<'a> {

View File

@ -51,8 +51,16 @@ standalone-docs:
$(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS) $(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS)
check: check:
$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS) $(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
check-cargotest: check-aux:
$(Q)$(BOOTSTRAP) test src/tools/cargotest $(BOOTSTRAP_ARGS) $(Q)$(BOOTSTRAP) test \
src/tools/cargotest \
src/test/pretty \
src/test/run-pass/pretty \
src/test/run-fail/pretty \
src/test/run-pass-valgrind/pretty \
src/test/run-pass-fulldeps/pretty \
src/test/run-fail-fulldeps/pretty \
$(BOOTSTRAP_ARGS)
dist: dist:
$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS) $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
distcheck: distcheck:

View File

@ -75,13 +75,18 @@ pub fn llvm(build: &Build, target: &str) {
(true, true) => "RelWithDebInfo", (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;NVPTX",
};
cfg.target(target) cfg.target(target)
.host(&build.config.build) .host(&build.config.build)
.out_dir(&dst) .out_dir(&dst)
.profile(profile) .profile(profile)
.define("LLVM_ENABLE_ASSERTIONS", assertions) .define("LLVM_ENABLE_ASSERTIONS", assertions)
.define("LLVM_TARGETS_TO_BUILD", .define("LLVM_TARGETS_TO_BUILD", llvm_targets)
"X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc")
.define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_EXAMPLES", "OFF")
.define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF")
.define("LLVM_INCLUDE_DOCS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF")

View File

@ -44,7 +44,7 @@ pub fn run(build: &Build) {
rules.run(&steps); 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); let mut rules = Rules::new(build);
// This is the first rule that we're going to define for rustbuild, which is // 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 // the compiler with no target libraries ready to go
rules.build("rustc", "src/rustc") rules.build("rustc", "src/rustc")
.dep(|s| s.name("create-sysroot").target(s.host))
.dep(move |s| { .dep(move |s| {
if s.stage == 0 { if s.stage == 0 {
Step::noop() Step::noop()
@ -151,77 +152,145 @@ pub fn build_rules(build: &Build) -> Rules {
// Crate compilations // Crate compilations
// //
// Tools used during the build system but not shipped // 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") 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") 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") 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("startup-objects"))
.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") { for (krate, path, _default) in krates("std_shim") {
rules.build(&krate.build_step, path) rules.build(&krate.build_step, path)
.dep(|s| s.name("startup-objects"))
.dep(move |s| s.name("rustc").host(&build.config.build).target(s.host)) .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host))
.dep(move |s| { .run(move |s| compile::std(build, s.target, &s.compiler()));
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)
}
});
} }
for (krate, path, default) in krates("test_shim") { for (krate, path, _default) in krates("test_shim") {
rules.build(&krate.build_step, path) rules.build(&krate.build_step, path)
.dep(|s| s.name("libstd")) .dep(|s| s.name("libstd-link"))
.dep(move |s| { .run(move |s| compile::test(build, s.target, &s.compiler()));
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)
}
});
} }
for (krate, path, default) in krates("rustc-main") { for (krate, path, _default) in krates("rustc-main") {
rules.build(&krate.build_step, path) 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| s.name("llvm").host(&build.config.build).stage(0))
.dep(move |s| { .run(move |s| compile::rustc(build, s.target, &s.compiler()));
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)
}
});
} }
rules.build("startup-objects", "src/rtstartup")
.dep(|s| s.name("create-sysroot").target(s.host))
.run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target));
// ======================================================================== // ========================================================================
// Test targets // Test targets
// //
// Various unit tests and tests suites we can run // Various unit tests and tests suites we can run
{ {
let mut suite = |name, path, dir, mode| { let mut suite = |name, path, mode, dir| {
rules.test(name, path) rules.test(name, path)
.dep(|s| s.name("libtest")) .dep(|s| s.name("libtest"))
.dep(|s| s.name("tool-compiletest").target(s.host)) .dep(|s| s.name("tool-compiletest").target(s.host))
@ -233,9 +302,9 @@ pub fn build_rules(build: &Build) -> Rules {
Step::noop() Step::noop()
} }
}) })
.default(true) .default(mode != "pretty") // pretty tests don't run everywhere
.run(move |s| { .run(move |s| {
check::compiletest(build, &s.compiler(), s.target, dir, mode) check::compiletest(build, &s.compiler(), s.target, mode, dir)
}); });
}; };
@ -254,13 +323,6 @@ pub fn build_rules(build: &Build) -> Rules {
suite("check-incremental", "src/test/incremental", "incremental", suite("check-incremental", "src/test/incremental", "incremental",
"incremental"); "incremental");
suite("check-ui", "src/test/ui", "ui", "ui"); 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") { if build.config.build.contains("msvc") {
@ -290,14 +352,15 @@ pub fn build_rules(build: &Build) -> Rules {
s.target)); s.target));
{ {
let mut suite = |name, path, dir, mode| { let mut suite = |name, path, mode, dir| {
rules.test(name, path) rules.test(name, path)
.dep(|s| s.name("librustc")) .dep(|s| s.name("librustc"))
.dep(|s| s.name("test-helpers"))
.dep(|s| s.name("tool-compiletest").target(s.host)) .dep(|s| s.name("tool-compiletest").target(s.host))
.default(true) .default(mode != "pretty")
.host(true) .host(true)
.run(move |s| { .run(move |s| {
check::compiletest(build, &s.compiler(), s.target, dir, mode) check::compiletest(build, &s.compiler(), s.target, mode, dir)
}); });
}; };
@ -307,9 +370,16 @@ pub fn build_rules(build: &Build) -> Rules {
"compile-fail", "compile-fail-fulldeps"); "compile-fail", "compile-fail-fulldeps");
suite("check-rmake", "src/test/run-make", "run-make", "run-make"); suite("check-rmake", "src/test/run-make", "run-make", "run-make");
suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc"); suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc");
suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps", 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-fail/pretty", "pretty",
"run-fail");
suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty",
"run-pass-valgrind");
suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty",
"pretty", "run-pass-fulldeps"); "pretty", "run-pass-fulldeps");
suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps", suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty",
"pretty", "run-fail-fulldeps"); "pretty", "run-fail-fulldeps");
} }
@ -444,25 +514,25 @@ pub fn build_rules(build: &Build) -> Rules {
.run(move |s| doc::standalone(build, s.stage, s.target)); .run(move |s| doc::standalone(build, s.stage, s.target));
rules.doc("doc-error-index", "src/tools/error_index_generator") 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("tool-error-index").target(&build.config.build))
.dep(move |s| s.name("librustc")) .dep(move |s| s.name("librustc-link"))
.default(build.config.docs) .default(build.config.docs)
.host(true) .host(true)
.run(move |s| doc::error_index(build, s.stage, s.target)); .run(move |s| doc::error_index(build, s.stage, s.target));
for (krate, path, default) in krates("std_shim") { for (krate, path, default) in krates("std_shim") {
rules.doc(&krate.doc_step, path) rules.doc(&krate.doc_step, path)
.dep(|s| s.name("libstd")) .dep(|s| s.name("libstd-link"))
.default(default && build.config.docs) .default(default && build.config.docs)
.run(move |s| doc::std(build, s.stage, s.target)); .run(move |s| doc::std(build, s.stage, s.target));
} }
for (krate, path, default) in krates("test_shim") { for (krate, path, default) in krates("test_shim") {
rules.doc(&krate.doc_step, path) rules.doc(&krate.doc_step, path)
.dep(|s| s.name("libtest")) .dep(|s| s.name("libtest-link"))
.default(default && build.config.compiler_docs) .default(default && build.config.compiler_docs)
.run(move |s| doc::test(build, s.stage, s.target)); .run(move |s| doc::test(build, s.stage, s.target));
} }
for (krate, path, default) in krates("rustc-main") { for (krate, path, default) in krates("rustc-main") {
rules.doc(&krate.doc_step, path) rules.doc(&krate.doc_step, path)
.dep(|s| s.name("librustc")) .dep(|s| s.name("librustc-link"))
.host(true) .host(true)
.default(default && build.config.compiler_docs) .default(default && build.config.compiler_docs)
.run(move |s| doc::rustc(build, s.stage, s.target)); .run(move |s| doc::rustc(build, s.stage, s.target));
@ -481,9 +551,9 @@ pub fn build_rules(build: &Build) -> Rules {
// for the `rust-std` package, so if this is a host target we // for the `rust-std` package, so if this is a host target we
// depend on librustc and otherwise we just depend on libtest. // depend on librustc and otherwise we just depend on libtest.
if build.config.host.iter().any(|t| t == s.target) { if build.config.host.iter().any(|t| t == s.target) {
s.name("librustc") s.name("librustc-link")
} else { } else {
s.name("libtest") s.name("libtest-link")
} }
}) })
.default(true) .default(true)

View File

@ -11,7 +11,6 @@ RUN dpkg --add-architecture i386 && \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
unzip \ unzip \
expect \ expect \
openjdk-9-jre \ openjdk-9-jre \
@ -50,5 +49,3 @@ ENV RUST_CONFIGURE_ARGS \
--i686-linux-android-ndk=/android/ndk-x86-9 \ --i686-linux-android-ndk=/android/ndk-x86-9 \
--aarch64-linux-android-ndk=/android/ndk-aarch64 --aarch64-linux-android-ndk=/android/ndk-aarch64
ENV XPY_CHECK test --target arm-linux-androideabi ENV XPY_CHECK test --target arm-linux-androideabi
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
gcc-arm-linux-gnueabi libc6-dev-armel-cross \ gcc-arm-linux-gnueabi libc6-dev-armel-cross \
@ -70,6 +69,3 @@ ENV AR_s390x_unknown_linux_gnu=s390x-linux-gnu-ar \
# FIXME(rust-lang/rust#36150): powerpc unfortunately aborts right now # FIXME(rust-lang/rust#36150): powerpc unfortunately aborts right now
ENV NO_LLVM_ASSERTIONS=1 ENV NO_LLVM_ASSERTIONS=1
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
gdb \ gdb \
xz-utils xz-utils
@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
ENV RUST_CHECK_TARGET check ENV RUST_CHECK_TARGET check
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
gdb \ gdb \
xz-utils xz-utils
@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
ENV RUST_CHECK_TARGET check ENV RUST_CHECK_TARGET check
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
bzip2 \ bzip2 \
xz-utils \ xz-utils \
@ -33,5 +32,3 @@ ENV \
ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-freebsd ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-freebsd
ENV RUST_CHECK_TARGET "" ENV RUST_CHECK_TARGET ""
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
libssl-dev \ libssl-dev \
sudo \ sudo \
xz-utils \ xz-utils \
@ -25,7 +24,5 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENTRYPOINT ["/usr/bin/dumb-init", "--"]
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
ENV RUST_CHECK_TARGET check-cargotest ENV RUST_CHECK_TARGET check-aux
ENV NO_VENDOR 1 ENV NO_VENDOR 1
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
gdb \ gdb \
xz-utils xz-utils
@ -28,5 +27,3 @@ ENV RUST_CONFIGURE_ARGS \
--enable-debug \ --enable-debug \
--enable-optimize --enable-optimize
ENV RUST_CHECK_TARGET "" ENV RUST_CHECK_TARGET ""
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -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 ""

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
gdb \ gdb \
llvm-3.7-tools \ llvm-3.7-tools \
@ -30,5 +29,3 @@ ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \ --build=x86_64-unknown-linux-gnu \
--llvm-root=/usr/lib/llvm-3.7 --llvm-root=/usr/lib/llvm-3.7
ENV RUST_CHECK_TARGET check ENV RUST_CHECK_TARGET check
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
gdb \ gdb \
xz-utils xz-utils
@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild
ENV RUST_CHECK_TARGET check ENV RUST_CHECK_TARGET check
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
gdb \ gdb \
xz-utils xz-utils
@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests
ENV RUST_CHECK_TARGET check ENV RUST_CHECK_TARGET check
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
sudo \ sudo \
gdb \ gdb \
xz-utils xz-utils
@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
ENV RUST_CHECK_TARGET check ENV RUST_CHECK_TARGET check
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \ python2.7 \
git \ git \
cmake \ cmake \
ccache \
xz-utils \ xz-utils \
sudo \ sudo \
gdb gdb
@ -33,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 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 PATH=$PATH:/musl-x86_64/bin
ENV XPY_CHECK test --target x86_64-unknown-linux-musl ENV XPY_CHECK test --target x86_64-unknown-linux-musl
RUN mkdir /tmp/obj
RUN chmod 777 /tmp/obj

View File

@ -283,7 +283,7 @@ fn call_with_one<F>(some_closure: F) -> i32
# some_closure(1) } # 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
isnt interesting. The next part is: isnt interesting. The next part is:
```rust ```rust
@ -293,7 +293,7 @@ isnt interesting. The next part is:
``` ```
Because `Fn` is a trait, we can use it as a bound for our generic type. In 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`. so the generic bound we use is `Fn(i32) -> i32`.
Theres one other key point here: because were bounding a generic with a Theres one other key point here: because were bounding a generic with a

View File

@ -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 definitions for the C standard library in the `libc` module, and Rust links
against `libc` and `libm` by default. 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" # The "nullable pointer optimization"
Certain Rust types are defined to never be `null`. This includes references (`&T`, Certain Rust types are defined to never be `null`. This includes references (`&T`,

View File

@ -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, 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 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 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 [traits]: traits.html

View File

@ -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 theyre There are other good reasons to avoid mutable state when possible, but theyre
out of the scope of this guide. In general, you can often avoid explicit 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 mutation, and so it is preferable in Rust. That said, sometimes, mutation is
what you need, so its not verboten. what you need, so its not forbidden.
# Initializing bindings # Initializing bindings

View File

@ -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 functions defined in Rust. The Rust compiler automatically translates between
the Rust ABI and the foreign ABI. 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. 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 By default external blocks assume that the library they are calling uses the

View File

@ -0,0 +1,13 @@
{
"intrinsic_prefix": "_",
"llvm_prefix": "llvm.cuda.",
"intrinsics": [
{
"intrinsic": "syncthreads",
"width": ["0"],
"llvm": "syncthreads",
"ret": "V",
"args": []
}
]
}

View File

@ -0,0 +1,7 @@
{
"platform": "nvptx",
"number_info": {
"signed": {}
},
"width_info": {}
}

View File

@ -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": []
}
]
}

View File

@ -55,24 +55,24 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. /// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types.
/// ///
/// `Arc` uses atomic operations for reference counting, so `Arc`s can be /// `Arc` uses atomic operations for reference counting, so `Arc`s can be
/// sent between threads. In other words, `Arc<T>` implements [`Send`][send] /// sent between threads. In other words, `Arc<T>` implements [`Send`]
/// as long as `T` implements `Send` and [`Sync`][sync]. The disadvantage is /// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is
/// that atomic operations are more expensive than ordinary memory accesses. /// that atomic operations are more expensive than ordinary memory accesses.
/// If you are not sharing reference-counted values between threads, consider /// If you are not sharing reference-counted values between threads, consider
/// using [`rc::Rc`][rc] for lower overhead. `Rc` is a safe default, because /// using [`rc::Rc`] for lower overhead. [`Rc`] is a safe default, because
/// the compiler will catch any attempt to send an `Rc` between threads. /// the compiler will catch any attempt to send an [`Rc`] between threads.
/// However, a library might choose `Arc` in order to give library consumers /// However, a library might choose `Arc` in order to give library consumers
/// more flexibility. /// more flexibility.
/// ///
/// The [`downgrade`][downgrade] method can be used to create a non-owning /// The [`downgrade`][downgrade] method can be used to create a non-owning
/// [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d /// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d
/// to an `Arc`, but this will return [`None`][option] if the value has /// to an `Arc`, but this will return [`None`] if the value has already been
/// already been dropped. /// dropped.
/// ///
/// A cycle between `Arc` pointers will never be deallocated. For this reason, /// 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 /// [`Weak`][weak] is used to break cycles. For example, a tree could have
/// `Arc` pointers from parent nodes to children, and `Weak` pointers from /// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak]
/// children back to their parents. /// pointers from children back to their parents.
/// ///
/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait), /// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
/// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
@ -86,22 +86,22 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// Arc::downgrade(&my_arc); /// Arc::downgrade(&my_arc);
/// ``` /// ```
/// ///
/// `Weak<T>` does not auto-dereference to `T`, because the value may have /// [`Weak<T>`][weak] does not auto-dereference to `T`, because the value may have
/// already been destroyed. /// already been destroyed.
/// ///
/// [arc]: struct.Arc.html /// [arc]: struct.Arc.html
/// [weak]: struct.Weak.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 /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [mutex]: ../../std/sync/struct.Mutex.html /// [mutex]: ../../std/sync/struct.Mutex.html
/// [rwlock]: ../../std/sync/struct.RwLock.html /// [rwlock]: ../../std/sync/struct.RwLock.html
/// [atomic]: ../../std/sync/atomic/index.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 /// [sync]: ../../std/marker/trait.Sync.html
/// [deref]: ../../std/ops/trait.Deref.html /// [deref]: ../../std/ops/trait.Deref.html
/// [downgrade]: struct.Arc.html#method.downgrade /// [downgrade]: struct.Arc.html#method.downgrade
/// [upgrade]: struct.Weak.html#method.upgrade /// [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 /// [assoc]: ../../book/method-syntax.html#associated-functions
/// ///
/// # Examples /// # 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 /// ```no_run
/// use std::sync::Arc; /// use std::sync::Arc;

View File

@ -429,7 +429,7 @@ impl PartialOrd for Ordering {
/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic /// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic
/// ordering based on the top-to-bottom declaration order of the struct's members. /// ordering based on the top-to-bottom declaration order of the struct's members.
/// ///
/// ## How can I implement `Ord`? /// ## How can I implement `PartialOrd`?
/// ///
/// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated /// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated
/// from default implementations. /// from default implementations.

View File

@ -237,11 +237,16 @@ impl AtomicBool {
/// Loads a value from the bool. /// 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
/// ///
/// 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 /// # Examples
/// ///
@ -260,7 +265,10 @@ impl AtomicBool {
/// Stores a value into the bool. /// 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 /// # Examples
/// ///
@ -286,7 +294,10 @@ impl AtomicBool {
/// Stores a value into the bool, returning the old value. /// 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 /// # Examples
/// ///
@ -309,8 +320,10 @@ impl AtomicBool {
/// The return value is always the previous value. If it is equal to `current`, then the value /// The return value is always the previous value. If it is equal to `current`, then the value
/// was updated. /// was updated.
/// ///
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// this operation. /// ordering of this operation.
///
/// [`Ordering`]: enum.Ordering.html
/// ///
/// # Examples /// # Examples
/// ///
@ -339,10 +352,15 @@ impl AtomicBool {
/// The return value is a result indicating whether the new value was written and containing /// 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`. /// 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 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// operation. The first describes the required ordering if the operation succeeds while the /// ordering of this operation. The first describes the required ordering if the
/// second describes the required ordering when the operation fails. The failure ordering can't /// operation succeeds while the second describes the required ordering when the
/// 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.
///
/// [`Ordering`]: enum.Ordering.html
/// [`Release`]: enum.Ordering.html#variant.Release
/// [`AcqRel`]: enum.Ordering.html#variant.Release
/// ///
/// # Examples /// # Examples
/// ///
@ -387,11 +405,15 @@ impl AtomicBool {
/// return value is a result indicating whether the new value was written and containing the /// return value is a result indicating whether the new value was written and containing the
/// previous value. /// 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 /// 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 /// 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 /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
/// success ordering. /// weaker than the success ordering.
///
/// [`Ordering`]: enum.Ordering.html
/// [`Release`]: enum.Ordering.html#variant.Release
/// [`AcqRel`]: enum.Ordering.html#variant.Release
/// ///
/// # Examples /// # Examples
/// ///
@ -619,11 +641,16 @@ impl<T> AtomicPtr<T> {
/// Loads a value from the pointer. /// 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
/// ///
/// 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 /// # Examples
/// ///
@ -643,7 +670,10 @@ impl<T> AtomicPtr<T> {
/// Stores a value into the pointer. /// 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 /// # Examples
/// ///
@ -671,7 +701,10 @@ impl<T> AtomicPtr<T> {
/// Stores a value into the pointer, returning the old value. /// 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 /// # Examples
/// ///
@ -696,8 +729,10 @@ impl<T> AtomicPtr<T> {
/// The return value is always the previous value. If it is equal to `current`, then the value /// The return value is always the previous value. If it is equal to `current`, then the value
/// was updated. /// was updated.
/// ///
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
/// this operation. /// ordering of this operation.
///
/// [`Ordering`]: enum.Ordering.html
/// ///
/// # Examples /// # Examples
/// ///
@ -726,10 +761,15 @@ impl<T> AtomicPtr<T> {
/// The return value is a result indicating whether the new value was written and containing /// 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`. /// 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 /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// operation. The first describes the required ordering if the operation succeeds while the /// ordering of this operation. The first describes the required ordering if
/// second describes the required ordering when the operation fails. The failure ordering can't /// the operation succeeds while the second describes the required ordering when
/// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering. /// 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 /// # Examples
/// ///
@ -768,16 +808,21 @@ impl<T> AtomicPtr<T> {
/// Stores a value into the pointer if the current value is the same as the `current` value. /// 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 /// 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 /// return value is a result indicating whether the new value was written and containing the
/// previous value. /// 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 /// 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 /// 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 /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
/// success ordering. /// 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 /// # Examples
/// ///
@ -913,12 +958,16 @@ macro_rules! atomic_int {
/// Loads a value from the atomic integer. /// 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. /// operation.
/// ///
/// # Panics /// # 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 /// # Examples
/// ///
@ -937,9 +986,11 @@ macro_rules! atomic_int {
/// Stores a value into the atomic integer. /// 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. /// operation.
/// ///
/// [`Ordering`]: enum.Ordering.html
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -962,9 +1013,11 @@ macro_rules! atomic_int {
/// Stores a value into the atomic integer, returning the old value. /// 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. /// operation.
/// ///
/// [`Ordering`]: enum.Ordering.html
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -986,9 +1039,11 @@ macro_rules! atomic_int {
/// The return value is always the previous value. If it is equal to `current`, then the /// The return value is always the previous value. If it is equal to `current`, then the
/// value was updated. /// 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 of this operation.
/// ///
/// [`Ordering`]: enum.Ordering.html
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -1024,11 +1079,15 @@ macro_rules! atomic_int {
/// containing the previous value. On success this value is guaranteed to be equal to /// containing the previous value. On success this value is guaranteed to be equal to
/// `current`. /// `current`.
/// ///
/// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
/// this operation. The first describes the required ordering if the operation succeeds /// ordering of this operation. The first describes the required ordering if
/// while the second describes the required ordering when the operation fails. The /// the operation succeeds while the second describes the required ordering when
/// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
/// than the success ordering. /// 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 /// # Examples
/// ///
@ -1062,16 +1121,21 @@ macro_rules! atomic_int {
/// Stores a value into the atomic integer if the current value is the same as the /// Stores a value into the atomic integer if the current value is the same as the
/// `current` value. /// `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
/// comparison succeeds, which can result in more efficient code on some platforms. The /// when the comparison succeeds, which can result in more efficient code on some
/// return value is a result indicating whether the new value was written and containing /// platforms. The return value is a result indicating whether the new value was
/// the previous value. /// 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 /// ordering of this operation. The first describes the required ordering if the
/// operation succeeds while the second describes the required ordering when 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 /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
/// equivalent or weaker than the success ordering. /// 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 /// # Examples
/// ///
@ -1431,24 +1495,31 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
/// An atomic fence. /// An atomic fence.
/// ///
/// A fence 'A' which has `Release` ordering semantics, synchronizes with a /// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a
/// fence 'B' with (at least) `Acquire` semantics, if and only if there exists /// fence 'B' with (at least) [`Acquire`] semantics, if and only if there exists
/// atomic operations X and Y, both operating on some atomic object 'M' such /// atomic operations X and Y, both operating on some atomic object 'M' such
/// that A is sequenced before X, Y is synchronized before B and Y observes /// that A is sequenced before X, Y is synchronized before B and Y observes
/// the change to M. This provides a happens-before dependence between A and B. /// the change to M. This provides a happens-before dependence between A and B.
/// ///
/// Atomic operations with `Release` or `Acquire` semantics can also synchronize /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
/// with a fence. /// with a fence.
/// ///
/// A fence which has `SeqCst` ordering, in addition to having both `Acquire` /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
/// and `Release` semantics, participates in the global program order of the /// and [`Release`] semantics, participates in the global program order of the
/// other `SeqCst` operations and/or fences. /// other [`SeqCst`] operations and/or fences.
/// ///
/// Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings. /// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if `order` is `Relaxed`. /// Panics if `order` is [`Relaxed`].
///
/// [`Ordering`]: enum.Ordering.html
/// [`Acquire`]: enum.Ordering.html#variant.Acquire
/// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
/// [`Release`]: enum.Ordering.html#variant.Release
/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
/// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn fence(order: Ordering) { pub fn fence(order: Ordering) {

View File

@ -96,7 +96,7 @@ fn main() {
let optional_components = let optional_components =
["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430", ["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 // FIXME: surely we don't need all these components, right? Stuff like mcjit
// or interpreter the compiler itself never uses. // or interpreter the compiler itself never uses.

View File

@ -42,6 +42,7 @@ pub enum CallConv {
X86StdcallCallConv = 64, X86StdcallCallConv = 64,
X86FastcallCallConv = 65, X86FastcallCallConv = 65,
ArmAapcsCallConv = 67, ArmAapcsCallConv = 67,
PtxKernel = 71,
X86_64_SysV = 78, X86_64_SysV = 78,
X86_64_Win64 = 79, X86_64_Win64 = 79,
X86_VectorCall = 80, X86_VectorCall = 80,

View File

@ -376,6 +376,11 @@ pub fn initialize_available_targets() {
LLVMInitializeSparcTargetMC, LLVMInitializeSparcTargetMC,
LLVMInitializeSparcAsmPrinter, LLVMInitializeSparcAsmPrinter,
LLVMInitializeSparcAsmParser); LLVMInitializeSparcAsmParser);
init_target!(llvm_component = "nvptx",
LLVMInitializeNVPTXTargetInfo,
LLVMInitializeNVPTXTarget,
LLVMInitializeNVPTXTargetMC,
LLVMInitializeNVPTXAsmPrinter);
} }
pub fn last_error() -> Option<String> { pub fn last_error() -> Option<String> {

View File

@ -95,6 +95,7 @@ static VOID: Type = Type::Void;
mod x86; mod x86;
mod arm; mod arm;
mod aarch64; mod aarch64;
mod nvptx;
impl Intrinsic { impl Intrinsic {
pub fn find(name: &str) -> Option<Intrinsic> { pub fn find(name: &str) -> Option<Intrinsic> {
@ -104,6 +105,8 @@ impl Intrinsic {
arm::find(name) arm::find(name)
} else if name.starts_with("aarch64_") { } else if name.starts_with("aarch64_") {
aarch64::find(name) aarch64::find(name)
} else if name.starts_with("nvptx_") {
nvptx::find(name)
} else { } else {
None None
} }

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// 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<Intrinsic> {
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,
})
}

View File

@ -25,6 +25,8 @@ use cabi_mips64;
use cabi_asmjs; use cabi_asmjs;
use cabi_msp430; use cabi_msp430;
use cabi_sparc; use cabi_sparc;
use cabi_nvptx;
use cabi_nvptx64;
use machine::{llalign_of_min, llsize_of, llsize_of_alloc}; use machine::{llalign_of_min, llsize_of, llsize_of_alloc};
use type_::Type; use type_::Type;
use type_of; use type_of;
@ -353,6 +355,7 @@ impl FnType {
Win64 => llvm::X86_64_Win64, Win64 => llvm::X86_64_Win64,
SysV64 => llvm::X86_64_SysV, SysV64 => llvm::X86_64_SysV,
Aapcs => llvm::ArmAapcsCallConv, Aapcs => llvm::ArmAapcsCallConv,
PtxKernel => llvm::PtxKernel,
// These API constants ought to be more specific... // These API constants ought to be more specific...
Cdecl => llvm::CCallConv, Cdecl => llvm::CCallConv,
@ -608,6 +611,8 @@ impl FnType {
"wasm32" => cabi_asmjs::compute_abi_info(ccx, self), "wasm32" => cabi_asmjs::compute_abi_info(ccx, self),
"msp430" => cabi_msp430::compute_abi_info(ccx, self), "msp430" => cabi_msp430::compute_abi_info(ccx, self),
"sparc" => cabi_sparc::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)) a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
} }

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// 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);
}
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// 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);
}
}

View File

@ -103,6 +103,8 @@ mod cabi_asmjs;
mod cabi_mips; mod cabi_mips;
mod cabi_mips64; mod cabi_mips64;
mod cabi_msp430; mod cabi_msp430;
mod cabi_nvptx;
mod cabi_nvptx64;
mod cabi_powerpc; mod cabi_powerpc;
mod cabi_powerpc64; mod cabi_powerpc64;
mod cabi_s390x; mod cabi_s390x;

View File

@ -2057,10 +2057,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
let item_type = m.type_(); let item_type = m.type_();
let id = derive_id(format!("{}.{}", item_type, name)); let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "<h3 id='{id}' class='method stab {stab}'>\ write!(w, "<h3 id='{id}' class='method'>\
<span id='{ns_id}' class='invisible'><code>", <span id='{ns_id}' class='invisible'><code>",
id = id, id = id,
stab = m.stability_class(),
ns_id = ns_id)?; ns_id = ns_id)?;
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?; render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?;
write!(w, "</code>")?; write!(w, "</code>")?;

View File

@ -10,8 +10,9 @@
#![unstable(reason = "not public", issue = "0", feature = "fd")] #![unstable(reason = "not public", issue = "0", feature = "fd")]
use cmp;
use io::{self, Read}; use io::{self, Read};
use libc::{self, c_int, c_void}; use libc::{self, c_int, c_void, ssize_t};
use mem; use mem;
use sync::atomic::{AtomicBool, Ordering}; use sync::atomic::{AtomicBool, Ordering};
use sys::cvt; use sys::cvt;
@ -23,6 +24,22 @@ pub struct FileDesc {
fd: c_int, 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") {
<c_int>::max_value() as usize - 1
} else {
<ssize_t>::max_value() as usize
}
}
impl FileDesc { impl FileDesc {
pub fn new(fd: c_int) -> FileDesc { pub fn new(fd: c_int) -> FileDesc {
FileDesc { fd: fd } FileDesc { fd: fd }
@ -41,7 +58,7 @@ impl FileDesc {
let ret = cvt(unsafe { let ret = cvt(unsafe {
libc::read(self.fd, libc::read(self.fd,
buf.as_mut_ptr() as *mut c_void, buf.as_mut_ptr() as *mut c_void,
buf.len()) cmp::min(buf.len(), max_len()))
})?; })?;
Ok(ret as usize) Ok(ret as usize)
} }
@ -69,7 +86,7 @@ impl FileDesc {
unsafe { unsafe {
cvt_pread64(self.fd, cvt_pread64(self.fd,
buf.as_mut_ptr() as *mut c_void, buf.as_mut_ptr() as *mut c_void,
buf.len(), cmp::min(buf.len(), max_len()),
offset as i64) offset as i64)
.map(|n| n as usize) .map(|n| n as usize)
} }
@ -79,7 +96,7 @@ impl FileDesc {
let ret = cvt(unsafe { let ret = cvt(unsafe {
libc::write(self.fd, libc::write(self.fd,
buf.as_ptr() as *const c_void, buf.as_ptr() as *const c_void,
buf.len()) cmp::min(buf.len(), max_len()))
})?; })?;
Ok(ret as usize) Ok(ret as usize)
} }
@ -102,7 +119,7 @@ impl FileDesc {
unsafe { unsafe {
cvt_pwrite64(self.fd, cvt_pwrite64(self.fd,
buf.as_ptr() as *const c_void, buf.as_ptr() as *const c_void,
buf.len(), cmp::min(buf.len(), max_len()),
offset as i64) offset as i64)
.map(|n| n as usize) .map(|n| n as usize)
} }

View File

@ -19,7 +19,6 @@ use ptr;
use sys::c; use sys::c;
use sys::cvt; use sys::cvt;
use sys_common::io::read_to_end_uninitialized; use sys_common::io::read_to_end_uninitialized;
use u32;
/// An owned container for `HANDLE` object, closing them on Drop. /// 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<usize> { pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
let mut read = 0; let mut read = 0;
// ReadFile takes a DWORD (u32) for the length so it only supports let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
// reading u32::MAX bytes at a time.
let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
let res = cvt(unsafe { let res = cvt(unsafe {
c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
len, &mut read, ptr::null_mut()) len, &mut read, ptr::null_mut())
@ -181,9 +178,7 @@ impl RawHandle {
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let mut amt = 0; let mut amt = 0;
// WriteFile takes a DWORD (u32) for the length so it only supports let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
// writing u32::MAX bytes at a time.
let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
cvt(unsafe { cvt(unsafe {
c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
len, &mut amt, ptr::null_mut()) len, &mut amt, ptr::null_mut())

View File

@ -216,6 +216,20 @@ pub use self::local::{LocalKey, LocalKeyState};
/// Thread configuration. Provides detailed control over the properties /// Thread configuration. Provides detailed control over the properties
/// and behavior of new threads. /// 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")] #[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)] #[derive(Debug)]
pub struct Builder { pub struct Builder {
@ -228,6 +242,22 @@ pub struct Builder {
impl Builder { impl Builder {
/// Generates the base configuration for spawning a thread, from which /// Generates the base configuration for spawning a thread, from which
/// configuration methods can be chained. /// 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")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> Builder { pub fn new() -> Builder {
Builder { Builder {
@ -241,7 +271,7 @@ impl Builder {
/// ///
/// # Examples /// # Examples
/// ///
/// ```rust /// ```
/// use std::thread; /// use std::thread;
/// ///
/// let builder = thread::Builder::new() /// let builder = thread::Builder::new()
@ -260,6 +290,14 @@ impl Builder {
} }
/// Sets the size of the stack for the new thread. /// 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")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn stack_size(mut self, size: usize) -> Builder { pub fn stack_size(mut self, size: usize) -> Builder {
self.stack_size = Some(size); self.stack_size = Some(size);
@ -275,9 +313,26 @@ impl Builder {
/// ///
/// # Errors /// # Errors
/// ///
/// Unlike the `spawn` free function, this method yields an /// Unlike the [`spawn`] free function, this method yields an
/// `io::Result` to capture any failure to create the thread at /// [`io::Result`] to capture any failure to create the thread at
/// the OS level. /// 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")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
F: FnOnce() -> T, F: Send + 'static, T: Send + 'static F: FnOnce() -> T, F: Send + 'static, T: Send + 'static

View File

@ -41,6 +41,7 @@ pub enum Abi {
Aapcs, Aapcs,
Win64, Win64,
SysV64, SysV64,
PtxKernel,
// Multiplatform / generic ABIs // Multiplatform / generic ABIs
Rust, Rust,
@ -82,6 +83,7 @@ const AbiDatas: &'static [AbiData] = &[
AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false }, AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false },
AbiData {abi: Abi::Win64, name: "win64", generic: false }, AbiData {abi: Abi::Win64, name: "win64", generic: false },
AbiData {abi: Abi::SysV64, name: "sysv64", generic: false }, AbiData {abi: Abi::SysV64, name: "sysv64", generic: false },
AbiData {abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
// Cross-platform ABIs // Cross-platform ABIs
AbiData {abi: Abi::Rust, name: "Rust", generic: true }, AbiData {abi: Abi::Rust, name: "Rust", generic: true },

View File

@ -318,6 +318,9 @@ declare_features! (
// Allow safe suggestions for potential type conversions. // Allow safe suggestions for potential type conversions.
(active, safe_suggestion, "1.0.0", Some(37384)), (active, safe_suggestion, "1.0.0", Some(37384)),
// `extern "ptx-*" fn()`
(active, abi_ptx, "1.15.0", None),
); );
declare_features! ( declare_features! (
@ -986,7 +989,19 @@ impl<'a> PostExpansionVisitor<'a> {
gate_feature_post!(&self, abi_sysv64, span, gate_feature_post!(&self, abi_sysv64, span,
"sysv64 ABI is experimental and subject to change"); "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 => {}
} }
} }
} }

View File

@ -190,7 +190,7 @@ impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
fn reset(&mut self) -> io::Result<bool> { fn reset(&mut self) -> io::Result<bool> {
// are there any terminals that have color/attrs and not sgr0? // are there any terminals that have color/attrs and not sgr0?
// Try falling back to sgr, then op // Try falling back to sgr, then op
let cmd = match ["sg0", "sgr", "op"] let cmd = match ["sgr0", "sgr", "op"]
.iter() .iter()
.filter_map(|cap| self.ti.strings.get(*cap)) .filter_map(|cap| self.ti.strings.get(*cap))
.next() { .next() {

View File

@ -33,12 +33,15 @@ struct RustArchiveMember {
struct RustArchiveIterator { struct RustArchiveIterator {
bool first;
Archive::child_iterator cur; Archive::child_iterator cur;
Archive::child_iterator end; Archive::child_iterator end;
#if LLVM_VERSION_GE(3, 9) #if LLVM_VERSION_GE(3, 9)
Error err; Error err;
RustArchiveIterator() : err(Error::success()) { } RustArchiveIterator() : first(true), err(Error::success()) { }
#else
RustArchiveIterator() : first(true) { }
#endif #endif
}; };
@ -120,6 +123,7 @@ LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
rai->cur = ar->child_begin(rai->err); rai->cur = ar->child_begin(rai->err);
if (rai->err) { if (rai->err) {
LLVMRustSetLastError(toString(std::move(rai->err)).c_str()); LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
delete rai;
return NULL; return NULL;
} }
#endif #endif
@ -129,19 +133,33 @@ LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
extern "C" LLVMRustArchiveChildConstRef extern "C" LLVMRustArchiveChildConstRef
LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) { LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
if (rai->cur == rai->end) return nullptr;
// Advancing the iterator validates the next child, and this can
// uncover an error. LLVM requires that we check all Errors,
// so we only advance the iterator if we actually need to fetch
// the next child.
// This means we must not advance the iterator in the *first* call,
// but instead advance it *before* fetching the child in all later calls.
if (!rai->first) {
++rai->cur;
#if LLVM_VERSION_GE(3, 9) #if LLVM_VERSION_GE(3, 9)
if (rai->err) { if (rai->err) {
LLVMRustSetLastError(toString(std::move(rai->err)).c_str()); LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
return NULL; return nullptr;
} }
#endif #endif
if (rai->cur == rai->end) } else {
return NULL; rai->first = false;
}
if (rai->cur == rai->end) return nullptr;
#if LLVM_VERSION_EQ(3, 8) #if LLVM_VERSION_EQ(3, 8)
const ErrorOr<Archive::Child>* cur = rai->cur.operator->(); const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
if (!*cur) { if (!*cur) {
LLVMRustSetLastError(cur->getError().message().c_str()); LLVMRustSetLastError(cur->getError().message().c_str());
return NULL; return nullptr;
} }
const Archive::Child &child = cur->get(); const Archive::Child &child = cur->get();
#else #else
@ -149,7 +167,6 @@ LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
#endif #endif
Archive::Child *ret = new Archive::Child(child); Archive::Child *ret = new Archive::Child(child);
++rai->cur;
return ret; return ret;
} }

View File

@ -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 --> $DIR/unicode.rs:11:8
| |
11 | extern "路濫狼á́́" fn foo() {} 11 | extern "路濫狼á́́" fn foo() {}

View File

@ -21,19 +21,38 @@ struct Test {
lock: Option<&'static str>, lock: Option<&'static str>,
} }
const TEST_REPOS: &'static [Test] = &[Test { const TEST_REPOS: &'static [Test] = &[
name: "cargo", Test {
repo: "https://github.com/rust-lang/cargo", name: "cargo",
sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76", repo: "https://github.com/rust-lang/cargo",
lock: None, sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
}, lock: None,
Test { },
name: "iron", Test {
repo: "https://github.com/iron/iron", name: "iron",
sha: "16c858ec2901e2992fe5e529780f59fa8ed12903", repo: "https://github.com/iron/iron",
lock: Some(include_str!("lockfiles/iron-Cargo.lock")), sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
}]; lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
},
Test {
name: "ripgrep",
repo: "https://github.com/BurntSushi/ripgrep",
sha: "b65bb37b14655e1a89c7cd19c8b011ef3e312791",
lock: None,
},
Test {
name: "tokei",
repo: "https://github.com/Aaronepower/tokei",
sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928",
lock: None,
},
Test {
name: "treeify",
repo: "https://github.com/dzamlo/treeify",
sha: "999001b223152441198f117a68fb81f57bc086dd",
lock: None,
},
];
fn main() { fn main() {
// One of the projects being tested here is Cargo, and when being tested // One of the projects being tested here is Cargo, and when being tested

View File

@ -261,7 +261,23 @@ pub fn run_tests(config: &Config) {
// android debug-info test uses remote debugger // android debug-info test uses remote debugger
// so, we test 1 thread at once. // so, we test 1 thread at once.
// also trying to isolate problems with adb_run_wrapper.sh ilooping // 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 => {}
_ => {
env::set_var("RUST_TEST_THREADS", "1");
}
}
} }
match config.mode { match config.mode {