mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Merge branch 'master' into sparc64
This commit is contained in:
commit
b14785d3d0
10
.travis.yml
10
.travis.yml
@ -19,12 +19,14 @@ matrix:
|
||||
- env: IMAGE=i686-gnu-nopt
|
||||
- env: IMAGE=x86_64-freebsd
|
||||
- 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-nopt
|
||||
- env: IMAGE=x86_64-gnu-make
|
||||
- env: IMAGE=x86_64-gnu-llvm-3.7 ALLOW_PR=1 RUST_BACKTRACE=1
|
||||
- env: IMAGE=x86_64-musl
|
||||
- env: IMAGE=x86_64-gnu-distcheck
|
||||
|
||||
# OSX builders
|
||||
- env: >
|
||||
@ -66,10 +68,10 @@ script:
|
||||
if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
|
||||
echo skipping, not a full build;
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
git submodule update --init;
|
||||
git submodule update --init &&
|
||||
src/ci/run.sh;
|
||||
else
|
||||
git submodule update --init;
|
||||
git submodule update --init &&
|
||||
src/ci/docker/run.sh $IMAGE;
|
||||
fi
|
||||
|
||||
@ -78,7 +80,7 @@ before_cache:
|
||||
- docker history -q rust-ci |
|
||||
grep -v missing |
|
||||
xargs docker save |
|
||||
gzip -9 > $HOME/docker/rust-ci.tar.gz
|
||||
gzip > $HOME/docker/rust-ci.tar.gz
|
||||
before_install:
|
||||
- zcat $HOME/docker/rust-ci.tar.gz | docker load || true
|
||||
|
||||
|
@ -82,8 +82,9 @@ build.
|
||||
# Install build tools needed for Rust. If you're building a 32-bit compiler,
|
||||
# then replace "x86_64" below with "i686". If you've already got git, python,
|
||||
# or CMake installed and in PATH you can remove them from this list. Note
|
||||
# that it is important that the `python2` and `cmake` packages **not** used.
|
||||
# The build has historically been known to fail with these packages.
|
||||
# that it is important that you do **not** use the 'python2' and 'cmake'
|
||||
# packages from the 'msys2' subsystem. The build has historically been known
|
||||
# to fail with these packages.
|
||||
$ pacman -S git \
|
||||
make \
|
||||
diffutils \
|
||||
|
@ -21,7 +21,7 @@ environment:
|
||||
# MSVC cargotest
|
||||
- MSYS_BITS: 64
|
||||
NO_VENDOR: 1
|
||||
RUST_CHECK_TARGET: check-cargotest
|
||||
RUST_CHECK_TARGET: check-aux
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
|
||||
|
||||
# 32/64-bit MinGW builds.
|
||||
@ -96,6 +96,13 @@ install:
|
||||
- 7z x -y sccache.tar > nul
|
||||
- set PATH=%PATH%;%CD%\sccache2
|
||||
|
||||
# Help debug some handle issues on AppVeyor
|
||||
- ps: Invoke-WebRequest -Uri https://download.sysinternals.com/files/Handle.zip -OutFile handle.zip
|
||||
- mkdir handle
|
||||
- ps: Expand-Archive handle.zip -dest handle
|
||||
- set PATH=%PATH%;%CD%\handle
|
||||
- handle.exe -accepteula -help
|
||||
|
||||
test_script:
|
||||
- git submodule update --init
|
||||
- set SRC=.
|
||||
|
1
configure
vendored
1
configure
vendored
@ -693,6 +693,7 @@ opt_nosave manage-submodules 1 "let the build manage the git submodules"
|
||||
opt_nosave clang 0 "prefer clang to gcc for building the runtime"
|
||||
opt_nosave jemalloc 1 "build liballoc with jemalloc"
|
||||
opt elf-tls 1 "elf thread local storage on platforms where supported"
|
||||
opt full-bootstrap 0 "build three compilers instead of two"
|
||||
|
||||
valopt_nosave prefix "/usr/local" "set installation prefix"
|
||||
valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary"
|
||||
|
25
mk/crates.mk
25
mk/crates.mk
@ -54,7 +54,7 @@ TARGET_CRATES := libc std term \
|
||||
compiler_builtins core alloc \
|
||||
std_unicode rustc_bitflags \
|
||||
alloc_system alloc_jemalloc \
|
||||
panic_abort panic_unwind unwind
|
||||
panic_abort panic_unwind unwind rustc_i128
|
||||
RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \
|
||||
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
|
||||
rustc_data_structures rustc_platform_intrinsics rustc_errors \
|
||||
@ -92,23 +92,26 @@ DEPS_getopts := std
|
||||
DEPS_graphviz := std
|
||||
DEPS_log := std
|
||||
DEPS_num := std
|
||||
DEPS_serialize := std log
|
||||
DEPS_serialize := std log rustc_i128
|
||||
DEPS_term := std
|
||||
DEPS_test := std getopts term native:rust_test_helpers
|
||||
DEPS_rustc_i128 = std
|
||||
|
||||
DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors syntax_pos rustc_data_structures
|
||||
DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors \
|
||||
syntax_pos rustc_data_structures rustc_i128
|
||||
DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro
|
||||
DEPS_proc_macro := syntax syntax_pos rustc_plugin log
|
||||
DEPS_syntax_pos := serialize
|
||||
DEPS_proc_macro_tokens := syntax syntax_pos log
|
||||
DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin log proc_macro_tokens
|
||||
|
||||
DEPS_rustc_const_math := std syntax log serialize
|
||||
DEPS_rustc_const_math := std syntax log serialize rustc_i128
|
||||
DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \
|
||||
rustc_back graphviz syntax_pos
|
||||
rustc_back graphviz syntax_pos rustc_i128
|
||||
|
||||
DEPS_rustc := syntax fmt_macros flate arena serialize getopts \
|
||||
log graphviz rustc_llvm rustc_back rustc_data_structures\
|
||||
rustc_const_math syntax_pos rustc_errors
|
||||
rustc_const_math syntax_pos rustc_errors rustc_i128
|
||||
DEPS_rustc_back := std syntax flate log libc
|
||||
DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_mir
|
||||
DEPS_rustc_data_structures := std log serialize libc
|
||||
@ -119,19 +122,20 @@ DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_bo
|
||||
rustc_passes rustc_save_analysis rustc_const_eval \
|
||||
rustc_incremental syntax_pos rustc_errors proc_macro rustc_data_structures
|
||||
DEPS_rustc_errors := log libc serialize syntax_pos
|
||||
DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval
|
||||
DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval rustc_i128
|
||||
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
|
||||
DEPS_proc_macro := std syntax
|
||||
DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \
|
||||
proc_macro syntax_ext
|
||||
proc_macro syntax_ext rustc_i128
|
||||
DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors
|
||||
DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags
|
||||
DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags \
|
||||
rustc_i128
|
||||
DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors
|
||||
DEPS_rustc_platform_intrinsics := std
|
||||
DEPS_rustc_plugin := rustc rustc_metadata syntax syntax_pos rustc_errors
|
||||
DEPS_rustc_privacy := rustc log syntax syntax_pos
|
||||
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
|
||||
log syntax serialize rustc_llvm rustc_platform_intrinsics \
|
||||
log syntax serialize rustc_llvm rustc_platform_intrinsics rustc_i128 \
|
||||
rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos
|
||||
DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
|
||||
DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
|
||||
@ -159,6 +163,7 @@ ONLY_RLIB_alloc := 1
|
||||
ONLY_RLIB_rand := 1
|
||||
ONLY_RLIB_collections := 1
|
||||
ONLY_RLIB_std_unicode := 1
|
||||
ONLY_RLIB_rustc_i128 := 1
|
||||
ONLY_RLIB_rustc_bitflags := 1
|
||||
ONLY_RLIB_alloc_system := 1
|
||||
ONLY_RLIB_alloc_jemalloc := 1
|
||||
|
17
src/Cargo.lock
generated
17
src/Cargo.lock
generated
@ -89,7 +89,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serialize 0.0.0",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -249,6 +249,7 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
@ -308,6 +309,7 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -318,6 +320,7 @@ name = "rustc_const_math"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
]
|
||||
@ -327,6 +330,7 @@ name = "rustc_data_structures"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
]
|
||||
|
||||
@ -372,6 +376,10 @@ dependencies = [
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_i128"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_incremental"
|
||||
version = "0.0.0"
|
||||
@ -380,6 +388,7 @@ dependencies = [
|
||||
"log 0.0.0",
|
||||
"rustc 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -393,6 +402,7 @@ dependencies = [
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_const_eval 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
@ -418,6 +428,7 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
@ -437,6 +448,7 @@ dependencies = [
|
||||
"rustc_const_eval 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
@ -519,6 +531,7 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"rustc_incremental 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"rustc_platform_intrinsics 0.0.0",
|
||||
@ -574,6 +587,7 @@ name = "serialize"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -619,6 +633,7 @@ dependencies = [
|
||||
"rustc_bitflags 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
@ -89,7 +89,9 @@ fn main() {
|
||||
// When we build Rust dylibs they're all intended for intermediate
|
||||
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
|
||||
// linking all deps statically into the dylib.
|
||||
cmd.arg("-Cprefer-dynamic");
|
||||
if env::var_os("RUSTC_NO_PREFER_DYNAMIC").is_none() {
|
||||
cmd.arg("-Cprefer-dynamic");
|
||||
}
|
||||
|
||||
// Help the libc crate compile by assisting it in finding the MUSL
|
||||
// native libraries.
|
||||
|
@ -62,9 +62,9 @@ impl fmt::Display for TestKind {
|
||||
///
|
||||
/// This tool in `src/tools` will verify the validity of all our links in the
|
||||
/// documentation to ensure we don't have a bunch of dead ones.
|
||||
pub fn linkcheck(build: &Build, stage: u32, host: &str) {
|
||||
println!("Linkcheck stage{} ({})", stage, host);
|
||||
let compiler = Compiler::new(stage, host);
|
||||
pub fn linkcheck(build: &Build, host: &str) {
|
||||
println!("Linkcheck ({})", host);
|
||||
let compiler = Compiler::new(0, host);
|
||||
|
||||
let _time = util::timeit();
|
||||
build.run(build.tool_cmd(&compiler, "linkchecker")
|
||||
@ -93,10 +93,11 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) {
|
||||
t!(fs::create_dir_all(&out_dir));
|
||||
|
||||
let _time = util::timeit();
|
||||
build.run(build.tool_cmd(compiler, "cargotest")
|
||||
.env("PATH", newpath)
|
||||
.arg(&build.cargo)
|
||||
.arg(&out_dir));
|
||||
let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest"));
|
||||
build.prepare_tool_cmd(compiler, &mut cmd);
|
||||
build.run(cmd.env("PATH", newpath)
|
||||
.arg(&build.cargo)
|
||||
.arg(&out_dir));
|
||||
}
|
||||
|
||||
/// Runs the `tidy` tool as compiled in `stage` by the `host` compiler.
|
||||
@ -104,9 +105,9 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) {
|
||||
/// This tool in `src/tools` checks up on various bits and pieces of style and
|
||||
/// otherwise just implements a few lint-like checks that are specific to the
|
||||
/// compiler itself.
|
||||
pub fn tidy(build: &Build, stage: u32, host: &str) {
|
||||
println!("tidy check stage{} ({})", stage, host);
|
||||
let compiler = Compiler::new(stage, host);
|
||||
pub fn tidy(build: &Build, host: &str) {
|
||||
println!("tidy check ({})", host);
|
||||
let compiler = Compiler::new(0, host);
|
||||
build.run(build.tool_cmd(&compiler, "tidy")
|
||||
.arg(build.src.join("src")));
|
||||
}
|
||||
@ -127,7 +128,9 @@ pub fn compiletest(build: &Build,
|
||||
suite: &str) {
|
||||
println!("Check compiletest suite={} mode={} ({} -> {})",
|
||||
suite, mode, compiler.host, target);
|
||||
let mut cmd = build.tool_cmd(compiler, "compiletest");
|
||||
let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host),
|
||||
"compiletest"));
|
||||
build.prepare_tool_cmd(compiler, &mut cmd);
|
||||
|
||||
// compiletest currently has... a lot of arguments, so let's just pass all
|
||||
// of them!
|
||||
@ -287,7 +290,8 @@ pub fn error_index(build: &Build, compiler: &Compiler) {
|
||||
let output = dir.join("error-index.md");
|
||||
|
||||
let _time = util::timeit();
|
||||
build.run(build.tool_cmd(compiler, "error_index_generator")
|
||||
build.run(build.tool_cmd(&Compiler::new(0, compiler.host),
|
||||
"error_index_generator")
|
||||
.arg("markdown")
|
||||
.arg(&output)
|
||||
.env("CFG_BUILD", &build.config.build));
|
||||
@ -341,12 +345,22 @@ pub fn krate(build: &Build,
|
||||
println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
|
||||
compiler.host, target);
|
||||
|
||||
// If we're not doing a full bootstrap but we're testing a stage2 version of
|
||||
// libstd, then what we're actually testing is the libstd produced in
|
||||
// stage1. Reflect that here by updating the compiler that we're working
|
||||
// with automatically.
|
||||
let compiler = if build.force_use_stage1(compiler, target) {
|
||||
Compiler::new(1, compiler.host)
|
||||
} else {
|
||||
compiler.clone()
|
||||
};
|
||||
|
||||
// Build up the base `cargo test` command.
|
||||
//
|
||||
// Pass in some standard flags then iterate over the graph we've discovered
|
||||
// in `cargo metadata` with the maps above and figure out what `-p`
|
||||
// arguments need to get passed.
|
||||
let mut cargo = build.cargo(compiler, mode, target, test_kind.subcommand());
|
||||
let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand());
|
||||
cargo.arg("--manifest-path")
|
||||
.arg(build.src.join(path).join("Cargo.toml"))
|
||||
.arg("--features").arg(features);
|
||||
@ -380,7 +394,7 @@ pub fn krate(build: &Build,
|
||||
// Note that to run the compiler we need to run with the *host* libraries,
|
||||
// but our wrapper scripts arrange for that to be the case anyway.
|
||||
let mut dylib_path = dylib_path();
|
||||
dylib_path.insert(0, build.sysroot_libdir(compiler, target));
|
||||
dylib_path.insert(0, build.sysroot_libdir(&compiler, target));
|
||||
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
|
||||
|
||||
if target.contains("android") {
|
||||
@ -399,10 +413,10 @@ pub fn krate(build: &Build,
|
||||
|
||||
if target.contains("android") {
|
||||
build.run(&mut cargo);
|
||||
krate_android(build, compiler, target, mode);
|
||||
krate_android(build, &compiler, target, mode);
|
||||
} else if target.contains("emscripten") {
|
||||
build.run(&mut cargo);
|
||||
krate_emscripten(build, compiler, target, mode);
|
||||
krate_emscripten(build, &compiler, target, mode);
|
||||
} else {
|
||||
cargo.args(&build.flags.cmd.test_args());
|
||||
build.run(&mut cargo);
|
||||
@ -497,6 +511,10 @@ fn find_tests(dir: &Path,
|
||||
pub fn android_copy_libs(build: &Build,
|
||||
compiler: &Compiler,
|
||||
target: &str) {
|
||||
if !target.contains("android") {
|
||||
return
|
||||
}
|
||||
|
||||
println!("Android copy libs to emulator ({})", target);
|
||||
build.run(Command::new("adb").arg("remount"));
|
||||
build.run(Command::new("adb").args(&["shell", "rm", "-r", ADB_TEST_DIR]));
|
||||
@ -544,6 +562,7 @@ pub fn distcheck(build: &Build) {
|
||||
.current_dir(&dir);
|
||||
build.run(&mut cmd);
|
||||
build.run(Command::new("./configure")
|
||||
.args(&build.config.configure_args)
|
||||
.current_dir(&dir));
|
||||
build.run(Command::new(build_helper::make(&build.config.build))
|
||||
.arg("check")
|
||||
|
@ -33,17 +33,12 @@ use {Build, Compiler, Mode};
|
||||
/// This will build the standard library for a particular stage of the build
|
||||
/// using the `compiler` targeting the `target` architecture. The artifacts
|
||||
/// created will also be linked into the sysroot directory.
|
||||
pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
||||
println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
|
||||
compiler.host, target);
|
||||
|
||||
pub fn std(build: &Build, target: &str, compiler: &Compiler) {
|
||||
let libdir = build.sysroot_libdir(compiler, target);
|
||||
let _ = fs::remove_dir_all(&libdir);
|
||||
t!(fs::create_dir_all(&libdir));
|
||||
|
||||
// Some platforms have startup objects that may be required to produce the
|
||||
// libstd dynamic library, for example.
|
||||
build_startup_objects(build, target, &libdir);
|
||||
println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
|
||||
compiler.host, target);
|
||||
|
||||
let out_dir = build.cargo_out(compiler, Mode::Libstd, target);
|
||||
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);
|
||||
update_mtime(&libstd_stamp(build, &compiler, target));
|
||||
std_link(build, target, compiler.stage, compiler.host);
|
||||
}
|
||||
|
||||
/// Link all libstd rlibs/dylibs into the sysroot location.
|
||||
///
|
||||
/// Links those artifacts generated in the given `stage` for `target` produced
|
||||
/// by `compiler` into `host`'s sysroot.
|
||||
/// Links those artifacts generated by `compiler` to a the `stage` compiler's
|
||||
/// sysroot for the specified `host` and `target`.
|
||||
///
|
||||
/// Note that this assumes that `compiler` has already generated the libstd
|
||||
/// libraries for `target`, and this method will find them in the relevant
|
||||
/// output directory.
|
||||
pub fn std_link(build: &Build,
|
||||
target: &str,
|
||||
stage: u32,
|
||||
host: &str) {
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let target_compiler = Compiler::new(compiler.stage, host);
|
||||
compiler: &Compiler,
|
||||
target_compiler: &Compiler,
|
||||
target: &str) {
|
||||
println!("Copying stage{} std from stage{} ({} -> {} / {})",
|
||||
target_compiler.stage,
|
||||
compiler.stage,
|
||||
compiler.host,
|
||||
target_compiler.host,
|
||||
target);
|
||||
let libdir = build.sysroot_libdir(&target_compiler, target);
|
||||
let out_dir = build.cargo_out(&compiler, Mode::Libstd, target);
|
||||
|
||||
// If we're linking one compiler host's output into another, then we weren't
|
||||
// called from the `std` method above. In that case we clean out what's
|
||||
// already there.
|
||||
if host != compiler.host {
|
||||
let _ = fs::remove_dir_all(&libdir);
|
||||
t!(fs::create_dir_all(&libdir));
|
||||
}
|
||||
t!(fs::create_dir_all(&libdir));
|
||||
add_to_sysroot(&out_dir, &libdir);
|
||||
|
||||
if target.contains("musl") && !target.contains("mips") {
|
||||
@ -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
|
||||
/// files, so we just use the nightly snapshot compiler to always build them (as
|
||||
/// 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") {
|
||||
return
|
||||
}
|
||||
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
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"))) {
|
||||
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")
|
||||
.arg("--target").arg(target)
|
||||
.arg("--emit=obj")
|
||||
.arg("--out-dir").arg(into)
|
||||
.arg("--out-dir").arg(&into)
|
||||
.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
|
||||
/// the build using the `compiler` targeting the `target` architecture. The
|
||||
/// artifacts created will also be linked into the sysroot directory.
|
||||
pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
||||
pub fn test(build: &Build, target: &str, compiler: &Compiler) {
|
||||
println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
|
||||
compiler.host, target);
|
||||
let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
|
||||
@ -147,19 +146,19 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
||||
.arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
|
||||
build.run(&mut cargo);
|
||||
update_mtime(&libtest_stamp(build, compiler, target));
|
||||
test_link(build, target, compiler.stage, compiler.host);
|
||||
}
|
||||
|
||||
/// Link all libtest rlibs/dylibs into the sysroot location.
|
||||
///
|
||||
/// Links those artifacts generated in the given `stage` for `target` produced
|
||||
/// by `compiler` into `host`'s sysroot.
|
||||
/// Same as `std_link`, only for libtest
|
||||
pub fn test_link(build: &Build,
|
||||
target: &str,
|
||||
stage: u32,
|
||||
host: &str) {
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let target_compiler = Compiler::new(compiler.stage, host);
|
||||
compiler: &Compiler,
|
||||
target_compiler: &Compiler,
|
||||
target: &str) {
|
||||
println!("Copying stage{} test from stage{} ({} -> {} / {})",
|
||||
target_compiler.stage,
|
||||
compiler.stage,
|
||||
compiler.host,
|
||||
target_compiler.host,
|
||||
target);
|
||||
let libdir = build.sysroot_libdir(&target_compiler, target);
|
||||
let out_dir = build.cargo_out(&compiler, Mode::Libtest, target);
|
||||
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
|
||||
/// the `compiler` targeting the `target` architecture. The artifacts
|
||||
/// created will also be linked into the sysroot directory.
|
||||
pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
||||
pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
|
||||
println!("Building stage{} compiler artifacts ({} -> {})",
|
||||
compiler.stage, compiler.host, target);
|
||||
|
||||
@ -222,20 +221,19 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
|
||||
cargo.env("CFG_DEFAULT_AR", s);
|
||||
}
|
||||
build.run(&mut cargo);
|
||||
|
||||
rustc_link(build, target, compiler.stage, compiler.host);
|
||||
}
|
||||
|
||||
/// Link all librustc rlibs/dylibs into the sysroot location.
|
||||
///
|
||||
/// Links those artifacts generated in the given `stage` for `target` produced
|
||||
/// by `compiler` into `host`'s sysroot.
|
||||
/// Same as `std_link`, only for librustc
|
||||
pub fn rustc_link(build: &Build,
|
||||
target: &str,
|
||||
stage: u32,
|
||||
host: &str) {
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let target_compiler = Compiler::new(compiler.stage, host);
|
||||
compiler: &Compiler,
|
||||
target_compiler: &Compiler,
|
||||
target: &str) {
|
||||
println!("Copying stage{} rustc from stage{} ({} -> {} / {})",
|
||||
target_compiler.stage,
|
||||
compiler.stage,
|
||||
compiler.host,
|
||||
target_compiler.host,
|
||||
target);
|
||||
let libdir = build.sysroot_libdir(&target_compiler, target);
|
||||
let out_dir = build.cargo_out(&compiler, Mode::Librustc, target);
|
||||
add_to_sysroot(&out_dir, &libdir);
|
||||
@ -259,6 +257,17 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
|
||||
PathBuf::from(out.trim())
|
||||
}
|
||||
|
||||
pub fn create_sysroot(build: &Build, compiler: &Compiler) {
|
||||
// nothing to do in stage0
|
||||
if compiler.stage == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
let sysroot = build.sysroot(compiler);
|
||||
let _ = fs::remove_dir_all(&sysroot);
|
||||
t!(fs::create_dir_all(&sysroot));
|
||||
}
|
||||
|
||||
/// Prepare a new compiler from the artifacts in `stage`
|
||||
///
|
||||
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler
|
||||
@ -269,18 +278,17 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
|
||||
if stage == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
println!("Copying stage{} compiler ({})", stage, host);
|
||||
|
||||
// The compiler that we're assembling
|
||||
let target_compiler = Compiler::new(stage, host);
|
||||
|
||||
// The compiler that compiled the compiler we're assembling
|
||||
let build_compiler = Compiler::new(stage - 1, &build.config.build);
|
||||
|
||||
// Clear out old files
|
||||
let sysroot = build.sysroot(&target_compiler);
|
||||
let _ = fs::remove_dir_all(&sysroot);
|
||||
t!(fs::create_dir_all(&sysroot));
|
||||
|
||||
// Link in all dylibs to the libdir
|
||||
let sysroot = build.sysroot(&target_compiler);
|
||||
let sysroot_libdir = sysroot.join(libdir(host));
|
||||
t!(fs::create_dir_all(&sysroot_libdir));
|
||||
let src_libdir = build.sysroot_libdir(&build_compiler, host);
|
||||
@ -371,6 +379,11 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
|
||||
let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
|
||||
cargo.arg("--manifest-path")
|
||||
.arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
|
||||
|
||||
// We don't want to build tools dynamically as they'll be running across
|
||||
// stages and such and it's just easier if they're not dynamically linked.
|
||||
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
|
||||
|
||||
build.run(&mut cargo);
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ pub struct Config {
|
||||
pub docs: bool,
|
||||
pub vendor: bool,
|
||||
pub target_config: HashMap<String, Target>,
|
||||
pub full_bootstrap: bool,
|
||||
|
||||
// llvm codegen options
|
||||
pub llvm_assertions: bool,
|
||||
@ -54,6 +55,7 @@ pub struct Config {
|
||||
pub llvm_version_check: bool,
|
||||
pub llvm_static_stdcpp: bool,
|
||||
pub llvm_link_shared: bool,
|
||||
pub llvm_targets: Option<String>,
|
||||
|
||||
// rust codegen options
|
||||
pub rust_optimize: bool,
|
||||
@ -92,6 +94,7 @@ pub struct Config {
|
||||
pub nodejs: Option<PathBuf>,
|
||||
pub gdb: Option<PathBuf>,
|
||||
pub python: Option<PathBuf>,
|
||||
pub configure_args: Vec<String>,
|
||||
}
|
||||
|
||||
/// Per-target configuration stored in the global configuration structure.
|
||||
@ -134,6 +137,7 @@ struct Build {
|
||||
vendor: Option<bool>,
|
||||
nodejs: Option<String>,
|
||||
python: Option<String>,
|
||||
full_bootstrap: Option<bool>,
|
||||
}
|
||||
|
||||
/// TOML representation of various global install decisions.
|
||||
@ -152,6 +156,7 @@ struct Llvm {
|
||||
release_debuginfo: Option<bool>,
|
||||
version_check: Option<bool>,
|
||||
static_libstdcpp: Option<bool>,
|
||||
targets: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(RustcDecodable)]
|
||||
@ -264,6 +269,7 @@ impl Config {
|
||||
set(&mut config.docs, build.docs);
|
||||
set(&mut config.submodules, build.submodules);
|
||||
set(&mut config.vendor, build.vendor);
|
||||
set(&mut config.full_bootstrap, build.full_bootstrap);
|
||||
|
||||
if let Some(ref install) = toml.install {
|
||||
config.prefix = install.prefix.clone();
|
||||
@ -285,6 +291,7 @@ impl Config {
|
||||
set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
|
||||
set(&mut config.llvm_version_check, llvm.version_check);
|
||||
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
|
||||
config.llvm_targets = llvm.targets.clone();
|
||||
}
|
||||
|
||||
if let Some(ref rust) = toml.rust {
|
||||
@ -393,6 +400,7 @@ impl Config {
|
||||
("NINJA", self.ninja),
|
||||
("CODEGEN_TESTS", self.codegen_tests),
|
||||
("VENDOR", self.vendor),
|
||||
("FULL_BOOTSTRAP", self.full_bootstrap),
|
||||
}
|
||||
|
||||
match key {
|
||||
@ -512,6 +520,11 @@ impl Config {
|
||||
"CFG_ENABLE_SCCACHE" if value == "1" => {
|
||||
self.ccache = Some("sccache".to_string());
|
||||
}
|
||||
"CFG_CONFIGURE_ARGS" if value.len() > 0 => {
|
||||
self.configure_args = value.split_whitespace()
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,17 @@
|
||||
# example.
|
||||
#ninja = false
|
||||
|
||||
# LLVM targets to build support for.
|
||||
# Note: this is NOT related to Rust compilation targets. However, as Rust is
|
||||
# dependent on LLVM for code generation, turning targets off here WILL lead to
|
||||
# the resulting rustc being unable to compile for the disabled architectures.
|
||||
# Also worth pointing out is that, in case support for new targets are added to
|
||||
# LLVM, enabling them here doesn't mean Rust is automatically gaining said
|
||||
# support. You'll need to write a target specification at least, and most
|
||||
# likely, teach rustc about the C ABI of the target. Get in touch with the
|
||||
# Rust team and file an issue if you need assistance in porting!
|
||||
#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX"
|
||||
|
||||
# =============================================================================
|
||||
# General build configuration options
|
||||
# =============================================================================
|
||||
@ -100,6 +111,13 @@
|
||||
# Indicate whether the vendored sources are used for Rust dependencies or not
|
||||
#vendor = false
|
||||
|
||||
# Typically the build system will build the rust compiler twice. The second
|
||||
# compiler, however, will simply use its own libraries to link against. If you
|
||||
# would rather to perform a full bootstrap, compiling the compiler three times,
|
||||
# then you can set this option to true. You shouldn't ever need to set this
|
||||
# option to true.
|
||||
#full-bootstrap = false
|
||||
|
||||
# =============================================================================
|
||||
# General install configuration options
|
||||
# =============================================================================
|
||||
|
@ -397,6 +397,13 @@ pub fn rust_src(build: &Build, host: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
// If we're inside the vendor directory then we need to preserve
|
||||
// everything as Cargo's vendoring support tracks all checksums and we
|
||||
// want to be sure we don't accidentally leave out a file.
|
||||
if spath.contains("vendor") {
|
||||
return true
|
||||
}
|
||||
|
||||
let excludes = [
|
||||
"CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules",
|
||||
".gitattributes", ".cvsignore", ".svn", ".arch-ids", "{arch}",
|
||||
|
@ -29,19 +29,19 @@ use util::{up_to_date, cp_r};
|
||||
///
|
||||
/// This will not actually generate any documentation if the documentation has
|
||||
/// already been generated.
|
||||
pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str) {
|
||||
pub fn rustbook(build: &Build, target: &str, name: &str) {
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
|
||||
let out = out.join(name);
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let src = build.src.join("src/doc").join(name);
|
||||
let index = out.join("index.html");
|
||||
let rustbook = build.tool(&compiler, "rustbook");
|
||||
if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
|
||||
return
|
||||
}
|
||||
println!("Rustbook stage{} ({}) - {}", stage, target, name);
|
||||
println!("Rustbook ({}) - {}", target, name);
|
||||
let _ = fs::remove_dir_all(&out);
|
||||
build.run(build.tool_cmd(&compiler, "rustbook")
|
||||
.arg("build")
|
||||
@ -137,6 +137,11 @@ pub fn std(build: &Build, stage: u32, target: &str) {
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = if build.force_use_stage1(&compiler, target) {
|
||||
Compiler::new(1, compiler.host)
|
||||
} else {
|
||||
compiler
|
||||
};
|
||||
let out_dir = build.stage_out(&compiler, Mode::Libstd)
|
||||
.join(target).join("doc");
|
||||
let rustdoc = build.rustdoc(&compiler);
|
||||
@ -146,7 +151,8 @@ pub fn std(build: &Build, stage: u32, target: &str) {
|
||||
let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc");
|
||||
cargo.arg("--manifest-path")
|
||||
.arg(build.src.join("src/rustc/std_shim/Cargo.toml"))
|
||||
.arg("--features").arg(build.std_features());
|
||||
.arg("--features").arg(build.std_features())
|
||||
.arg("-p").arg("std");
|
||||
build.run(&mut cargo);
|
||||
cp_r(&out_dir, &out)
|
||||
}
|
||||
@ -160,6 +166,11 @@ pub fn test(build: &Build, stage: u32, target: &str) {
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = if build.force_use_stage1(&compiler, target) {
|
||||
Compiler::new(1, compiler.host)
|
||||
} else {
|
||||
compiler
|
||||
};
|
||||
let out_dir = build.stage_out(&compiler, Mode::Libtest)
|
||||
.join(target).join("doc");
|
||||
let rustdoc = build.rustdoc(&compiler);
|
||||
@ -182,6 +193,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = if build.force_use_stage1(&compiler, target) {
|
||||
Compiler::new(1, compiler.host)
|
||||
} else {
|
||||
compiler
|
||||
};
|
||||
let out_dir = build.stage_out(&compiler, Mode::Librustc)
|
||||
.join(target).join("doc");
|
||||
let rustdoc = build.rustdoc(&compiler);
|
||||
@ -198,11 +214,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
|
||||
|
||||
/// Generates the HTML rendered error-index by running the
|
||||
/// `error_index_generator` tool.
|
||||
pub fn error_index(build: &Build, stage: u32, target: &str) {
|
||||
println!("Documenting stage{} error index ({})", stage, target);
|
||||
pub fn error_index(build: &Build, target: &str) {
|
||||
println!("Documenting error index ({})", target);
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let mut index = build.tool_cmd(&compiler, "error_index_generator");
|
||||
index.arg("html");
|
||||
index.arg(out.join("error-index.html"));
|
||||
|
@ -521,7 +521,7 @@ impl Build {
|
||||
.env(format!("CFLAGS_{}", target), self.cflags(target).join(" "));
|
||||
}
|
||||
|
||||
if self.config.channel == "nightly" && compiler.stage == 2 {
|
||||
if self.config.channel == "nightly" && compiler.is_final_stage(self) {
|
||||
cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string());
|
||||
}
|
||||
|
||||
@ -570,11 +570,18 @@ impl Build {
|
||||
/// `host`.
|
||||
fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command {
|
||||
let mut cmd = Command::new(self.tool(&compiler, tool));
|
||||
self.prepare_tool_cmd(compiler, &mut cmd);
|
||||
return cmd
|
||||
}
|
||||
|
||||
/// Prepares the `cmd` provided to be able to run the `compiler` provided.
|
||||
///
|
||||
/// Notably this munges the dynamic library lookup path to point to the
|
||||
/// right location to run `compiler`.
|
||||
fn prepare_tool_cmd(&self, compiler: &Compiler, cmd: &mut Command) {
|
||||
let host = compiler.host;
|
||||
let mut paths = vec![
|
||||
self.cargo_out(compiler, Mode::Libstd, host).join("deps"),
|
||||
self.cargo_out(compiler, Mode::Libtest, host).join("deps"),
|
||||
self.cargo_out(compiler, Mode::Librustc, host).join("deps"),
|
||||
self.sysroot_libdir(compiler, compiler.host),
|
||||
self.cargo_out(compiler, Mode::Tool, host).join("deps"),
|
||||
];
|
||||
|
||||
@ -595,8 +602,7 @@ impl Build {
|
||||
}
|
||||
}
|
||||
}
|
||||
add_lib_path(paths, &mut cmd);
|
||||
return cmd
|
||||
add_lib_path(paths, cmd);
|
||||
}
|
||||
|
||||
/// Get the space-separated set of activated features for the standard
|
||||
@ -880,6 +886,30 @@ impl Build {
|
||||
fn python(&self) -> &Path {
|
||||
self.config.python.as_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Tests whether the `compiler` compiling for `target` should be forced to
|
||||
/// use a stage1 compiler instead.
|
||||
///
|
||||
/// Currently, by default, the build system does not perform a "full
|
||||
/// bootstrap" by default where we compile the compiler three times.
|
||||
/// Instead, we compile the compiler two times. The final stage (stage2)
|
||||
/// just copies the libraries from the previous stage, which is what this
|
||||
/// method detects.
|
||||
///
|
||||
/// Here we return `true` if:
|
||||
///
|
||||
/// * The build isn't performing a full bootstrap
|
||||
/// * The `compiler` is in the final stage, 2
|
||||
/// * We're not cross-compiling, so the artifacts are already available in
|
||||
/// stage1
|
||||
///
|
||||
/// When all of these conditions are met the build will lift artifacts from
|
||||
/// the previous stage forward.
|
||||
fn force_use_stage1(&self, compiler: &Compiler, target: &str) -> bool {
|
||||
!self.config.full_bootstrap &&
|
||||
compiler.stage >= 2 &&
|
||||
self.config.host.iter().any(|h| h == target)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Compiler<'a> {
|
||||
@ -892,4 +922,13 @@ impl<'a> Compiler<'a> {
|
||||
fn is_snapshot(&self, build: &Build) -> bool {
|
||||
self.stage == 0 && self.host == build.config.build
|
||||
}
|
||||
|
||||
/// Returns if this compiler should be treated as a final stage one in the
|
||||
/// current build session.
|
||||
/// This takes into account whether we're performing a full bootstrap or
|
||||
/// not; don't directly compare the stage with `2`!
|
||||
fn is_final_stage(&self, build: &Build) -> bool {
|
||||
let final_stage = if build.config.full_bootstrap { 2 } else { 1 };
|
||||
self.stage >= final_stage
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +51,16 @@ standalone-docs:
|
||||
$(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS)
|
||||
check:
|
||||
$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
|
||||
check-cargotest:
|
||||
$(Q)$(BOOTSTRAP) test src/tools/cargotest $(BOOTSTRAP_ARGS)
|
||||
check-aux:
|
||||
$(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:
|
||||
$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
|
||||
distcheck:
|
||||
@ -61,7 +69,7 @@ distcheck:
|
||||
install:
|
||||
$(Q)$(BOOTSTRAP) dist --install $(BOOTSTRAP_ARGS)
|
||||
tidy:
|
||||
$(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS) --stage 0
|
||||
$(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS)
|
||||
|
||||
check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu:
|
||||
$(Q)$(BOOTSTRAP) test --target arm-linux-androideabi
|
||||
|
@ -75,13 +75,18 @@ pub fn llvm(build: &Build, target: &str) {
|
||||
(true, true) => "RelWithDebInfo",
|
||||
};
|
||||
|
||||
// NOTE: remember to also update `config.toml.example` when changing the defaults!
|
||||
let llvm_targets = match build.config.llvm_targets {
|
||||
Some(ref s) => s,
|
||||
None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX",
|
||||
};
|
||||
|
||||
cfg.target(target)
|
||||
.host(&build.config.build)
|
||||
.out_dir(&dst)
|
||||
.profile(profile)
|
||||
.define("LLVM_ENABLE_ASSERTIONS", assertions)
|
||||
.define("LLVM_TARGETS_TO_BUILD",
|
||||
"X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc")
|
||||
.define("LLVM_TARGETS_TO_BUILD", llvm_targets)
|
||||
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
|
||||
.define("LLVM_INCLUDE_TESTS", "OFF")
|
||||
.define("LLVM_INCLUDE_DOCS", "OFF")
|
||||
|
@ -44,7 +44,7 @@ pub fn run(build: &Build) {
|
||||
rules.run(&steps);
|
||||
}
|
||||
|
||||
pub fn build_rules(build: &Build) -> Rules {
|
||||
pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
let mut rules = Rules::new(build);
|
||||
|
||||
// This is the first rule that we're going to define for rustbuild, which is
|
||||
@ -117,6 +117,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
|
||||
// the compiler with no target libraries ready to go
|
||||
rules.build("rustc", "src/rustc")
|
||||
.dep(|s| s.name("create-sysroot").target(s.host))
|
||||
.dep(move |s| {
|
||||
if s.stage == 0 {
|
||||
Step::noop()
|
||||
@ -151,91 +152,153 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
// Crate compilations
|
||||
//
|
||||
// Tools used during the build system but not shipped
|
||||
rules.build("create-sysroot", "path/to/nowhere")
|
||||
.run(move |s| compile::create_sysroot(build, &s.compiler()));
|
||||
|
||||
// These rules are "pseudo rules" that don't actually do any work
|
||||
// themselves, but represent a complete sysroot with the relevant compiler
|
||||
// linked into place.
|
||||
//
|
||||
// That is, depending on "libstd" means that when the rule is completed then
|
||||
// the `stage` sysroot for the compiler `host` will be available with a
|
||||
// standard library built for `target` linked in place. Not all rules need
|
||||
// the compiler itself to be available, just the standard library, so
|
||||
// there's a distinction between the two.
|
||||
rules.build("libstd", "src/libstd")
|
||||
.dep(|s| s.name("build-crate-std_shim"));
|
||||
.dep(|s| s.name("rustc").target(s.host))
|
||||
.dep(|s| s.name("libstd-link"));
|
||||
rules.build("libtest", "src/libtest")
|
||||
.dep(|s| s.name("build-crate-test_shim"));
|
||||
.dep(|s| s.name("libstd"))
|
||||
.dep(|s| s.name("libtest-link"))
|
||||
.default(true);
|
||||
rules.build("librustc", "src/librustc")
|
||||
.dep(|s| s.name("build-crate-rustc-main"));
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("librustc-link"))
|
||||
.host(true)
|
||||
.default(true);
|
||||
|
||||
// Helper method to define the rules to link a crate into its place in the
|
||||
// sysroot.
|
||||
//
|
||||
// The logic here is a little subtle as there's a few cases to consider.
|
||||
// Not all combinations of (stage, host, target) actually require something
|
||||
// to be compiled, but rather libraries could get propagated from a
|
||||
// different location. For example:
|
||||
//
|
||||
// * Any crate with a `host` that's not the build triple will not actually
|
||||
// compile something. A different `host` means that the build triple will
|
||||
// actually compile the libraries, and then we'll copy them over from the
|
||||
// build triple to the `host` directory.
|
||||
//
|
||||
// * Some crates aren't even compiled by the build triple, but may be copied
|
||||
// from previous stages. For example if we're not doing a full bootstrap
|
||||
// then we may just depend on the stage1 versions of libraries to be
|
||||
// available to get linked forward.
|
||||
//
|
||||
// * Finally, there are some cases, however, which do indeed comiple crates
|
||||
// and link them into place afterwards.
|
||||
//
|
||||
// The rule definition below mirrors these three cases. The `dep` method
|
||||
// calculates the correct dependency which either comes from stage1, a
|
||||
// different compiler, or from actually building the crate itself (the `dep`
|
||||
// rule). The `run` rule then mirrors these three cases and links the cases
|
||||
// forward into the compiler sysroot specified from the correct location.
|
||||
fn crate_rule<'a, 'b>(build: &'a Build,
|
||||
rules: &'b mut Rules<'a>,
|
||||
krate: &'a str,
|
||||
dep: &'a str,
|
||||
link: fn(&Build, &Compiler, &Compiler, &str))
|
||||
-> RuleBuilder<'a, 'b> {
|
||||
let mut rule = rules.build(&krate, "path/to/nowhere");
|
||||
rule.dep(move |s| {
|
||||
if build.force_use_stage1(&s.compiler(), s.target) {
|
||||
s.host(&build.config.build).stage(1)
|
||||
} else if s.host == build.config.build {
|
||||
s.name(dep)
|
||||
} else {
|
||||
s.host(&build.config.build)
|
||||
}
|
||||
})
|
||||
.run(move |s| {
|
||||
if build.force_use_stage1(&s.compiler(), s.target) {
|
||||
link(build,
|
||||
&s.stage(1).host(&build.config.build).compiler(),
|
||||
&s.compiler(),
|
||||
s.target)
|
||||
} else if s.host == build.config.build {
|
||||
link(build, &s.compiler(), &s.compiler(), s.target)
|
||||
} else {
|
||||
link(build,
|
||||
&s.host(&build.config.build).compiler(),
|
||||
&s.compiler(),
|
||||
s.target)
|
||||
}
|
||||
});
|
||||
return rule
|
||||
}
|
||||
|
||||
// Similar to the `libstd`, `libtest`, and `librustc` rules above, except
|
||||
// these rules only represent the libraries being available in the sysroot,
|
||||
// not the compiler itself. This is done as not all rules need a compiler in
|
||||
// the sysroot, but may just need the libraries.
|
||||
//
|
||||
// All of these rules use the helper definition above.
|
||||
crate_rule(build,
|
||||
&mut rules,
|
||||
"libstd-link",
|
||||
"build-crate-std_shim",
|
||||
compile::std_link)
|
||||
.dep(|s| s.name("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") {
|
||||
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| {
|
||||
if s.host == build.config.build {
|
||||
Step::noop()
|
||||
} else {
|
||||
s.host(&build.config.build)
|
||||
}
|
||||
})
|
||||
.run(move |s| {
|
||||
if s.host == build.config.build {
|
||||
compile::std(build, s.target, &s.compiler())
|
||||
} else {
|
||||
compile::std_link(build, s.target, s.stage, s.host)
|
||||
}
|
||||
});
|
||||
.run(move |s| compile::std(build, s.target, &s.compiler()));
|
||||
}
|
||||
for (krate, path, default) in krates("test_shim") {
|
||||
for (krate, path, _default) in krates("test_shim") {
|
||||
rules.build(&krate.build_step, path)
|
||||
.dep(|s| s.name("libstd"))
|
||||
.dep(move |s| {
|
||||
if s.host == build.config.build {
|
||||
Step::noop()
|
||||
} else {
|
||||
s.host(&build.config.build)
|
||||
}
|
||||
})
|
||||
.default(default)
|
||||
.run(move |s| {
|
||||
if s.host == build.config.build {
|
||||
compile::test(build, s.target, &s.compiler())
|
||||
} else {
|
||||
compile::test_link(build, s.target, s.stage, s.host)
|
||||
}
|
||||
});
|
||||
.dep(|s| s.name("libstd-link"))
|
||||
.run(move |s| compile::test(build, s.target, &s.compiler()));
|
||||
}
|
||||
for (krate, path, default) in krates("rustc-main") {
|
||||
for (krate, path, _default) in krates("rustc-main") {
|
||||
rules.build(&krate.build_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("libtest-link"))
|
||||
.dep(move |s| s.name("llvm").host(&build.config.build).stage(0))
|
||||
.dep(move |s| {
|
||||
if s.host == build.config.build {
|
||||
Step::noop()
|
||||
} else {
|
||||
s.host(&build.config.build)
|
||||
}
|
||||
})
|
||||
.host(true)
|
||||
.default(default)
|
||||
.run(move |s| {
|
||||
if s.host == build.config.build {
|
||||
compile::rustc(build, s.target, &s.compiler())
|
||||
} else {
|
||||
compile::rustc_link(build, s.target, s.stage, s.host)
|
||||
}
|
||||
});
|
||||
.run(move |s| compile::rustc(build, s.target, &s.compiler()));
|
||||
}
|
||||
|
||||
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
|
||||
//
|
||||
// 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)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(move |s| {
|
||||
if s.target.contains("android") {
|
||||
s.name("android-copy-libs")
|
||||
} else {
|
||||
Step::noop()
|
||||
}
|
||||
})
|
||||
.default(true)
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.default(mode != "pretty") // pretty tests don't run everywhere
|
||||
.run(move |s| {
|
||||
check::compiletest(build, &s.compiler(), s.target, dir, mode)
|
||||
check::compiletest(build, &s.compiler(), s.target, mode, dir)
|
||||
});
|
||||
};
|
||||
|
||||
@ -254,35 +317,33 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
suite("check-incremental", "src/test/incremental", "incremental",
|
||||
"incremental");
|
||||
suite("check-ui", "src/test/ui", "ui", "ui");
|
||||
suite("check-pretty", "src/test/pretty", "pretty", "pretty");
|
||||
suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty",
|
||||
"run-pass");
|
||||
suite("check-pretty-rfail", "src/test/run-pass/pretty", "pretty",
|
||||
"run-fail");
|
||||
suite("check-pretty-valgrind", "src/test/run-pass-valgrind", "pretty",
|
||||
"run-pass-valgrind");
|
||||
}
|
||||
|
||||
if build.config.build.contains("msvc") {
|
||||
// nothing to do for debuginfo tests
|
||||
} else if build.config.build.contains("apple") {
|
||||
rules.test("check-debuginfo", "src/test/debuginfo")
|
||||
.default(true)
|
||||
} else {
|
||||
rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("debugger-scripts"))
|
||||
.run(move |s| check::compiletest(build, &s.compiler(), s.target,
|
||||
"debuginfo-lldb", "debuginfo"));
|
||||
} else {
|
||||
rules.test("check-debuginfo", "src/test/debuginfo")
|
||||
.default(true)
|
||||
rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("debugger-scripts"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.run(move |s| check::compiletest(build, &s.compiler(), s.target,
|
||||
"debuginfo-gdb", "debuginfo"));
|
||||
let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
|
||||
rule.default(true);
|
||||
if build.config.build.contains("apple") {
|
||||
rule.dep(|s| s.name("check-debuginfo-lldb"));
|
||||
} else {
|
||||
rule.dep(|s| s.name("check-debuginfo-gdb"));
|
||||
}
|
||||
}
|
||||
|
||||
rules.test("debugger-scripts", "src/etc/lldb_batchmode.py")
|
||||
@ -290,14 +351,15 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
s.target));
|
||||
|
||||
{
|
||||
let mut suite = |name, path, dir, mode| {
|
||||
let mut suite = |name, path, mode, dir| {
|
||||
rules.test(name, path)
|
||||
.dep(|s| s.name("librustc"))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host))
|
||||
.default(true)
|
||||
.dep(|s| s.name("test-helpers"))
|
||||
.dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
|
||||
.default(mode != "pretty")
|
||||
.host(true)
|
||||
.run(move |s| {
|
||||
check::compiletest(build, &s.compiler(), s.target, dir, mode)
|
||||
check::compiletest(build, &s.compiler(), s.target, mode, dir)
|
||||
});
|
||||
};
|
||||
|
||||
@ -307,21 +369,30 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
"compile-fail", "compile-fail-fulldeps");
|
||||
suite("check-rmake", "src/test/run-make", "run-make", "run-make");
|
||||
suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc");
|
||||
suite("check-pretty-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");
|
||||
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");
|
||||
}
|
||||
|
||||
for (krate, path, _default) in krates("std_shim") {
|
||||
rules.test(&krate.test_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libstd, TestKind::Test,
|
||||
Some(&krate.name)));
|
||||
}
|
||||
rules.test("check-std-all", "path/to/nowhere")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.default(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libstd, TestKind::Test, None));
|
||||
@ -330,12 +401,14 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
for (krate, path, _default) in krates("std_shim") {
|
||||
rules.bench(&krate.bench_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libstd, TestKind::Bench,
|
||||
Some(&krate.name)));
|
||||
}
|
||||
rules.bench("bench-std-all", "path/to/nowhere")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.default(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libstd, TestKind::Bench, None));
|
||||
@ -343,18 +416,21 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
for (krate, path, _default) in krates("test_shim") {
|
||||
rules.test(&krate.test_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libtest, TestKind::Test,
|
||||
Some(&krate.name)));
|
||||
}
|
||||
rules.test("check-test-all", "path/to/nowhere")
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.default(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Libtest, TestKind::Test, None));
|
||||
for (krate, path, _default) in krates("rustc-main") {
|
||||
rules.test(&krate.test_step, path)
|
||||
.dep(|s| s.name("librustc"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.host(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Librustc, TestKind::Test,
|
||||
@ -362,19 +438,20 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
}
|
||||
rules.test("check-rustc-all", "path/to/nowhere")
|
||||
.dep(|s| s.name("librustc"))
|
||||
.dep(|s| s.name("android-copy-libs"))
|
||||
.default(true)
|
||||
.host(true)
|
||||
.run(move |s| check::krate(build, &s.compiler(), s.target,
|
||||
Mode::Librustc, TestKind::Test, None));
|
||||
|
||||
rules.test("check-linkchecker", "src/tools/linkchecker")
|
||||
.dep(|s| s.name("tool-linkchecker"))
|
||||
.dep(|s| s.name("tool-linkchecker").stage(0))
|
||||
.dep(|s| s.name("default:doc"))
|
||||
.default(true)
|
||||
.host(true)
|
||||
.run(move |s| check::linkcheck(build, s.stage, s.target));
|
||||
.run(move |s| check::linkcheck(build, s.target));
|
||||
rules.test("check-cargotest", "src/tools/cargotest")
|
||||
.dep(|s| s.name("tool-cargotest"))
|
||||
.dep(|s| s.name("tool-cargotest").stage(0))
|
||||
.dep(|s| s.name("librustc"))
|
||||
.host(true)
|
||||
.run(move |s| check::cargotest(build, s.stage, s.target));
|
||||
@ -382,10 +459,10 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
.dep(|s| s.name("tool-tidy").stage(0))
|
||||
.default(true)
|
||||
.host(true)
|
||||
.run(move |s| check::tidy(build, 0, s.target));
|
||||
.run(move |s| check::tidy(build, s.target));
|
||||
rules.test("check-error-index", "src/tools/error_index_generator")
|
||||
.dep(|s| s.name("libstd"))
|
||||
.dep(|s| s.name("tool-error-index").host(s.host))
|
||||
.dep(|s| s.name("tool-error-index").host(s.host).stage(0))
|
||||
.default(true)
|
||||
.host(true)
|
||||
.run(move |s| check::error_index(build, &s.compiler()));
|
||||
@ -431,38 +508,38 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
// ========================================================================
|
||||
// Documentation targets
|
||||
rules.doc("doc-book", "src/doc/book")
|
||||
.dep(move |s| s.name("tool-rustbook").target(&build.config.build))
|
||||
.dep(move |s| s.name("tool-rustbook").target(&build.config.build).stage(0))
|
||||
.default(build.config.docs)
|
||||
.run(move |s| doc::rustbook(build, s.stage, s.target, "book"));
|
||||
.run(move |s| doc::rustbook(build, s.target, "book"));
|
||||
rules.doc("doc-nomicon", "src/doc/nomicon")
|
||||
.dep(move |s| s.name("tool-rustbook").target(&build.config.build))
|
||||
.dep(move |s| s.name("tool-rustbook").target(&build.config.build).stage(0))
|
||||
.default(build.config.docs)
|
||||
.run(move |s| doc::rustbook(build, s.stage, s.target, "nomicon"));
|
||||
.run(move |s| doc::rustbook(build, s.target, "nomicon"));
|
||||
rules.doc("doc-standalone", "src/doc")
|
||||
.dep(move |s| s.name("rustc").host(&build.config.build).target(&build.config.build))
|
||||
.default(build.config.docs)
|
||||
.run(move |s| doc::standalone(build, s.stage, s.target));
|
||||
rules.doc("doc-error-index", "src/tools/error_index_generator")
|
||||
.dep(move |s| s.name("tool-error-index").target(&build.config.build))
|
||||
.dep(move |s| s.name("librustc"))
|
||||
.dep(move |s| s.name("tool-error-index").target(&build.config.build).stage(0))
|
||||
.dep(move |s| s.name("librustc-link").stage(0))
|
||||
.default(build.config.docs)
|
||||
.host(true)
|
||||
.run(move |s| doc::error_index(build, s.stage, s.target));
|
||||
.run(move |s| doc::error_index(build, s.target));
|
||||
for (krate, path, default) in krates("std_shim") {
|
||||
rules.doc(&krate.doc_step, path)
|
||||
.dep(|s| s.name("libstd"))
|
||||
.dep(|s| s.name("libstd-link"))
|
||||
.default(default && build.config.docs)
|
||||
.run(move |s| doc::std(build, s.stage, s.target));
|
||||
}
|
||||
for (krate, path, default) in krates("test_shim") {
|
||||
rules.doc(&krate.doc_step, path)
|
||||
.dep(|s| s.name("libtest"))
|
||||
.dep(|s| s.name("libtest-link"))
|
||||
.default(default && build.config.compiler_docs)
|
||||
.run(move |s| doc::test(build, s.stage, s.target));
|
||||
}
|
||||
for (krate, path, default) in krates("rustc-main") {
|
||||
rules.doc(&krate.doc_step, path)
|
||||
.dep(|s| s.name("librustc"))
|
||||
.dep(|s| s.name("librustc-link"))
|
||||
.host(true)
|
||||
.default(default && build.config.compiler_docs)
|
||||
.run(move |s| doc::rustc(build, s.stage, s.target));
|
||||
@ -481,9 +558,9 @@ pub fn build_rules(build: &Build) -> Rules {
|
||||
// for the `rust-std` package, so if this is a host target we
|
||||
// depend on librustc and otherwise we just depend on libtest.
|
||||
if build.config.host.iter().any(|t| t == s.target) {
|
||||
s.name("librustc")
|
||||
s.name("librustc-link")
|
||||
} else {
|
||||
s.name("libtest")
|
||||
s.name("libtest-link")
|
||||
}
|
||||
})
|
||||
.default(true)
|
||||
|
@ -76,9 +76,9 @@ pub fn cp_r(src: &Path, dst: &Path) {
|
||||
/// Copies the `src` directory recursively to `dst`. Both are assumed to exist
|
||||
/// when this function is called. Unwanted files or directories can be skipped
|
||||
/// by returning `false` from the filter function.
|
||||
pub fn cp_filtered<F: Fn(&Path) -> bool>(src: &Path, dst: &Path, filter: &F) {
|
||||
pub fn cp_filtered(src: &Path, dst: &Path, filter: &Fn(&Path) -> bool) {
|
||||
// Inner function does the actual work
|
||||
fn recurse<F: Fn(&Path) -> bool>(src: &Path, dst: &Path, relative: &Path, filter: &F) {
|
||||
fn recurse(src: &Path, dst: &Path, relative: &Path, filter: &Fn(&Path) -> bool) {
|
||||
for f in t!(fs::read_dir(src)) {
|
||||
let f = t!(f);
|
||||
let path = f.path();
|
||||
|
@ -11,7 +11,6 @@ RUN dpkg --add-architecture i386 && \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
unzip \
|
||||
expect \
|
||||
openjdk-9-jre \
|
||||
@ -50,5 +49,3 @@ ENV RUST_CONFIGURE_ARGS \
|
||||
--i686-linux-android-ndk=/android/ndk-x86-9 \
|
||||
--aarch64-linux-android-ndk=/android/ndk-aarch64
|
||||
ENV XPY_CHECK test --target arm-linux-androideabi
|
||||
RUN mkdir /tmp/obj
|
||||
RUN chmod 777 /tmp/obj
|
||||
|
@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
|
||||
gcc-arm-linux-gnueabi libc6-dev-armel-cross \
|
||||
@ -70,6 +69,3 @@ ENV AR_s390x_unknown_linux_gnu=s390x-linux-gnu-ar \
|
||||
|
||||
# FIXME(rust-lang/rust#36150): powerpc unfortunately aborts right now
|
||||
ENV NO_LLVM_ASSERTIONS=1
|
||||
|
||||
RUN mkdir /tmp/obj
|
||||
RUN chmod 777 /tmp/obj
|
||||
|
@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb \
|
||||
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_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 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils
|
||||
@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
|
||||
ENV RUST_CHECK_TARGET check
|
||||
RUN mkdir /tmp/obj
|
||||
RUN chmod 777 /tmp/obj
|
||||
|
@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
bzip2 \
|
||||
xz-utils \
|
||||
@ -33,5 +32,3 @@ ENV \
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-freebsd
|
||||
ENV RUST_CHECK_TARGET ""
|
||||
RUN mkdir /tmp/obj
|
||||
RUN chmod 777 /tmp/obj
|
||||
|
@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
libssl-dev \
|
||||
sudo \
|
||||
xz-utils \
|
||||
@ -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", "--"]
|
||||
|
||||
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
|
||||
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 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils
|
||||
@ -28,5 +27,3 @@ ENV RUST_CONFIGURE_ARGS \
|
||||
--enable-debug \
|
||||
--enable-optimize
|
||||
ENV RUST_CHECK_TARGET ""
|
||||
RUN mkdir /tmp/obj
|
||||
RUN chmod 777 /tmp/obj
|
||||
|
26
src/ci/docker/x86_64-gnu-distcheck/Dockerfile
Normal file
26
src/ci/docker/x86_64-gnu-distcheck/Dockerfile
Normal file
@ -0,0 +1,26 @@
|
||||
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
|
||||
ENV XPY_RUN test distcheck
|
28
src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
Normal file
28
src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
Normal file
@ -0,0 +1,28 @@
|
||||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
make \
|
||||
file \
|
||||
curl \
|
||||
ca-certificates \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils
|
||||
|
||||
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
|
||||
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
|
||||
tar xJf - -C /usr/local/bin --strip-components=1
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
--enable-full-bootstrap
|
||||
ENV RUST_CHECK_TARGET ""
|
@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb \
|
||||
llvm-3.7-tools \
|
||||
@ -30,5 +29,3 @@ ENV RUST_CONFIGURE_ARGS \
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
--llvm-root=/usr/lib/llvm-3.7
|
||||
ENV RUST_CHECK_TARGET check
|
||||
RUN mkdir /tmp/obj
|
||||
RUN chmod 777 /tmp/obj
|
||||
|
@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb \
|
||||
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_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 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb \
|
||||
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_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 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils
|
||||
@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
|
||||
ENV RUST_CHECK_TARGET check
|
||||
RUN mkdir /tmp/obj
|
||||
RUN chmod 777 /tmp/obj
|
||||
|
@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python2.7 \
|
||||
git \
|
||||
cmake \
|
||||
ccache \
|
||||
xz-utils \
|
||||
sudo \
|
||||
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 PATH=$PATH:/musl-x86_64/bin
|
||||
ENV XPY_CHECK test --target x86_64-unknown-linux-musl
|
||||
|
||||
RUN mkdir /tmp/obj
|
||||
RUN chmod 777 /tmp/obj
|
||||
|
@ -43,10 +43,14 @@ else
|
||||
ncpus=$(nproc)
|
||||
fi
|
||||
|
||||
make -j $ncpus tidy
|
||||
make -j $ncpus
|
||||
if [ ! -z "$XPY_CHECK" ]; then
|
||||
exec python2.7 $SRC/x.py $XPY_CHECK
|
||||
if [ ! -z "$XPY_RUN" ]; then
|
||||
exec python2.7 $SRC/x.py $XPY_RUN
|
||||
else
|
||||
exec make $RUST_CHECK_TARGET -j $ncpus
|
||||
make -j $ncpus tidy
|
||||
make -j $ncpus
|
||||
if [ ! -z "$XPY_CHECK" ]; then
|
||||
exec python2.7 $SRC/x.py $XPY_CHECK
|
||||
else
|
||||
exec make $RUST_CHECK_TARGET -j $ncpus
|
||||
fi
|
||||
fi
|
||||
|
@ -283,7 +283,7 @@ fn call_with_one<F>(some_closure: F) -> i32
|
||||
# some_closure(1) }
|
||||
```
|
||||
|
||||
We take one parameter, and it has the type `F`. We also return a `i32`. This part
|
||||
We take one parameter, and it has the type `F`. We also return an `i32`. This part
|
||||
isn’t interesting. The next part is:
|
||||
|
||||
```rust
|
||||
@ -293,7 +293,7 @@ isn’t interesting. The next part is:
|
||||
```
|
||||
|
||||
Because `Fn` is a trait, we can use it as a bound for our generic type. In
|
||||
this case, our closure takes a `i32` as an argument and returns an `i32`, and
|
||||
this case, our closure takes an `i32` as an argument and returns an `i32`, and
|
||||
so the generic bound we use is `Fn(i32) -> i32`.
|
||||
|
||||
There’s one other key point here: because we’re bounding a generic with a
|
||||
|
@ -574,6 +574,31 @@ The [`libc` crate on crates.io][libc] includes type aliases and function
|
||||
definitions for the C standard library in the `libc` module, and Rust links
|
||||
against `libc` and `libm` by default.
|
||||
|
||||
# Variadic functions
|
||||
|
||||
In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can
|
||||
be achieved in Rust by specifying `...` within the argument list of a foreign function declaration:
|
||||
|
||||
```no_run
|
||||
extern {
|
||||
fn foo(x: i32, ...);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
foo(10, 20, 30, 40, 50);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Normal Rust functions can *not* be variadic:
|
||||
|
||||
```ignore
|
||||
// This will not compile
|
||||
|
||||
fn foo(x: i32, ...) { }
|
||||
```
|
||||
|
||||
# The "nullable pointer optimization"
|
||||
|
||||
Certain Rust types are defined to never be `null`. This includes references (`&T`,
|
||||
|
@ -128,7 +128,7 @@ _descriptive_, not _prescriptive_. This means that how long a reference is valid
|
||||
is determined by the code, not by the annotations. The annotations, however,
|
||||
give information about lifetimes to the compiler that uses them to check the
|
||||
validity of references. The compiler can do so without annotations in simple
|
||||
cases, but needs the programmers support in complex scenarios.
|
||||
cases, but needs the programmer's support in complex scenarios.
|
||||
|
||||
[traits]: traits.html
|
||||
|
||||
|
@ -102,7 +102,7 @@ mutation, then the solution is quite easy: add `mut`.
|
||||
There are other good reasons to avoid mutable state when possible, but they’re
|
||||
out of the scope of this guide. In general, you can often avoid explicit
|
||||
mutation, and so it is preferable in Rust. That said, sometimes, mutation is
|
||||
what you need, so it’s not verboten.
|
||||
what you need, so it’s not forbidden.
|
||||
|
||||
# Initializing bindings
|
||||
|
||||
|
@ -1657,6 +1657,15 @@ Functions within external blocks may be called by Rust code, just like
|
||||
functions defined in Rust. The Rust compiler automatically translates between
|
||||
the Rust ABI and the foreign ABI.
|
||||
|
||||
Functions within external blocks may be variadic by specifying `...` after one
|
||||
or more named arguments in the argument list:
|
||||
|
||||
```ignore
|
||||
extern {
|
||||
fn foo(x: i32, ...);
|
||||
}
|
||||
```
|
||||
|
||||
A number of [attributes](#ffi-attributes) control the behavior of external blocks.
|
||||
|
||||
By default external blocks assume that the library they are calling uses the
|
||||
|
13
src/etc/platform-intrinsics/nvptx/cuda.json
Normal file
13
src/etc/platform-intrinsics/nvptx/cuda.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"intrinsic_prefix": "_",
|
||||
"llvm_prefix": "llvm.cuda.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "syncthreads",
|
||||
"width": ["0"],
|
||||
"llvm": "syncthreads",
|
||||
"ret": "V",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
7
src/etc/platform-intrinsics/nvptx/info.json
Normal file
7
src/etc/platform-intrinsics/nvptx/info.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"platform": "nvptx",
|
||||
"number_info": {
|
||||
"signed": {}
|
||||
},
|
||||
"width_info": {}
|
||||
}
|
90
src/etc/platform-intrinsics/nvptx/sreg.json
Normal file
90
src/etc/platform-intrinsics/nvptx/sreg.json
Normal file
@ -0,0 +1,90 @@
|
||||
{
|
||||
"intrinsic_prefix": "_",
|
||||
"llvm_prefix": "llvm.nvvm.read.ptx.sreg.",
|
||||
"intrinsics": [
|
||||
{
|
||||
"intrinsic": "block_dim_x",
|
||||
"width": ["0"],
|
||||
"llvm": "ntid.x",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "block_dim_y",
|
||||
"width": ["0"],
|
||||
"llvm": "ntid.y",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "block_dim_z",
|
||||
"width": ["0"],
|
||||
"llvm": "ntid.z",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "block_idx_x",
|
||||
"width": ["0"],
|
||||
"llvm": "ctaid.x",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "block_idx_y",
|
||||
"width": ["0"],
|
||||
"llvm": "ctaid.y",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "block_idx_z",
|
||||
"width": ["0"],
|
||||
"llvm": "ctaid.z",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "grid_dim_x",
|
||||
"width": ["0"],
|
||||
"llvm": "nctaid.x",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "grid_dim_y",
|
||||
"width": ["0"],
|
||||
"llvm": "nctaid.y",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "grid_dim_z",
|
||||
"width": ["0"],
|
||||
"llvm": "nctaid.z",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "thread_idx_x",
|
||||
"width": ["0"],
|
||||
"llvm": "tid.x",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "thread_idx_y",
|
||||
"width": ["0"],
|
||||
"llvm": "tid.y",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"intrinsic": "thread_idx_z",
|
||||
"width": ["0"],
|
||||
"llvm": "tid.z",
|
||||
"ret": "S32",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
@ -55,24 +55,24 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||
/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types.
|
||||
///
|
||||
/// `Arc` uses atomic operations for reference counting, so `Arc`s can be
|
||||
/// sent between threads. In other words, `Arc<T>` implements [`Send`][send]
|
||||
/// as long as `T` implements `Send` and [`Sync`][sync]. The disadvantage is
|
||||
/// sent between threads. In other words, `Arc<T>` implements [`Send`]
|
||||
/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is
|
||||
/// that atomic operations are more expensive than ordinary memory accesses.
|
||||
/// If you are not sharing reference-counted values between threads, consider
|
||||
/// using [`rc::Rc`][rc] for lower overhead. `Rc` is a safe default, because
|
||||
/// the compiler will catch any attempt to send an `Rc` between threads.
|
||||
/// using [`rc::Rc`] for lower overhead. [`Rc`] is a safe default, because
|
||||
/// the compiler will catch any attempt to send an [`Rc`] between threads.
|
||||
/// However, a library might choose `Arc` in order to give library consumers
|
||||
/// more flexibility.
|
||||
///
|
||||
/// The [`downgrade`][downgrade] method can be used to create a non-owning
|
||||
/// [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d
|
||||
/// to an `Arc`, but this will return [`None`][option] if the value has
|
||||
/// already been dropped.
|
||||
/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d
|
||||
/// to an `Arc`, but this will return [`None`] if the value has already been
|
||||
/// dropped.
|
||||
///
|
||||
/// A cycle between `Arc` pointers will never be deallocated. For this reason,
|
||||
/// `Weak` is used to break cycles. For example, a tree could have strong
|
||||
/// `Arc` pointers from parent nodes to children, and `Weak` pointers from
|
||||
/// children back to their parents.
|
||||
/// [`Weak`][weak] is used to break cycles. For example, a tree could have
|
||||
/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak]
|
||||
/// pointers from children back to their parents.
|
||||
///
|
||||
/// `Arc<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
|
||||
@ -86,22 +86,22 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||
/// 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.
|
||||
///
|
||||
/// [arc]: struct.Arc.html
|
||||
/// [weak]: struct.Weak.html
|
||||
/// [rc]: ../../std/rc/struct.Rc.html
|
||||
/// [`Rc`]: ../../std/rc/struct.Rc.html
|
||||
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
|
||||
/// [mutex]: ../../std/sync/struct.Mutex.html
|
||||
/// [rwlock]: ../../std/sync/struct.RwLock.html
|
||||
/// [atomic]: ../../std/sync/atomic/index.html
|
||||
/// [send]: ../../std/marker/trait.Send.html
|
||||
/// [`Send`]: ../../std/marker/trait.Send.html
|
||||
/// [sync]: ../../std/marker/trait.Sync.html
|
||||
/// [deref]: ../../std/ops/trait.Deref.html
|
||||
/// [downgrade]: struct.Arc.html#method.downgrade
|
||||
/// [upgrade]: struct.Weak.html#method.upgrade
|
||||
/// [option]: ../../std/option/enum.Option.html
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
/// [assoc]: ../../book/method-syntax.html#associated-functions
|
||||
///
|
||||
/// # Examples
|
||||
@ -127,7 +127,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Sharing a mutable `AtomicUsize`:
|
||||
/// Sharing a mutable [`AtomicUsize`]:
|
||||
///
|
||||
/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::sync::Arc;
|
||||
|
@ -9,6 +9,7 @@ links = "jemalloc"
|
||||
name = "alloc_jemalloc"
|
||||
path = "lib.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../libcore" }
|
||||
|
@ -7,6 +7,7 @@ version = "0.0.0"
|
||||
name = "alloc_system"
|
||||
path = "lib.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../libcore" }
|
||||
|
@ -9,6 +9,7 @@ name = "compiler_builtins"
|
||||
path = "lib.rs"
|
||||
test = false
|
||||
bench = false
|
||||
doc = false
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../libcore" }
|
||||
|
@ -16,4 +16,787 @@
|
||||
issue = "0")]
|
||||
#![crate_name = "compiler_builtins"]
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(staged_api)]
|
||||
#![allow(unused_features)]
|
||||
#![feature(staged_api, core_intrinsics, repr_simd,
|
||||
i128_type, core_float, abi_unadjusted, associated_consts)]
|
||||
#![allow(non_camel_case_types, unused_variables, unused_imports)]
|
||||
#![cfg_attr(stage0, allow(dead_code))]
|
||||
|
||||
#[cfg(any(target_pointer_width="32", target_pointer_width="16", target_os="windows",
|
||||
target_arch="mips64"))]
|
||||
pub mod reimpls {
|
||||
|
||||
#![allow(unused_comparisons)]
|
||||
|
||||
use core::intrinsics::unchecked_div;
|
||||
use core::intrinsics::unchecked_rem;
|
||||
use core::ptr;
|
||||
|
||||
// C API is expected to tolerate some amount of size mismatch in ABI. Hopefully the amount of
|
||||
// handling is sufficient for bootstrapping.
|
||||
#[cfg(stage0)]
|
||||
type u128_ = u64;
|
||||
#[cfg(stage0)]
|
||||
type i128_ = i64;
|
||||
#[cfg(not(stage0))]
|
||||
type u128_ = u128;
|
||||
#[cfg(not(stage0))]
|
||||
type i128_ = i128;
|
||||
|
||||
macro_rules! ashl {
|
||||
($a:expr, $b:expr, $ty:ty) => {{
|
||||
let (a, b) = ($a, $b);
|
||||
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
|
||||
let half_bits = bits >> 1;
|
||||
if b & half_bits != 0 {
|
||||
<$ty>::from_parts(0, a.low().wrapping_shl(
|
||||
b.wrapping_sub(half_bits) as u32))
|
||||
} else if b == 0 {
|
||||
a
|
||||
} else {
|
||||
<$ty>::from_parts(a.low().wrapping_shl(b as u32),
|
||||
a.high().wrapping_shl(b as u32)
|
||||
| a.low()
|
||||
.wrapping_shr(half_bits.wrapping_sub(b) as u32))
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#[export_name="__ashlti3"]
|
||||
pub extern "C" fn shl(a: u128_, b: u128_) -> u128_ {
|
||||
ashl!(a, b, u128_)
|
||||
}
|
||||
|
||||
macro_rules! ashr {
|
||||
($a: expr, $b: expr, $ty:ty) => {{
|
||||
let (a, b) = ($a, $b);
|
||||
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
|
||||
let half_bits = bits >> 1;
|
||||
if b & half_bits != 0 {
|
||||
<$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32)
|
||||
as <$ty as LargeInt>::LowHalf,
|
||||
a.high().wrapping_shr(half_bits.wrapping_sub(1) as u32))
|
||||
} else if b == 0 {
|
||||
a
|
||||
} else {
|
||||
let high_unsigned = a.high() as <$ty as LargeInt>::LowHalf;
|
||||
<$ty>::from_parts(high_unsigned.wrapping_shl(half_bits.wrapping_sub(b) as u32)
|
||||
| a.low().wrapping_shr(b as u32),
|
||||
a.high().wrapping_shr(b as u32))
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#[export_name="__ashrti3"]
|
||||
pub extern "C" fn shr(a: i128_, b: i128_) -> i128_ {
|
||||
ashr!(a, b, i128_)
|
||||
}
|
||||
|
||||
macro_rules! lshr {
|
||||
($a: expr, $b: expr, $ty:ty) => {{
|
||||
let (a, b) = ($a, $b);
|
||||
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
|
||||
let half_bits = bits >> 1;
|
||||
if b & half_bits != 0 {
|
||||
<$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32), 0)
|
||||
} else if b == 0 {
|
||||
a
|
||||
} else {
|
||||
<$ty>::from_parts(a.high().wrapping_shl(half_bits.wrapping_sub(b) as u32)
|
||||
| a.low().wrapping_shr(b as u32),
|
||||
a.high().wrapping_shr(b as u32))
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
#[export_name="__lshrti3"]
|
||||
pub extern "C" fn lshr(a: u128_, b: u128_) -> u128_ {
|
||||
lshr!(a, b, u128_)
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ {
|
||||
unsafe {
|
||||
if !rem.is_null() {
|
||||
*rem = unchecked_rem(n, d);
|
||||
}
|
||||
unchecked_div(n, d)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ {
|
||||
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
|
||||
unsafe {
|
||||
// special cases, X is unknown, K != 0
|
||||
if n.high() == 0 {
|
||||
if d.high() == 0 {
|
||||
// 0 X
|
||||
// ---
|
||||
// 0 X
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from(unchecked_rem(n.low(), d.low()));
|
||||
}
|
||||
return u128::from(unchecked_div(n.low(), d.low()));
|
||||
} else {
|
||||
// 0 X
|
||||
// ---
|
||||
// K X
|
||||
if !rem.is_null() {
|
||||
*rem = n;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
let mut sr;
|
||||
let mut q;
|
||||
let mut r;
|
||||
|
||||
if d.low() == 0 {
|
||||
if d.high() == 0 {
|
||||
// K X
|
||||
// ---
|
||||
// 0 0
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from(unchecked_rem(n.high(), d.low()));
|
||||
}
|
||||
return u128::from(unchecked_div(n.high(), d.low()));
|
||||
}
|
||||
|
||||
if n.low() == 0 {
|
||||
// K 0
|
||||
// ---
|
||||
// K 0
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from_parts(0, unchecked_rem(n.high(), d.high()));
|
||||
}
|
||||
return u128::from(unchecked_div(n.high(), d.high()));
|
||||
}
|
||||
|
||||
// K K
|
||||
// ---
|
||||
// K 0
|
||||
|
||||
if d.high().is_power_of_two() {
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from_parts(n.low(),
|
||||
n.high() & (d.high().wrapping_sub(1)));
|
||||
}
|
||||
return u128::from(n.high().wrapping_shr(d.high().trailing_zeros()));
|
||||
}
|
||||
|
||||
// K K
|
||||
// ---
|
||||
// K 0
|
||||
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
|
||||
|
||||
// D > N
|
||||
if sr > 64 - 2 {
|
||||
if !rem.is_null() {
|
||||
*rem = n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sr = sr.wrapping_add(1);
|
||||
|
||||
// 1 <= sr <= u64::bits() - 1
|
||||
q = n.wrapping_shl(64u32.wrapping_sub(sr));
|
||||
r = n.wrapping_shr(sr);
|
||||
} else {
|
||||
if d.high() == 0 {
|
||||
// K X
|
||||
// ---
|
||||
// 0 K
|
||||
if d.low().is_power_of_two() {
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from(n.low() & (d.low().wrapping_sub(1)));
|
||||
}
|
||||
|
||||
if d.low() == 1 {
|
||||
return n;
|
||||
} else {
|
||||
let sr = d.low().trailing_zeros();
|
||||
return n.wrapping_shr(sr);
|
||||
};
|
||||
}
|
||||
|
||||
sr = (1 + 64u32)
|
||||
.wrapping_add(d.low().leading_zeros())
|
||||
.wrapping_sub(n.high().leading_zeros());
|
||||
|
||||
// 2 <= sr <= u64::bits() - 1
|
||||
q = n.wrapping_shl(128u32.wrapping_sub(sr));
|
||||
r = n.wrapping_shr(sr);
|
||||
// FIXME the C compiler-rt implementation has something here
|
||||
// that looks like a speed optimisation.
|
||||
// It would be worth a try to port it to Rust too and
|
||||
// compare the speed.
|
||||
} else {
|
||||
// K X
|
||||
// ---
|
||||
// K K
|
||||
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
|
||||
|
||||
// D > N
|
||||
if sr > 64 - 1 {
|
||||
if !rem.is_null() {
|
||||
*rem = n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sr = sr.wrapping_add(1);
|
||||
|
||||
// 1 <= sr <= u32::bits()
|
||||
q = n.wrapping_shl(128u32.wrapping_sub(sr));
|
||||
r = n.wrapping_shr(sr);
|
||||
}
|
||||
}
|
||||
|
||||
// Not a special case
|
||||
// q and r are initialized with
|
||||
// q = n << (u64::bits() - sr)
|
||||
// r = n >> sr
|
||||
// 1 <= sr <= u64::bits() - 1
|
||||
let mut carry = 0;
|
||||
|
||||
// FIXME: replace this with a for loop
|
||||
// (atm not doable as this generates call to
|
||||
// eh_personality when optimisations are turned off,
|
||||
// which in turn gives a linker error in later
|
||||
// compilation steps)
|
||||
while sr > 0 {
|
||||
// r:q = ((r:q) << 1) | carry
|
||||
r = r.wrapping_shl(1) | q.wrapping_shr(128 - 1);
|
||||
q = q.wrapping_shl(1) | carry as u128;
|
||||
|
||||
// carry = 0
|
||||
// if r >= d {
|
||||
// r -= d;
|
||||
// carry = 1;
|
||||
// }
|
||||
let s = ((d.wrapping_sub(r).wrapping_sub(1)) as i128).wrapping_shr(128 - 1);
|
||||
carry = (s & 1) as u64;
|
||||
r = r.wrapping_sub(d & s as u128);
|
||||
sr = sr.wrapping_sub(1);
|
||||
}
|
||||
|
||||
if !rem.is_null() {
|
||||
*rem = r;
|
||||
}
|
||||
(q.wrapping_shl(1)) | carry as u128
|
||||
}
|
||||
}
|
||||
|
||||
fn i128_mod(a: i128_, b: i128_) -> i128_ {
|
||||
let b = b.uabs();
|
||||
let sa = a.signum();
|
||||
let a = a.uabs();
|
||||
unsafe {
|
||||
let mut r = ::core::mem::zeroed();
|
||||
u128_div_mod(a, b, &mut r);
|
||||
if sa == -1 { (r as i128_).unchecked_neg() } else { r as i128_ }
|
||||
}
|
||||
}
|
||||
|
||||
fn i128_div(a: i128_, b: i128_) -> i128_ {
|
||||
let sa = a.signum();
|
||||
let sb = b.signum();
|
||||
let a = a.uabs();
|
||||
let b = b.uabs();
|
||||
let sr = sa.wrapping_mul(sb); // sign of quotient
|
||||
(if sr == -1 {
|
||||
(u128_div_mod(a, b, ptr::null_mut()) as i128_).unchecked_neg()
|
||||
} else {
|
||||
u128_div_mod(a, b, ptr::null_mut()) as i128_
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[export_name="__udivti3"]
|
||||
pub extern "C" fn u128_div(a: u128_, b: u128_) -> u128_ {
|
||||
(a / b)
|
||||
}
|
||||
|
||||
macro_rules! mulo {
|
||||
($a:expr, $b:expr, $o: expr, $ty: ty) => {{
|
||||
let (a, b, overflow) = ($a, $b, $o);
|
||||
*overflow = 0;
|
||||
let result = a.wrapping_mul(b);
|
||||
if a == <$ty>::min_value() {
|
||||
if b != 0 && b != 1 {
|
||||
*overflow = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if b == <$ty>::min_value() {
|
||||
if a != 0 && a != 1 {
|
||||
*overflow = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let sa = a.signum();
|
||||
let abs_a = a.iabs();
|
||||
let sb = b.signum();
|
||||
let abs_b = b.iabs();
|
||||
if abs_a < 2 || abs_b < 2 {
|
||||
return result;
|
||||
}
|
||||
if sa == sb {
|
||||
if abs_a > unchecked_div(<$ty>::max_value(), abs_b) {
|
||||
*overflow = 1;
|
||||
}
|
||||
} else {
|
||||
if abs_a > unchecked_div(<$ty>::min_value(), abs_b.unchecked_neg()) {
|
||||
*overflow = 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
}}
|
||||
}
|
||||
|
||||
pub trait LargeInt {
|
||||
type LowHalf;
|
||||
type HighHalf;
|
||||
|
||||
fn low(self) -> Self::LowHalf;
|
||||
fn high(self) -> Self::HighHalf;
|
||||
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
|
||||
}
|
||||
impl LargeInt for u64 {
|
||||
type LowHalf = u32;
|
||||
type HighHalf = u32;
|
||||
|
||||
fn low(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
fn high(self) -> u32 {
|
||||
(self.wrapping_shr(32)) as u32
|
||||
}
|
||||
fn from_parts(low: u32, high: u32) -> u64 {
|
||||
low as u64 | (high as u64).wrapping_shl(32)
|
||||
}
|
||||
}
|
||||
impl LargeInt for i64 {
|
||||
type LowHalf = u32;
|
||||
type HighHalf = i32;
|
||||
|
||||
fn low(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
fn high(self) -> i32 {
|
||||
self.wrapping_shr(32) as i32
|
||||
}
|
||||
fn from_parts(low: u32, high: i32) -> i64 {
|
||||
low as i64 | (high as i64).wrapping_shl(32)
|
||||
}
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
impl LargeInt for u128 {
|
||||
type LowHalf = u64;
|
||||
type HighHalf = u64;
|
||||
|
||||
fn low(self) -> u64 {
|
||||
self as u64
|
||||
}
|
||||
fn high(self) -> u64 {
|
||||
unsafe { *(&self as *const u128 as *const u64).offset(1) }
|
||||
}
|
||||
fn from_parts(low: u64, high: u64) -> u128 {
|
||||
#[repr(C, packed)] struct Parts(u64, u64);
|
||||
unsafe { ::core::mem::transmute(Parts(low, high)) }
|
||||
}
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
impl LargeInt for i128 {
|
||||
type LowHalf = u64;
|
||||
type HighHalf = i64;
|
||||
|
||||
fn low(self) -> u64 {
|
||||
self as u64
|
||||
}
|
||||
fn high(self) -> i64 {
|
||||
unsafe { *(&self as *const i128 as *const i64).offset(1) }
|
||||
}
|
||||
fn from_parts(low: u64, high: i64) -> i128 {
|
||||
u128::from_parts(low, high as u64) as i128
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! mul {
|
||||
($a:expr, $b:expr, $ty: ty, $tyh: ty) => {{
|
||||
let (a, b) = ($a, $b);
|
||||
let half_bits = ((::core::mem::size_of::<$tyh>() * 8) / 2) as u32;
|
||||
let lower_mask = (!0u64).wrapping_shr(half_bits);
|
||||
let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask);
|
||||
let mut t = low.wrapping_shr(half_bits);
|
||||
low &= lower_mask;
|
||||
t = t.wrapping_add(a.low().wrapping_shr(half_bits)
|
||||
.wrapping_mul(b.low() & lower_mask));
|
||||
low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
|
||||
let mut high = t.wrapping_shr(half_bits) as $tyh;
|
||||
t = low.wrapping_shr(half_bits);
|
||||
low &= lower_mask;
|
||||
t = t.wrapping_add(b.low().wrapping_shr(half_bits)
|
||||
.wrapping_mul(a.low() & lower_mask));
|
||||
low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
|
||||
high = high.wrapping_add(t.wrapping_shr(half_bits) as $tyh);
|
||||
high = high.wrapping_add(a.low().wrapping_shr(half_bits)
|
||||
.wrapping_mul(b.low().wrapping_shr(half_bits)) as $tyh);
|
||||
high = high
|
||||
.wrapping_add(a.high()
|
||||
.wrapping_mul(b.low() as $tyh))
|
||||
.wrapping_add((a.low() as $tyh)
|
||||
.wrapping_mul(b.high()));
|
||||
<$ty>::from_parts(low, high)
|
||||
}}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[export_name="__multi3"]
|
||||
pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ {
|
||||
((a as i64).wrapping_mul(b as i64) as i128_)
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[export_name="__multi3"]
|
||||
pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ {
|
||||
mul!(a, b, i128_, i64)
|
||||
}
|
||||
|
||||
trait AbsExt: Sized {
|
||||
fn uabs(self) -> u128_ {
|
||||
self.iabs() as u128_
|
||||
}
|
||||
fn iabs(self) -> i128_;
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
impl AbsExt for i128_ {
|
||||
fn iabs(self) -> i128_ {
|
||||
let s = self >> 63;
|
||||
((self ^ s).wrapping_sub(s))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
impl AbsExt for i128_ {
|
||||
fn iabs(self) -> i128_ {
|
||||
let s = self >> 127;
|
||||
((self ^ s).wrapping_sub(s))
|
||||
}
|
||||
}
|
||||
|
||||
trait NegExt: Sized {
|
||||
fn unchecked_neg(self) -> i128_;
|
||||
}
|
||||
|
||||
impl NegExt for i128_ {
|
||||
fn unchecked_neg(self) -> i128_ {
|
||||
(!self).wrapping_add(1)
|
||||
}
|
||||
}
|
||||
|
||||
trait FloatStuff: Sized {
|
||||
type ToBytes;
|
||||
|
||||
const MANTISSA_BITS: u32;
|
||||
const MAX_EXP: i32;
|
||||
const EXP_MASK: Self::ToBytes;
|
||||
const MANTISSA_MASK: Self::ToBytes;
|
||||
const MANTISSA_LEAD_BIT: Self::ToBytes;
|
||||
|
||||
fn to_bytes(self) -> Self::ToBytes;
|
||||
fn get_exponent(self) -> i32;
|
||||
}
|
||||
|
||||
impl FloatStuff for f32 {
|
||||
type ToBytes = u32;
|
||||
const MANTISSA_BITS: u32 = 23;
|
||||
const MAX_EXP: i32 = 127;
|
||||
const EXP_MASK: u32 = 0x7F80_0000;
|
||||
const MANTISSA_MASK: u32 = 0x007F_FFFF;
|
||||
const MANTISSA_LEAD_BIT: u32 = 0x0080_0000;
|
||||
|
||||
fn to_bytes(self) -> u32 { unsafe { ::core::mem::transmute(self) } }
|
||||
fn get_exponent(self) -> i32 {
|
||||
((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
|
||||
.wrapping_sub(Self::MAX_EXP)
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatStuff for f64 {
|
||||
type ToBytes = u64;
|
||||
const MANTISSA_BITS: u32 = 52;
|
||||
const MAX_EXP: i32 = 1023;
|
||||
const EXP_MASK: u64 = 0x7FF0_0000_0000_0000;
|
||||
const MANTISSA_MASK: u64 = 0x000F_FFFF_FFFF_FFFF;
|
||||
const MANTISSA_LEAD_BIT: u64 = 0x0010_0000_0000_0000;
|
||||
|
||||
fn to_bytes(self) -> u64 { unsafe { ::core::mem::transmute(self) } }
|
||||
fn get_exponent(self) -> i32 {
|
||||
((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
|
||||
.wrapping_sub(Self::MAX_EXP)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! float_as_unsigned {
|
||||
($from: expr, $fromty: ty, $outty: ty) => { {
|
||||
use core::num::Float;
|
||||
let repr = $from.to_bytes();
|
||||
let sign = $from.signum();
|
||||
let exponent = $from.get_exponent();
|
||||
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
|
||||
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
|
||||
if sign == -1.0 || exponent < 0 { return 0 as u128_; }
|
||||
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
|
||||
return !(0 as u128_);
|
||||
}
|
||||
(if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
|
||||
(mantissa as $outty)
|
||||
.wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
|
||||
.wrapping_sub(exponent) as u32)
|
||||
} else {
|
||||
(mantissa as $outty)
|
||||
.wrapping_shl(exponent.wrapping_sub(
|
||||
<$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
|
||||
})
|
||||
} }
|
||||
}
|
||||
|
||||
macro_rules! float_as_signed {
|
||||
($from: expr, $fromty: ty, $outty: ty) => {{
|
||||
use core::num::Float;
|
||||
let repr = $from.to_bytes();
|
||||
let sign = $from.signum();
|
||||
let exponent = $from.get_exponent();
|
||||
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
|
||||
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
|
||||
|
||||
if exponent < 0 { return 0 as i128_; }
|
||||
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
|
||||
let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() };
|
||||
return ret
|
||||
}
|
||||
let r = if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
|
||||
(mantissa as $outty)
|
||||
.wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
|
||||
.wrapping_sub(exponent) as u32)
|
||||
} else {
|
||||
(mantissa as $outty)
|
||||
.wrapping_shl(exponent.wrapping_sub(
|
||||
<$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
|
||||
};
|
||||
(if sign >= 0.0 { r } else { r.unchecked_neg() })
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
fn i128_as_f64(a: i128_) -> f64 {
|
||||
match a.signum() {
|
||||
1 => u128_as_f64(a.uabs()),
|
||||
0 => 0.0,
|
||||
_ => -u128_as_f64(a.uabs()),
|
||||
}
|
||||
}
|
||||
|
||||
fn i128_as_f32(a: i128_) -> f32 {
|
||||
match a.signum() {
|
||||
1 => u128_as_f32(a.uabs()),
|
||||
0 => 0.0,
|
||||
_ => -u128_as_f32(a.uabs()),
|
||||
}
|
||||
}
|
||||
|
||||
fn u128_as_f64(mut a: u128_) -> f64 {
|
||||
use ::core::f64::MANTISSA_DIGITS;
|
||||
if a == 0 { return 0.0; }
|
||||
let sd = 128u32.wrapping_sub(a.leading_zeros());
|
||||
let mut e = sd.wrapping_sub(1);
|
||||
const MD1 : u32 = MANTISSA_DIGITS + 1;
|
||||
const MD2 : u32 = MANTISSA_DIGITS + 2;
|
||||
|
||||
// SNAP: replace this with !0u128
|
||||
let negn :u128_ = !0;
|
||||
|
||||
if sd > MANTISSA_DIGITS {
|
||||
a = match sd {
|
||||
MD1 => a.wrapping_shl(1),
|
||||
MD2 => a,
|
||||
_ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
|
||||
(if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
|
||||
.wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 })
|
||||
};
|
||||
a |= if (a & 4) == 0 { 0 } else { 1 };
|
||||
a = a.wrapping_add(1);
|
||||
a = a.wrapping_shr(2);
|
||||
if a & (1 << MANTISSA_DIGITS) != 0 {
|
||||
a = a.wrapping_shr(1);
|
||||
e = e.wrapping_add(1);
|
||||
}
|
||||
} else {
|
||||
a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
|
||||
}
|
||||
unsafe {
|
||||
::core::mem::transmute((e as u64).wrapping_add(1023).wrapping_shl(52)
|
||||
| (a as u64 & 0x000f_ffff_ffff_ffff))
|
||||
}
|
||||
}
|
||||
|
||||
fn u128_as_f32(mut a: u128_) -> f32 {
|
||||
use ::core::f32::MANTISSA_DIGITS;
|
||||
if a == 0 { return 0.0; }
|
||||
let sd = 128u32.wrapping_sub(a.leading_zeros());
|
||||
let mut e = sd.wrapping_sub(1);
|
||||
const MD1 : u32 = MANTISSA_DIGITS + 1;
|
||||
const MD2 : u32 = MANTISSA_DIGITS + 2;
|
||||
|
||||
// SNAP: replace this with !0u128
|
||||
let negn :u128_ = !0;
|
||||
|
||||
if sd > MANTISSA_DIGITS {
|
||||
a = match sd {
|
||||
MD1 => a.wrapping_shl(1),
|
||||
MD2 => a,
|
||||
_ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
|
||||
(if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
|
||||
.wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 })
|
||||
};
|
||||
a |= if (a & 4) == 0 { 0 } else { 1 };
|
||||
a = a.wrapping_add(1);
|
||||
a = a.wrapping_shr(2);
|
||||
if a & (1 << MANTISSA_DIGITS) != 0 {
|
||||
a = a.wrapping_shr(1);
|
||||
e = e.wrapping_add(1);
|
||||
}
|
||||
} else {
|
||||
a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
|
||||
}
|
||||
unsafe {
|
||||
::core::mem::transmute((e as u32).wrapping_add(127).wrapping_shl(23)
|
||||
| (a as u32 & 0x007f_ffff))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
macro_rules! why_are_abi_strings_checked_by_parser { ($cret:ty, $conv:expr, $unadj:tt) => {
|
||||
mod imp {
|
||||
use super::{i128_, u128_, LargeInt, FloatStuff, NegExt, AbsExt};
|
||||
use super::{i128_as_f64, i128_as_f32, u128_as_f64, u128_as_f32,
|
||||
i128_div, i128_mod, u128_div_mod, unchecked_div, ptr};
|
||||
// For x64
|
||||
// rdx:rcx, r9:r8, stack -> rdx:rax
|
||||
// aka.
|
||||
// define i128 @__muloti4(i128, i128, i32*)
|
||||
#[export_name="__muloti4"]
|
||||
pub unsafe extern $unadj fn i128_mul_oflow(a: i128_, b: i128_, o: *mut i32) -> i128_ {
|
||||
mulo!(a, b, o, i128_)
|
||||
}
|
||||
|
||||
// For x64
|
||||
// rdx:rax -> xmm0
|
||||
// aka.
|
||||
// define double @__muloti4(i128)
|
||||
#[export_name="__floattidf"]
|
||||
pub extern $unadj fn i128_as_f64_(a: i128_) -> f64 {
|
||||
i128_as_f64(a)
|
||||
}
|
||||
#[export_name="__floattisf"]
|
||||
pub extern $unadj fn i128_as_f32_(a: i128_) -> f32 {
|
||||
i128_as_f32(a)
|
||||
}
|
||||
#[export_name="__floatuntidf"]
|
||||
pub extern $unadj fn u128_as_f64_(a: u128_) -> f64 {
|
||||
u128_as_f64(a)
|
||||
}
|
||||
#[export_name="__floatuntisf"]
|
||||
pub extern $unadj fn u128_as_f32_(a: u128_) -> f32 {
|
||||
u128_as_f32(a)
|
||||
}
|
||||
|
||||
// For x64
|
||||
// xmm0 -> rdx:rax
|
||||
// aka.
|
||||
// define i128 @stuff(double)
|
||||
#[export_name="__fixunsdfti"]
|
||||
pub extern $unadj fn f64_as_u128(a: f64) -> u128_ {
|
||||
float_as_unsigned!(a, f64, u128_)
|
||||
}
|
||||
|
||||
#[export_name="__fixunssfti"]
|
||||
pub extern "unadjusted" fn f32_as_u128(a: f32) -> u128_ {
|
||||
float_as_unsigned!(a, f32, u128_)
|
||||
}
|
||||
|
||||
#[export_name="__fixdfti"]
|
||||
pub extern "unadjusted" fn f64_as_i128(a: f64) -> i128_ {
|
||||
float_as_signed!(a, f64, i128_)
|
||||
}
|
||||
|
||||
#[export_name="__fixsfti"]
|
||||
pub extern "unadjusted" fn f32_as_i128(a: f32) -> i128_ {
|
||||
float_as_signed!(a, f32, i128_)
|
||||
}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct u64x2(u64, u64);
|
||||
|
||||
// For x64
|
||||
// pointers -> xmm0
|
||||
// aka.
|
||||
// define <2 x u64> @stuff(i128*, i128*, i128*)
|
||||
//
|
||||
// That almost matches the C ABI, so we simply use the C ABI
|
||||
#[export_name="__udivmodti4"]
|
||||
pub extern "C" fn u128_div_mod_(n: u128_, d: u128_, rem: *mut u128_) -> $cret {
|
||||
let x = u128_div_mod(n, d, rem);
|
||||
($conv)(x)
|
||||
}
|
||||
|
||||
#[export_name="__udivti3"]
|
||||
pub extern "C" fn u128_div_(a: u128_, b: u128_) -> $cret {
|
||||
let x = u128_div_mod(a, b, ptr::null_mut());
|
||||
($conv)(x)
|
||||
}
|
||||
|
||||
#[export_name="__umodti3"]
|
||||
pub extern "C" fn u128_mod_(a: u128_, b: u128_) -> $cret {
|
||||
unsafe {
|
||||
let mut r = ::core::mem::zeroed();
|
||||
u128_div_mod(a, b, &mut r);
|
||||
($conv)(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[export_name="__divti3"]
|
||||
pub extern "C" fn i128_div_(a: i128_, b: i128_) -> $cret {
|
||||
let x = i128_div(a, b);
|
||||
($conv)(x as u128_)
|
||||
}
|
||||
|
||||
#[export_name="__modti3"]
|
||||
pub extern "C" fn i128_mod_(a: i128_, b: i128_) -> $cret {
|
||||
let x = i128_mod(a, b);
|
||||
($conv)(x as u128_)
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
// LLVM expectations for ABI on windows x64 are pure madness.
|
||||
#[cfg(not(stage0))]
|
||||
#[cfg(all(windows, target_pointer_width="64"))]
|
||||
why_are_abi_strings_checked_by_parser!(u64x2,
|
||||
|i: u128_| u64x2(i.low(), i.high()),
|
||||
"unadjusted");
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[cfg(not(all(windows, target_pointer_width="64")))]
|
||||
why_are_abi_strings_checked_by_parser!(u128_, |i|{ i }, "C");
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub use self::imp::*;
|
||||
}
|
||||
|
@ -153,12 +153,16 @@ clone_impl! { i8 }
|
||||
clone_impl! { i16 }
|
||||
clone_impl! { i32 }
|
||||
clone_impl! { i64 }
|
||||
#[cfg(not(stage0))]
|
||||
clone_impl! { i128 }
|
||||
|
||||
clone_impl! { usize }
|
||||
clone_impl! { u8 }
|
||||
clone_impl! { u16 }
|
||||
clone_impl! { u32 }
|
||||
clone_impl! { u64 }
|
||||
#[cfg(not(stage0))]
|
||||
clone_impl! { u128 }
|
||||
|
||||
clone_impl! { f32 }
|
||||
clone_impl! { f64 }
|
||||
|
@ -429,7 +429,7 @@ impl PartialOrd for Ordering {
|
||||
/// 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.
|
||||
///
|
||||
/// ## How can I implement `Ord`?
|
||||
/// ## How can I implement `PartialOrd`?
|
||||
///
|
||||
/// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated
|
||||
/// from default implementations.
|
||||
@ -681,6 +681,8 @@ mod impls {
|
||||
partial_eq_impl! {
|
||||
bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
partial_eq_impl! { u128 i128 }
|
||||
|
||||
macro_rules! eq_impl {
|
||||
($($t:ty)*) => ($(
|
||||
@ -690,6 +692,8 @@ mod impls {
|
||||
}
|
||||
|
||||
eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
eq_impl! { u128 i128 }
|
||||
|
||||
macro_rules! partial_ord_impl {
|
||||
($($t:ty)*) => ($(
|
||||
@ -779,6 +783,8 @@ mod impls {
|
||||
}
|
||||
|
||||
ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
ord_impl! { u128 i128 }
|
||||
|
||||
#[unstable(feature = "never_type_impls", issue = "35121")]
|
||||
impl PartialEq for ! {
|
||||
|
@ -144,12 +144,16 @@ default_impl! { u8, 0 }
|
||||
default_impl! { u16, 0 }
|
||||
default_impl! { u32, 0 }
|
||||
default_impl! { u64, 0 }
|
||||
#[cfg(not(stage0))]
|
||||
default_impl! { u128, 0 }
|
||||
|
||||
default_impl! { isize, 0 }
|
||||
default_impl! { i8, 0 }
|
||||
default_impl! { i16, 0 }
|
||||
default_impl! { i32, 0 }
|
||||
default_impl! { i64, 0 }
|
||||
#[cfg(not(stage0))]
|
||||
default_impl! { i128, 0 }
|
||||
|
||||
default_impl! { f32, 0.0f32 }
|
||||
default_impl! { f64, 0.0f64 }
|
||||
|
@ -30,6 +30,8 @@ trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
|
||||
fn to_u16(&self) -> u16;
|
||||
fn to_u32(&self) -> u32;
|
||||
fn to_u64(&self) -> u64;
|
||||
#[cfg(not(stage0))]
|
||||
fn to_u128(&self) -> u128;
|
||||
}
|
||||
|
||||
macro_rules! doit {
|
||||
@ -39,9 +41,13 @@ macro_rules! doit {
|
||||
fn to_u16(&self) -> u16 { *self as u16 }
|
||||
fn to_u32(&self) -> u32 { *self as u32 }
|
||||
fn to_u64(&self) -> u64 { *self as u64 }
|
||||
#[cfg(not(stage0))]
|
||||
fn to_u128(&self) -> u128 { *self as u128 }
|
||||
})*)
|
||||
}
|
||||
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
|
||||
#[cfg(not(stage0))]
|
||||
doit! { i128 u128 }
|
||||
|
||||
/// A type that represents a specific radix
|
||||
#[doc(hidden)]
|
||||
@ -59,11 +65,11 @@ trait GenericRadix {
|
||||
|
||||
/// Format an integer using the radix using a formatter.
|
||||
fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// The radix can be as low as 2, so we need a buffer of at least 64
|
||||
// The radix can be as low as 2, so we need a buffer of at least 128
|
||||
// characters for a base 2 number.
|
||||
let zero = T::zero();
|
||||
let is_nonnegative = x >= zero;
|
||||
let mut buf = [0; 64];
|
||||
let mut buf = [0; 128];
|
||||
let mut curr = buf.len();
|
||||
let base = T::from_u8(self.base());
|
||||
if is_nonnegative {
|
||||
@ -182,6 +188,8 @@ integer! { i8, u8 }
|
||||
integer! { i16, u16 }
|
||||
integer! { i32, u32 }
|
||||
integer! { i64, u64 }
|
||||
#[cfg(not(stage0))]
|
||||
integer! { i128, u128 }
|
||||
|
||||
const DEC_DIGITS_LUT: &'static[u8] =
|
||||
b"0001020304050607080910111213141516171819\
|
||||
@ -203,14 +211,15 @@ macro_rules! impl_Display {
|
||||
// convert the negative num to positive by summing 1 to it's 2 complement
|
||||
(!self.$conv_fn()).wrapping_add(1)
|
||||
};
|
||||
let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
|
||||
let mut buf: [u8; 39] = unsafe { mem::uninitialized() };
|
||||
let mut curr = buf.len() as isize;
|
||||
let buf_ptr = buf.as_mut_ptr();
|
||||
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
|
||||
|
||||
unsafe {
|
||||
// eagerly decode 4 characters at a time
|
||||
if <$t>::max_value() as u64 >= 10000 {
|
||||
// need at least 16 bits for the 4-characters-at-a-time to work.
|
||||
if ::mem::size_of::<$t>() >= 2 {
|
||||
// eagerly decode 4 characters at a time
|
||||
while n >= 10000 {
|
||||
let rem = (n % 10000) as isize;
|
||||
n /= 10000;
|
||||
@ -256,6 +265,8 @@ macro_rules! impl_Display {
|
||||
|
||||
impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
|
||||
impl_Display!(i64, u64: to_u64);
|
||||
#[cfg(not(stage0))]
|
||||
impl_Display!(i128, u128: to_u128);
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
impl_Display!(isize, usize: to_u16);
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
|
@ -186,6 +186,13 @@ pub trait Hasher {
|
||||
fn write_u64(&mut self, i: u64) {
|
||||
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
/// Writes a single `u128` into this hasher.
|
||||
#[inline]
|
||||
#[unstable(feature = "i128", issue = "35118")]
|
||||
fn write_u128(&mut self, i: u128) {
|
||||
self.write(&unsafe { mem::transmute::<_, [u8; 16]>(i) })
|
||||
}
|
||||
/// Writes a single `usize` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
@ -220,6 +227,13 @@ pub trait Hasher {
|
||||
fn write_i64(&mut self, i: i64) {
|
||||
self.write_u64(i as u64)
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
/// Writes a single `i128` into this hasher.
|
||||
#[inline]
|
||||
#[unstable(feature = "i128", issue = "35118")]
|
||||
fn write_i128(&mut self, i: i128) {
|
||||
self.write_u128(i as u128)
|
||||
}
|
||||
/// Writes a single `isize` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
@ -362,6 +376,11 @@ mod impls {
|
||||
(i64, write_i64),
|
||||
(isize, write_isize),
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
impl_write! {
|
||||
(u128, write_u128),
|
||||
(i128, write_i128),
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for bool {
|
||||
|
@ -242,6 +242,8 @@ step_impl_signed!(i64);
|
||||
// assume here that it is less than 64-bits.
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
step_impl_no_between!(u64 i64);
|
||||
#[cfg(not(stage0))]
|
||||
step_impl_no_between!(u128 i128);
|
||||
|
||||
/// An adapter for stepping range iterators by a custom amount.
|
||||
///
|
||||
|
@ -90,6 +90,7 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(never_type)]
|
||||
#![cfg_attr(not(stage0), feature(i128_type))]
|
||||
#![feature(prelude_import)]
|
||||
|
||||
#[prelude_import]
|
||||
@ -120,12 +121,20 @@ mod uint_macros;
|
||||
#[path = "num/i32.rs"] pub mod i32;
|
||||
#[path = "num/i64.rs"] pub mod i64;
|
||||
|
||||
// SNAP
|
||||
#[cfg(not(stage0))]
|
||||
#[path = "num/i128.rs"] pub mod i128;
|
||||
|
||||
#[path = "num/usize.rs"] pub mod usize;
|
||||
#[path = "num/u8.rs"] pub mod u8;
|
||||
#[path = "num/u16.rs"] pub mod u16;
|
||||
#[path = "num/u32.rs"] pub mod u32;
|
||||
#[path = "num/u64.rs"] pub mod u64;
|
||||
|
||||
// SNAP
|
||||
#[cfg(not(stage0))]
|
||||
#[path = "num/u128.rs"] pub mod u128;
|
||||
|
||||
#[path = "num/f32.rs"] pub mod f32;
|
||||
#[path = "num/f64.rs"] pub mod f64;
|
||||
|
||||
|
@ -30,6 +30,10 @@ unsafe impl Zeroable for i32 {}
|
||||
unsafe impl Zeroable for u32 {}
|
||||
unsafe impl Zeroable for i64 {}
|
||||
unsafe impl Zeroable for u64 {}
|
||||
#[cfg(not(stage0))]
|
||||
unsafe impl Zeroable for i128 {}
|
||||
#[cfg(not(stage0))]
|
||||
unsafe impl Zeroable for u128 {}
|
||||
|
||||
/// A wrapper type for raw pointers and integers that will never be
|
||||
/// NULL or 0 that might allow certain optimizations.
|
||||
|
17
src/libcore/num/i128.rs
Normal file
17
src/libcore/num/i128.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
//! The 128-bit signed integer type.
|
||||
//!
|
||||
//! *[See also the `i128` primitive type](../../std/primitive.i128.html).*
|
||||
|
||||
#![unstable(feature = "i128", issue="35118")]
|
||||
|
||||
int_module! { i128 }
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
int_module! { i16, 16 }
|
||||
int_module! { i16 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
int_module! { i32, 32 }
|
||||
int_module! { i32 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
int_module! { i64, 64 }
|
||||
int_module! { i64 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
int_module! { i8, 8 }
|
||||
int_module! { i8 }
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#![doc(hidden)]
|
||||
|
||||
macro_rules! int_module { ($T:ident, $bits:expr) => (
|
||||
macro_rules! int_module { ($T:ident) => (
|
||||
|
||||
/// The smallest value that can be represented by this integer type.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -14,9 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
int_module! { isize, 16 }
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
int_module! { isize, 32 }
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
int_module! { isize, 64 }
|
||||
int_module! { isize }
|
||||
|
@ -145,6 +145,8 @@ macro_rules! zero_one_impl {
|
||||
)*)
|
||||
}
|
||||
zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
|
||||
#[cfg(not(stage0))]
|
||||
zero_one_impl! { u128 i128 }
|
||||
|
||||
macro_rules! zero_one_impl_float {
|
||||
($($t:ty)*) => ($(
|
||||
@ -191,7 +193,7 @@ macro_rules! int_impl {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub const fn min_value() -> Self {
|
||||
(-1 as Self) << ($BITS - 1)
|
||||
!0 ^ ((!0 as $UnsignedT) >> 1) as Self
|
||||
}
|
||||
|
||||
/// Returns the largest value that can be represented by this integer type.
|
||||
@ -1298,6 +1300,16 @@ impl i64 {
|
||||
intrinsics::mul_with_overflow }
|
||||
}
|
||||
|
||||
// SNAP
|
||||
#[cfg(not(stage0))]
|
||||
#[lang = "i128"]
|
||||
impl i128 {
|
||||
int_impl! { i128, u128, 128,
|
||||
intrinsics::add_with_overflow,
|
||||
intrinsics::sub_with_overflow,
|
||||
intrinsics::mul_with_overflow }
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
#[lang = "isize"]
|
||||
impl isize {
|
||||
@ -2330,6 +2342,20 @@ impl u64 {
|
||||
intrinsics::mul_with_overflow }
|
||||
}
|
||||
|
||||
// SNAP
|
||||
#[cfg(not(stage0))]
|
||||
#[lang = "u128"]
|
||||
impl u128 {
|
||||
uint_impl! { u128, 128,
|
||||
intrinsics::ctpop,
|
||||
intrinsics::ctlz,
|
||||
intrinsics::cttz,
|
||||
intrinsics::bswap,
|
||||
intrinsics::add_with_overflow,
|
||||
intrinsics::sub_with_overflow,
|
||||
intrinsics::mul_with_overflow }
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
#[lang = "usize"]
|
||||
impl usize {
|
||||
@ -2543,6 +2569,8 @@ macro_rules! from_str_radix_int_impl {
|
||||
)*}
|
||||
}
|
||||
from_str_radix_int_impl! { isize i8 i16 i32 i64 usize u8 u16 u32 u64 }
|
||||
#[cfg(not(stage0))]
|
||||
from_str_radix_int_impl! { u128 i128 }
|
||||
|
||||
/// The error type returned when a checked integral type conversion fails.
|
||||
#[unstable(feature = "try_from", issue = "33417")]
|
||||
@ -2567,7 +2595,7 @@ impl fmt::Display for TryFromIntError {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! same_sign_from_int_impl {
|
||||
macro_rules! same_sign_try_from_int_impl {
|
||||
($storage:ty, $target:ty, $($source:ty),*) => {$(
|
||||
#[unstable(feature = "try_from", issue = "33417")]
|
||||
impl TryFrom<$source> for $target {
|
||||
@ -2586,16 +2614,51 @@ macro_rules! same_sign_from_int_impl {
|
||||
)*}
|
||||
}
|
||||
|
||||
same_sign_from_int_impl!(u64, u8, u8, u16, u32, u64, usize);
|
||||
same_sign_from_int_impl!(i64, i8, i8, i16, i32, i64, isize);
|
||||
same_sign_from_int_impl!(u64, u16, u8, u16, u32, u64, usize);
|
||||
same_sign_from_int_impl!(i64, i16, i8, i16, i32, i64, isize);
|
||||
same_sign_from_int_impl!(u64, u32, u8, u16, u32, u64, usize);
|
||||
same_sign_from_int_impl!(i64, i32, i8, i16, i32, i64, isize);
|
||||
same_sign_from_int_impl!(u64, u64, u8, u16, u32, u64, usize);
|
||||
same_sign_from_int_impl!(i64, i64, i8, i16, i32, i64, isize);
|
||||
same_sign_from_int_impl!(u64, usize, u8, u16, u32, u64, usize);
|
||||
same_sign_from_int_impl!(i64, isize, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, u8, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, i8, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, u16, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, i16, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, u32, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, i32, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, u64, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, i64, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, usize, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, isize, i8, i16, i32, i64, isize);
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(u128, u8, u8, u16, u32, u64, u128, usize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(i128, i8, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(u128, u16, u8, u16, u32, u64, u128, usize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(i128, i16, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(u128, u32, u8, u16, u32, u64, u128, usize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(i128, i32, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(u128, u64, u8, u16, u32, u64, u128, usize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(i128, i64, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(u128, u128, u8, u16, u32, u64, u128, usize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(i128, i128, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(u128, usize, u8, u16, u32, u64, u128, usize);
|
||||
#[cfg(not(stage0))]
|
||||
same_sign_try_from_int_impl!(i128, isize, i8, i16, i32, i64, i128, isize);
|
||||
|
||||
macro_rules! cross_sign_from_int_impl {
|
||||
($unsigned:ty, $($signed:ty),*) => {$(
|
||||
@ -2629,12 +2692,30 @@ macro_rules! cross_sign_from_int_impl {
|
||||
)*}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
cross_sign_from_int_impl!(u8, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
cross_sign_from_int_impl!(u16, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
cross_sign_from_int_impl!(u32, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
cross_sign_from_int_impl!(u64, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
cross_sign_from_int_impl!(usize, i8, i16, i32, i64, isize);
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
cross_sign_from_int_impl!(u8, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
cross_sign_from_int_impl!(u16, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
cross_sign_from_int_impl!(u32, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
cross_sign_from_int_impl!(u64, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
cross_sign_from_int_impl!(u128, i8, i16, i32, i64, i128, isize);
|
||||
#[cfg(not(stage0))]
|
||||
cross_sign_from_int_impl!(usize, i8, i16, i32, i64, i128, isize);
|
||||
|
||||
#[doc(hidden)]
|
||||
trait FromStrRadixHelper: PartialOrd + Copy {
|
||||
fn min_value() -> Self;
|
||||
@ -2662,6 +2743,8 @@ macro_rules! doit {
|
||||
})*)
|
||||
}
|
||||
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
|
||||
#[cfg(not(stage0))]
|
||||
doit! { i128 u128 }
|
||||
|
||||
fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
|
||||
use self::IntErrorKind::*;
|
||||
@ -2795,27 +2878,51 @@ macro_rules! impl_from {
|
||||
impl_from! { u8, u16 }
|
||||
impl_from! { u8, u32 }
|
||||
impl_from! { u8, u64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { u8, u128 }
|
||||
impl_from! { u8, usize }
|
||||
impl_from! { u16, u32 }
|
||||
impl_from! { u16, u64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { u16, u128 }
|
||||
impl_from! { u32, u64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { u32, u128 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { u64, u128 }
|
||||
|
||||
// Signed -> Signed
|
||||
impl_from! { i8, i16 }
|
||||
impl_from! { i8, i32 }
|
||||
impl_from! { i8, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { i8, i128 }
|
||||
impl_from! { i8, isize }
|
||||
impl_from! { i16, i32 }
|
||||
impl_from! { i16, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { i16, i128 }
|
||||
impl_from! { i32, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { i32, i128 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { i64, i128 }
|
||||
|
||||
// Unsigned -> Signed
|
||||
impl_from! { u8, i16 }
|
||||
impl_from! { u8, i32 }
|
||||
impl_from! { u8, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { u8, i128 }
|
||||
impl_from! { u16, i32 }
|
||||
impl_from! { u16, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { u16, i128 }
|
||||
impl_from! { u32, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { u32, i128 }
|
||||
#[cfg(not(stage0))]
|
||||
impl_from! { u64, i128 }
|
||||
|
||||
// Note: integers can only be represented with full precision in a float if
|
||||
// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
|
||||
|
16
src/libcore/num/u128.rs
Normal file
16
src/libcore/num/u128.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// 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.
|
||||
|
||||
//! The 128-bit unsigned integer type.
|
||||
//!
|
||||
//! *[See also the `u128` primitive type](../../std/primitive.u128.html).*
|
||||
|
||||
#![unstable(feature = "i128", issue="35118")]
|
||||
uint_module! { u128 }
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
uint_module! { u16, 16 }
|
||||
uint_module! { u16 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
uint_module! { u32, 32 }
|
||||
uint_module! { u32 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
uint_module! { u64, 64 }
|
||||
uint_module! { u64 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
uint_module! { u8, 8 }
|
||||
uint_module! { u8 }
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#![doc(hidden)]
|
||||
|
||||
macro_rules! uint_module { ($T:ident, $bits:expr) => (
|
||||
macro_rules! uint_module { ($T:ident) => (
|
||||
|
||||
/// The smallest value that can be represented by this integer type.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -14,9 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
uint_module! { usize, 16 }
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
uint_module! { usize, 32 }
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
uint_module! { usize, 64 }
|
||||
uint_module! { usize }
|
||||
|
@ -298,6 +298,8 @@ macro_rules! wrapping_impl {
|
||||
}
|
||||
|
||||
wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
wrapping_impl! { u128 i128 }
|
||||
|
||||
mod shift_max {
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
@ -268,6 +268,8 @@ macro_rules! add_impl {
|
||||
}
|
||||
|
||||
add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
add_impl! { u128 i128 }
|
||||
|
||||
/// The `Sub` trait is used to specify the functionality of `-`.
|
||||
///
|
||||
@ -341,6 +343,8 @@ macro_rules! sub_impl {
|
||||
}
|
||||
|
||||
sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
sub_impl! { u128 i128 }
|
||||
|
||||
/// The `Mul` trait is used to specify the functionality of `*`.
|
||||
///
|
||||
@ -463,6 +467,8 @@ macro_rules! mul_impl {
|
||||
}
|
||||
|
||||
mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
mul_impl! { u128 i128 }
|
||||
|
||||
/// The `Div` trait is used to specify the functionality of `/`.
|
||||
///
|
||||
@ -592,6 +598,8 @@ macro_rules! div_impl_integer {
|
||||
}
|
||||
|
||||
div_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
div_impl_integer! { u128 i128 }
|
||||
|
||||
macro_rules! div_impl_float {
|
||||
($($t:ty)*) => ($(
|
||||
@ -671,6 +679,9 @@ macro_rules! rem_impl_integer {
|
||||
}
|
||||
|
||||
rem_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
rem_impl_integer! { u128 i128 }
|
||||
|
||||
|
||||
macro_rules! rem_impl_float {
|
||||
($($t:ty)*) => ($(
|
||||
@ -766,6 +777,8 @@ macro_rules! neg_impl_unsigned {
|
||||
|
||||
// neg_impl_unsigned! { usize u8 u16 u32 u64 }
|
||||
neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
neg_impl_numeric! { i128 }
|
||||
|
||||
/// The `Not` trait is used to specify the functionality of unary `!`.
|
||||
///
|
||||
@ -824,6 +837,8 @@ macro_rules! not_impl {
|
||||
}
|
||||
|
||||
not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
not_impl! { u128 i128 }
|
||||
|
||||
/// The `BitAnd` trait is used to specify the functionality of `&`.
|
||||
///
|
||||
@ -907,6 +922,8 @@ macro_rules! bitand_impl {
|
||||
}
|
||||
|
||||
bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
bitand_impl! { u128 i128 }
|
||||
|
||||
/// The `BitOr` trait is used to specify the functionality of `|`.
|
||||
///
|
||||
@ -990,6 +1007,8 @@ macro_rules! bitor_impl {
|
||||
}
|
||||
|
||||
bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
bitor_impl! { u128 i128 }
|
||||
|
||||
/// The `BitXor` trait is used to specify the functionality of `^`.
|
||||
///
|
||||
@ -1076,6 +1095,8 @@ macro_rules! bitxor_impl {
|
||||
}
|
||||
|
||||
bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
bitxor_impl! { u128 i128 }
|
||||
|
||||
/// The `Shl` trait is used to specify the functionality of `<<`.
|
||||
///
|
||||
@ -1166,17 +1187,23 @@ macro_rules! shl_impl_all {
|
||||
shl_impl! { $t, u16 }
|
||||
shl_impl! { $t, u32 }
|
||||
shl_impl! { $t, u64 }
|
||||
#[cfg(not(stage0))]
|
||||
shl_impl! { $t, u128 }
|
||||
shl_impl! { $t, usize }
|
||||
|
||||
shl_impl! { $t, i8 }
|
||||
shl_impl! { $t, i16 }
|
||||
shl_impl! { $t, i32 }
|
||||
shl_impl! { $t, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
shl_impl! { $t, i128 }
|
||||
shl_impl! { $t, isize }
|
||||
)*)
|
||||
}
|
||||
|
||||
shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
|
||||
#[cfg(not(stage0))]
|
||||
shl_impl_all! { u128 i128 }
|
||||
|
||||
/// The `Shr` trait is used to specify the functionality of `>>`.
|
||||
///
|
||||
@ -1267,17 +1294,23 @@ macro_rules! shr_impl_all {
|
||||
shr_impl! { $t, u16 }
|
||||
shr_impl! { $t, u32 }
|
||||
shr_impl! { $t, u64 }
|
||||
#[cfg(not(stage0))]
|
||||
shr_impl! { $t, u128 }
|
||||
shr_impl! { $t, usize }
|
||||
|
||||
shr_impl! { $t, i8 }
|
||||
shr_impl! { $t, i16 }
|
||||
shr_impl! { $t, i32 }
|
||||
shr_impl! { $t, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
shr_impl! { $t, i128 }
|
||||
shr_impl! { $t, isize }
|
||||
)*)
|
||||
}
|
||||
|
||||
shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
|
||||
#[cfg(not(stage0))]
|
||||
shr_impl_all! { u128 i128 }
|
||||
|
||||
/// The `AddAssign` trait is used to specify the functionality of `+=`.
|
||||
///
|
||||
@ -1334,6 +1367,8 @@ macro_rules! add_assign_impl {
|
||||
}
|
||||
|
||||
add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
add_assign_impl! { u128 i128 }
|
||||
|
||||
/// The `SubAssign` trait is used to specify the functionality of `-=`.
|
||||
///
|
||||
@ -1390,6 +1425,8 @@ macro_rules! sub_assign_impl {
|
||||
}
|
||||
|
||||
sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
sub_assign_impl! { u128 i128 }
|
||||
|
||||
/// The `MulAssign` trait is used to specify the functionality of `*=`.
|
||||
///
|
||||
@ -1435,6 +1472,8 @@ macro_rules! mul_assign_impl {
|
||||
}
|
||||
|
||||
mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
mul_assign_impl! { u128 i128 }
|
||||
|
||||
/// The `DivAssign` trait is used to specify the functionality of `/=`.
|
||||
///
|
||||
@ -1479,6 +1518,8 @@ macro_rules! div_assign_impl {
|
||||
}
|
||||
|
||||
div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
div_assign_impl! { u128 i128 }
|
||||
|
||||
/// The `RemAssign` trait is used to specify the functionality of `%=`.
|
||||
///
|
||||
@ -1523,6 +1564,8 @@ macro_rules! rem_assign_impl {
|
||||
}
|
||||
|
||||
rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
|
||||
#[cfg(not(stage0))]
|
||||
rem_assign_impl! { u128 i128 }
|
||||
|
||||
/// The `BitAndAssign` trait is used to specify the functionality of `&=`.
|
||||
///
|
||||
@ -1609,6 +1652,8 @@ macro_rules! bitand_assign_impl {
|
||||
}
|
||||
|
||||
bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
bitand_assign_impl! { u128 i128 }
|
||||
|
||||
/// The `BitOrAssign` trait is used to specify the functionality of `|=`.
|
||||
///
|
||||
@ -1653,6 +1698,8 @@ macro_rules! bitor_assign_impl {
|
||||
}
|
||||
|
||||
bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
bitor_assign_impl! { u128 i128 }
|
||||
|
||||
/// The `BitXorAssign` trait is used to specify the functionality of `^=`.
|
||||
///
|
||||
@ -1697,6 +1744,8 @@ macro_rules! bitxor_assign_impl {
|
||||
}
|
||||
|
||||
bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
bitxor_assign_impl! { u128 i128 }
|
||||
|
||||
/// The `ShlAssign` trait is used to specify the functionality of `<<=`.
|
||||
///
|
||||
@ -1749,17 +1798,23 @@ macro_rules! shl_assign_impl_all {
|
||||
shl_assign_impl! { $t, u16 }
|
||||
shl_assign_impl! { $t, u32 }
|
||||
shl_assign_impl! { $t, u64 }
|
||||
#[cfg(not(stage0))]
|
||||
shl_assign_impl! { $t, u128 }
|
||||
shl_assign_impl! { $t, usize }
|
||||
|
||||
shl_assign_impl! { $t, i8 }
|
||||
shl_assign_impl! { $t, i16 }
|
||||
shl_assign_impl! { $t, i32 }
|
||||
shl_assign_impl! { $t, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
shl_assign_impl! { $t, i128 }
|
||||
shl_assign_impl! { $t, isize }
|
||||
)*)
|
||||
}
|
||||
|
||||
shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
|
||||
#[cfg(not(stage0))]
|
||||
shl_assign_impl_all! { u128 i128 }
|
||||
|
||||
/// The `ShrAssign` trait is used to specify the functionality of `>>=`.
|
||||
///
|
||||
@ -1812,17 +1867,23 @@ macro_rules! shr_assign_impl_all {
|
||||
shr_assign_impl! { $t, u16 }
|
||||
shr_assign_impl! { $t, u32 }
|
||||
shr_assign_impl! { $t, u64 }
|
||||
#[cfg(not(stage0))]
|
||||
shr_assign_impl! { $t, u128 }
|
||||
shr_assign_impl! { $t, usize }
|
||||
|
||||
shr_assign_impl! { $t, i8 }
|
||||
shr_assign_impl! { $t, i16 }
|
||||
shr_assign_impl! { $t, i32 }
|
||||
shr_assign_impl! { $t, i64 }
|
||||
#[cfg(not(stage0))]
|
||||
shr_assign_impl! { $t, i128 }
|
||||
shr_assign_impl! { $t, isize }
|
||||
)*)
|
||||
}
|
||||
|
||||
shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
|
||||
#[cfg(not(stage0))]
|
||||
shr_assign_impl_all! { u128 i128 }
|
||||
|
||||
/// The `Index` trait is used to specify the functionality of indexing operations
|
||||
/// like `container[index]` when used in an immutable context.
|
||||
|
@ -237,11 +237,16 @@ impl AtomicBool {
|
||||
|
||||
/// Loads a value from the bool.
|
||||
///
|
||||
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
|
||||
/// `load` takes an [`Ordering`] argument which describes the memory ordering
|
||||
/// of this operation.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `order` is `Release` or `AcqRel`.
|
||||
/// Panics if `order` is [`Release`] or [`AcqRel`].
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.Release
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -260,7 +265,10 @@ impl AtomicBool {
|
||||
|
||||
/// Stores a value into the bool.
|
||||
///
|
||||
/// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
|
||||
/// `store` takes an [`Ordering`] argument which describes the memory ordering
|
||||
/// of this operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -286,7 +294,10 @@ impl AtomicBool {
|
||||
|
||||
/// Stores a value into the bool, returning the old value.
|
||||
///
|
||||
/// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
|
||||
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
|
||||
/// of this operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -309,8 +320,10 @@ impl AtomicBool {
|
||||
/// The return value is always the previous value. If it is equal to `current`, then the value
|
||||
/// was updated.
|
||||
///
|
||||
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
|
||||
/// this operation.
|
||||
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
|
||||
/// ordering of this operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -339,10 +352,15 @@ impl AtomicBool {
|
||||
/// The return value is a result indicating whether the new value was written and containing
|
||||
/// the previous value. On success this value is guaranteed to be equal to `current`.
|
||||
///
|
||||
/// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
|
||||
/// operation. The first describes the required ordering if the operation succeeds while the
|
||||
/// second describes the required ordering when the operation fails. The failure ordering can't
|
||||
/// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering.
|
||||
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
|
||||
/// ordering of this operation. The first describes the required ordering if the
|
||||
/// operation succeeds while the second describes the required ordering when the
|
||||
/// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must
|
||||
/// be equivalent or weaker than the success ordering.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.Release
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -387,11 +405,15 @@ impl AtomicBool {
|
||||
/// return value is a result indicating whether the new value was written and containing the
|
||||
/// previous value.
|
||||
///
|
||||
/// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
|
||||
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
|
||||
/// ordering of this operation. The first describes the required ordering if the operation
|
||||
/// succeeds while the second describes the required ordering when the operation fails. The
|
||||
/// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the
|
||||
/// success ordering.
|
||||
/// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
|
||||
/// weaker than the success ordering.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.Release
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -619,11 +641,16 @@ impl<T> AtomicPtr<T> {
|
||||
|
||||
/// Loads a value from the pointer.
|
||||
///
|
||||
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
|
||||
/// `load` takes an [`Ordering`] argument which describes the memory ordering
|
||||
/// of this operation.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `order` is `Release` or `AcqRel`.
|
||||
/// Panics if `order` is [`Release`] or [`AcqRel`].
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -643,7 +670,10 @@ impl<T> AtomicPtr<T> {
|
||||
|
||||
/// Stores a value into the pointer.
|
||||
///
|
||||
/// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
|
||||
/// `store` takes an [`Ordering`] argument which describes the memory ordering
|
||||
/// of this operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -671,7 +701,10 @@ impl<T> AtomicPtr<T> {
|
||||
|
||||
/// Stores a value into the pointer, returning the old value.
|
||||
///
|
||||
/// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
|
||||
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
|
||||
/// of this operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -696,8 +729,10 @@ impl<T> AtomicPtr<T> {
|
||||
/// The return value is always the previous value. If it is equal to `current`, then the value
|
||||
/// was updated.
|
||||
///
|
||||
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
|
||||
/// this operation.
|
||||
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
|
||||
/// ordering of this operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -726,10 +761,15 @@ impl<T> AtomicPtr<T> {
|
||||
/// The return value is a result indicating whether the new value was written and containing
|
||||
/// the previous value. On success this value is guaranteed to be equal to `current`.
|
||||
///
|
||||
/// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
|
||||
/// operation. The first describes the required ordering if the operation succeeds while the
|
||||
/// second describes the required ordering when the operation fails. The failure ordering can't
|
||||
/// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering.
|
||||
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
|
||||
/// ordering of this operation. The first describes the required ordering if
|
||||
/// the operation succeeds while the second describes the required ordering when
|
||||
/// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`]
|
||||
/// and must be equivalent or weaker than the success ordering.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -768,16 +808,21 @@ impl<T> AtomicPtr<T> {
|
||||
|
||||
/// Stores a value into the pointer if the current value is the same as the `current` value.
|
||||
///
|
||||
/// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
|
||||
/// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the
|
||||
/// comparison succeeds, which can result in more efficient code on some platforms. The
|
||||
/// return value is a result indicating whether the new value was written and containing the
|
||||
/// previous value.
|
||||
///
|
||||
/// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
|
||||
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
|
||||
/// ordering of this operation. The first describes the required ordering if the operation
|
||||
/// succeeds while the second describes the required ordering when the operation fails. The
|
||||
/// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the
|
||||
/// success ordering.
|
||||
/// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
|
||||
/// weaker than the success ordering.
|
||||
///
|
||||
/// [`compare_exchange`]: #method.compare_exchange
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -913,12 +958,16 @@ macro_rules! atomic_int {
|
||||
|
||||
/// Loads a value from the atomic integer.
|
||||
///
|
||||
/// `load` takes an `Ordering` argument which describes the memory ordering of this
|
||||
/// `load` takes an [`Ordering`] argument which describes the memory ordering of this
|
||||
/// operation.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `order` is `Release` or `AcqRel`.
|
||||
/// Panics if `order` is [`Release`] or [`AcqRel`].
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -937,9 +986,11 @@ macro_rules! atomic_int {
|
||||
|
||||
/// Stores a value into the atomic integer.
|
||||
///
|
||||
/// `store` takes an `Ordering` argument which describes the memory ordering of this
|
||||
/// `store` takes an [`Ordering`] argument which describes the memory ordering of this
|
||||
/// operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -962,9 +1013,11 @@ macro_rules! atomic_int {
|
||||
|
||||
/// Stores a value into the atomic integer, returning the old value.
|
||||
///
|
||||
/// `swap` takes an `Ordering` argument which describes the memory ordering of this
|
||||
/// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
|
||||
/// operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -986,9 +1039,11 @@ macro_rules! atomic_int {
|
||||
/// The return value is always the previous value. If it is equal to `current`, then the
|
||||
/// value was updated.
|
||||
///
|
||||
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory
|
||||
/// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
|
||||
/// ordering of this operation.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -1024,11 +1079,15 @@ macro_rules! atomic_int {
|
||||
/// containing the previous value. On success this value is guaranteed to be equal to
|
||||
/// `current`.
|
||||
///
|
||||
/// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of
|
||||
/// this operation. The first describes the required ordering if the operation succeeds
|
||||
/// while the second describes the required ordering when the operation fails. The
|
||||
/// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker
|
||||
/// than the success ordering.
|
||||
/// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
|
||||
/// ordering of this operation. The first describes the required ordering if
|
||||
/// the operation succeeds while the second describes the required ordering when
|
||||
/// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
|
||||
/// must be equivalent or weaker than the success ordering.
|
||||
///
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1062,16 +1121,21 @@ macro_rules! atomic_int {
|
||||
/// Stores a value into the atomic integer if the current value is the same as the
|
||||
/// `current` value.
|
||||
///
|
||||
/// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
|
||||
/// comparison succeeds, which can result in more efficient code on some platforms. The
|
||||
/// return value is a result indicating whether the new value was written and containing
|
||||
/// the previous value.
|
||||
/// Unlike [`compare_exchange`], this function is allowed to spuriously fail even
|
||||
/// when the comparison succeeds, which can result in more efficient code on some
|
||||
/// platforms. The return value is a result indicating whether the new value was
|
||||
/// written and containing the previous value.
|
||||
///
|
||||
/// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
|
||||
/// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
|
||||
/// ordering of this operation. The first describes the required ordering if the
|
||||
/// operation succeeds while the second describes the required ordering when the
|
||||
/// operation fails. The failure ordering can't be `Release` or `AcqRel` and must be
|
||||
/// equivalent or weaker than the success ordering.
|
||||
/// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
|
||||
/// must be equivalent or weaker than the success ordering.
|
||||
///
|
||||
/// [`compare_exchange`]: #method.compare_exchange
|
||||
/// [`Ordering`]: enum.Ordering.html
|
||||
/// [`Release`]: enum.Ordering.html#variant.Release
|
||||
/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1431,24 +1495,31 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
|
||||
/// An atomic fence.
|
||||
///
|
||||
/// A fence 'A' which has `Release` ordering semantics, synchronizes with a
|
||||
/// fence 'B' with (at least) `Acquire` semantics, if and only if there exists
|
||||
/// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a
|
||||
/// 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
|
||||
/// 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.
|
||||
///
|
||||
/// Atomic operations with `Release` or `Acquire` semantics can also synchronize
|
||||
/// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
|
||||
/// with a fence.
|
||||
///
|
||||
/// A fence which has `SeqCst` ordering, in addition to having both `Acquire`
|
||||
/// and `Release` semantics, participates in the global program order of the
|
||||
/// other `SeqCst` operations and/or fences.
|
||||
/// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
|
||||
/// and [`Release`] semantics, participates in the global program order of the
|
||||
/// other [`SeqCst`] operations and/or fences.
|
||||
///
|
||||
/// Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
|
||||
/// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
|
||||
///
|
||||
/// # 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]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn fence(order: Ordering) {
|
||||
|
@ -7,6 +7,7 @@ version = "0.0.0"
|
||||
path = "lib.rs"
|
||||
test = false
|
||||
bench = false
|
||||
doc = false
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../libcore" }
|
||||
|
@ -7,6 +7,7 @@ version = "0.0.0"
|
||||
path = "lib.rs"
|
||||
test = false
|
||||
bench = false
|
||||
doc = false
|
||||
|
||||
[dependencies]
|
||||
alloc = { path = "../liballoc" }
|
||||
|
@ -6,6 +6,7 @@ version = "0.0.0"
|
||||
[lib]
|
||||
name = "rand"
|
||||
path = "lib.rs"
|
||||
doc = false
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../libcore" }
|
||||
|
@ -20,6 +20,7 @@ rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_llvm = { path = "../librustc_llvm" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
@ -62,6 +62,9 @@ extern crate rustc_errors as errors;
|
||||
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
// SNAP:
|
||||
extern crate rustc_i128;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate test;
|
||||
|
||||
|
@ -260,11 +260,13 @@ language_item_table! {
|
||||
I16ImplItem, "i16", i16_impl;
|
||||
I32ImplItem, "i32", i32_impl;
|
||||
I64ImplItem, "i64", i64_impl;
|
||||
I128ImplItem, "i128", i128_impl;
|
||||
IsizeImplItem, "isize", isize_impl;
|
||||
U8ImplItem, "u8", u8_impl;
|
||||
U16ImplItem, "u16", u16_impl;
|
||||
U32ImplItem, "u32", u32_impl;
|
||||
U64ImplItem, "u64", u64_impl;
|
||||
U128ImplItem, "u128", u128_impl;
|
||||
UsizeImplItem, "usize", usize_impl;
|
||||
F32ImplItem, "f32", f32_impl;
|
||||
F64ImplItem, "f64", f64_impl;
|
||||
|
@ -194,11 +194,13 @@ pub struct CommonTypes<'tcx> {
|
||||
pub i16: Ty<'tcx>,
|
||||
pub i32: Ty<'tcx>,
|
||||
pub i64: Ty<'tcx>,
|
||||
pub i128: Ty<'tcx>,
|
||||
pub usize: Ty<'tcx>,
|
||||
pub u8: Ty<'tcx>,
|
||||
pub u16: Ty<'tcx>,
|
||||
pub u32: Ty<'tcx>,
|
||||
pub u64: Ty<'tcx>,
|
||||
pub u128: Ty<'tcx>,
|
||||
pub f32: Ty<'tcx>,
|
||||
pub f64: Ty<'tcx>,
|
||||
pub never: Ty<'tcx>,
|
||||
@ -359,11 +361,13 @@ impl<'tcx> CommonTypes<'tcx> {
|
||||
i16: mk(TyInt(ast::IntTy::I16)),
|
||||
i32: mk(TyInt(ast::IntTy::I32)),
|
||||
i64: mk(TyInt(ast::IntTy::I64)),
|
||||
i128: mk(TyInt(ast::IntTy::I128)),
|
||||
usize: mk(TyUint(ast::UintTy::Us)),
|
||||
u8: mk(TyUint(ast::UintTy::U8)),
|
||||
u16: mk(TyUint(ast::UintTy::U16)),
|
||||
u32: mk(TyUint(ast::UintTy::U32)),
|
||||
u64: mk(TyUint(ast::UintTy::U64)),
|
||||
u128: mk(TyUint(ast::UintTy::U128)),
|
||||
f32: mk(TyFloat(ast::FloatTy::F32)),
|
||||
f64: mk(TyFloat(ast::FloatTy::F64)),
|
||||
}
|
||||
@ -1304,6 +1308,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
ast::IntTy::I16 => self.types.i16,
|
||||
ast::IntTy::I32 => self.types.i32,
|
||||
ast::IntTy::I64 => self.types.i64,
|
||||
ast::IntTy::I128 => self.types.i128,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1314,6 +1319,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
ast::UintTy::U16 => self.types.u16,
|
||||
ast::UintTy::U32 => self.types.u32,
|
||||
ast::UintTy::U64 => self.types.u64,
|
||||
ast::UintTy::U128 => self.types.u128,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@ use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
use syntax::attr;
|
||||
use syntax_pos::DUMMY_SP;
|
||||
use rustc_i128::u128;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
@ -35,6 +37,7 @@ pub struct TargetDataLayout {
|
||||
pub i16_align: Align,
|
||||
pub i32_align: Align,
|
||||
pub i64_align: Align,
|
||||
pub i128_align: Align,
|
||||
pub f32_align: Align,
|
||||
pub f64_align: Align,
|
||||
pub pointer_size: Size,
|
||||
@ -55,6 +58,7 @@ impl Default for TargetDataLayout {
|
||||
i16_align: Align::from_bits(16, 16).unwrap(),
|
||||
i32_align: Align::from_bits(32, 32).unwrap(),
|
||||
i64_align: Align::from_bits(32, 64).unwrap(),
|
||||
i128_align: Align::from_bits(32, 64).unwrap(),
|
||||
f32_align: Align::from_bits(32, 32).unwrap(),
|
||||
f64_align: Align::from_bits(64, 64).unwrap(),
|
||||
pointer_size: Size::from_bits(64),
|
||||
@ -99,6 +103,7 @@ impl TargetDataLayout {
|
||||
};
|
||||
|
||||
let mut dl = TargetDataLayout::default();
|
||||
let mut i128_align_src = 64;
|
||||
for spec in sess.target.target.data_layout.split("-") {
|
||||
match &spec.split(":").collect::<Vec<_>>()[..] {
|
||||
&["e"] => dl.endian = Endian::Little,
|
||||
@ -111,19 +116,28 @@ impl TargetDataLayout {
|
||||
dl.pointer_align = align(a, p);
|
||||
}
|
||||
&[s, ref a..] if s.starts_with("i") => {
|
||||
let ty_align = match s[1..].parse::<u64>() {
|
||||
Ok(1) => &mut dl.i8_align,
|
||||
Ok(8) => &mut dl.i8_align,
|
||||
Ok(16) => &mut dl.i16_align,
|
||||
Ok(32) => &mut dl.i32_align,
|
||||
Ok(64) => &mut dl.i64_align,
|
||||
Ok(_) => continue,
|
||||
let bits = match s[1..].parse::<u64>() {
|
||||
Ok(bits) => bits,
|
||||
Err(_) => {
|
||||
size(&s[1..], "i"); // For the user error.
|
||||
continue;
|
||||
}
|
||||
};
|
||||
*ty_align = align(a, s);
|
||||
let a = align(a, s);
|
||||
match bits {
|
||||
1 => dl.i1_align = a,
|
||||
8 => dl.i8_align = a,
|
||||
16 => dl.i16_align = a,
|
||||
32 => dl.i32_align = a,
|
||||
64 => dl.i64_align = a,
|
||||
_ => {}
|
||||
}
|
||||
if bits >= i128_align_src && bits <= 128 {
|
||||
// Default alignment for i128 is decided by taking the alignment of
|
||||
// largest-sized i{64...128}.
|
||||
i128_align_src = bits;
|
||||
dl.i128_align = a;
|
||||
}
|
||||
}
|
||||
&[s, ref a..] if s.starts_with("v") => {
|
||||
let v_size = size(&s[1..], "v");
|
||||
@ -325,7 +339,8 @@ pub enum Integer {
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64
|
||||
I64,
|
||||
I128,
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
@ -336,6 +351,7 @@ impl Integer {
|
||||
I16 => Size::from_bytes(2),
|
||||
I32 => Size::from_bytes(4),
|
||||
I64 => Size::from_bytes(8),
|
||||
I128 => Size::from_bytes(16),
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,6 +362,7 @@ impl Integer {
|
||||
I16 => dl.i16_align,
|
||||
I32 => dl.i32_align,
|
||||
I64 => dl.i64_align,
|
||||
I128 => dl.i128_align,
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,33 +374,37 @@ impl Integer {
|
||||
(I16, false) => tcx.types.u16,
|
||||
(I32, false) => tcx.types.u32,
|
||||
(I64, false) => tcx.types.u64,
|
||||
(I128, false) => tcx.types.u128,
|
||||
(I1, true) => tcx.types.i8,
|
||||
(I8, true) => tcx.types.i8,
|
||||
(I16, true) => tcx.types.i16,
|
||||
(I32, true) => tcx.types.i32,
|
||||
(I64, true) => tcx.types.i64,
|
||||
(I128, true) => tcx.types.i128,
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the smallest Integer type which can represent the signed value.
|
||||
pub fn fit_signed(x: i64) -> Integer {
|
||||
match x {
|
||||
-0x0000_0001...0x0000_0000 => I1,
|
||||
-0x0000_0080...0x0000_007f => I8,
|
||||
-0x0000_8000...0x0000_7fff => I16,
|
||||
-0x8000_0000...0x7fff_ffff => I32,
|
||||
_ => I64
|
||||
-0x0000_0000_0000_0001...0x0000_0000_0000_0000 => I1,
|
||||
-0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
|
||||
-0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
|
||||
-0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
|
||||
-0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
|
||||
_ => I128
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the smallest Integer type which can represent the unsigned value.
|
||||
pub fn fit_unsigned(x: u64) -> Integer {
|
||||
match x {
|
||||
0...0x0000_0001 => I1,
|
||||
0...0x0000_00ff => I8,
|
||||
0...0x0000_ffff => I16,
|
||||
0...0xffff_ffff => I32,
|
||||
_ => I64
|
||||
0...0x0000_0000_0000_0001 => I1,
|
||||
0...0x0000_0000_0000_00ff => I8,
|
||||
0...0x0000_0000_0000_ffff => I16,
|
||||
0...0x0000_0000_ffff_ffff => I32,
|
||||
0...0xffff_ffff_ffff_ffff => I64,
|
||||
_ => I128,
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,6 +427,7 @@ impl Integer {
|
||||
attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16,
|
||||
attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32,
|
||||
attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64,
|
||||
attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128,
|
||||
attr::SignedInt(IntTy::Is) | attr::UnsignedInt(UintTy::Us) => {
|
||||
dl.ptr_sized_integer()
|
||||
}
|
||||
@ -486,6 +508,7 @@ impl Primitive {
|
||||
Int(I16) => Size::from_bits(16),
|
||||
Int(I32) | F32 => Size::from_bits(32),
|
||||
Int(I64) | F64 => Size::from_bits(64),
|
||||
Int(I128) => Size::from_bits(128),
|
||||
Pointer => dl.pointer_size
|
||||
}
|
||||
}
|
||||
@ -497,6 +520,7 @@ impl Primitive {
|
||||
Int(I16) => dl.i16_align,
|
||||
Int(I32) => dl.i32_align,
|
||||
Int(I64) => dl.i64_align,
|
||||
Int(I128) => dl.i128_align,
|
||||
F32 => dl.f32_align,
|
||||
F64 => dl.f64_align,
|
||||
Pointer => dl.pointer_align
|
||||
@ -1175,19 +1199,30 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
|
||||
if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
|
||||
// All bodies empty -> intlike
|
||||
let (mut min, mut max, mut non_zero) = (i64::MAX, i64::MIN, true);
|
||||
let (mut min, mut max, mut non_zero) = (i64::max_value(),
|
||||
i64::min_value(),
|
||||
true);
|
||||
for v in &def.variants {
|
||||
let x = v.disr_val.to_u64_unchecked() as i64;
|
||||
let x = match v.disr_val.erase_type() {
|
||||
ConstInt::InferSigned(i) => i as i64,
|
||||
ConstInt::Infer(i) => i as u64 as i64,
|
||||
_ => bug!()
|
||||
};
|
||||
if x == 0 { non_zero = false; }
|
||||
if x < min { min = x; }
|
||||
if x > max { max = x; }
|
||||
}
|
||||
|
||||
let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..], min, max);
|
||||
// FIXME: should handle i128? signed-value based impl is weird and hard to
|
||||
// grok.
|
||||
let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..],
|
||||
min,
|
||||
max);
|
||||
return success(CEnum {
|
||||
discr: discr,
|
||||
signed: signed,
|
||||
non_zero: non_zero,
|
||||
// FIXME: should be u128?
|
||||
min: min as u64,
|
||||
max: max as u64
|
||||
});
|
||||
@ -1232,7 +1267,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
// non-empty body, explicit discriminants should have
|
||||
// been rejected by a checker before this point.
|
||||
for (i, v) in def.variants.iter().enumerate() {
|
||||
if i as u64 != v.disr_val.to_u64_unchecked() {
|
||||
if i as u128 != v.disr_val.to_u128_unchecked() {
|
||||
bug!("non-C-like enum {} with specified discriminants",
|
||||
tcx.item_path_str(def.did));
|
||||
}
|
||||
|
@ -51,11 +51,13 @@ impl IntTypeExt for attr::IntType {
|
||||
SignedInt(ast::IntTy::I16) => tcx.types.i16,
|
||||
SignedInt(ast::IntTy::I32) => tcx.types.i32,
|
||||
SignedInt(ast::IntTy::I64) => tcx.types.i64,
|
||||
SignedInt(ast::IntTy::I128) => tcx.types.i128,
|
||||
SignedInt(ast::IntTy::Is) => tcx.types.isize,
|
||||
UnsignedInt(ast::UintTy::U8) => tcx.types.u8,
|
||||
UnsignedInt(ast::UintTy::U16) => tcx.types.u16,
|
||||
UnsignedInt(ast::UintTy::U32) => tcx.types.u32,
|
||||
UnsignedInt(ast::UintTy::U64) => tcx.types.u64,
|
||||
UnsignedInt(ast::UintTy::U128) => tcx.types.u128,
|
||||
UnsignedInt(ast::UintTy::Us) => tcx.types.usize,
|
||||
}
|
||||
}
|
||||
@ -66,6 +68,7 @@ impl IntTypeExt for attr::IntType {
|
||||
SignedInt(ast::IntTy::I16) => ConstInt::I16(0),
|
||||
SignedInt(ast::IntTy::I32) => ConstInt::I32(0),
|
||||
SignedInt(ast::IntTy::I64) => ConstInt::I64(0),
|
||||
SignedInt(ast::IntTy::I128) => ConstInt::I128(0),
|
||||
SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type {
|
||||
ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)),
|
||||
ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)),
|
||||
@ -76,6 +79,7 @@ impl IntTypeExt for attr::IntType {
|
||||
UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0),
|
||||
UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0),
|
||||
UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0),
|
||||
UnsignedInt(ast::UintTy::U128) => ConstInt::U128(0),
|
||||
UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type {
|
||||
ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)),
|
||||
ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)),
|
||||
@ -91,11 +95,13 @@ impl IntTypeExt for attr::IntType {
|
||||
(SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => {},
|
||||
(SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {},
|
||||
(SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {},
|
||||
(SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {},
|
||||
(SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {},
|
||||
_ => bug!("disr type mismatch: {:?} vs {:?}", self, val),
|
||||
}
|
||||
|
@ -9,11 +9,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
use super::{Target, TargetOptions};
|
||||
use super::emscripten_base::{cmd};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
let opts = TargetOptions {
|
||||
linker: "emcc".to_string(),
|
||||
ar: "emar".to_string(),
|
||||
linker: cmd("emcc"),
|
||||
ar: cmd("emar"),
|
||||
|
||||
dynamic_linking: false,
|
||||
executables: true,
|
||||
|
17
src/librustc_back/target/emscripten_base.rs
Normal file
17
src/librustc_back/target/emscripten_base.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2014-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.
|
||||
|
||||
pub fn cmd(name: &str) -> String {
|
||||
if cfg!(windows) {
|
||||
format!("{}.bat", name)
|
||||
} else {
|
||||
name.to_string()
|
||||
}
|
||||
}
|
@ -58,6 +58,7 @@ mod apple_ios_base;
|
||||
mod arm_base;
|
||||
mod bitrig_base;
|
||||
mod dragonfly_base;
|
||||
mod emscripten_base;
|
||||
mod freebsd_base;
|
||||
mod haiku_base;
|
||||
mod linux_base;
|
||||
|
@ -9,11 +9,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
use super::{Target, TargetOptions};
|
||||
use super::emscripten_base::{cmd};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
let opts = TargetOptions {
|
||||
linker: "emcc".to_string(),
|
||||
ar: "emar".to_string(),
|
||||
linker: cmd("emcc"),
|
||||
ar: cmd("emar"),
|
||||
|
||||
dynamic_linking: false,
|
||||
executables: true,
|
||||
|
@ -19,4 +19,5 @@ rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
graphviz = { path = "../libgraphviz" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
|
@ -43,6 +43,8 @@ use std::cmp::Ordering;
|
||||
use rustc_const_math::*;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
|
||||
use rustc_i128::{i128, u128};
|
||||
|
||||
macro_rules! math {
|
||||
($e:expr, $op:expr) => {
|
||||
match $op {
|
||||
@ -588,38 +590,43 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
if let hir::ExprLit(ref lit) = inner.node {
|
||||
use syntax::ast::*;
|
||||
use syntax::ast::LitIntType::*;
|
||||
const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1;
|
||||
const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1;
|
||||
const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1;
|
||||
const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1;
|
||||
const I8_OVERFLOW: u128 = i8::max_value() as u128 + 1;
|
||||
const I16_OVERFLOW: u128 = i16::max_value() as u128 + 1;
|
||||
const I32_OVERFLOW: u128 = i32::max_value() as u128 + 1;
|
||||
const I64_OVERFLOW: u128 = i64::max_value() as u128 + 1;
|
||||
const I128_OVERFLOW: u128 = i128::max_value() as u128 + 1;
|
||||
match (&lit.node, ety.map(|t| &t.sty)) {
|
||||
(&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) |
|
||||
(&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
|
||||
return Ok(Integral(I8(::std::i8::MIN)))
|
||||
return Ok(Integral(I8(i8::min_value())))
|
||||
},
|
||||
(&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) |
|
||||
(&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
|
||||
return Ok(Integral(I16(::std::i16::MIN)))
|
||||
return Ok(Integral(I16(i16::min_value())))
|
||||
},
|
||||
(&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) |
|
||||
(&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
|
||||
return Ok(Integral(I32(::std::i32::MIN)))
|
||||
return Ok(Integral(I32(i32::min_value())))
|
||||
},
|
||||
(&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) |
|
||||
(&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
|
||||
return Ok(Integral(I64(::std::i64::MIN)))
|
||||
return Ok(Integral(I64(i64::min_value())))
|
||||
},
|
||||
(&LitKind::Int(I128_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I128))) |
|
||||
(&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
|
||||
return Ok(Integral(I128(i128::min_value())))
|
||||
},
|
||||
(&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) |
|
||||
(&LitKind::Int(n, Signed(IntTy::Is)), _) => {
|
||||
match tcx.sess.target.int_type {
|
||||
IntTy::I16 => if n == I16_OVERFLOW {
|
||||
return Ok(Integral(Isize(Is16(::std::i16::MIN))));
|
||||
return Ok(Integral(Isize(Is16(i16::min_value()))));
|
||||
},
|
||||
IntTy::I32 => if n == I32_OVERFLOW {
|
||||
return Ok(Integral(Isize(Is32(::std::i32::MIN))));
|
||||
return Ok(Integral(Isize(Is32(i32::min_value()))));
|
||||
},
|
||||
IntTy::I64 => if n == I64_OVERFLOW {
|
||||
return Ok(Integral(Isize(Is64(::std::i64::MIN))));
|
||||
return Ok(Integral(Isize(Is64(i64::min_value()))));
|
||||
},
|
||||
_ => bug!(),
|
||||
}
|
||||
@ -973,26 +980,30 @@ fn infer<'a, 'tcx>(i: ConstInt,
|
||||
(&ty::TyInt(IntTy::I16), result @ I16(_)) => Ok(result),
|
||||
(&ty::TyInt(IntTy::I32), result @ I32(_)) => Ok(result),
|
||||
(&ty::TyInt(IntTy::I64), result @ I64(_)) => Ok(result),
|
||||
(&ty::TyInt(IntTy::I128), result @ I128(_)) => Ok(result),
|
||||
(&ty::TyInt(IntTy::Is), result @ Isize(_)) => Ok(result),
|
||||
|
||||
(&ty::TyUint(UintTy::U8), result @ U8(_)) => Ok(result),
|
||||
(&ty::TyUint(UintTy::U16), result @ U16(_)) => Ok(result),
|
||||
(&ty::TyUint(UintTy::U32), result @ U32(_)) => Ok(result),
|
||||
(&ty::TyUint(UintTy::U64), result @ U64(_)) => Ok(result),
|
||||
(&ty::TyUint(UintTy::U128), result @ U128(_)) => Ok(result),
|
||||
(&ty::TyUint(UintTy::Us), result @ Usize(_)) => Ok(result),
|
||||
|
||||
(&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i64 as i8)),
|
||||
(&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i64 as i16)),
|
||||
(&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i64 as i32)),
|
||||
(&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i64)),
|
||||
(&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i128 as i8)),
|
||||
(&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i128 as i16)),
|
||||
(&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i128 as i32)),
|
||||
(&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i128 as i64)),
|
||||
(&ty::TyInt(IntTy::I128), Infer(i)) => Ok(I128(i as i128)),
|
||||
(&ty::TyInt(IntTy::Is), Infer(i)) => {
|
||||
Ok(Isize(ConstIsize::new_truncating(i as i64, tcx.sess.target.int_type)))
|
||||
Ok(Isize(ConstIsize::new_truncating(i as i128, tcx.sess.target.int_type)))
|
||||
},
|
||||
|
||||
(&ty::TyInt(IntTy::I8), InferSigned(i)) => Ok(I8(i as i8)),
|
||||
(&ty::TyInt(IntTy::I16), InferSigned(i)) => Ok(I16(i as i16)),
|
||||
(&ty::TyInt(IntTy::I32), InferSigned(i)) => Ok(I32(i as i32)),
|
||||
(&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i)),
|
||||
(&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i as i64)),
|
||||
(&ty::TyInt(IntTy::I128), InferSigned(i)) => Ok(I128(i)),
|
||||
(&ty::TyInt(IntTy::Is), InferSigned(i)) => {
|
||||
Ok(Isize(ConstIsize::new_truncating(i, tcx.sess.target.int_type)))
|
||||
},
|
||||
@ -1000,7 +1011,8 @@ fn infer<'a, 'tcx>(i: ConstInt,
|
||||
(&ty::TyUint(UintTy::U8), Infer(i)) => Ok(U8(i as u8)),
|
||||
(&ty::TyUint(UintTy::U16), Infer(i)) => Ok(U16(i as u16)),
|
||||
(&ty::TyUint(UintTy::U32), Infer(i)) => Ok(U32(i as u32)),
|
||||
(&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i)),
|
||||
(&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i as u64)),
|
||||
(&ty::TyUint(UintTy::U128), Infer(i)) => Ok(U128(i)),
|
||||
(&ty::TyUint(UintTy::Us), Infer(i)) => {
|
||||
Ok(Usize(ConstUsize::new_truncating(i, tcx.sess.target.uint_type)))
|
||||
},
|
||||
@ -1071,21 +1083,23 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(
|
||||
}
|
||||
|
||||
fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::Ty) -> CastResult {
|
||||
let v = val.to_u64_unchecked();
|
||||
let v = val.to_u128_unchecked();
|
||||
match ty.sty {
|
||||
ty::TyBool if v == 0 => Ok(Bool(false)),
|
||||
ty::TyBool if v == 1 => Ok(Bool(true)),
|
||||
ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i64 as i8))),
|
||||
ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i64 as i16))),
|
||||
ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i64 as i32))),
|
||||
ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i64))),
|
||||
ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i128 as i8))),
|
||||
ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i128 as i16))),
|
||||
ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i128 as i32))),
|
||||
ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i128 as i64))),
|
||||
ty::TyInt(ast::IntTy::I128) => Ok(Integral(I128(v as i128))),
|
||||
ty::TyInt(ast::IntTy::Is) => {
|
||||
Ok(Integral(Isize(ConstIsize::new_truncating(v as i64, tcx.sess.target.int_type))))
|
||||
Ok(Integral(Isize(ConstIsize::new_truncating(v as i128, tcx.sess.target.int_type))))
|
||||
},
|
||||
ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))),
|
||||
ty::TyUint(ast::UintTy::U16) => Ok(Integral(U16(v as u16))),
|
||||
ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))),
|
||||
ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v))),
|
||||
ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))),
|
||||
ty::TyUint(ast::UintTy::U128) => Ok(Integral(U128(v as u128))),
|
||||
ty::TyUint(ast::UintTy::Us) => {
|
||||
Ok(Integral(Usize(ConstUsize::new_truncating(v, tcx.sess.target.uint_type))))
|
||||
},
|
||||
@ -1115,13 +1129,13 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
match ty.sty {
|
||||
ty::TyInt(_) | ty::TyUint(_) => {
|
||||
let i = match val {
|
||||
F32(f) if f >= 0.0 => Infer(f as u64),
|
||||
F32(f) if f >= 0.0 => Infer(f as u128),
|
||||
FInfer { f64: f, .. } |
|
||||
F64(f) if f >= 0.0 => Infer(f as u64),
|
||||
F64(f) if f >= 0.0 => Infer(f as u128),
|
||||
|
||||
F32(f) => InferSigned(f as i64),
|
||||
F32(f) => InferSigned(f as i128),
|
||||
FInfer { f64: f, .. } |
|
||||
F64(f) => InferSigned(f as i64)
|
||||
F64(f) => InferSigned(f as i128)
|
||||
};
|
||||
|
||||
if let (InferSigned(_), &ty::TyUint(_)) = (i, &ty.sty) {
|
||||
@ -1145,9 +1159,9 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult {
|
||||
match val {
|
||||
Integral(i) => cast_const_int(tcx, i, ty),
|
||||
Bool(b) => cast_const_int(tcx, Infer(b as u64), ty),
|
||||
Bool(b) => cast_const_int(tcx, Infer(b as u128), ty),
|
||||
Float(f) => cast_const_float(tcx, f, ty),
|
||||
Char(c) => cast_const_int(tcx, Infer(c as u64), ty),
|
||||
Char(c) => cast_const_int(tcx, Infer(c as u128), ty),
|
||||
Function(_) => Err(UnimplementedConstVal("casting fn pointers")),
|
||||
ByteStr(b) => match ty.sty {
|
||||
ty::TyRawPtr(_) => {
|
||||
@ -1185,28 +1199,29 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
|
||||
LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
|
||||
LitKind::Byte(n) => Ok(Integral(U8(n))),
|
||||
LitKind::Int(n, Signed(ity)) => {
|
||||
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral)
|
||||
infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral)
|
||||
},
|
||||
|
||||
// FIXME: this should become u128.
|
||||
LitKind::Int(n, Unsuffixed) => {
|
||||
match ty_hint.map(|t| &t.sty) {
|
||||
Some(&ty::TyInt(ity)) => {
|
||||
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral)
|
||||
infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral)
|
||||
},
|
||||
Some(&ty::TyUint(uty)) => {
|
||||
infer(Infer(n), tcx, &ty::TyUint(uty)).map(Integral)
|
||||
infer(Infer(n as u128), tcx, &ty::TyUint(uty)).map(Integral)
|
||||
},
|
||||
None => Ok(Integral(Infer(n))),
|
||||
None => Ok(Integral(Infer(n as u128))),
|
||||
Some(&ty::TyAdt(adt, _)) => {
|
||||
let hints = tcx.lookup_repr_hints(adt.did);
|
||||
let int_ty = tcx.enum_repr_type(hints.iter().next());
|
||||
infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty).map(Integral)
|
||||
infer(Infer(n as u128), tcx, &int_ty.to_ty(tcx).sty).map(Integral)
|
||||
},
|
||||
Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
|
||||
}
|
||||
},
|
||||
LitKind::Int(n, Unsigned(ity)) => {
|
||||
infer(Infer(n), tcx, &ty::TyUint(ity)).map(Integral)
|
||||
infer(Infer(n as u128), tcx, &ty::TyUint(ity)).map(Integral)
|
||||
},
|
||||
|
||||
LitKind::Float(n, fty) => {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_fn)]
|
||||
|
||||
extern crate arena;
|
||||
#[macro_use] extern crate syntax;
|
||||
@ -41,6 +42,8 @@ extern crate graphviz;
|
||||
extern crate syntax_pos;
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
extern crate rustc_i128;
|
||||
|
||||
// NB: This module needs to be declared first so diagnostics are
|
||||
// registered before they are used.
|
||||
pub mod diagnostics;
|
||||
|
@ -12,3 +12,4 @@ crate-type = ["dylib"]
|
||||
log = { path = "../liblog" }
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
|
@ -74,11 +74,13 @@ impl ConstMathErr {
|
||||
ULitOutOfRange(ast::UintTy::U16) => "literal out of range for u16",
|
||||
ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32",
|
||||
ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64",
|
||||
ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128",
|
||||
ULitOutOfRange(ast::UintTy::Us) => "literal out of range for usize",
|
||||
LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8",
|
||||
LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16",
|
||||
LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32",
|
||||
LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64",
|
||||
LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128",
|
||||
LitOutOfRange(ast::IntTy::Is) => "literal out of range for isize",
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
use std::cmp::Ordering;
|
||||
use syntax::attr::IntType;
|
||||
use syntax::ast::{IntTy, UintTy};
|
||||
use rustc_i128::{i128, u128};
|
||||
|
||||
use super::is::*;
|
||||
use super::us::*;
|
||||
@ -22,45 +23,98 @@ pub enum ConstInt {
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
I128(i128),
|
||||
Isize(ConstIsize),
|
||||
U8(u8),
|
||||
U16(u16),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
U128(u128),
|
||||
Usize(ConstUsize),
|
||||
Infer(u64),
|
||||
InferSigned(i64),
|
||||
Infer(u128),
|
||||
InferSigned(i128),
|
||||
}
|
||||
pub use self::ConstInt::*;
|
||||
|
||||
|
||||
macro_rules! bounds {
|
||||
($($t:ident $min:ident $max:ident)*) => {
|
||||
mod as_u64 {
|
||||
$(
|
||||
#[allow(dead_code)]
|
||||
pub const $min: u64 = ::std::$t::MIN as u64;
|
||||
#[allow(dead_code)]
|
||||
pub const $max: u64 = ::std::$t::MAX as u64;
|
||||
)*
|
||||
}
|
||||
mod as_i64 {
|
||||
$(
|
||||
#[allow(dead_code)]
|
||||
pub const $min: i64 = ::std::$t::MIN as i64;
|
||||
#[allow(dead_code)]
|
||||
pub const $max: i64 = ::std::$t::MAX as i64;
|
||||
)*
|
||||
}
|
||||
($ct: ty, $($t:ident $min:ident $max:ident)*) => {
|
||||
$(
|
||||
pub const $min: $ct = $t::min_value() as $ct;
|
||||
pub const $max: $ct = $t::max_value() as $ct;
|
||||
)*
|
||||
};
|
||||
($ct: ty: $min_val: expr, $($t:ident $min:ident $max:ident)*) => {
|
||||
$(
|
||||
pub const $min: $ct = $min_val;
|
||||
pub const $max: $ct = $t::max_value() as $ct;
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
bounds!{
|
||||
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX isize IMIN IMAX
|
||||
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX usize UMIN UMAX
|
||||
mod ubounds {
|
||||
#![allow(dead_code)]
|
||||
use rustc_i128::{u128, i128};
|
||||
bounds!{u128: 0,
|
||||
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
|
||||
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX
|
||||
// do not add constants for isize/usize, because these are guaranteed to be wrong for
|
||||
// arbitrary host/target combinations
|
||||
}
|
||||
}
|
||||
|
||||
mod ibounds {
|
||||
#![allow(dead_code)]
|
||||
use rustc_i128::i128;
|
||||
#[cfg(stage0)]
|
||||
pub const U64MIN: i128 = 0;
|
||||
#[cfg(stage0)]
|
||||
pub const U64MAX: i128 = i128::max_value();
|
||||
#[cfg(not(stage0))]
|
||||
bounds!(i128, u64 U64MIN U64MAX);
|
||||
|
||||
pub const U128MIN: i128 = 0;
|
||||
pub const U128MAX: i128 = i128::max_value();
|
||||
|
||||
bounds!{i128,
|
||||
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
|
||||
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX
|
||||
// do not add constants for isize/usize, because these are guaranteed to be wrong for
|
||||
// arbitrary host/target combinations
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstInt {
|
||||
/// Creates a new unsigned ConstInt with matching type while also checking that overflow does
|
||||
/// not happen.
|
||||
pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option<ConstInt> {
|
||||
match ty {
|
||||
UintTy::U8 if val <= ubounds::U8MAX => Some(U8(val as u8)),
|
||||
UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)),
|
||||
UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)),
|
||||
UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)),
|
||||
UintTy::Us if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
|
||||
.map(Usize),
|
||||
UintTy::U128 => Some(U128(val)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new unsigned ConstInt with matching type while also checking that overflow does
|
||||
/// not happen.
|
||||
pub fn new_signed(val: i128, ty: IntTy, isize_ty: IntTy) -> Option<ConstInt> {
|
||||
match ty {
|
||||
IntTy::I8 if val <= ibounds::I8MAX => Some(I8(val as i8)),
|
||||
IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)),
|
||||
IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)),
|
||||
IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)),
|
||||
IntTy::Is if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
|
||||
.map(Isize),
|
||||
IntTy::I128 => Some(I128(val)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// If either value is `Infer` or `InferSigned`, try to turn the value into the type of
|
||||
/// the other value. If both values have no type, don't do anything
|
||||
pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> {
|
||||
@ -68,46 +122,54 @@ impl ConstInt {
|
||||
(InferSigned(_), InferSigned(_))
|
||||
| (Infer(_), Infer(_)) => self, // no inference possible
|
||||
// kindof wrong, you could have had values > I64MAX during computation of a
|
||||
(Infer(a @ 0...as_u64::I64MAX), InferSigned(_)) => InferSigned(a as i64),
|
||||
(Infer(a @ 0...ubounds::I64MAX), InferSigned(_)) => InferSigned(a as i128),
|
||||
(Infer(_), InferSigned(_)) => return Err(ConstMathErr::NotInRange),
|
||||
(_, InferSigned(_))
|
||||
| (_, Infer(_)) => return other.infer(self).map(|(b, a)| (a, b)),
|
||||
|
||||
(Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i64 as i8),
|
||||
(Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i64 as i16),
|
||||
(Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i64 as i32),
|
||||
(Infer(a @ 0...as_u64::I64MAX), I64(_)) => I64(a as i64),
|
||||
(Infer(a @ 0...as_u64::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)),
|
||||
(Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
|
||||
(Infer(a @ 0...as_u64::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
|
||||
(Infer(a @ 0...as_u64::U8MAX), U8(_)) => U8(a as u8),
|
||||
(Infer(a @ 0...as_u64::U16MAX), U16(_)) => U16(a as u16),
|
||||
(Infer(a @ 0...as_u64::U32MAX), U32(_)) => U32(a as u32),
|
||||
(Infer(a), U64(_)) => U64(a),
|
||||
(Infer(a @ 0...as_u64::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
|
||||
(Infer(a @ 0...as_u64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
|
||||
(Infer(a), Usize(Us64(_))) => Usize(Us64(a)),
|
||||
(Infer(a @ 0...ubounds::I8MAX), I8(_)) => I8(a as i64 as i8),
|
||||
(Infer(a @ 0...ubounds::I16MAX), I16(_)) => I16(a as i64 as i16),
|
||||
(Infer(a @ 0...ubounds::I32MAX), I32(_)) => I32(a as i64 as i32),
|
||||
(Infer(a @ 0...ubounds::I64MAX), I64(_)) => I64(a as i64),
|
||||
(Infer(a @ 0...ubounds::I128MAX), I128(_)) => I128(a as i128),
|
||||
(Infer(a @ 0...ubounds::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)),
|
||||
(Infer(a @ 0...ubounds::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
|
||||
(Infer(a @ 0...ubounds::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
|
||||
(Infer(a @ 0...ubounds::U8MAX), U8(_)) => U8(a as u8),
|
||||
(Infer(a @ 0...ubounds::U16MAX), U16(_)) => U16(a as u16),
|
||||
(Infer(a @ 0...ubounds::U32MAX), U32(_)) => U32(a as u32),
|
||||
(Infer(a @ 0...ubounds::U64MAX), U64(_)) => U64(a as u64),
|
||||
(Infer(a @ 0...ubounds::U128MAX), U128(_)) => U128(a as u128),
|
||||
(Infer(a @ 0...ubounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
|
||||
(Infer(a @ 0...ubounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
|
||||
(Infer(a @ 0...ubounds::U64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
|
||||
|
||||
(Infer(_), _) => return Err(ConstMathErr::NotInRange),
|
||||
|
||||
(InferSigned(a @ as_i64::I8MIN...as_i64::I8MAX), I8(_)) => I8(a as i8),
|
||||
(InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), I16(_)) => I16(a as i16),
|
||||
(InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), I32(_)) => I32(a as i32),
|
||||
(InferSigned(a), I64(_)) => I64(a),
|
||||
(InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), Isize(Is16(_))) => {
|
||||
(InferSigned(a @ ibounds::I8MIN...ibounds::I8MAX), I8(_)) => I8(a as i8),
|
||||
(InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), I16(_)) => I16(a as i16),
|
||||
(InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), I32(_)) => I32(a as i32),
|
||||
(InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), I64(_)) => I64(a as i64),
|
||||
(InferSigned(a @ ibounds::I128MIN...ibounds::I128MAX), I128(_)) => I128(a as i128),
|
||||
(InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), Isize(Is16(_))) => {
|
||||
Isize(Is16(a as i16))
|
||||
},
|
||||
(InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), Isize(Is32(_))) => {
|
||||
(InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), Isize(Is32(_))) => {
|
||||
Isize(Is32(a as i32))
|
||||
},
|
||||
(InferSigned(a), Isize(Is64(_))) => Isize(Is64(a)),
|
||||
(InferSigned(a @ 0...as_i64::U8MAX), U8(_)) => U8(a as u8),
|
||||
(InferSigned(a @ 0...as_i64::U16MAX), U16(_)) => U16(a as u16),
|
||||
(InferSigned(a @ 0...as_i64::U32MAX), U32(_)) => U32(a as u32),
|
||||
(InferSigned(a @ 0...as_i64::I64MAX), U64(_)) => U64(a as u64),
|
||||
(InferSigned(a @ 0...as_i64::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
|
||||
(InferSigned(a @ 0...as_i64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
|
||||
(InferSigned(a @ 0...as_i64::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
|
||||
(InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), Isize(Is64(_))) => {
|
||||
Isize(Is64(a as i64))
|
||||
},
|
||||
(InferSigned(a @ 0...ibounds::U8MAX), U8(_)) => U8(a as u8),
|
||||
(InferSigned(a @ 0...ibounds::U16MAX), U16(_)) => U16(a as u16),
|
||||
(InferSigned(a @ 0...ibounds::U32MAX), U32(_)) => U32(a as u32),
|
||||
// SNAP: replace with U64MAX
|
||||
(InferSigned(a @ 0...ibounds::I64MAX), U64(_)) => U64(a as u64),
|
||||
(InferSigned(a @ 0...ibounds::I128MAX), U128(_)) => U128(a as u128),
|
||||
(InferSigned(a @ 0...ibounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
|
||||
(InferSigned(a @ 0...ibounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
|
||||
// SNAP: replace with U64MAX
|
||||
(InferSigned(a @ 0...ibounds::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
|
||||
(InferSigned(_), _) => return Err(ConstMathErr::NotInRange),
|
||||
_ => self, // already known types
|
||||
};
|
||||
@ -119,28 +181,31 @@ impl ConstInt {
|
||||
match self {
|
||||
Infer(i) => Infer(i),
|
||||
InferSigned(i) if i < 0 => InferSigned(i),
|
||||
I8(i) if i < 0 => InferSigned(i as i64),
|
||||
I16(i) if i < 0 => InferSigned(i as i64),
|
||||
I32(i) if i < 0 => InferSigned(i as i64),
|
||||
I64(i) if i < 0 => InferSigned(i as i64),
|
||||
Isize(Is16(i)) if i < 0 => InferSigned(i as i64),
|
||||
Isize(Is32(i)) if i < 0 => InferSigned(i as i64),
|
||||
Isize(Is64(i)) if i < 0 => InferSigned(i as i64),
|
||||
InferSigned(i) => Infer(i as u64),
|
||||
I8(i) => Infer(i as u64),
|
||||
I16(i) => Infer(i as u64),
|
||||
I32(i) => Infer(i as u64),
|
||||
I64(i) => Infer(i as u64),
|
||||
Isize(Is16(i)) => Infer(i as u64),
|
||||
Isize(Is32(i)) => Infer(i as u64),
|
||||
Isize(Is64(i)) => Infer(i as u64),
|
||||
U8(i) => Infer(i as u64),
|
||||
U16(i) => Infer(i as u64),
|
||||
U32(i) => Infer(i as u64),
|
||||
U64(i) => Infer(i as u64),
|
||||
Usize(Us16(i)) => Infer(i as u64),
|
||||
Usize(Us32(i)) => Infer(i as u64),
|
||||
Usize(Us64(i)) => Infer(i),
|
||||
I8(i) if i < 0 => InferSigned(i as i128),
|
||||
I16(i) if i < 0 => InferSigned(i as i128),
|
||||
I32(i) if i < 0 => InferSigned(i as i128),
|
||||
I64(i) if i < 0 => InferSigned(i as i128),
|
||||
I128(i) if i < 0 => InferSigned(i as i128),
|
||||
Isize(Is16(i)) if i < 0 => InferSigned(i as i128),
|
||||
Isize(Is32(i)) if i < 0 => InferSigned(i as i128),
|
||||
Isize(Is64(i)) if i < 0 => InferSigned(i as i128),
|
||||
InferSigned(i) => Infer(i as u128),
|
||||
I8(i) => Infer(i as u128),
|
||||
I16(i) => Infer(i as u128),
|
||||
I32(i) => Infer(i as u128),
|
||||
I64(i) => Infer(i as u128),
|
||||
I128(i) => Infer(i as u128),
|
||||
Isize(Is16(i)) => Infer(i as u128),
|
||||
Isize(Is32(i)) => Infer(i as u128),
|
||||
Isize(Is64(i)) => Infer(i as u128),
|
||||
U8(i) => Infer(i as u128),
|
||||
U16(i) => Infer(i as u128),
|
||||
U32(i) => Infer(i as u128),
|
||||
U64(i) => Infer(i as u128),
|
||||
U128(i) => Infer(i as u128),
|
||||
Usize(Us16(i)) => Infer(i as u128),
|
||||
Usize(Us32(i)) => Infer(i as u128),
|
||||
Usize(Us64(i)) => Infer(i as u128),
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,67 +218,66 @@ impl ConstInt {
|
||||
I16(_) => "i16",
|
||||
I32(_) => "i32",
|
||||
I64(_) => "i64",
|
||||
I128(_) => "i128",
|
||||
Isize(_) => "isize",
|
||||
U8(_) => "u8",
|
||||
U16(_) => "u16",
|
||||
U32(_) => "u32",
|
||||
U64(_) => "u64",
|
||||
U128(_) => "u128",
|
||||
Usize(_) => "usize",
|
||||
}
|
||||
}
|
||||
|
||||
/// Erases the type and returns a u64.
|
||||
/// This is not the same as `-5i8 as u64` but as `-5i8 as i64 as u64`
|
||||
pub fn to_u64_unchecked(self) -> u64 {
|
||||
/// Erases the type and returns a u128.
|
||||
/// This is not the same as `-5i8 as u128` but as `-5i8 as i128 as u128`
|
||||
pub fn to_u128_unchecked(self) -> u128 {
|
||||
match self.erase_type() {
|
||||
ConstInt::Infer(i) => i,
|
||||
ConstInt::InferSigned(i) => i as u64,
|
||||
ConstInt::InferSigned(i) => i as u128,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the value to a `u32` if it's in the range 0...std::u32::MAX
|
||||
pub fn to_u32(&self) -> Option<u32> {
|
||||
match *self {
|
||||
I8(v) if v >= 0 => Some(v as u32),
|
||||
I16(v) if v >= 0 => Some(v as u32),
|
||||
I32(v) if v >= 0 => Some(v as u32),
|
||||
InferSigned(v)
|
||||
| Isize(Is64(v))
|
||||
| I64(v) if v >= 0 && v <= ::std::u32::MAX as i64 => Some(v as u32),
|
||||
Isize(Is32(v)) if v >= 0 => Some(v as u32),
|
||||
Isize(Is16(v)) if v >= 0 => Some(v as u32),
|
||||
U8(v) => Some(v as u32),
|
||||
U16(v) => Some(v as u32),
|
||||
U32(v) => Some(v),
|
||||
Infer(v)
|
||||
| Usize(Us64(v))
|
||||
| U64(v) if v <= ::std::u32::MAX as u64 => Some(v as u32),
|
||||
Usize(Us32(v)) => Some(v),
|
||||
Usize(Us16(v)) => Some(v as u32),
|
||||
_ => None,
|
||||
}
|
||||
self.to_u128().and_then(|v| if v <= u32::max_value() as u128 {
|
||||
Some(v as u32)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts the value to a `u64` if it's >= 0
|
||||
/// Converts the value to a `u64` if it's in the range 0...std::u64::MAX
|
||||
pub fn to_u64(&self) -> Option<u64> {
|
||||
self.to_u128().and_then(|v| if v <= u64::max_value() as u128 {
|
||||
Some(v as u64)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts the value to a `u128` if it's in the range 0...std::u128::MAX
|
||||
pub fn to_u128(&self) -> Option<u128> {
|
||||
match *self {
|
||||
Infer(v) => Some(v),
|
||||
InferSigned(v) if v >= 0 => Some(v as u64),
|
||||
I8(v) if v >= 0 => Some(v as u64),
|
||||
I16(v) if v >= 0 => Some(v as u64),
|
||||
I32(v) if v >= 0 => Some(v as u64),
|
||||
I64(v) if v >= 0 => Some(v as u64),
|
||||
Isize(Is16(v)) if v >= 0 => Some(v as u64),
|
||||
Isize(Is32(v)) if v >= 0 => Some(v as u64),
|
||||
Isize(Is64(v)) if v >= 0 => Some(v as u64),
|
||||
U8(v) => Some(v as u64),
|
||||
U16(v) => Some(v as u64),
|
||||
U32(v) => Some(v as u64),
|
||||
U64(v) => Some(v),
|
||||
Usize(Us16(v)) => Some(v as u64),
|
||||
Usize(Us32(v)) => Some(v as u64),
|
||||
Usize(Us64(v)) => Some(v),
|
||||
InferSigned(v) if v >= 0 => Some(v as u128),
|
||||
I8(v) if v >= 0 => Some(v as u128),
|
||||
I16(v) if v >= 0 => Some(v as u128),
|
||||
I32(v) if v >= 0 => Some(v as u128),
|
||||
I64(v) if v >= 0 => Some(v as u128),
|
||||
I128(v) if v >= 0 => Some(v as u128),
|
||||
Isize(Is16(v)) if v >= 0 => Some(v as u128),
|
||||
Isize(Is32(v)) if v >= 0 => Some(v as u128),
|
||||
Isize(Is64(v)) if v >= 0 => Some(v as u128),
|
||||
U8(v) => Some(v as u128),
|
||||
U16(v) => Some(v as u128),
|
||||
U32(v) => Some(v as u128),
|
||||
U64(v) => Some(v as u128),
|
||||
U128(v) => Some(v as u128),
|
||||
Usize(Us16(v)) => Some(v as u128),
|
||||
Usize(Us32(v)) => Some(v as u128),
|
||||
Usize(Us64(v)) => Some(v as u128),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -224,6 +288,7 @@ impl ConstInt {
|
||||
I16(v) => v < 0,
|
||||
I32(v) => v < 0,
|
||||
I64(v) => v < 0,
|
||||
I128(v) => v < 0,
|
||||
Isize(Is16(v)) => v < 0,
|
||||
Isize(Is32(v)) => v < 0,
|
||||
Isize(Is64(v)) => v < 0,
|
||||
@ -239,6 +304,7 @@ impl ConstInt {
|
||||
(I16(a), I16(b)) => Ok(a.cmp(&b)),
|
||||
(I32(a), I32(b)) => Ok(a.cmp(&b)),
|
||||
(I64(a), I64(b)) => Ok(a.cmp(&b)),
|
||||
(I128(a), I128(b)) => Ok(a.cmp(&b)),
|
||||
(Isize(Is16(a)), Isize(Is16(b))) => Ok(a.cmp(&b)),
|
||||
(Isize(Is32(a)), Isize(Is32(b))) => Ok(a.cmp(&b)),
|
||||
(Isize(Is64(a)), Isize(Is64(b))) => Ok(a.cmp(&b)),
|
||||
@ -246,6 +312,7 @@ impl ConstInt {
|
||||
(U16(a), U16(b)) => Ok(a.cmp(&b)),
|
||||
(U32(a), U32(b)) => Ok(a.cmp(&b)),
|
||||
(U64(a), U64(b)) => Ok(a.cmp(&b)),
|
||||
(U128(a), U128(b)) => Ok(a.cmp(&b)),
|
||||
(Usize(Us16(a)), Usize(Us16(b))) => Ok(a.cmp(&b)),
|
||||
(Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)),
|
||||
(Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)),
|
||||
@ -265,6 +332,7 @@ impl ConstInt {
|
||||
ConstInt::I16(i) => ConstInt::I16(add1!(i)),
|
||||
ConstInt::I32(i) => ConstInt::I32(add1!(i)),
|
||||
ConstInt::I64(i) => ConstInt::I64(add1!(i)),
|
||||
ConstInt::I128(i) => ConstInt::I128(add1!(i)),
|
||||
ConstInt::Isize(ConstIsize::Is16(i)) => ConstInt::Isize(ConstIsize::Is16(add1!(i))),
|
||||
ConstInt::Isize(ConstIsize::Is32(i)) => ConstInt::Isize(ConstIsize::Is32(add1!(i))),
|
||||
ConstInt::Isize(ConstIsize::Is64(i)) => ConstInt::Isize(ConstIsize::Is64(add1!(i))),
|
||||
@ -272,6 +340,7 @@ impl ConstInt {
|
||||
ConstInt::U16(i) => ConstInt::U16(add1!(i)),
|
||||
ConstInt::U32(i) => ConstInt::U32(add1!(i)),
|
||||
ConstInt::U64(i) => ConstInt::U64(add1!(i)),
|
||||
ConstInt::U128(i) => ConstInt::U128(add1!(i)),
|
||||
ConstInt::Usize(ConstUsize::Us16(i)) => ConstInt::Usize(ConstUsize::Us16(add1!(i))),
|
||||
ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))),
|
||||
ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))),
|
||||
@ -285,11 +354,13 @@ impl ConstInt {
|
||||
ConstInt::I16(_) => Some(IntType::SignedInt(IntTy::I16)),
|
||||
ConstInt::I32(_) => Some(IntType::SignedInt(IntTy::I32)),
|
||||
ConstInt::I64(_) => Some(IntType::SignedInt(IntTy::I64)),
|
||||
ConstInt::I128(_) => Some(IntType::SignedInt(IntTy::I128)),
|
||||
ConstInt::Isize(_) => Some(IntType::SignedInt(IntTy::Is)),
|
||||
ConstInt::U8(_) => Some(IntType::UnsignedInt(UintTy::U8)),
|
||||
ConstInt::U16(_) => Some(IntType::UnsignedInt(UintTy::U16)),
|
||||
ConstInt::U32(_) => Some(IntType::UnsignedInt(UintTy::U32)),
|
||||
ConstInt::U64(_) => Some(IntType::UnsignedInt(UintTy::U64)),
|
||||
ConstInt::U128(_) => Some(IntType::UnsignedInt(UintTy::U128)),
|
||||
ConstInt::Usize(_) => Some(IntType::UnsignedInt(UintTy::Us)),
|
||||
_ => None,
|
||||
}
|
||||
@ -317,6 +388,7 @@ impl ::std::fmt::Display for ConstInt {
|
||||
I16(i) => write!(fmt, "{}i16", i),
|
||||
I32(i) => write!(fmt, "{}i32", i),
|
||||
I64(i) => write!(fmt, "{}i64", i),
|
||||
I128(i) => write!(fmt, "{}i128", i),
|
||||
Isize(ConstIsize::Is64(i)) => write!(fmt, "{}isize", i),
|
||||
Isize(ConstIsize::Is32(i)) => write!(fmt, "{}isize", i),
|
||||
Isize(ConstIsize::Is16(i)) => write!(fmt, "{}isize", i),
|
||||
@ -324,6 +396,7 @@ impl ::std::fmt::Display for ConstInt {
|
||||
U16(i) => write!(fmt, "{}u16", i),
|
||||
U32(i) => write!(fmt, "{}u32", i),
|
||||
U64(i) => write!(fmt, "{}u64", i),
|
||||
U128(i) => write!(fmt, "{}u128", i),
|
||||
Usize(ConstUsize::Us64(i)) => write!(fmt, "{}usize", i),
|
||||
Usize(ConstUsize::Us32(i)) => write!(fmt, "{}usize", i),
|
||||
Usize(ConstUsize::Us16(i)) => write!(fmt, "{}usize", i),
|
||||
@ -351,6 +424,7 @@ macro_rules! impl_binop {
|
||||
(I16(a), I16(b)) => a.$checked_func(b).map(I16),
|
||||
(I32(a), I32(b)) => a.$checked_func(b).map(I32),
|
||||
(I64(a), I64(b)) => a.$checked_func(b).map(I64),
|
||||
(I128(a), I128(b)) => a.$checked_func(b).map(I128),
|
||||
(Isize(Is16(a)), Isize(Is16(b))) => a.$checked_func(b).map(Is16).map(Isize),
|
||||
(Isize(Is32(a)), Isize(Is32(b))) => a.$checked_func(b).map(Is32).map(Isize),
|
||||
(Isize(Is64(a)), Isize(Is64(b))) => a.$checked_func(b).map(Is64).map(Isize),
|
||||
@ -358,6 +432,7 @@ macro_rules! impl_binop {
|
||||
(U16(a), U16(b)) => a.$checked_func(b).map(U16),
|
||||
(U32(a), U32(b)) => a.$checked_func(b).map(U32),
|
||||
(U64(a), U64(b)) => a.$checked_func(b).map(U64),
|
||||
(U128(a), U128(b)) => a.$checked_func(b).map(U128),
|
||||
(Usize(Us16(a)), Usize(Us16(b))) => a.$checked_func(b).map(Us16).map(Usize),
|
||||
(Usize(Us32(a)), Usize(Us32(b))) => a.$checked_func(b).map(Us32).map(Usize),
|
||||
(Usize(Us64(a)), Usize(Us64(b))) => a.$checked_func(b).map(Us64).map(Usize),
|
||||
@ -380,6 +455,7 @@ macro_rules! derive_binop {
|
||||
(I16(a), I16(b)) => Ok(I16(a.$func(b))),
|
||||
(I32(a), I32(b)) => Ok(I32(a.$func(b))),
|
||||
(I64(a), I64(b)) => Ok(I64(a.$func(b))),
|
||||
(I128(a), I128(b)) => Ok(I128(a.$func(b))),
|
||||
(Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a.$func(b)))),
|
||||
(Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a.$func(b)))),
|
||||
(Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a.$func(b)))),
|
||||
@ -387,6 +463,7 @@ macro_rules! derive_binop {
|
||||
(U16(a), U16(b)) => Ok(U16(a.$func(b))),
|
||||
(U32(a), U32(b)) => Ok(U32(a.$func(b))),
|
||||
(U64(a), U64(b)) => Ok(U64(a.$func(b))),
|
||||
(U128(a), U128(b)) => Ok(U128(a.$func(b))),
|
||||
(Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a.$func(b)))),
|
||||
(Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a.$func(b)))),
|
||||
(Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a.$func(b)))),
|
||||
@ -406,6 +483,11 @@ derive_binop!(BitAnd, bitand);
|
||||
derive_binop!(BitOr, bitor);
|
||||
derive_binop!(BitXor, bitxor);
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
const I128_MIN: i128 = ::std::i128::MIN;
|
||||
#[cfg(stage0)]
|
||||
const I128_MIN: i128 = ::std::i64::MIN;
|
||||
|
||||
fn check_division(
|
||||
lhs: ConstInt,
|
||||
rhs: ConstInt,
|
||||
@ -417,6 +499,7 @@ fn check_division(
|
||||
(I16(_), I16(0)) => Err(zerr),
|
||||
(I32(_), I32(0)) => Err(zerr),
|
||||
(I64(_), I64(0)) => Err(zerr),
|
||||
(I128(_), I128(0)) => Err(zerr),
|
||||
(Isize(_), Isize(Is16(0))) => Err(zerr),
|
||||
(Isize(_), Isize(Is32(0))) => Err(zerr),
|
||||
(Isize(_), Isize(Is64(0))) => Err(zerr),
|
||||
@ -426,6 +509,7 @@ fn check_division(
|
||||
(U16(_), U16(0)) => Err(zerr),
|
||||
(U32(_), U32(0)) => Err(zerr),
|
||||
(U64(_), U64(0)) => Err(zerr),
|
||||
(U128(_), U128(0)) => Err(zerr),
|
||||
(Usize(_), Usize(Us16(0))) => Err(zerr),
|
||||
(Usize(_), Usize(Us32(0))) => Err(zerr),
|
||||
(Usize(_), Usize(Us64(0))) => Err(zerr),
|
||||
@ -435,10 +519,11 @@ fn check_division(
|
||||
(I16(::std::i16::MIN), I16(-1)) => Err(Overflow(op)),
|
||||
(I32(::std::i32::MIN), I32(-1)) => Err(Overflow(op)),
|
||||
(I64(::std::i64::MIN), I64(-1)) => Err(Overflow(op)),
|
||||
(I128(I128_MIN), I128(-1)) => Err(Overflow(op)),
|
||||
(Isize(Is16(::std::i16::MIN)), Isize(Is16(-1))) => Err(Overflow(op)),
|
||||
(Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)),
|
||||
(Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)),
|
||||
(InferSigned(::std::i64::MIN), InferSigned(-1)) => Err(Overflow(op)),
|
||||
(InferSigned(I128_MIN), InferSigned(-1)) => Err(Overflow(op)),
|
||||
|
||||
_ => Ok(()),
|
||||
}
|
||||
@ -454,6 +539,7 @@ impl ::std::ops::Div for ConstInt {
|
||||
(I16(a), I16(b)) => Ok(I16(a/b)),
|
||||
(I32(a), I32(b)) => Ok(I32(a/b)),
|
||||
(I64(a), I64(b)) => Ok(I64(a/b)),
|
||||
(I128(a), I128(b)) => Ok(I128(a/b)),
|
||||
(Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a/b))),
|
||||
(Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))),
|
||||
(Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))),
|
||||
@ -463,6 +549,7 @@ impl ::std::ops::Div for ConstInt {
|
||||
(U16(a), U16(b)) => Ok(U16(a/b)),
|
||||
(U32(a), U32(b)) => Ok(U32(a/b)),
|
||||
(U64(a), U64(b)) => Ok(U64(a/b)),
|
||||
(U128(a), U128(b)) => Ok(U128(a/b)),
|
||||
(Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a/b))),
|
||||
(Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))),
|
||||
(Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))),
|
||||
@ -484,6 +571,7 @@ impl ::std::ops::Rem for ConstInt {
|
||||
(I16(a), I16(b)) => Ok(I16(a%b)),
|
||||
(I32(a), I32(b)) => Ok(I32(a%b)),
|
||||
(I64(a), I64(b)) => Ok(I64(a%b)),
|
||||
(I128(a), I128(b)) => Ok(I128(a%b)),
|
||||
(Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a%b))),
|
||||
(Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))),
|
||||
(Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))),
|
||||
@ -493,6 +581,7 @@ impl ::std::ops::Rem for ConstInt {
|
||||
(U16(a), U16(b)) => Ok(U16(a%b)),
|
||||
(U32(a), U32(b)) => Ok(U32(a%b)),
|
||||
(U64(a), U64(b)) => Ok(U64(a%b)),
|
||||
(U128(a), U128(b)) => Ok(U128(a%b)),
|
||||
(Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a%b))),
|
||||
(Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))),
|
||||
(Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))),
|
||||
@ -512,6 +601,7 @@ impl ::std::ops::Shl<ConstInt> for ConstInt {
|
||||
I16(a) => Ok(I16(overflowing!(a.overflowing_shl(b), Op::Shl))),
|
||||
I32(a) => Ok(I32(overflowing!(a.overflowing_shl(b), Op::Shl))),
|
||||
I64(a) => Ok(I64(overflowing!(a.overflowing_shl(b), Op::Shl))),
|
||||
I128(a) => Ok(I128(overflowing!(a.overflowing_shl(b), Op::Shl))),
|
||||
Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
|
||||
Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
|
||||
Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
|
||||
@ -519,6 +609,7 @@ impl ::std::ops::Shl<ConstInt> for ConstInt {
|
||||
U16(a) => Ok(U16(overflowing!(a.overflowing_shl(b), Op::Shl))),
|
||||
U32(a) => Ok(U32(overflowing!(a.overflowing_shl(b), Op::Shl))),
|
||||
U64(a) => Ok(U64(overflowing!(a.overflowing_shl(b), Op::Shl))),
|
||||
U128(a) => Ok(U128(overflowing!(a.overflowing_shl(b), Op::Shl))),
|
||||
Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
|
||||
Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
|
||||
Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
|
||||
@ -537,6 +628,7 @@ impl ::std::ops::Shr<ConstInt> for ConstInt {
|
||||
I16(a) => Ok(I16(overflowing!(a.overflowing_shr(b), Op::Shr))),
|
||||
I32(a) => Ok(I32(overflowing!(a.overflowing_shr(b), Op::Shr))),
|
||||
I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shr))),
|
||||
I128(a) => Ok(I128(overflowing!(a.overflowing_shr(b), Op::Shr))),
|
||||
Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
|
||||
Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
|
||||
Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
|
||||
@ -544,6 +636,7 @@ impl ::std::ops::Shr<ConstInt> for ConstInt {
|
||||
U16(a) => Ok(U16(overflowing!(a.overflowing_shr(b), Op::Shr))),
|
||||
U32(a) => Ok(U32(overflowing!(a.overflowing_shr(b), Op::Shr))),
|
||||
U64(a) => Ok(U64(overflowing!(a.overflowing_shr(b), Op::Shr))),
|
||||
U128(a) => Ok(U128(overflowing!(a.overflowing_shr(b), Op::Shr))),
|
||||
Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
|
||||
Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
|
||||
Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
|
||||
@ -561,22 +654,14 @@ impl ::std::ops::Neg for ConstInt {
|
||||
I16(a) => Ok(I16(overflowing!(a.overflowing_neg(), Op::Neg))),
|
||||
I32(a) => Ok(I32(overflowing!(a.overflowing_neg(), Op::Neg))),
|
||||
I64(a) => Ok(I64(overflowing!(a.overflowing_neg(), Op::Neg))),
|
||||
I128(a) => Ok(I128(overflowing!(a.overflowing_neg(), Op::Neg))),
|
||||
Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_neg(), Op::Neg)))),
|
||||
Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_neg(), Op::Neg)))),
|
||||
Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_neg(), Op::Neg)))),
|
||||
U8(0) => Ok(U8(0)),
|
||||
U16(0) => Ok(U16(0)),
|
||||
U32(0) => Ok(U32(0)),
|
||||
U64(0) => Ok(U64(0)),
|
||||
Usize(Us16(0)) => Ok(Usize(Us16(0))),
|
||||
Usize(Us32(0)) => Ok(Usize(Us32(0))),
|
||||
Usize(Us64(0)) => Ok(Usize(Us64(0))),
|
||||
U8(_) => Err(UnsignedNegation),
|
||||
U16(_) => Err(UnsignedNegation),
|
||||
U32(_) => Err(UnsignedNegation),
|
||||
U64(_) => Err(UnsignedNegation),
|
||||
Usize(_) => Err(UnsignedNegation),
|
||||
Infer(a @ 0...as_u64::I64MAX) => Ok(InferSigned(-(a as i64))),
|
||||
a@U8(0) | a@U16(0) | a@U32(0) | a@U64(0) | a@U128(0) |
|
||||
a@Usize(Us16(0)) | a@Usize(Us32(0)) | a@Usize(Us64(0)) => Ok(a),
|
||||
U8(_) | U16(_) | U32(_) | U64(_) | U128(_) | Usize(_) => Err(UnsignedNegation),
|
||||
Infer(a @ 0...ubounds::I64MAX) => Ok(InferSigned(-(a as i128))),
|
||||
Infer(_) => Err(Overflow(Op::Neg)),
|
||||
InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_neg(), Op::Neg))),
|
||||
}
|
||||
@ -591,6 +676,7 @@ impl ::std::ops::Not for ConstInt {
|
||||
I16(a) => Ok(I16(!a)),
|
||||
I32(a) => Ok(I32(!a)),
|
||||
I64(a) => Ok(I64(!a)),
|
||||
I128(a) => Ok(I128(!a)),
|
||||
Isize(Is16(a)) => Ok(Isize(Is16(!a))),
|
||||
Isize(Is32(a)) => Ok(Isize(Is32(!a))),
|
||||
Isize(Is64(a)) => Ok(Isize(Is64(!a))),
|
||||
@ -598,6 +684,7 @@ impl ::std::ops::Not for ConstInt {
|
||||
U16(a) => Ok(U16(!a)),
|
||||
U32(a) => Ok(U32(!a)),
|
||||
U64(a) => Ok(U64(!a)),
|
||||
U128(a) => Ok(U128(!a)),
|
||||
Usize(Us16(a)) => Ok(Usize(Us16(!a))),
|
||||
Usize(Us32(a)) => Ok(Usize(Us32(!a))),
|
||||
Usize(Us64(a)) => Ok(Usize(Us64(!a))),
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
use syntax::ast;
|
||||
use super::err::*;
|
||||
use rustc_i128::i128;
|
||||
|
||||
/// Depending on the target only one variant is ever used in a compilation.
|
||||
/// Anything else is an error. This invariant is checked at several locations
|
||||
@ -41,11 +42,11 @@ impl ConstIsize {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn new_truncating(i: i64, target_int_ty: ast::IntTy) -> Self {
|
||||
pub fn new_truncating(i: i128, target_int_ty: ast::IntTy) -> Self {
|
||||
match target_int_ty {
|
||||
ast::IntTy::I16 => Is16(i as i16),
|
||||
ast::IntTy::I32 => Is32(i as i32),
|
||||
ast::IntTy::I64 => Is64(i),
|
||||
ast::IntTy::I64 => Is64(i as i64),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,14 @@
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(const_fn)]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
||||
// SNAP: remove use of this crate
|
||||
extern crate rustc_i128;
|
||||
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
mod float;
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
use syntax::ast;
|
||||
use super::err::*;
|
||||
use rustc_i128::u128;
|
||||
|
||||
/// Depending on the target only one variant is ever used in a compilation.
|
||||
/// Anything else is an error. This invariant is checked at several locations
|
||||
@ -41,11 +42,11 @@ impl ConstUsize {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn new_truncating(i: u64, target_uint_ty: ast::UintTy) -> Self {
|
||||
pub fn new_truncating(i: u128, target_uint_ty: ast::UintTy) -> Self {
|
||||
match target_uint_ty {
|
||||
ast::UintTy::U16 => Us16(i as u16),
|
||||
ast::UintTy::U32 => Us32(i as u32),
|
||||
ast::UintTy::U64 => Us64(i),
|
||||
ast::UintTy::U64 => Us64(i as u64),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -11,3 +11,4 @@ crate-type = ["dylib"]
|
||||
[dependencies]
|
||||
log = { path = "../liblog" }
|
||||
serialize = { path = "../libserialize" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
|
@ -44,6 +44,8 @@ extern crate serialize as rustc_serialize; // used by deriving
|
||||
#[cfg(unix)]
|
||||
extern crate libc;
|
||||
|
||||
extern crate rustc_i128;
|
||||
|
||||
pub use rustc_serialize::hex::ToHex;
|
||||
|
||||
pub mod array_vec;
|
||||
|
@ -13,13 +13,14 @@ use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use blake2b::Blake2bHasher;
|
||||
use rustc_serialize::leb128;
|
||||
use rustc_i128::{u128,i128};
|
||||
|
||||
fn write_unsigned_leb128_to_buf(buf: &mut [u8; 16], value: u64) -> usize {
|
||||
leb128::write_unsigned_leb128_to(value, |i, v| buf[i] = v)
|
||||
leb128::write_unsigned_leb128_to(value as u128, |i, v| buf[i] = v)
|
||||
}
|
||||
|
||||
fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize {
|
||||
leb128::write_signed_leb128_to(value, |i, v| buf[i] = v)
|
||||
leb128::write_signed_leb128_to(value as i128, |i, v| buf[i] = v)
|
||||
}
|
||||
|
||||
/// When hashing something that ends up affecting properties like symbol names. We
|
||||
|
8
src/librustc_i128/Cargo.toml
Normal file
8
src/librustc_i128/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_i128"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "rustc_i128"
|
||||
path = "lib.rs"
|
29
src/librustc_i128/lib.rs
Normal file
29
src/librustc_i128/lib.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
#![allow(non_camel_case_types)]
|
||||
#![cfg_attr(not(stage0), feature(i128_type))]
|
||||
#![no_std]
|
||||
#![crate_type="rlib"]
|
||||
#![crate_name="rustc_i128"]
|
||||
|
||||
#[cfg(stage0)]
|
||||
pub type i128 = i64;
|
||||
#[cfg(stage0)]
|
||||
pub type u128 = u64;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub type i128 = int::_i128;
|
||||
#[cfg(not(stage0))]
|
||||
pub type u128 = int::_u128;
|
||||
#[cfg(not(stage0))]
|
||||
mod int {
|
||||
pub type _i128 = i128;
|
||||
pub type _u128 = u128;
|
||||
}
|
@ -16,3 +16,4 @@ serialize = { path = "../libserialize" }
|
||||
log = { path = "../liblog" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user