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:
commit
7f2d2afa91
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
|
||||||
// called from the `std` method above. In that case we clean out what's
|
|
||||||
// already there.
|
|
||||||
if host != compiler.host {
|
|
||||||
let _ = fs::remove_dir_all(&libdir);
|
|
||||||
t!(fs::create_dir_all(&libdir));
|
t!(fs::create_dir_all(&libdir));
|
||||||
}
|
|
||||||
add_to_sysroot(&out_dir, &libdir);
|
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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
}
|
||||||
})
|
for (krate, path, _default) in krates("test_shim") {
|
||||||
.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") {
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
})
|
for (krate, path, _default) in krates("rustc-main") {
|
||||||
.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") {
|
|
||||||
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)
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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 ""
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
isn’t interesting. The next part is:
|
isn’t interesting. The next part is:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
@ -293,7 +293,7 @@ isn’t interesting. The next part is:
|
||||||
```
|
```
|
||||||
|
|
||||||
Because `Fn` is a trait, we can use it as a bound for our generic type. In
|
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`.
|
||||||
|
|
||||||
There’s one other key point here: because we’re bounding a generic with a
|
There’s one other key point here: because we’re bounding a generic with a
|
||||||
|
|
|
@ -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`,
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ mutation, then the solution is quite easy: add `mut`.
|
||||||
There are other good reasons to avoid mutable state when possible, but they’re
|
There are other good reasons to avoid mutable state when possible, but they’re
|
||||||
out of the scope of this guide. In general, you can often avoid explicit
|
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 it’s not verboten.
|
what you need, so it’s not forbidden.
|
||||||
|
|
||||||
# Initializing bindings
|
# Initializing bindings
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"intrinsic_prefix": "_",
|
||||||
|
"llvm_prefix": "llvm.cuda.",
|
||||||
|
"intrinsics": [
|
||||||
|
{
|
||||||
|
"intrinsic": "syncthreads",
|
||||||
|
"width": ["0"],
|
||||||
|
"llvm": "syncthreads",
|
||||||
|
"ret": "V",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"platform": "nvptx",
|
||||||
|
"number_info": {
|
||||||
|
"signed": {}
|
||||||
|
},
|
||||||
|
"width_info": {}
|
||||||
|
}
|
|
@ -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": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
})
|
||||||
|
}
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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>")?;
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
|
@ -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 => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -21,7 +21,8 @@ struct Test {
|
||||||
lock: Option<&'static str>,
|
lock: Option<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEST_REPOS: &'static [Test] = &[Test {
|
const TEST_REPOS: &'static [Test] = &[
|
||||||
|
Test {
|
||||||
name: "cargo",
|
name: "cargo",
|
||||||
repo: "https://github.com/rust-lang/cargo",
|
repo: "https://github.com/rust-lang/cargo",
|
||||||
sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
|
sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
|
||||||
|
@ -32,8 +33,26 @@ const TEST_REPOS: &'static [Test] = &[Test {
|
||||||
repo: "https://github.com/iron/iron",
|
repo: "https://github.com/iron/iron",
|
||||||
sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
|
sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
|
||||||
lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
|
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
|
||||||
|
|
|
@ -261,9 +261,25 @@ 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
|
||||||
|
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");
|
env::set_var("RUST_TEST_THREADS", "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match config.mode {
|
match config.mode {
|
||||||
DebugInfoLldb => {
|
DebugInfoLldb => {
|
||||||
if let Some(lldb_version) = config.lldb_version.as_ref() {
|
if let Some(lldb_version) = config.lldb_version.as_ref() {
|
||||||
|
|
Loading…
Reference in New Issue