Merge branch 'master' into sparc64

This commit is contained in:
Seo Sanghyeon 2017-01-01 12:40:10 +09:00 committed by GitHub
commit b14785d3d0
197 changed files with 4850 additions and 2420 deletions

View file

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

View file

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

View file

@ -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
View file

@ -693,6 +693,7 @@ opt_nosave manage-submodules 1 "let the build manage the git submodules"
opt_nosave clang 0 "prefer clang to gcc for building the runtime"
opt_nosave 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"

View file

@ -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
View file

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

View file

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

View file

@ -62,9 +62,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
///
/// 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")

View file

@ -33,17 +33,12 @@
/// 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);
}

View file

@ -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 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> 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 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> 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 @@ macro_rules! check {
("NINJA", self.ninja),
("CODEGEN_TESTS", self.codegen_tests),
("VENDOR", self.vendor),
("FULL_BOOTSTRAP", self.full_bootstrap),
}
match key {
@ -512,6 +520,11 @@ macro_rules! check {
"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();
}
_ => {}
}
}

View file

@ -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
# =============================================================================

View file

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

View file

@ -29,19 +29,19 @@
///
/// 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"));

View file

@ -521,7 +521,7 @@ fn cargo(&self,
.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 @@ fn rustdoc(&self, compiler: &Compiler) -> PathBuf {
/// `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 @@ fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command {
}
}
}
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 @@ fn musl_root(&self, target: &str) -> Option<&Path> {
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 @@ fn new(stage: u32, host: &'a str) -> 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
}
}

View file

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

View file

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

View file

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

View file

@ -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();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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

View file

@ -0,0 +1,28 @@
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
make \
file \
curl \
ca-certificates \
python2.7 \
git \
cmake \
sudo \
gdb \
xz-utils
ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
tar xJf - -C /usr/local/bin --strip-components=1
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
dpkg -i dumb-init_*.deb && \
rm dumb-init_*.deb
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
--enable-full-bootstrap
ENV RUST_CHECK_TARGET ""

View file

@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python2.7 \
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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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
isnt interesting. The next part is:
```rust
@ -293,7 +293,7 @@ isnt interesting. The next part is:
```
Because `Fn` is a trait, we can use it as a bound for our generic type. In
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`.
Theres one other key point here: because were bounding a generic with a

View file

@ -574,6 +574,31 @@ The [`libc` crate on crates.io][libc] includes type aliases and function
definitions for the C standard library in the `libc` module, and Rust links
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`,

View file

@ -128,7 +128,7 @@ _descriptive_, not _prescriptive_. This means that how long a reference is valid
is determined by the code, not by the annotations. The annotations, however,
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

View file

@ -102,7 +102,7 @@ mutation, then the solution is quite easy: add `mut`.
There are other good reasons to avoid mutable state when possible, but theyre
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 its not verboten.
what you need, so its not forbidden.
# Initializing bindings

View file

@ -1657,6 +1657,15 @@ Functions within external blocks may be called by Rust code, just like
functions defined in Rust. The Rust compiler automatically translates between
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

View file

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

View file

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

View file

@ -0,0 +1,90 @@
{
"intrinsic_prefix": "_",
"llvm_prefix": "llvm.nvvm.read.ptx.sreg.",
"intrinsics": [
{
"intrinsic": "block_dim_x",
"width": ["0"],
"llvm": "ntid.x",
"ret": "S32",
"args": []
},
{
"intrinsic": "block_dim_y",
"width": ["0"],
"llvm": "ntid.y",
"ret": "S32",
"args": []
},
{
"intrinsic": "block_dim_z",
"width": ["0"],
"llvm": "ntid.z",
"ret": "S32",
"args": []
},
{
"intrinsic": "block_idx_x",
"width": ["0"],
"llvm": "ctaid.x",
"ret": "S32",
"args": []
},
{
"intrinsic": "block_idx_y",
"width": ["0"],
"llvm": "ctaid.y",
"ret": "S32",
"args": []
},
{
"intrinsic": "block_idx_z",
"width": ["0"],
"llvm": "ctaid.z",
"ret": "S32",
"args": []
},
{
"intrinsic": "grid_dim_x",
"width": ["0"],
"llvm": "nctaid.x",
"ret": "S32",
"args": []
},
{
"intrinsic": "grid_dim_y",
"width": ["0"],
"llvm": "nctaid.y",
"ret": "S32",
"args": []
},
{
"intrinsic": "grid_dim_z",
"width": ["0"],
"llvm": "nctaid.z",
"ret": "S32",
"args": []
},
{
"intrinsic": "thread_idx_x",
"width": ["0"],
"llvm": "tid.x",
"ret": "S32",
"args": []
},
{
"intrinsic": "thread_idx_y",
"width": ["0"],
"llvm": "tid.y",
"ret": "S32",
"args": []
},
{
"intrinsic": "thread_idx_z",
"width": ["0"],
"llvm": "tid.z",
"ret": "S32",
"args": []
}
]
}

View file

@ -55,24 +55,24 @@
/// [`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 @@
/// 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 @@
/// }
/// ```
///
/// Sharing a mutable `AtomicUsize`:
/// Sharing a mutable [`AtomicUsize`]:
///
/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html
///
/// ```no_run
/// use std::sync::Arc;

View file

@ -9,6 +9,7 @@ links = "jemalloc"
name = "alloc_jemalloc"
path = "lib.rs"
test = false
doc = false
[dependencies]
core = { path = "../libcore" }

View file

@ -7,6 +7,7 @@ version = "0.0.0"
name = "alloc_system"
path = "lib.rs"
test = false
doc = false
[dependencies]
core = { path = "../libcore" }

View file

@ -9,6 +9,7 @@ name = "compiler_builtins"
path = "lib.rs"
test = false
bench = false
doc = false
[dependencies]
core = { path = "../libcore" }

View file

@ -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::*;
}

View file

@ -153,12 +153,16 @@ fn clone(&self) -> $t { *self }
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 }

View file

@ -429,7 +429,7 @@ fn partial_cmp(&self, other: &Ordering) -> Option<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 @@ fn ne(&self, _other: &()) -> bool { false }
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 @@ impl Eq for $t {}
}
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 @@ fn cmp(&self, other: &bool) -> Ordering {
}
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 ! {

View file

@ -144,12 +144,16 @@ fn default() -> $t { $v }
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 }

View file

@ -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 @@ fn to_u8(&self) -> u8 { *self as u8 }
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 @@ fn prefix(&self) -> &'static str {
/// 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 @@ macro_rules! integer {
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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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")]

View file

@ -186,6 +186,13 @@ fn write_u32(&mut self, i: u32) {
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 @@ fn write_i32(&mut self, i: i32) {
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 @@ fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
(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 {

View file

@ -242,6 +242,8 @@ fn steps_between_by_one(start: &Self, end: &Self) -> Option<usize> {
// 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.
///

View file

@ -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 @@
#[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;

View file

@ -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
View 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 }

View file

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
int_module! { i16, 16 }
int_module! { i16 }

View file

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
int_module! { i32, 32 }
int_module! { i32 }

View file

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
int_module! { i64, 64 }
int_module! { i64 }

View file

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
int_module! { i8, 8 }
int_module! { i8 }

View file

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

View file

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

View file

@ -145,6 +145,8 @@ fn one() -> Self { 1 }
)*)
}
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 @@ fn from_str(src: &str) -> Result<Self, ParseIntError> {
)*}
}
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 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
}
}
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 @@ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
)*}
}
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 @@ fn try_from(u: $signed) -> Result<$unsigned, TryFromIntError> {
)*}
}
#[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 @@ fn checked_add(&self, other: u32) -> Option<Self> {
})*)
}
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 @@ fn from(small: $Small) -> $Large {
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
View 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 }

View file

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
uint_module! { u16, 16 }
uint_module! { u16 }

View file

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
uint_module! { u32, 32 }
uint_module! { u32 }

View file

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
uint_module! { u64, 64 }
uint_module! { u64 }

View file

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
uint_module! { u8, 8 }
uint_module! { u8 }

View file

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

View file

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

View file

@ -298,6 +298,8 @@ fn neg(self) -> Self {
}
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)]

View file

@ -268,6 +268,8 @@ fn add(self, other: $t) -> $t { self + other }
}
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 @@ fn sub(self, other: $t) -> $t { self - other }
}
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 @@ fn mul(self, other: $t) -> $t { self * other }
}
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 @@ fn div(self, other: $t) -> $t { self / other }
}
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 @@ fn rem(self, other: $t) -> $t { self % other }
}
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 @@ fn not(self) -> $t { !self }
}
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 @@ fn bitand(self, rhs: $t) -> $t { self & rhs }
}
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 @@ fn bitor(self, rhs: $t) -> $t { self | rhs }
}
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 @@ fn bitxor(self, other: $t) -> $t { self ^ other }
}
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 @@ fn add_assign(&mut self, other: $t) { *self += other }
}
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 @@ fn sub_assign(&mut self, other: $t) { *self -= other }
}
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 @@ fn mul_assign(&mut self, other: $t) { *self *= other }
}
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 @@ fn div_assign(&mut self, other: $t) { *self /= other }
}
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 @@ fn rem_assign(&mut self, other: $t) { *self %= other }
}
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 @@ fn bitand_assign(&mut self, other: $t) { *self &= other }
}
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 @@ fn bitor_assign(&mut self, other: $t) { *self |= other }
}
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 @@ fn bitxor_assign(&mut self, other: $t) { *self ^= other }
}
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.

View file

@ -237,11 +237,16 @@ pub fn into_inner(self) -> bool {
/// Loads a value from the bool.
///
/// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
/// `load` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation.
///
/// # Panics
///
/// Panics 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 @@ pub fn load(&self, order: Ordering) -> bool {
/// Stores a value into the bool.
///
/// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
/// `store` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation.
///
/// [`Ordering`]: enum.Ordering.html
///
/// # Examples
///
@ -286,7 +294,10 @@ pub fn store(&self, val: bool, order: Ordering) {
/// 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 @@ pub fn swap(&self, val: bool, order: Ordering) -> bool {
/// 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 @@ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> boo
/// 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 @@ pub fn compare_exchange(&self,
/// 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 @@ pub fn into_inner(self) -> *mut 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 @@ pub fn load(&self, order: Ordering) -> *mut 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 @@ pub fn store(&self, ptr: *mut T, order: Ordering) {
/// 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 @@ pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut 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 @@ pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) ->
/// 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 @@ pub fn compare_exchange(&self,
/// 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 @@ pub fn into_inner(self) -> $int_type {
/// 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 @@ pub fn load(&self, order: Ordering) -> $int_type {
/// 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 @@ pub fn store(&self, val: $int_type, order: Ordering) {
/// 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 @@ pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
/// 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 @@ pub fn compare_and_swap(&self,
/// 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 @@ pub fn compare_exchange(&self,
/// 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) {

View file

@ -7,6 +7,7 @@ version = "0.0.0"
path = "lib.rs"
test = false
bench = false
doc = false
[dependencies]
core = { path = "../libcore" }

View file

@ -7,6 +7,7 @@ version = "0.0.0"
path = "lib.rs"
test = false
bench = false
doc = false
[dependencies]
alloc = { path = "../liballoc" }

View file

@ -6,6 +6,7 @@ version = "0.0.0"
[lib]
name = "rand"
path = "lib.rs"
doc = false
[dependencies]
core = { path = "../libcore" }

View file

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

View file

@ -62,6 +62,9 @@
extern crate serialize as rustc_serialize; // used by deriving
// SNAP:
extern crate rustc_i128;
#[cfg(test)]
extern crate test;

View file

@ -260,11 +260,13 @@ pub fn collect_language_items(session: &Session,
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;

View file

@ -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 @@ fn new(interners: &CtxtInterners<'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 @@ pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'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 @@ pub fn mk_mach_uint(self, tm: ast::UintTy) -> Ty<'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,
}
}

View file

@ -20,6 +20,8 @@
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 @@ fn default() -> 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 @@ pub fn parse(sess: &Session) -> 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 @@ pub fn parse(sess: &Session) -> 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 @@ pub fn size(&self) -> Size {
I16 => Size::from_bytes(2),
I32 => Size::from_bytes(4),
I64 => Size::from_bytes(8),
I128 => Size::from_bytes(16),
}
}
@ -346,6 +362,7 @@ pub fn align(&self, dl: &TargetDataLayout)-> Align {
I16 => dl.i16_align,
I32 => dl.i32_align,
I64 => dl.i64_align,
I128 => dl.i128_align,
}
}
@ -357,33 +374,37 @@ pub fn to_ty<'a, 'tcx>(&self, tcx: &ty::TyCtxt<'a, 'tcx, 'tcx>,
(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 @@ pub fn from_attr(dl: &TargetDataLayout, ity: attr::IntType) -> 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 @@ pub fn size(self, dl: &TargetDataLayout) -> Size {
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 @@ pub fn align(self, dl: &TargetDataLayout) -> Align {
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 @@ pub fn compute_uncached(ty: Ty<'gcx>,
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 @@ pub fn compute_uncached(ty: Ty<'gcx>,
// 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));
}

View file

@ -51,11 +51,13 @@ fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
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 @@ fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr {
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 @@ fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr {
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 @@ fn assert_ty_matches(&self, val: Disr) {
(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),
}

View file

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

View 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()
}
}

View file

@ -58,6 +58,7 @@
mod arm_base;
mod bitrig_base;
mod dragonfly_base;
mod emscripten_base;
mod freebsd_base;
mod haiku_base;
mod linux_base;

View file

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

View file

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

View file

@ -43,6 +43,8 @@
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) => {

View file

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

View file

@ -12,3 +12,4 @@ crate-type = ["dylib"]
log = { path = "../liblog" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
rustc_i128 = { path = "../librustc_i128" }

View file

@ -74,11 +74,13 @@ pub fn description(&self) -> &'static str {
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",
}
}

View file

@ -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 @@ pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> {
(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 @@ pub fn erase_type(self) -> Self {
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 @@ pub fn description(&self) -> &'static str {
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 @@ pub fn is_negative(&self) -> bool {
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 @@ pub fn try_cmp(self, rhs: Self) -> Result<::std::cmp::Ordering, ConstMathErr> {
(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 @@ pub fn try_cmp(self, rhs: Self) -> Result<::std::cmp::Ordering, ConstMathErr> {
(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 @@ macro_rules! add1 {
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 @@ macro_rules! add1 {
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 @@ pub fn int_type(self) -> Option<IntType> {
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 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error>
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 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error>
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 @@ fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
(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 @@ fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
(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 @@ fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
(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 @@ fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
(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 @@ fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
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 @@ fn div(self, rhs: Self) -> Result<Self, ConstMathErr> {
(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 @@ fn div(self, rhs: Self) -> Result<Self, ConstMathErr> {
(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 @@ fn rem(self, rhs: Self) -> Result<Self, ConstMathErr> {
(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 @@ fn rem(self, rhs: Self) -> Result<Self, ConstMathErr> {
(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 @@ fn shl(self, rhs: Self) -> Result<Self, ConstMathErr> {
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 @@ fn shl(self, rhs: Self) -> Result<Self, ConstMathErr> {
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 @@ fn shr(self, rhs: Self) -> Result<Self, ConstMathErr> {
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 @@ fn shr(self, rhs: Self) -> Result<Self, ConstMathErr> {
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 @@ fn neg(self) -> Result<Self, ConstMathErr> {
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 @@ fn not(self) -> Result<Self, ConstMathErr> {
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 @@ fn not(self) -> Result<Self, ConstMathErr> {
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))),

View file

@ -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 @@ pub fn new(i: i64, target_int_ty: ast::IntTy) -> Result<Self, ConstMathErr> {
_ => 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!(),
}
}

View file

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

View file

@ -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 @@ pub fn new(i: u64, target_uint_ty: ast::UintTy) -> Result<Self, ConstMathErr> {
_ => 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!(),
}
}

View file

@ -11,3 +11,4 @@ crate-type = ["dylib"]
[dependencies]
log = { path = "../liblog" }
serialize = { path = "../libserialize" }
rustc_i128 = { path = "../librustc_i128" }

View file

@ -44,6 +44,8 @@
#[cfg(unix)]
extern crate libc;
extern crate rustc_i128;
pub use rustc_serialize::hex::ToHex;
pub mod array_vec;

View file

@ -13,13 +13,14 @@
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

View 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
View 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;
}

View file

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