From 283619cf5ca25272b294525273ec42e9c7820edb Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Sat, 29 May 2021 12:38:46 +0000 Subject: [PATCH 01/58] bootstrap: Disable initial-exec TLS model on powerpc Fixes #81334. --- src/bootstrap/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index f39e89a9d01f7..061d7ed5ee08b 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1237,7 +1237,7 @@ impl<'a> Builder<'a> { // efficient initial-exec TLS model. This doesn't work with `dlopen`, // so we can't use it by default in general, but we can use it for tools // and our own internal libraries. - if !mode.must_support_dlopen() { + if !mode.must_support_dlopen() && !target.triple.starts_with("powerpc-") { rustflags.arg("-Ztls-model=initial-exec"); } From 135edbf4ba7762ec25e4bfeb04ab17ce893ada23 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 6 Jul 2021 15:31:38 +0200 Subject: [PATCH 02/58] Move LinkerInfo into CrateInfo --- src/driver/aot.rs | 4 +--- src/driver/jit.rs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 6676d88602c45..50fd53481f745 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -4,7 +4,6 @@ use std::path::PathBuf; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; -use rustc_codegen_ssa::back::linker::LinkerInfo; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -296,8 +295,7 @@ pub(crate) fn run_aot( allocator_module, metadata_module, metadata, - linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()), - crate_info: CrateInfo::new(tcx), + crate_info: CrateInfo::new(tcx, crate::target_triple(tcx.sess).to_string()), }, work_products, )) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 3f96e741d350f..04ec01ad28148 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -178,7 +178,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> { let mut dylib_paths = Vec::new(); - let crate_info = CrateInfo::new(tcx); + let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); let formats = tcx.dependency_formats(()); let data = &formats .iter() From 4cfa1fcb5b566e9bbe24fafb77027a39685dfe6b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 6 Jul 2021 17:49:23 +0200 Subject: [PATCH 03/58] Don't pass local_crate_name to link_binary separately It is already part of CodegenResults --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index b817bf4aff771..ebf98e8694b78 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -219,7 +219,6 @@ impl CodegenBackend for CraneliftCodegenBackend { sess, &codegen_results, outputs, - &codegen_results.crate_info.local_crate_name.as_str(), ); Ok(()) From fb92375755a00a39a900da50f581917519b5af6b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 7 Jul 2021 11:14:20 +0200 Subject: [PATCH 04/58] Merge commit '3a31c6d8272c14388a34622193baf553636fe470' into sync_cg_clif-2021-07-07 --- .cirrus.yml | 2 +- .github/workflows/main.yml | 73 +++++- .github/workflows/rustc.yml | 4 +- .gitignore | 2 + .vscode/settings.json | 21 +- Cargo.lock | 56 +++-- Cargo.toml | 4 +- Readme.md | 10 +- build.sh | 89 -------- build_sysroot/Cargo.lock | 14 +- build_sysroot/build_sysroot.sh | 39 ---- build_sysroot/prepare_sysroot_src.sh | 39 ---- build_system/build_backend.rs | 40 ++++ build_system/build_sysroot.rs | 216 ++++++++++++++++++ build_system/config.rs | 55 +++++ build_system/prepare.rs | 133 +++++++++++ build_system/rustc_info.rs | 65 ++++++ build_system/utils.rs | 35 +++ clean_all.sh | 3 +- config.txt | 17 ++ docs/usage.md | 11 +- example/mini_core_hello_world.rs | 6 +- example/std_example.rs | 2 - ...ins-Disable-128bit-atomic-operations.patch | 0 ...1-rand-Enable-c2-chacha-simd-feature.patch | 0 .../0002-rand-Disable-failing-test.patch | 0 ...sysroot-Disable-not-compiling-tests.patch} | 0 ...> 0023-sysroot-Ignore-failing-tests.patch} | 0 ...27-sysroot-128bit-atomic-operations.patch} | 0 prepare.sh | 29 --- rust-toolchain | 2 +- scripts/cargo.rs | 70 ++++++ scripts/cargo.sh | 18 -- scripts/config.sh | 25 +- scripts/ext_config.sh | 7 +- scripts/filter_profile.rs | 5 +- scripts/rustup.sh | 2 +- scripts/setup_rust_fork.sh | 6 +- scripts/test_rustc_tests.sh | 4 +- scripts/tests.sh | 36 +-- src/base.rs | 25 +- src/bin/cg_clif.rs | 2 +- src/common.rs | 1 - src/constant.rs | 141 ++++++------ src/debuginfo/line_info.rs | 2 +- src/debuginfo/mod.rs | 8 +- src/driver/aot.rs | 5 +- src/driver/jit.rs | 127 ++++++++-- src/intrinsics/llvm.rs | 58 +++++ src/lib.rs | 14 +- src/optimize/mod.rs | 5 +- src/pretty_clif.rs | 19 +- src/vtable.rs | 25 +- test.sh | 4 +- y.rs | 153 +++++++++++++ 55 files changed, 1283 insertions(+), 446 deletions(-) delete mode 100755 build.sh delete mode 100755 build_sysroot/build_sysroot.sh delete mode 100755 build_sysroot/prepare_sysroot_src.sh create mode 100644 build_system/build_backend.rs create mode 100644 build_system/build_sysroot.rs create mode 100644 build_system/config.rs create mode 100644 build_system/prepare.rs create mode 100644 build_system/rustc_info.rs create mode 100644 build_system/utils.rs create mode 100644 config.txt rename {crate_patches => patches}/0001-compiler-builtins-Disable-128bit-atomic-operations.patch (100%) rename {crate_patches => patches}/0001-rand-Enable-c2-chacha-simd-feature.patch (100%) rename {crate_patches => patches}/0002-rand-Disable-failing-test.patch (100%) rename patches/{0022-core-Disable-not-compiling-tests.patch => 0022-sysroot-Disable-not-compiling-tests.patch} (100%) rename patches/{0023-core-Ignore-failing-tests.patch => 0023-sysroot-Ignore-failing-tests.patch} (100%) rename patches/{0027-Disable-128bit-atomic-operations.patch => 0027-sysroot-128bit-atomic-operations.patch} (100%) delete mode 100755 prepare.sh create mode 100644 scripts/cargo.rs delete mode 100755 scripts/cargo.sh create mode 100755 y.rs diff --git a/.cirrus.yml b/.cirrus.yml index e173df423a765..61da6a2491c52 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -14,7 +14,7 @@ task: - . $HOME/.cargo/env - git config --global user.email "user@example.com" - git config --global user.name "User" - - ./prepare.sh + - ./y.rs prepare test_script: - . $HOME/.cargo/env - # Enable backtraces for easier debugging diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4d45e36c956c9..f81ac87726052 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,6 +19,9 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-pc-windows-gnu + - os: ubuntu-latest + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu steps: - uses: actions/checkout@v2 @@ -49,11 +52,19 @@ jobs: sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable rustup target add x86_64-pc-windows-gnu + - name: Install AArch64 toolchain and qemu + if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu' + run: | + sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user + - name: Prepare dependencies run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.rs prepare + + - name: Build + run: ./y.rs build --sysroot none - name: Test env: @@ -87,3 +98,63 @@ jobs: with: name: cg_clif-${{ runner.os }}-cross-x86_64-mingw path: cg_clif.tar.xz + + build_windows: + runs-on: windows-latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v2 + + #- name: Cache cargo installed crates + # uses: actions/cache@v2 + # with: + # path: ~/.cargo/bin + # key: ${{ runner.os }}-cargo-installed-crates + + #- name: Cache cargo registry and index + # uses: actions/cache@v2 + # with: + # path: | + # ~/.cargo/registry + # ~/.cargo/git + # key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} + + #- name: Cache cargo target dir + # uses: actions/cache@v2 + # with: + # path: target + # key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Prepare dependencies + run: | + git config --global user.email "user@example.com" + git config --global user.name "User" + git config --global core.autocrlf false + rustup set default-host x86_64-pc-windows-gnu + rustc y.rs -o y.exe -g + ./y.exe prepare + + - name: Build + #name: Test + run: | + # Enable backtraces for easier debugging + #export RUST_BACKTRACE=1 + + # Reduce amount of benchmark runs as they are slow + #export COMPILE_RUNS=2 + #export RUN_RUNS=2 + + # Enable extra checks + #export CG_CLIF_ENABLE_VERIFIER=1 + + ./y.exe build + + #- name: Package prebuilt cg_clif + # run: tar cvfJ cg_clif.tar.xz build + + #- name: Upload prebuilt cg_clif + # uses: actions/upload-artifact@v2 + # with: + # name: cg_clif-${{ runner.os }} + # path: cg_clif.tar.xz diff --git a/.github/workflows/rustc.yml b/.github/workflows/rustc.yml index e01a92598bab7..1c08e5ece33d2 100644 --- a/.github/workflows/rustc.yml +++ b/.github/workflows/rustc.yml @@ -34,7 +34,7 @@ jobs: run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.rs prepare - name: Test run: | @@ -72,7 +72,7 @@ jobs: run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.rs prepare - name: Test run: | diff --git a/.gitignore b/.gitignore index b241bef9d1e7f..12e779fe7c7d7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,11 @@ perf.data perf.data.old *.events *.string* +/y.bin /build /build_sysroot/sysroot_src /build_sysroot/compiler-builtins +/build_sysroot/rustc_version /rust /rand /regex diff --git a/.vscode/settings.json b/.vscode/settings.json index 9009a532c54dc..f62e59cefc241 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,9 @@ { // source for rustc_* is not included in the rust-src component; disable the errors about this "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"], - "rust-analyzer.assist.importMergeBehavior": "last", + "rust-analyzer.assist.importGranularity": "module", + "rust-analyzer.assist.importEnforceGranularity": true, + "rust-analyzer.assist.importPrefix": "crate", "rust-analyzer.cargo.runBuildScripts": true, "rust-analyzer.linkedProjects": [ "./Cargo.toml", @@ -49,6 +51,23 @@ "cfg": [], }, ] + }, + { + "roots": ["./y.rs"], + "crates": [ + { + "root_module": "./y.rs", + "edition": "2018", + "deps": [{ "crate": 1, "name": "std" }], + "cfg": [], + }, + { + "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs", + "edition": "2018", + "deps": [], + "cfg": [], + }, + ] } ] } diff --git a/Cargo.lock b/Cargo.lock index a6f5925149b92..56d0974b25371 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,16 +33,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -57,8 +57,8 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -66,18 +66,18 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" [[package]] name = "cranelift-entity" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" [[package]] name = "cranelift-frontend" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen", "log", @@ -87,8 +87,8 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", @@ -104,8 +104,8 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", @@ -115,17 +115,18 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen", + "libc", "target-lexicon", ] [[package]] name = "cranelift-object" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", @@ -171,9 +172,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" [[package]] name = "libloading" @@ -203,14 +204,21 @@ dependencies = [ "libc", ] +[[package]] +name = "memchr" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" + [[package]] name = "object" -version = "0.24.0" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" +checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" dependencies = [ "crc32fast", "indexmap", + "memchr", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index fd149af454735..ef68d7ee532dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind"] } +cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind", "all-arch"] } cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } @@ -17,7 +17,7 @@ cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", bran cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } target-lexicon = "0.12.0" gimli = { version = "0.24.0", default-features = false, features = ["write"]} -object = { version = "0.24.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.25.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } indexmap = "1.0.2" diff --git a/Readme.md b/Readme.md index 08f9373be6262..dad8ed90b53b8 100644 --- a/Readme.md +++ b/Readme.md @@ -10,8 +10,8 @@ If not please open an issue. ```bash $ git clone https://github.com/bjorn3/rustc_codegen_cranelift.git $ cd rustc_codegen_cranelift -$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking -$ ./build.sh +$ ./y.rs prepare # download and patch sysroot src and install hyperfine for benchmarking +$ ./y.rs build ``` To run the test suite replace the last command with: @@ -20,7 +20,7 @@ To run the test suite replace the last command with: $ ./test.sh ``` -This will implicitly build cg_clif too. Both `build.sh` and `test.sh` accept a `--debug` argument to +This will implicitly build cg_clif too. Both `y.rs build` and `test.sh` accept a `--debug` argument to build in debug mode. Alternatively you can download a pre built version from [GHA]. It is listed in the artifacts section @@ -32,12 +32,12 @@ of workflow runs. Unfortunately due to GHA restrictions you need to be logged in rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects. -Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`). +Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`). In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo.sh build +$ $cg_clif_dir/build/cargo build ``` This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. diff --git a/build.sh b/build.sh deleted file mode 100755 index 76bc1884334af..0000000000000 --- a/build.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env bash -set -e - -# Settings -export CHANNEL="release" -build_sysroot="clif" -target_dir='build' -while [[ $# != 0 ]]; do - case $1 in - "--debug") - export CHANNEL="debug" - ;; - "--sysroot") - build_sysroot=$2 - shift - ;; - "--target-dir") - target_dir=$2 - shift - ;; - *) - echo "Unknown flag '$1'" - echo "Usage: ./build.sh [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]" - exit 1 - ;; - esac - shift -done - -# Build cg_clif -unset CARGO_TARGET_DIR -unamestr=$(uname) -if [[ "$unamestr" == 'Linux' || "$unamestr" == "FreeBSD" ]]; then - export RUSTFLAGS='-Clink-arg=-Wl,-rpath=$ORIGIN/../lib '$RUSTFLAGS -elif [[ "$unamestr" == 'Darwin' ]]; then - export RUSTFLAGS='-Csplit-debuginfo=unpacked -Clink-arg=-Wl,-rpath,@loader_path/../lib -Zosx-rpath-install-name '$RUSTFLAGS - dylib_ext='dylib' -else - echo "Unsupported os $unamestr" - exit 1 -fi -if [[ "$CHANNEL" == "release" ]]; then - cargo build --release -else - cargo build -fi - -source scripts/ext_config.sh - -rm -rf "$target_dir" -mkdir "$target_dir" -mkdir "$target_dir"/bin "$target_dir"/lib -ln target/$CHANNEL/cg_clif{,_build_sysroot} "$target_dir"/bin -ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib -ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir" - -mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" -mkdir -p "$target_dir/lib/rustlib/$HOST_TRIPLE/lib/" -if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then - cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" -fi - -case "$build_sysroot" in - "none") - ;; - "llvm") - cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/" - if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - cp -r $(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/lib "$target_dir/lib/rustlib/$HOST_TRIPLE/" - fi - ;; - "clif") - echo "[BUILD] sysroot" - dir=$(pwd) - cd "$target_dir" - time "$dir/build_sysroot/build_sysroot.sh" - if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - time TARGET_TRIPLE="$HOST_TRIPLE" "$dir/build_sysroot/build_sysroot.sh" - fi - cp lib/rustlib/*/lib/libstd-* lib/ - ;; - *) - echo "Unknown sysroot kind \`$build_sysroot\`." - echo "The allowed values are:" - echo " none A sysroot that doesn't contain the standard library" - echo " llvm Copy the sysroot from rustc compiled by cg_llvm" - echo " clif Build a new sysroot using cg_clif" - exit 1 -esac diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index 923deb9aec4c0..46f661107e73b 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -56,7 +56,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.43" +version = "0.1.46" dependencies = [ "rustc-std-workspace-core", ] @@ -121,9 +121,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "compiler_builtins", "libc", @@ -132,9 +132,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" +checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" dependencies = [ "rustc-std-workspace-core", ] @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce" +checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", diff --git a/build_sysroot/build_sysroot.sh b/build_sysroot/build_sysroot.sh deleted file mode 100755 index 0354304e55bf7..0000000000000 --- a/build_sysroot/build_sysroot.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -# Requires the CHANNEL env var to be set to `debug` or `release.` - -set -e - -source ./config.sh - -dir=$(pwd) - -# Use rustc with cg_clif as hotpluggable backend instead of the custom cg_clif driver so that -# build scripts are still compiled using cg_llvm. -export RUSTC=$dir"/bin/cg_clif_build_sysroot" -export RUSTFLAGS=$RUSTFLAGS" --clif" - -cd "$(dirname "$0")" - -# Cleanup for previous run -# v Clean target dir except for build scripts and incremental cache -rm -r target/*/{debug,release}/{build,deps,examples,libsysroot*,native} 2>/dev/null || true - -# We expect the target dir in the default location. Guard against the user changing it. -export CARGO_TARGET_DIR=target - -# Build libs -export RUSTFLAGS="$RUSTFLAGS -Zforce-unstable-if-unmarked -Cpanic=abort" -export __CARGO_DEFAULT_LIB_METADATA="cg_clif" -if [[ "$1" != "--debug" ]]; then - sysroot_channel='release' - # FIXME Enable incremental again once rust-lang/rust#74946 is fixed - CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target "$TARGET_TRIPLE" --release -else - sysroot_channel='debug' - cargo build --target "$TARGET_TRIPLE" -fi - -# Copy files to sysroot -ln "target/$TARGET_TRIPLE/$sysroot_channel/deps/"* "$dir/lib/rustlib/$TARGET_TRIPLE/lib/" -rm "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"*.{rmeta,d} diff --git a/build_sysroot/prepare_sysroot_src.sh b/build_sysroot/prepare_sysroot_src.sh deleted file mode 100755 index 54b7a94750c52..0000000000000 --- a/build_sysroot/prepare_sysroot_src.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -set -e -cd "$(dirname "$0")" - -SRC_DIR="$(dirname "$(rustup which rustc)")/../lib/rustlib/src/rust/" -DST_DIR="sysroot_src" - -if [ ! -e "$SRC_DIR" ]; then - echo "Please install rust-src component" - exit 1 -fi - -rm -rf $DST_DIR -mkdir -p $DST_DIR/library -cp -a "$SRC_DIR/library" $DST_DIR/ - -pushd $DST_DIR -echo "[GIT] init" -git init -echo "[GIT] add" -git add . -echo "[GIT] commit" -git commit -m "Initial commit" -q -for file in $(ls ../../patches/ | grep -v patcha); do -echo "[GIT] apply" "$file" -git apply ../../patches/"$file" -git add -A -git commit --no-gpg-sign -m "Patch $file" -done -popd - -git clone https://github.com/rust-lang/compiler-builtins.git || echo "rust-lang/compiler-builtins has already been cloned" -pushd compiler-builtins -git checkout -- . -git checkout 0.1.43 -git apply ../../crate_patches/000*-compiler-builtins-*.patch -popd - -echo "Successfully prepared sysroot source for building" diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs new file mode 100644 index 0000000000000..1df2bcc4541ca --- /dev/null +++ b/build_system/build_backend.rs @@ -0,0 +1,40 @@ +use std::env; +use std::path::{Path, PathBuf}; +use std::process::Command; + +pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf { + let mut cmd = Command::new("cargo"); + cmd.arg("build").arg("--target").arg(host_triple); + + match channel { + "debug" => {} + "release" => { + cmd.arg("--release"); + } + _ => unreachable!(), + } + + if cfg!(unix) { + if cfg!(target_os = "macos") { + cmd.env( + "RUSTFLAGS", + "-Csplit-debuginfo=unpacked \ + -Clink-arg=-Wl,-rpath,@loader_path/../lib \ + -Zosx-rpath-install-name" + .to_string() + + env::var("RUSTFLAGS").as_deref().unwrap_or(""), + ); + } else { + cmd.env( + "RUSTFLAGS", + "-Clink-arg=-Wl,-rpath=$ORIGIN/../lib ".to_string() + + env::var("RUSTFLAGS").as_deref().unwrap_or(""), + ); + } + } + + eprintln!("[BUILD] rustc_codegen_cranelift"); + crate::utils::spawn_and_wait(cmd); + + Path::new("target").join(host_triple).join(channel) +} diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs new file mode 100644 index 0000000000000..9fb88c279613f --- /dev/null +++ b/build_system/build_sysroot.rs @@ -0,0 +1,216 @@ +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::{self, Command}; + +use crate::rustc_info::{get_file_name, get_rustc_version}; +use crate::utils::{spawn_and_wait, try_hard_link}; +use crate::SysrootKind; + +pub(crate) fn build_sysroot( + channel: &str, + sysroot_kind: SysrootKind, + target_dir: &Path, + cg_clif_build_dir: PathBuf, + host_triple: &str, + target_triple: &str, +) { + if target_dir.exists() { + fs::remove_dir_all(target_dir).unwrap(); + } + fs::create_dir_all(target_dir.join("bin")).unwrap(); + fs::create_dir_all(target_dir.join("lib")).unwrap(); + + // Copy the backend + for file in ["cg_clif", "cg_clif_build_sysroot"] { + try_hard_link( + cg_clif_build_dir.join(get_file_name(file, "bin")), + target_dir.join("bin").join(get_file_name(file, "bin")), + ); + } + + let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib"); + try_hard_link( + cg_clif_build_dir.join(&cg_clif_dylib), + target_dir + .join(if cfg!(windows) { + // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the + // binaries. + "bin" + } else { + "lib" + }) + .join(cg_clif_dylib), + ); + + // Build and copy cargo wrapper + let mut build_cargo_wrapper_cmd = Command::new("rustc"); + build_cargo_wrapper_cmd + .arg("scripts/cargo.rs") + .arg("-o") + .arg(target_dir.join("cargo")) + .arg("-g"); + spawn_and_wait(build_cargo_wrapper_cmd); + + let default_sysroot = crate::rustc_info::get_default_sysroot(); + + let rustlib = target_dir.join("lib").join("rustlib"); + let host_rustlib_lib = rustlib.join(host_triple).join("lib"); + let target_rustlib_lib = rustlib.join(target_triple).join("lib"); + fs::create_dir_all(&host_rustlib_lib).unwrap(); + fs::create_dir_all(&target_rustlib_lib).unwrap(); + + if target_triple == "x86_64-pc-windows-gnu" { + if !default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib").exists() { + eprintln!( + "The x86_64-pc-windows-gnu target needs to be installed first before it is possible \ + to compile a sysroot for it.", + ); + process::exit(1); + } + for file in fs::read_dir( + default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"), + ) + .unwrap() + { + let file = file.unwrap().path(); + if file.extension().map_or(true, |ext| ext.to_str().unwrap() != "o") { + continue; // only copy object files + } + try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap())); + } + } + + match sysroot_kind { + SysrootKind::None => {} // Nothing to do + SysrootKind::Llvm => { + for file in fs::read_dir( + default_sysroot.join("lib").join("rustlib").join(host_triple).join("lib"), + ) + .unwrap() + { + let file = file.unwrap().path(); + let file_name_str = file.file_name().unwrap().to_str().unwrap(); + if file_name_str.contains("rustc_") + || file_name_str.contains("chalk") + || file_name_str.contains("tracing") + || file_name_str.contains("regex") + { + // These are large crates that are part of the rustc-dev component and are not + // necessary to run regular programs. + continue; + } + try_hard_link(&file, host_rustlib_lib.join(file.file_name().unwrap())); + } + + if target_triple != host_triple { + for file in fs::read_dir( + default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"), + ) + .unwrap() + { + let file = file.unwrap().path(); + try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap())); + } + } + } + SysrootKind::Clif => { + build_clif_sysroot_for_triple(channel, target_dir, host_triple, None); + + if host_triple != target_triple { + // When cross-compiling it is often necessary to manually pick the right linker + let linker = if target_triple == "aarch64-unknown-linux-gnu" { + Some("aarch64-linux-gnu-gcc") + } else { + None + }; + build_clif_sysroot_for_triple(channel, target_dir, target_triple, linker); + } + + // Copy std for the host to the lib dir. This is necessary for the jit mode to find + // libstd. + for file in fs::read_dir(host_rustlib_lib).unwrap() { + let file = file.unwrap().path(); + if file.file_name().unwrap().to_str().unwrap().contains("std-") { + try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap())); + } + } + } + } +} + +fn build_clif_sysroot_for_triple( + channel: &str, + target_dir: &Path, + triple: &str, + linker: Option<&str>, +) { + match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) { + Err(e) => { + eprintln!("Failed to get rustc version for patched sysroot source: {}", e); + eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source"); + process::exit(1); + } + Ok(source_version) => { + let rustc_version = get_rustc_version(); + if source_version != rustc_version { + eprintln!("The patched sysroot source is outdated"); + eprintln!("Source version: {}", source_version.trim()); + eprintln!("Rustc version: {}", rustc_version.trim()); + eprintln!("Hint: Try `./y.rs prepare` to update the patched sysroot source"); + process::exit(1); + } + } + } + + let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel); + + if !crate::config::get_bool("keep_sysroot") { + // Cleanup the target dir with the exception of build scripts and the incremental cache + for dir in ["build", "deps", "examples", "native"] { + if build_dir.join(dir).exists() { + fs::remove_dir_all(build_dir.join(dir)).unwrap(); + } + } + } + + // Build sysroot + let mut build_cmd = Command::new("cargo"); + build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot"); + let mut rustflags = "--clif -Zforce-unstable-if-unmarked".to_string(); + if channel == "release" { + build_cmd.arg("--release"); + rustflags.push_str(" -Zmir-opt-level=3"); + } + if let Some(linker) = linker { + use std::fmt::Write; + write!(rustflags, " -Clinker={}", linker).unwrap(); + } + build_cmd.env("RUSTFLAGS", rustflags); + build_cmd.env( + "RUSTC", + env::current_dir().unwrap().join(target_dir).join("bin").join("cg_clif_build_sysroot"), + ); + // FIXME Enable incremental again once rust-lang/rust#74946 is fixed + build_cmd.env("CARGO_INCREMENTAL", "0").env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); + spawn_and_wait(build_cmd); + + // Copy all relevant files to the sysroot + for entry in + fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps")) + .unwrap() + { + let entry = entry.unwrap(); + if let Some(ext) = entry.path().extension() { + if ext == "rmeta" || ext == "d" || ext == "dSYM" { + continue; + } + } else { + continue; + }; + try_hard_link( + entry.path(), + target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()), + ); + } +} diff --git a/build_system/config.rs b/build_system/config.rs new file mode 100644 index 0000000000000..ef540cf1f822b --- /dev/null +++ b/build_system/config.rs @@ -0,0 +1,55 @@ +use std::{fs, process}; + +fn load_config_file() -> Vec<(String, Option)> { + fs::read_to_string("config.txt") + .unwrap() + .lines() + .map(|line| if let Some((line, _comment)) = line.split_once('#') { line } else { line }) + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + .map(|line| { + if let Some((key, val)) = line.split_once('=') { + (key.trim().to_owned(), Some(val.trim().to_owned())) + } else { + (line.to_owned(), None) + } + }) + .collect() +} + +pub(crate) fn get_bool(name: &str) -> bool { + let values = load_config_file() + .into_iter() + .filter(|(key, _)| key == name) + .map(|(_, val)| val) + .collect::>(); + if values.is_empty() { + false + } else { + if values.iter().any(|val| val.is_some()) { + eprintln!("Boolean config `{}` has a value", name); + process::exit(1); + } + true + } +} + +pub(crate) fn get_value(name: &str) -> Option { + let values = load_config_file() + .into_iter() + .filter(|(key, _)| key == name) + .map(|(_, val)| val) + .collect::>(); + if values.is_empty() { + None + } else if values.len() == 1 { + if values[0].is_none() { + eprintln!("Config `{}` missing value", name); + process::exit(1); + } + values.into_iter().next().unwrap() + } else { + eprintln!("Config `{}` given multiple values: {:?}", name, values); + process::exit(1); + } +} diff --git a/build_system/prepare.rs b/build_system/prepare.rs new file mode 100644 index 0000000000000..401b8271abcc5 --- /dev/null +++ b/build_system/prepare.rs @@ -0,0 +1,133 @@ +use std::env; +use std::ffi::OsStr; +use std::ffi::OsString; +use std::fs; +use std::path::Path; +use std::process::Command; + +use crate::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; +use crate::utils::{copy_dir_recursively, spawn_and_wait}; + +pub(crate) fn prepare() { + prepare_sysroot(); + + eprintln!("[INSTALL] hyperfine"); + Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap(); + + clone_repo( + "rand", + "https://github.com/rust-random/rand.git", + "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", + ); + apply_patches("rand", Path::new("rand")); + + clone_repo( + "regex", + "https://github.com/rust-lang/regex.git", + "341f207c1071f7290e3f228c710817c280c8dca1", + ); + + clone_repo( + "simple-raytracer", + "https://github.com/ebobby/simple-raytracer", + "804a7a21b9e673a482797aa289a18ed480e4d813", + ); + + eprintln!("[LLVM BUILD] simple-raytracer"); + let mut build_cmd = Command::new("cargo"); + build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer"); + spawn_and_wait(build_cmd); + fs::copy( + Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), + // FIXME use get_file_name here too once testing is migrated to rust + "simple-raytracer/raytracer_cg_llvm", + ) + .unwrap(); +} + +fn prepare_sysroot() { + let rustc_path = get_rustc_path(); + let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust"); + let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src"); + + assert!(sysroot_src_orig.exists()); + + if sysroot_src.exists() { + fs::remove_dir_all(&sysroot_src).unwrap(); + } + fs::create_dir_all(sysroot_src.join("library")).unwrap(); + eprintln!("[COPY] sysroot src"); + copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library")); + + let rustc_version = get_rustc_version(); + fs::write( + Path::new("build_sysroot").join("rustc_version"), + &rustc_version, + ) + .unwrap(); + + eprintln!("[GIT] init"); + let mut git_init_cmd = Command::new("git"); + git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src); + spawn_and_wait(git_init_cmd); + + let mut git_add_cmd = Command::new("git"); + git_add_cmd.arg("add").arg(".").current_dir(&sysroot_src); + spawn_and_wait(git_add_cmd); + + let mut git_commit_cmd = Command::new("git"); + git_commit_cmd + .arg("commit") + .arg("-m") + .arg("Initial commit") + .arg("-q") + .current_dir(&sysroot_src); + spawn_and_wait(git_commit_cmd); + + apply_patches("sysroot", &sysroot_src); + + clone_repo( + "build_sysroot/compiler-builtins", + "https://github.com/rust-lang/compiler-builtins.git", + "0.1.46", + ); + apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins")); +} + +fn clone_repo(target_dir: &str, repo: &str, rev: &str) { + eprintln!("[CLONE] {}", repo); + // Ignore exit code as the repo may already have been checked out + Command::new("git").arg("clone").arg(repo).arg(target_dir).spawn().unwrap().wait().unwrap(); + + let mut clean_cmd = Command::new("git"); + clean_cmd.arg("checkout").arg("--").arg(".").current_dir(target_dir); + spawn_and_wait(clean_cmd); + + let mut checkout_cmd = Command::new("git"); + checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(target_dir); + spawn_and_wait(checkout_cmd); +} + +fn get_patches(crate_name: &str) -> Vec { + let mut patches: Vec<_> = fs::read_dir("patches") + .unwrap() + .map(|entry| entry.unwrap().path()) + .filter(|path| path.extension() == Some(OsStr::new("patch"))) + .map(|path| path.file_name().unwrap().to_owned()) + .filter(|file_name| { + file_name.to_str().unwrap().split_once("-").unwrap().1.starts_with(crate_name) + }) + .collect(); + patches.sort(); + patches +} + +fn apply_patches(crate_name: &str, target_dir: &Path) { + for patch in get_patches(crate_name) { + eprintln!("[PATCH] {:?} <- {:?}", target_dir.file_name().unwrap(), patch); + let patch_arg = env::current_dir().unwrap().join("patches").join(patch); + let mut apply_patch_cmd = Command::new("git"); + apply_patch_cmd.arg("am").arg(patch_arg).arg("-q").current_dir(target_dir); + spawn_and_wait(apply_patch_cmd); + } +} diff --git a/build_system/rustc_info.rs b/build_system/rustc_info.rs new file mode 100644 index 0000000000000..9206bb02bd3da --- /dev/null +++ b/build_system/rustc_info.rs @@ -0,0 +1,65 @@ +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; + +pub(crate) fn get_rustc_version() -> String { + let version_info = + Command::new("rustc").stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout; + String::from_utf8(version_info).unwrap() +} + +pub(crate) fn get_host_triple() -> String { + let version_info = + Command::new("rustc").stderr(Stdio::inherit()).args(&["-vV"]).output().unwrap().stdout; + String::from_utf8(version_info) + .unwrap() + .lines() + .to_owned() + .find(|line| line.starts_with("host")) + .unwrap() + .split(":") + .nth(1) + .unwrap() + .trim() + .to_owned() +} + +pub(crate) fn get_rustc_path() -> PathBuf { + let rustc_path = Command::new("rustup") + .stderr(Stdio::inherit()) + .args(&["which", "rustc"]) + .output() + .unwrap() + .stdout; + Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned() +} + +pub(crate) fn get_default_sysroot() -> PathBuf { + let default_sysroot = Command::new("rustc") + .stderr(Stdio::inherit()) + .args(&["--print", "sysroot"]) + .output() + .unwrap() + .stdout; + Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned() +} + +pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { + let file_name = Command::new("rustc") + .stderr(Stdio::inherit()) + .args(&[ + "--crate-name", + crate_name, + "--crate-type", + crate_type, + "--print", + "file-names", + "-", + ]) + .output() + .unwrap() + .stdout; + let file_name = String::from_utf8(file_name).unwrap().trim().to_owned(); + assert!(!file_name.contains('\n')); + assert!(file_name.contains(crate_name)); + file_name +} diff --git a/build_system/utils.rs b/build_system/utils.rs new file mode 100644 index 0000000000000..12b5d70fad853 --- /dev/null +++ b/build_system/utils.rs @@ -0,0 +1,35 @@ +use std::fs; +use std::path::Path; +use std::process::{self, Command}; + +#[track_caller] +pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { + let src = src.as_ref(); + let dst = dst.as_ref(); + if let Err(_) = fs::hard_link(src, dst) { + fs::copy(src, dst).unwrap(); // Fallback to copying if hardlinking failed + } +} + +#[track_caller] +pub(crate) fn spawn_and_wait(mut cmd: Command) { + if !cmd.spawn().unwrap().wait().unwrap().success() { + process::exit(1); + } +} + +pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { + for entry in fs::read_dir(from).unwrap() { + let entry = entry.unwrap(); + let filename = entry.file_name(); + if filename == "." || filename == ".." { + continue; + } + if entry.metadata().unwrap().is_dir() { + fs::create_dir(to.join(&filename)).unwrap(); + copy_dir_recursively(&from.join(&filename), &to.join(&filename)); + } else { + fs::copy(from.join(&filename), to.join(&filename)).unwrap(); + } + } +} diff --git a/clean_all.sh b/clean_all.sh index a7bbeb05cac5a..f4f8c82d69f10 100755 --- a/clean_all.sh +++ b/clean_all.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash set -e -rm -rf target/ build/ build_sysroot/{sysroot_src/,target/,compiler-builtins/} perf.data{,.old} +rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} +rm -rf target/ build/ perf.data{,.old} rm -rf rand/ regex/ simple-raytracer/ diff --git a/config.txt b/config.txt new file mode 100644 index 0000000000000..b14db27d6206f --- /dev/null +++ b/config.txt @@ -0,0 +1,17 @@ +# This file allows configuring the build system. + +# Which triple to produce a compiler toolchain for. +# +# Defaults to the default triple of rustc on the host system. +#host = x86_64-unknown-linux-gnu + +# Which triple to build libraries (core/alloc/std/test/proc_macro) for. +# +# Defaults to `host`. +#target = x86_64-unknown-linux-gnu + +# Disables cleaning of the sysroot dir. This will cause old compiled artifacts to be re-used when +# the sysroot source hasn't changed. This is useful when the codegen backend hasn't been modified. +# This option can be changed while the build system is already running for as long as sysroot +# building hasn't started yet. +#keep_sysroot diff --git a/docs/usage.md b/docs/usage.md index 3eee3b554e3b6..956d5905a97ad 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -2,14 +2,14 @@ rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects. -Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`). +Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`). ## Cargo In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo.sh build +$ $cg_clif_dir/build/cargo build ``` This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. @@ -30,7 +30,7 @@ In jit mode cg_clif will immediately execute your code without creating an execu > The jit mode will probably need cargo integration to make this possible. ```bash -$ $cg_clif_dir/build/cargo.sh jit +$ $cg_clif_dir/build/cargo jit ``` or @@ -40,11 +40,10 @@ $ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate. ``` There is also an experimental lazy jit mode. In this mode functions are only compiled once they are -first called. It currently does not work with multi-threaded programs. When a not yet compiled -function is called from another thread than the main thread, you will get an ICE. +first called. ```bash -$ $cg_clif_dir/build/cargo.sh lazy-jit +$ $cg_clif_dir/build/cargo lazy-jit ``` ## Shell diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 6570f2bf9f297..d997ce6d1b379 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -292,7 +292,7 @@ fn main() { #[cfg(not(any(jit, windows)))] test_tls(); - #[cfg(all(not(jit), target_os = "linux"))] + #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] unsafe { global_asm_test(); } @@ -303,12 +303,12 @@ fn main() { assert_eq!(*REF1, *REF2); } -#[cfg(all(not(jit), target_os = "linux"))] +#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] extern "C" { fn global_asm_test(); } -#[cfg(all(not(jit), target_os = "linux"))] +#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] global_asm! { " .global global_asm_test diff --git a/example/std_example.rs b/example/std_example.rs index 7d608df9253df..5bc51a541b58c 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -15,8 +15,6 @@ fn main() { let stderr = ::std::io::stderr(); let mut stderr = stderr.lock(); - // FIXME support lazy jit when multi threading - #[cfg(not(lazy_jit))] std::thread::spawn(move || { println!("Hello from another thread!"); }); diff --git a/crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch b/patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch similarity index 100% rename from crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch rename to patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch diff --git a/crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch b/patches/0001-rand-Enable-c2-chacha-simd-feature.patch similarity index 100% rename from crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch rename to patches/0001-rand-Enable-c2-chacha-simd-feature.patch diff --git a/crate_patches/0002-rand-Disable-failing-test.patch b/patches/0002-rand-Disable-failing-test.patch similarity index 100% rename from crate_patches/0002-rand-Disable-failing-test.patch rename to patches/0002-rand-Disable-failing-test.patch diff --git a/patches/0022-core-Disable-not-compiling-tests.patch b/patches/0022-sysroot-Disable-not-compiling-tests.patch similarity index 100% rename from patches/0022-core-Disable-not-compiling-tests.patch rename to patches/0022-sysroot-Disable-not-compiling-tests.patch diff --git a/patches/0023-core-Ignore-failing-tests.patch b/patches/0023-sysroot-Ignore-failing-tests.patch similarity index 100% rename from patches/0023-core-Ignore-failing-tests.patch rename to patches/0023-sysroot-Ignore-failing-tests.patch diff --git a/patches/0027-Disable-128bit-atomic-operations.patch b/patches/0027-sysroot-128bit-atomic-operations.patch similarity index 100% rename from patches/0027-Disable-128bit-atomic-operations.patch rename to patches/0027-sysroot-128bit-atomic-operations.patch diff --git a/prepare.sh b/prepare.sh deleted file mode 100755 index 64c097261c908..0000000000000 --- a/prepare.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -set -e - -./build_sysroot/prepare_sysroot_src.sh -cargo install hyperfine || echo "Skipping hyperfine install" - -git clone https://github.com/rust-random/rand.git || echo "rust-random/rand has already been cloned" -pushd rand -git checkout -- . -git checkout 0f933f9c7176e53b2a3c7952ded484e1783f0bf1 -git am ../crate_patches/*-rand-*.patch -popd - -git clone https://github.com/rust-lang/regex.git || echo "rust-lang/regex has already been cloned" -pushd regex -git checkout -- . -git checkout 341f207c1071f7290e3f228c710817c280c8dca1 -popd - -git clone https://github.com/ebobby/simple-raytracer || echo "ebobby/simple-raytracer has already been cloned" -pushd simple-raytracer -git checkout -- . -git checkout 804a7a21b9e673a482797aa289a18ed480e4d813 - -# build with cg_llvm for perf comparison -unset CARGO_TARGET_DIR -cargo build -mv target/debug/main raytracer_cg_llvm -popd diff --git a/rust-toolchain b/rust-toolchain index 9fe6e093a7b81..f806f7bdcd98a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-05-26" +channel = "nightly-2021-07-07" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/scripts/cargo.rs b/scripts/cargo.rs new file mode 100644 index 0000000000000..b7e8dd4497479 --- /dev/null +++ b/scripts/cargo.rs @@ -0,0 +1,70 @@ +use std::env; +#[cfg(unix)] +use std::os::unix::process::CommandExt; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + if env::var("RUSTC_WRAPPER").map_or(false, |wrapper| wrapper.contains("sccache")) { + eprintln!( + "\x1b[1;93m=== Warning: Unsetting RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m" + ); + env::remove_var("RUSTC_WRAPPER"); + } + + let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + + env::set_var("RUSTC", sysroot.join("bin/cg_clif".to_string() + env::consts::EXE_SUFFIX)); + + let mut rustdoc_flags = env::var("RUSTDOCFLAGS").unwrap_or(String::new()); + rustdoc_flags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend="); + rustdoc_flags.push_str( + sysroot + .join(if cfg!(windows) { "bin" } else { "lib" }) + .join( + env::consts::DLL_PREFIX.to_string() + + "rustc_codegen_cranelift" + + env::consts::DLL_SUFFIX, + ) + .to_str() + .unwrap(), + ); + rustdoc_flags.push_str(" --sysroot "); + rustdoc_flags.push_str(sysroot.to_str().unwrap()); + env::set_var("RUSTDOCFLAGS", rustdoc_flags); + + // Ensure that the right toolchain is used + env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN")); + + let args: Vec<_> = match env::args().nth(1).as_deref() { + Some("jit") => { + env::set_var( + "RUSTFLAGS", + env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", + ); + std::array::IntoIter::new(["rustc".to_string()]) + .chain(env::args().skip(2)) + .chain(["--".to_string(), "-Cllvm-args=mode=jit".to_string()]) + .collect() + } + Some("lazy-jit") => { + env::set_var( + "RUSTFLAGS", + env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", + ); + std::array::IntoIter::new(["rustc".to_string()]) + .chain(env::args().skip(2)) + .chain(["--".to_string(), "-Cllvm-args=mode=jit-lazy".to_string()]) + .collect() + } + _ => env::args().skip(1).collect(), + }; + + #[cfg(unix)] + Command::new("cargo").args(args).exec(); + + #[cfg(not(unix))] + std::process::exit( + Command::new("cargo").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1), + ); +} diff --git a/scripts/cargo.sh b/scripts/cargo.sh deleted file mode 100755 index 1daa5a78f7bd2..0000000000000 --- a/scripts/cargo.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -dir=$(dirname "$0") -source "$dir/config.sh" - -# read nightly compiler from rust-toolchain file -TOOLCHAIN=$(cat "$dir/rust-toolchain" | grep channel | sed "s/channel = \"\(.*\)\"/\1/") - -cmd=$1 -shift || true - -if [[ "$cmd" = "jit" ]]; then -cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit -Cprefer-dynamic -elif [[ "$cmd" = "lazy-jit" ]]; then -cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit-lazy -Cprefer-dynamic -else -cargo "+${TOOLCHAIN}" "$cmd" "$@" -fi diff --git a/scripts/config.sh b/scripts/config.sh index 99b302ee1d94b..53ada369b089a 100644 --- a/scripts/config.sh +++ b/scripts/config.sh @@ -2,26 +2,5 @@ set -e -dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -) - -if echo "$RUSTC_WRAPPER" | grep sccache; then -echo -echo -e "\x1b[1;93m=== Warning: Unset RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m" -echo -export RUSTC_WRAPPER= -fi - -dir=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd) - -export RUSTC=$dir"/bin/cg_clif" - -export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\ -'-Zcodegen-backend='$dir'/lib/'$dylib' --sysroot '$dir - -# FIXME fix `#[linkage = "extern_weak"]` without this -if [[ "$(uname)" == 'Darwin' ]]; then - export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" -fi - -export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:"$dir"/lib" -export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH +export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH" +export DYLD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$DYLD_LIBRARY_PATH" diff --git a/scripts/ext_config.sh b/scripts/ext_config.sh index 3f98d77d76cad..11d6c4c831867 100644 --- a/scripts/ext_config.sh +++ b/scripts/ext_config.sh @@ -1,6 +1,6 @@ # Note to people running shellcheck: this file should only be sourced, not executed directly. -# Various env vars that should only be set for the build system but not for cargo.sh +# Various env vars that should only be set for the build system set -e @@ -25,3 +25,8 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then echo "Unknown non-native platform" fi fi + +# FIXME fix `#[linkage = "extern_weak"]` without this +if [[ "$(uname)" == 'Darwin' ]]; then + export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" +fi diff --git a/scripts/filter_profile.rs b/scripts/filter_profile.rs index 15388926ec9ec..9e196afbe4f57 100755 --- a/scripts/filter_profile.rs +++ b/scripts/filter_profile.rs @@ -2,9 +2,10 @@ #![forbid(unsafe_code)]/* This line is ignored by bash # This block is ignored by rustc pushd $(dirname "$0")/../ -source build/config.sh +source scripts/config.sh +RUSTC="$(pwd)/build/bin/cg_clif" popd -PROFILE=$1 OUTPUT=$2 exec $RUSTC $RUSTFLAGS -Cllvm-args=mode=jit -Cprefer-dynamic $0 +PROFILE=$1 OUTPUT=$2 exec $RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic $0 #*/ //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse diff --git a/scripts/rustup.sh b/scripts/rustup.sh index fa7557653d879..cc34c08088665 100755 --- a/scripts/rustup.sh +++ b/scripts/rustup.sh @@ -17,7 +17,7 @@ case $1 in done ./clean_all.sh - ./prepare.sh + ./y.rs prepare (cd build_sysroot && cargo update) diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 43c4887669cf6..52adaaa8de673 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -1,8 +1,8 @@ #!/bin/bash set -e -./build.sh -source build/config.sh +./y.rs build +source scripts/config.sh echo "[SETUP] Rust fork" git clone https://github.com/rust-lang/rust.git || true @@ -33,7 +33,7 @@ index d95b5b7f17f..00b6f0e3635 100644 [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "0.1.43", features = ['rustc-dep-of-std', 'no-asm'] } ++compiler_builtins = { version = "0.1.45", features = ['rustc-dep-of-std', 'no-asm'] } [dev-dependencies] rand = "0.7" diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 347fb40e6f9e7..2f5c2cf737b05 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -38,7 +38,8 @@ rm src/test/ui/threads-sendsync/task-stderr.rs rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs rm src/test/ui/drop/drop-trait-enum.rs rm src/test/ui/numbers-arithmetic/issue-8460.rs -rm src/test/incremental/change_crate_dep_kind.rs # requires -Cpanic=unwind +rm src/test/ui/rt-explody-panic-payloads.rs +rm src/test/incremental/change_crate_dep_kind.rs rm src/test/ui/issues/issue-28950.rs # depends on stack size optimizations rm src/test/ui/init-large-type.rs # same @@ -64,6 +65,7 @@ rm src/test/incremental/lto.rs # requires lto rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/ rm -r src/test/run-make/unstable-flag-required # same +rm -r src/test/run-make/emit-named-files # requires full --emit support rm src/test/pretty/asm.rs # inline asm rm src/test/pretty/raw-str-nonexpr.rs # same diff --git a/scripts/tests.sh b/scripts/tests.sh index 0d99d2c507c95..5df04c533a70e 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -2,9 +2,10 @@ set -e -source build/config.sh +source scripts/config.sh source scripts/ext_config.sh -MY_RUSTC="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2" +export RUSTC=false # ensure that cg_llvm isn't accidentally used +MY_RUSTC="$(pwd)/build/bin/cg_clif $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2" function no_sysroot_tests() { echo "[BUILD] mini_core" @@ -46,7 +47,7 @@ function base_sysroot_tests() { $MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" echo "[JIT-lazy] std_example" - $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --cfg lazy_jit --target "$HOST_TRIPLE" + $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" else echo "[JIT] std_example (skipped)" fi @@ -75,63 +76,64 @@ function base_sysroot_tests() { function extended_sysroot_tests() { pushd rand - cargo clean + ../build/cargo clean if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[TEST] rust-random/rand" - ../build/cargo.sh test --workspace + ../build/cargo test --workspace else echo "[AOT] rust-random/rand" - ../build/cargo.sh build --workspace --target $TARGET_TRIPLE --tests + ../build/cargo build --workspace --target $TARGET_TRIPLE --tests fi popd pushd simple-raytracer if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[BENCH COMPILE] ebobby/simple-raytracer" - hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \ + hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo clean" \ "RUSTC=rustc RUSTFLAGS='' cargo build" \ - "../build/cargo.sh build" + "../build/cargo build" echo "[BENCH RUN] ebobby/simple-raytracer" cp ./target/debug/main ./raytracer_cg_clif hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif else + ../build/cargo clean echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[COMPILE] ebobby/simple-raytracer" - ../build/cargo.sh build --target $TARGET_TRIPLE + ../build/cargo build --target $TARGET_TRIPLE echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" fi popd pushd build_sysroot/sysroot_src/library/core/tests echo "[TEST] libcore" - cargo clean + ../../../../../build/cargo clean if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../../../../../build/cargo.sh test + ../../../../../build/cargo test else - ../../../../../build/cargo.sh build --target $TARGET_TRIPLE --tests + ../../../../../build/cargo build --target $TARGET_TRIPLE --tests fi popd pushd regex echo "[TEST] rust-lang/regex example shootout-regex-dna" - cargo clean + ../build/cargo clean export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning # Make sure `[codegen mono items] start` doesn't poison the diff - ../build/cargo.sh build --example shootout-regex-dna --target $TARGET_TRIPLE + ../build/cargo build --example shootout-regex-dna --target $TARGET_TRIPLE if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then cat examples/regexdna-input.txt \ - | ../build/cargo.sh run --example shootout-regex-dna --target $TARGET_TRIPLE \ + | ../build/cargo run --example shootout-regex-dna --target $TARGET_TRIPLE \ | grep -v "Spawned thread" > res.txt diff -u res.txt examples/regexdna-output.txt fi if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[TEST] rust-lang/regex tests" - ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + ../build/cargo test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q else echo "[AOT] rust-lang/regex tests" - ../build/cargo.sh build --tests --target $TARGET_TRIPLE + ../build/cargo build --tests --target $TARGET_TRIPLE fi popd } diff --git a/src/base.rs b/src/base.rs index ec3e17e5b758d..3d78eed77b94c 100644 --- a/src/base.rs +++ b/src/base.rs @@ -21,6 +21,11 @@ pub(crate) fn codegen_fn<'tcx>( debug_assert!(!instance.substs.needs_infer()); let mir = tcx.instance_mir(instance.def); + let _mir_guard = crate::PrintOnPanic(|| { + let mut buf = Vec::new(); + rustc_mir::util::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap(); + String::from_utf8_lossy(&buf).into_owned() + }); // Declare function let symbol_name = tcx.symbol_name(instance); @@ -52,7 +57,6 @@ pub(crate) fn codegen_fn<'tcx>( module, tcx, pointer_type, - vtables: FxHashMap::default(), constants_cx: ConstantCx::new(), instance, @@ -105,7 +109,14 @@ pub(crate) fn codegen_fn<'tcx>( let context = &mut cx.cached_context; context.func = func; - crate::pretty_clif::write_clif_file(tcx, "unopt", None, instance, &context, &clif_comments); + crate::pretty_clif::write_clif_file( + tcx, + "unopt", + module.isa(), + instance, + &context, + &clif_comments, + ); // Verify function verify_func(tcx, &clif_comments, &context.func); @@ -122,7 +133,13 @@ pub(crate) fn codegen_fn<'tcx>( // Perform rust specific optimizations tcx.sess.time("optimize clif ir", || { - crate::optimize::optimize_function(tcx, instance, context, &mut clif_comments); + crate::optimize::optimize_function( + tcx, + module.isa(), + instance, + context, + &mut clif_comments, + ); }); // Define function @@ -137,7 +154,7 @@ pub(crate) fn codegen_fn<'tcx>( crate::pretty_clif::write_clif_file( tcx, "opt", - Some(module.isa()), + module.isa(), instance, &context, &clif_comments, diff --git a/src/bin/cg_clif.rs b/src/bin/cg_clif.rs index 2643fae0a810a..a044b43b86470 100644 --- a/src/bin/cg_clif.rs +++ b/src/bin/cg_clif.rs @@ -6,8 +6,8 @@ extern crate rustc_interface; extern crate rustc_session; extern crate rustc_target; -use std::panic; use std::lazy::SyncLazy; +use std::panic; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_interface::interface; diff --git a/src/common.rs b/src/common.rs index a8a0bb52a246e..892ccf27f6df8 100644 --- a/src/common.rs +++ b/src/common.rs @@ -233,7 +233,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) module: &'m mut dyn Module, pub(crate) tcx: TyCtxt<'tcx>, pub(crate) pointer_type: Type, // Cached from module - pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option>), Pointer>, pub(crate) constants_cx: ConstantCx, pub(crate) instance: Instance<'tcx>, diff --git a/src/constant.rs b/src/constant.rs index a87b3703949f9..2a2573aad2950 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -1,16 +1,13 @@ //! Handling of `static`s, `const`s and promoted allocations -use rustc_span::DUMMY_SP; - -use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::ErrorReported; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{ - alloc_range, read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, - Scalar, + read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar, }; use rustc_middle::ty::ConstKind; +use rustc_span::DUMMY_SP; use cranelift_codegen::ir::GlobalValueData; use cranelift_module::*; @@ -171,66 +168,74 @@ pub(crate) fn codegen_const_value<'tcx>( } match const_val { - ConstValue::Scalar(x) => { - if fx.clif_type(layout.ty).is_none() { - let (size, align) = (layout.size, layout.align.pref); - let mut alloc = Allocation::from_bytes( - std::iter::repeat(0).take(size.bytes_usize()).collect::>(), - align, - Mutability::Not, - ); - alloc.write_scalar(fx, alloc_range(Size::ZERO, size), x.into()).unwrap(); - let alloc = fx.tcx.intern_const_alloc(alloc); - return CValue::by_ref(pointer_for_allocation(fx, alloc), layout); - } - - match x { - Scalar::Int(int) => CValue::const_val(fx, layout, int), - Scalar::Ptr(ptr) => { - let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id); - let base_addr = match alloc_kind { - Some(GlobalAlloc::Memory(alloc)) => { - fx.constants_cx.todo.push(TodoItem::Alloc(ptr.alloc_id)); - let data_id = data_id_for_alloc_id( - &mut fx.constants_cx, - fx.module, - ptr.alloc_id, - alloc.mutability, - ); - let local_data_id = - fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - if fx.clif_comments.enabled() { - fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id)); - } - fx.bcx.ins().global_value(fx.pointer_type, local_data_id) - } - Some(GlobalAlloc::Function(instance)) => { - let func_id = crate::abi::import_function(fx.tcx, fx.module, instance); - let local_func_id = - fx.module.declare_func_in_func(func_id, &mut fx.bcx.func); - fx.bcx.ins().func_addr(fx.pointer_type, local_func_id) - } - Some(GlobalAlloc::Static(def_id)) => { - assert!(fx.tcx.is_static(def_id)); - let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false); - let local_data_id = - fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - if fx.clif_comments.enabled() { - fx.add_comment(local_data_id, format!("{:?}", def_id)); - } - fx.bcx.ins().global_value(fx.pointer_type, local_data_id) + ConstValue::Scalar(x) => match x { + Scalar::Int(int) => { + if fx.clif_type(layout.ty).is_some() { + return CValue::const_val(fx, layout, int); + } else { + let raw_val = int.to_bits(int.size()).unwrap(); + let val = match int.size().bytes() { + 1 => fx.bcx.ins().iconst(types::I8, raw_val as i64), + 2 => fx.bcx.ins().iconst(types::I16, raw_val as i64), + 4 => fx.bcx.ins().iconst(types::I32, raw_val as i64), + 8 => fx.bcx.ins().iconst(types::I64, raw_val as i64), + 16 => { + let lsb = fx.bcx.ins().iconst(types::I64, raw_val as u64 as i64); + let msb = + fx.bcx.ins().iconst(types::I64, (raw_val >> 64) as u64 as i64); + fx.bcx.ins().iconcat(lsb, msb) } - None => bug!("missing allocation {:?}", ptr.alloc_id), - }; - let val = if ptr.offset.bytes() != 0 { - fx.bcx.ins().iadd_imm(base_addr, i64::try_from(ptr.offset.bytes()).unwrap()) - } else { - base_addr + _ => unreachable!(), }; - CValue::by_val(val, layout) + + let place = CPlace::new_stack_slot(fx, layout); + place.to_ptr().store(fx, val, MemFlags::trusted()); + place.to_cvalue(fx) } } - } + Scalar::Ptr(ptr) => { + let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id); + let base_addr = match alloc_kind { + Some(GlobalAlloc::Memory(alloc)) => { + let data_id = data_id_for_alloc_id( + &mut fx.constants_cx, + fx.module, + ptr.alloc_id, + alloc.mutability, + ); + let local_data_id = + fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id)); + } + fx.bcx.ins().global_value(fx.pointer_type, local_data_id) + } + Some(GlobalAlloc::Function(instance)) => { + let func_id = crate::abi::import_function(fx.tcx, fx.module, instance); + let local_func_id = + fx.module.declare_func_in_func(func_id, &mut fx.bcx.func); + fx.bcx.ins().func_addr(fx.pointer_type, local_func_id) + } + Some(GlobalAlloc::Static(def_id)) => { + assert!(fx.tcx.is_static(def_id)); + let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false); + let local_data_id = + fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("{:?}", def_id)); + } + fx.bcx.ins().global_value(fx.pointer_type, local_data_id) + } + None => bug!("missing allocation {:?}", ptr.alloc_id), + }; + let val = if ptr.offset.bytes() != 0 { + fx.bcx.ins().iadd_imm(base_addr, i64::try_from(ptr.offset.bytes()).unwrap()) + } else { + base_addr + }; + CValue::by_val(val, layout) + } + }, ConstValue::ByRef { alloc, offset } => CValue::by_ref( pointer_for_allocation(fx, alloc) .offset_i64(fx, i64::try_from(offset.bytes()).unwrap()), @@ -254,7 +259,6 @@ pub(crate) fn pointer_for_allocation<'tcx>( alloc: &'tcx Allocation, ) -> crate::pointer::Pointer { let alloc_id = fx.tcx.create_memory_alloc(alloc); - fx.constants_cx.todo.push(TodoItem::Alloc(alloc_id)); let data_id = data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, alloc.mutability); @@ -266,12 +270,13 @@ pub(crate) fn pointer_for_allocation<'tcx>( crate::pointer::Pointer::new(global_ptr) } -fn data_id_for_alloc_id( +pub(crate) fn data_id_for_alloc_id( cx: &mut ConstantCx, module: &mut dyn Module, alloc_id: AllocId, mutability: rustc_hir::Mutability, ) -> DataId { + cx.todo.push(TodoItem::Alloc(alloc_id)); *cx.anon_allocs.entry(alloc_id).or_insert_with(|| { module.declare_anonymous_data(mutability == rustc_hir::Mutability::Mut, false).unwrap() }) @@ -352,7 +357,14 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant GlobalAlloc::Memory(alloc) => alloc, GlobalAlloc::Function(_) | GlobalAlloc::Static(_) => unreachable!(), }; - let data_id = data_id_for_alloc_id(cx, module, alloc_id, alloc.mutability); + let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| { + module + .declare_anonymous_data( + alloc.mutability == rustc_hir::Mutability::Mut, + false, + ) + .unwrap() + }); (data_id, alloc, None) } TodoItem::Static(def_id) => { @@ -415,7 +427,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant continue; } GlobalAlloc::Memory(target_alloc) => { - cx.todo.push(TodoItem::Alloc(reloc)); data_id_for_alloc_id(cx, module, reloc, target_alloc.mutability) } GlobalAlloc::Static(def_id) => { diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index 9eb067706309e..c7e15f81e0301 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -10,7 +10,7 @@ use rustc_span::{ }; use cranelift_codegen::binemit::CodeOffset; -use cranelift_codegen::machinst::MachSrcLoc; +use cranelift_codegen::MachSrcLoc; use gimli::write::{ Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable, diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 61e54a76f29ba..c67336eb3f2c3 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -61,9 +61,11 @@ impl<'tcx> DebugContext<'tcx> { let mut dwarf = DwarfUnit::new(encoding); - // FIXME: how to get version when building out of tree? - // Normally this would use option_env!("CFG_VERSION"). - let producer = format!("cg_clif (rustc {})", "unknown version"); + let producer = format!( + "cg_clif (rustc {}, cranelift {})", + rustc_interface::util::version_str().unwrap_or("unknown version"), + cranelift_codegen::VERSION, + ); let comp_dir = tcx.sess.working_dir.to_string_lossy(false).into_owned(); let (name, file_info) = match tcx.sess.local_crate_source_file.clone() { Some(path) => { diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 50fd53481f745..a8b802f449437 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -289,13 +289,16 @@ pub(crate) fn run_aot( None }; + // FIXME handle `-Ctarget-cpu=native` + let target_cpu = + tcx.sess.opts.cg.target_cpu.as_ref().unwrap_or(&tcx.sess.target.cpu).to_owned(); Box::new(( CodegenResults { modules, allocator_module, metadata_module, metadata, - crate_info: CrateInfo::new(tcx, crate::target_triple(tcx.sess).to_string()), + crate_info: CrateInfo::new(tcx, target_cpu), }, work_products, )) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 04ec01ad28148..76fbc9ad51e8e 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -3,11 +3,14 @@ use std::cell::RefCell; use std::ffi::CString; +use std::lazy::{Lazy, SyncOnceCell}; use std::os::raw::{c_char, c_int}; +use std::sync::{mpsc, Mutex}; use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; +use rustc_session::Session; use cranelift_jit::{JITBuilder, JITModule}; @@ -23,12 +26,48 @@ thread_local! { static LAZY_JIT_STATE: RefCell> = RefCell::new(None); } +/// The Sender owned by the rustc thread +static GLOBAL_MESSAGE_SENDER: SyncOnceCell>> = + SyncOnceCell::new(); + +/// A message that is sent from the jitted runtime to the rustc thread. +/// Senders are responsible for upholding `Send` semantics. +enum UnsafeMessage { + /// Request that the specified `Instance` be lazily jitted. + /// + /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after + /// this message is sent. + JitFn { + instance_ptr: *const Instance<'static>, + trampoline_ptr: *const u8, + tx: mpsc::Sender<*const u8>, + }, +} +unsafe impl Send for UnsafeMessage {} + +impl UnsafeMessage { + /// Send the message. + fn send(self) -> Result<(), mpsc::SendError> { + thread_local! { + /// The Sender owned by the local thread + static LOCAL_MESSAGE_SENDER: Lazy> = Lazy::new(|| + GLOBAL_MESSAGE_SENDER + .get().unwrap() + .lock().unwrap() + .clone() + ); + } + LOCAL_MESSAGE_SENDER.with(|sender| sender.send(self)) + } +} + fn create_jit_module<'tcx>( tcx: TyCtxt<'tcx>, backend_config: &BackendConfig, hotswap: bool, ) -> (JITModule, CodegenCx<'tcx>) { - let imported_symbols = load_imported_symbols_for_jit(tcx); + let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); + let imported_symbols = load_imported_symbols_for_jit(tcx.sess, crate_info); let isa = crate::build_isa(tcx.sess, backend_config); let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); @@ -116,11 +155,6 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { .chain(backend_config.jit_args.iter().map(|arg| &**arg)) .map(|arg| CString::new(arg).unwrap()) .collect::>(); - let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); - - // Push a null pointer as a terminating argument. This is required by POSIX and - // useful as some dynamic linkers use it as a marker to jump over. - argv.push(std::ptr::null()); let start_sig = Signature { params: vec![ @@ -128,7 +162,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { AbiParam::new(jit_module.target_config().pointer_type()), ], returns: vec![AbiParam::new(jit_module.target_config().pointer_type() /*isize*/)], - call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), + call_conv: jit_module.target_config().default_call_conv, }; let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap(); let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id); @@ -141,12 +175,51 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { let f: extern "C" fn(c_int, *const *const c_char) -> c_int = unsafe { ::std::mem::transmute(finalized_start) }; - let ret = f(args.len() as c_int, argv.as_ptr()); - std::process::exit(ret); + + let (tx, rx) = mpsc::channel(); + GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap(); + + // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages + // (eg to lazily JIT further functions as required) + std::thread::spawn(move || { + let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); + + // Push a null pointer as a terminating argument. This is required by POSIX and + // useful as some dynamic linkers use it as a marker to jump over. + argv.push(std::ptr::null()); + + let ret = f(args.len() as c_int, argv.as_ptr()); + std::process::exit(ret); + }); + + // Handle messages + loop { + match rx.recv().unwrap() { + // lazy JIT compilation request - compile requested instance and return pointer to result + UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => { + tx.send(jit_fn(instance_ptr, trampoline_ptr)) + .expect("jitted runtime hung up before response to lazy JIT request was sent"); + } + } + } } #[no_mangle] -extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 { +extern "C" fn __clif_jit_fn( + instance_ptr: *const Instance<'static>, + trampoline_ptr: *const u8, +) -> *const u8 { + // send the JIT request to the rustc thread, with a channel for the response + let (tx, rx) = mpsc::channel(); + UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } + .send() + .expect("rustc thread hung up before lazy JIT request was sent"); + + // block on JIT compilation result + rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request") +} + +fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 { rustc_middle::ty::tls::with(|tcx| { // lift is used to ensure the correct lifetime for instance. let instance = tcx.lift(unsafe { *instance_ptr }).unwrap(); @@ -160,6 +233,17 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 let name = tcx.symbol_name(instance).name; let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance); let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap(); + + let current_ptr = jit_module.read_got_entry(func_id); + + // If the function's GOT entry has already been updated to point at something other + // than the shim trampoline, don't re-jit but just return the new pointer instead. + // This does not need synchronization as this code is executed only by a sole rustc + // thread. + if current_ptr != trampoline_ptr { + return current_ptr; + } + jit_module.prepare_for_function_redefine(func_id).unwrap(); let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module.isa(), false); @@ -173,14 +257,16 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 }) } -fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> { +fn load_imported_symbols_for_jit( + sess: &Session, + crate_info: CrateInfo, +) -> Vec<(String, *const u8)> { use rustc_middle::middle::dependency_format::Linkage; let mut dylib_paths = Vec::new(); - let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); - let formats = tcx.dependency_formats(()); - let data = &formats + let data = &crate_info + .dependency_formats .iter() .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable) .unwrap() @@ -190,9 +276,8 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> { match data[cnum.as_usize() - 1] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { - let name = tcx.crate_name(cnum); - let mut err = - tcx.sess.struct_err(&format!("Can't load static lib {}", name.as_str())); + let name = &crate_info.crate_name[&cnum]; + let mut err = sess.struct_err(&format!("Can't load static lib {}", name.as_str())); err.note("rustc_codegen_cranelift can only load dylibs in JIT mode."); err.emit(); } @@ -232,7 +317,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> { std::mem::forget(lib) } - tcx.sess.abort_if_errors(); + sess.abort_if_errors(); imported_symbols } @@ -254,7 +339,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In Linkage::Import, &Signature { call_conv: module.target_config().default_call_conv, - params: vec![AbiParam::new(pointer_type)], + params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)], returns: vec![AbiParam::new(pointer_type)], }, ) @@ -267,6 +352,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In let mut builder_ctx = FunctionBuilderContext::new(); let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx); + let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func); let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func); let sig_ref = trampoline_builder.func.import_signature(sig); @@ -276,7 +362,8 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In trampoline_builder.switch_to_block(entry_block); let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64); - let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr]); + let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn); + let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]); let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0]; let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args); let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec(); diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index ba4ed2162cd5d..be3704ca2768e 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -106,6 +106,26 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout()); dest.write_cvalue(fx, a); }; + "llvm.x86.addcarry.64", (v c_in, c a, c b) { + llvm_add_sub( + fx, + BinOp::Add, + ret, + c_in, + a, + b + ); + }; + "llvm.x86.subborrow.64", (v b_in, c a, c b) { + llvm_add_sub( + fx, + BinOp::Sub, + ret, + b_in, + a, + b + ); + }; } if let Some((_, dest)) = destination { @@ -121,3 +141,41 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( // llvm.x86.avx2.pshuf.b // llvm.x86.avx2.psrli.w // llvm.x86.sse2.psrli.w + +fn llvm_add_sub<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + bin_op: BinOp, + ret: CPlace<'tcx>, + cb_in: Value, + a: CValue<'tcx>, + b: CValue<'tcx>, +) { + assert_eq!( + a.layout().ty, + fx.tcx.types.u64, + "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64" + ); + assert_eq!( + b.layout().ty, + fx.tcx.types.u64, + "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64" + ); + + // c + carry -> c + first intermediate carry or borrow respectively + let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b); + let c = int0.value_field(fx, mir::Field::new(0)); + let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx); + + // c + carry -> c + second intermediate carry or borrow respectively + let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in); + let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64)); + let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64); + let (c, cb1) = int1.load_scalar_pair(fx); + + // carry0 | carry1 -> carry or borrow respectively + let cb_out = fx.bcx.ins().bor(cb0, cb1); + + let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter())); + let val = CValue::by_val_pair(cb_out, c, layout); + ret.write_cvalue(fx, val); +} diff --git a/src/lib.rs b/src/lib.rs index ebf98e8694b78..cb1cb3c74dbb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)] +#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts, once_cell)] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] @@ -14,7 +14,9 @@ extern crate rustc_fs_util; extern crate rustc_hir; extern crate rustc_incremental; extern crate rustc_index; +extern crate rustc_interface; extern crate rustc_metadata; +extern crate rustc_mir; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; @@ -284,10 +286,12 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box { let mut builder = - cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap(); - // Don't use "haswell" as the default, as it implies `has_lzcnt`. - // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. - builder.enable("nehalem").unwrap(); + cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant).unwrap(); + if target_triple.architecture == target_lexicon::Architecture::X86_64 { + // Don't use "haswell" as the default, as it implies `has_lzcnt`. + // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. + builder.enable("nehalem").unwrap(); + } builder } }; diff --git a/src/optimize/mod.rs b/src/optimize/mod.rs index 137fb5f77313c..61033d85a1274 100644 --- a/src/optimize/mod.rs +++ b/src/optimize/mod.rs @@ -1,17 +1,20 @@ //! Various optimizations specific to cg_clif +use cranelift_codegen::isa::TargetIsa; + use crate::prelude::*; pub(crate) mod peephole; pub(crate) fn optimize_function<'tcx>( tcx: TyCtxt<'tcx>, + isa: &dyn TargetIsa, instance: Instance<'tcx>, ctx: &mut Context, clif_comments: &mut crate::pretty_clif::CommentWriter, ) { // FIXME classify optimizations over opt levels once we have more - crate::pretty_clif::write_clif_file(tcx, "preopt", None, instance, &ctx, &*clif_comments); + crate::pretty_clif::write_clif_file(tcx, "preopt", isa, instance, &ctx, &*clif_comments); crate::base::verify_func(tcx, &*clif_comments, &ctx.func); } diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index cd8c5b5160836..05db74745a1c0 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -233,7 +233,7 @@ pub(crate) fn write_ir_file( pub(crate) fn write_clif_file<'tcx>( tcx: TyCtxt<'tcx>, postfix: &str, - isa: Option<&dyn cranelift_codegen::isa::TargetIsa>, + isa: &dyn cranelift_codegen::isa::TargetIsa, instance: Instance<'tcx>, context: &cranelift_codegen::Context, mut clif_comments: &CommentWriter, @@ -242,22 +242,23 @@ pub(crate) fn write_clif_file<'tcx>( tcx, || format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix), |file| { - let value_ranges = isa - .map(|isa| context.build_value_labels_ranges(isa).expect("value location ranges")); - let mut clif = String::new(); cranelift_codegen::write::decorate_function( &mut clif_comments, &mut clif, &context.func, - &DisplayFunctionAnnotations { isa, value_ranges: value_ranges.as_ref() }, + &DisplayFunctionAnnotations { isa: Some(isa), value_ranges: None }, ) .unwrap(); - writeln!(file, "test compile")?; - writeln!(file, "set is_pic")?; - writeln!(file, "set enable_simd")?; - writeln!(file, "target {} haswell", crate::target_triple(tcx.sess))?; + for flag in isa.flags().iter() { + writeln!(file, "set {}", flag)?; + } + write!(file, "target {}", isa.triple().architecture.to_string())?; + for isa_flag in isa.isa_flags().iter() { + write!(file, " {}", isa_flag)?; + } + writeln!(file, "\n")?; writeln!(file)?; file.write_all(clif.as_bytes())?; Ok(()) diff --git a/src/vtable.rs b/src/vtable.rs index 12f7092d935a3..4a5f9f133a2bb 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -1,10 +1,9 @@ //! Codegen vtables and vtable accesses. //! //! See `rustc_codegen_ssa/src/meth.rs` for reference. -// FIXME dedup this logic between miri, cg_llvm and cg_clif +use crate::constant::data_id_for_alloc_id; use crate::prelude::*; -use super::constant::pointer_for_allocation; fn vtable_memflags() -> MemFlags { let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap. @@ -38,7 +37,7 @@ pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) - pointer_ty(fx.tcx), vtable_memflags(), vtable, - (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32, + (ty::COMMON_VTABLE_ENTRIES_ALIGN * usize_size) as i32, ) } @@ -69,16 +68,12 @@ pub(crate) fn get_vtable<'tcx>( ty: Ty<'tcx>, trait_ref: Option>, ) -> Value { - let vtable_ptr = if let Some(vtable_ptr) = fx.vtables.get(&(ty, trait_ref)) { - *vtable_ptr - } else { - let vtable_alloc_id = fx.tcx.vtable_allocation(ty, trait_ref); - let vtable_allocation = fx.tcx.global_alloc(vtable_alloc_id).unwrap_memory(); - let vtable_ptr = pointer_for_allocation(fx, vtable_allocation); - - fx.vtables.insert((ty, trait_ref), vtable_ptr); - vtable_ptr - }; - - vtable_ptr.get_addr(fx) + let alloc_id = fx.tcx.vtable_allocation(ty, trait_ref); + let data_id = + data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not); + let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id)); + } + fx.bcx.ins().global_value(fx.pointer_type, local_data_id) } diff --git a/test.sh b/test.sh index e222adc7b8058..a10924628bb0e 100755 --- a/test.sh +++ b/test.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash set -e -./build.sh --sysroot none "$@" +./y.rs build --sysroot none "$@" rm -r target/out || true scripts/tests.sh no_sysroot -./build.sh "$@" +./y.rs build "$@" scripts/tests.sh base_sysroot scripts/tests.sh extended_sysroot diff --git a/y.rs b/y.rs new file mode 100755 index 0000000000000..43937588b481d --- /dev/null +++ b/y.rs @@ -0,0 +1,153 @@ +#!/usr/bin/env bash +#![allow()] /*This line is ignored by bash +# This block is ignored by rustc +set -e +echo "[BUILD] y.rs" 1>&2 +rustc $0 -o ${0/.rs/.bin} -g +exec ${0/.rs/.bin} $@ +*/ + +//! The build system for cg_clif +//! +//! # Manual compilation +//! +//! If your system doesn't support shell scripts you can manually compile and run this file using +//! for example: +//! +//! ```shell +//! $ rustc y.rs -o build/y.bin +//! $ build/y.bin +//! ``` +//! +//! # Naming +//! +//! The name `y.rs` was chosen to not conflict with rustc's `x.py`. + +use std::env; +use std::path::PathBuf; +use std::process; + +#[path = "build_system/build_backend.rs"] +mod build_backend; +#[path = "build_system/build_sysroot.rs"] +mod build_sysroot; +#[path = "build_system/config.rs"] +mod config; +#[path = "build_system/prepare.rs"] +mod prepare; +#[path = "build_system/rustc_info.rs"] +mod rustc_info; +#[path = "build_system/utils.rs"] +mod utils; + +fn usage() { + eprintln!("Usage:"); + eprintln!(" ./y.rs prepare"); + eprintln!(" ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]"); +} + +macro_rules! arg_error { + ($($err:tt)*) => {{ + eprintln!($($err)*); + usage(); + std::process::exit(1); + }}; +} + +enum Command { + Build, +} + +#[derive(Copy, Clone)] +enum SysrootKind { + None, + Clif, + Llvm, +} + +fn main() { + env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1"); + env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1"); + // The target dir is expected in the default location. Guard against the user changing it. + env::set_var("CARGO_TARGET_DIR", "target"); + + let mut args = env::args().skip(1); + let command = match args.next().as_deref() { + Some("prepare") => { + if args.next().is_some() { + arg_error!("./x.rs prepare doesn't expect arguments"); + } + prepare::prepare(); + process::exit(0); + } + Some("build") => Command::Build, + Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), + Some(command) => arg_error!("Unknown command {}", command), + None => { + usage(); + process::exit(0); + } + }; + + let mut target_dir = PathBuf::from("build"); + let mut channel = "release"; + let mut sysroot_kind = SysrootKind::Clif; + while let Some(arg) = args.next().as_deref() { + match arg { + "--target-dir" => { + target_dir = PathBuf::from(args.next().unwrap_or_else(|| { + arg_error!("--target-dir requires argument"); + })) + } + "--debug" => channel = "debug", + "--sysroot" => { + sysroot_kind = match args.next().as_deref() { + Some("none") => SysrootKind::None, + Some("clif") => SysrootKind::Clif, + Some("llvm") => SysrootKind::Llvm, + Some(arg) => arg_error!("Unknown sysroot kind {}", arg), + None => arg_error!("--sysroot requires argument"), + } + } + flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag), + arg => arg_error!("Unexpected argument {}", arg), + } + } + + let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { + host_triple + } else if let Some(host_triple) = crate::config::get_value("host") { + host_triple + } else { + rustc_info::get_host_triple() + }; + let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { + if target_triple != "" { + target_triple + } else { + host_triple.clone() // Empty target triple can happen on GHA + } + } else if let Some(target_triple) = crate::config::get_value("target") { + target_triple + } else { + host_triple.clone() + }; + + if target_triple.ends_with("-msvc") { + eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); + eprintln!("Switch to the MinGW toolchain for Windows support."); + eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); + eprintln!("set the global default target to MinGW"); + process::exit(1); + } + + let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple); + build_sysroot::build_sysroot( + channel, + sysroot_kind, + &target_dir, + cg_clif_build_dir, + &host_triple, + &target_triple, + ); +} From ab4da1174c9bc85e85c7348576f913327ebc9f0d Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 8 Jul 2021 18:03:50 +0200 Subject: [PATCH 05/58] Rustup to rustc 1.55.0-nightly (d2b04f075 2021-07-07) --- build_sysroot/Cargo.lock | 4 ++-- rust-toolchain | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index 46f661107e73b..431688abfa26c 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -132,9 +132,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.97" +version = "0.2.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" +checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" dependencies = [ "rustc-std-workspace-core", ] diff --git a/rust-toolchain b/rust-toolchain index f806f7bdcd98a..586b05a071903 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-07-07" +channel = "nightly-2021-07-08" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From ea8d9aefdaa92526018c0de76090fb35c545faa9 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 30 May 2021 18:04:07 -0700 Subject: [PATCH 06/58] Implement the raw_eq intrinsic in codegen_cranelift --- src/intrinsics/mod.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/value_and_place.rs | 6 ++++++ 2 files changed, 45 insertions(+) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 52896fc7127e8..3e658cb121138 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1115,6 +1115,45 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( ); ret.write_cvalue(fx, CValue::by_val(res, ret.layout())); }; + + raw_eq, (v lhs_ref, v rhs_ref) { + fn type_by_size(size: Size) -> Option { + Some(match size.bits() { + 8 => types::I8, + 16 => types::I16, + 32 => types::I32, + 64 => types::I64, + 128 => types::I128, + _ => return None, + }) + } + + let size = fx.layout_of(T).layout.size; + let is_eq_value = + if size == Size::ZERO { + // No bytes means they're trivially equal + fx.bcx.ins().bconst(types::B1, true) + } else if let Some(clty) = type_by_size(size) { + // Can't use `trusted` for these loads; they could be unaligned. + let mut flags = MemFlags::new(); + flags.set_notrap(); + let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); + let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); + fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val) + } else { + // Just call `memcmp` (like slices do in core) when the + // size is too large or it's not a power-of-two. + let ptr_ty = pointer_ty(fx.tcx); + let signed_bytes = i64::try_from(size.bytes()).unwrap(); + let bytes_val = fx.bcx.ins().iconst(ptr_ty, signed_bytes); + let params = vec![AbiParam::new(ptr_ty); 3]; + let returns = vec![AbiParam::new(types::I32)]; + let args = &[lhs_ref, rhs_ref, bytes_val]; + let cmp = fx.lib_call("memcmp", params, returns, args)[0]; + fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0) + }; + ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout())); + }; } if let Some((_, dest)) = destination { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 171f39805f896..b6f5f5707fbc5 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -437,6 +437,12 @@ impl<'tcx> CPlace<'tcx> { | (types::F32, types::I32) | (types::I64, types::F64) | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data), + + // Widen an abstract SSA boolean to something that can be stored in memory + (types::B1, types::I8 | types::I16 | types::I32 | types::I64 | types::I128) => { + fx.bcx.ins().bint(dst_ty, data) + } + _ if src_ty.is_vector() && dst_ty.is_vector() => { fx.bcx.ins().raw_bitcast(dst_ty, data) } From 7a0574d826d3bb03941b5cc80bfe99e8e5742aa0 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 31 May 2021 10:26:08 -0700 Subject: [PATCH 07/58] PR Feedback: Don't put SSA-only types in `CValue`s --- src/intrinsics/mod.rs | 8 +++++--- src/value_and_place.rs | 10 ++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 3e658cb121138..31f7e0d4e37b1 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1132,14 +1132,15 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( let is_eq_value = if size == Size::ZERO { // No bytes means they're trivially equal - fx.bcx.ins().bconst(types::B1, true) + fx.bcx.ins().iconst(types::I8, 1) } else if let Some(clty) = type_by_size(size) { // Can't use `trusted` for these loads; they could be unaligned. let mut flags = MemFlags::new(); flags.set_notrap(); let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); - fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val) + let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val); + fx.bcx.ins().bint(types::I8, eq) } else { // Just call `memcmp` (like slices do in core) when the // size is too large or it's not a power-of-two. @@ -1150,7 +1151,8 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( let returns = vec![AbiParam::new(types::I32)]; let args = &[lhs_ref, rhs_ref, bytes_val]; let cmp = fx.lib_call("memcmp", params, returns, args)[0]; - fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0) + let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0); + fx.bcx.ins().bint(types::I8, eq) }; ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout())); }; diff --git a/src/value_and_place.rs b/src/value_and_place.rs index b6f5f5707fbc5..ae8ccc626b470 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -437,12 +437,6 @@ impl<'tcx> CPlace<'tcx> { | (types::F32, types::I32) | (types::I64, types::F64) | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data), - - // Widen an abstract SSA boolean to something that can be stored in memory - (types::B1, types::I8 | types::I16 | types::I32 | types::I64 | types::I128) => { - fx.bcx.ins().bint(dst_ty, data) - } - _ if src_ty.is_vector() && dst_ty.is_vector() => { fx.bcx.ins().raw_bitcast(dst_ty, data) } @@ -459,6 +453,10 @@ impl<'tcx> CPlace<'tcx> { ptr.store(fx, data, MemFlags::trusted()); ptr.load(fx, dst_ty, MemFlags::trusted()) } + + // `CValue`s should never contain SSA-only types, so if you ended + // up here having seen an error like `B1 -> I8`, then before + // calling `write_cvalue` you need to add a `bint` instruction. _ => unreachable!("write_cvalue_transmute: {:?} -> {:?}", src_ty, dst_ty), }; //fx.bcx.set_val_label(data, cranelift_codegen::ir::ValueLabel::new(var.index())); From e3091d74d876bbb6b02cf218b064ee47d1551e41 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 1 Jun 2021 06:19:49 -0700 Subject: [PATCH 08/58] Use cranelift's `Type::int` instead of doing the match myself --- src/intrinsics/mod.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 31f7e0d4e37b1..3979886e10cfc 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1118,14 +1118,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( raw_eq, (v lhs_ref, v rhs_ref) { fn type_by_size(size: Size) -> Option { - Some(match size.bits() { - 8 => types::I8, - 16 => types::I16, - 32 => types::I32, - 64 => types::I64, - 128 => types::I128, - _ => return None, - }) + Type::int(size.bits().try_into().ok()?) } let size = fx.layout_of(T).layout.size; From e7a43236742ee52523b48bbc4fdd325b995b18f0 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 13 Jul 2021 21:32:23 +0200 Subject: [PATCH 09/58] Remove explicit branch="main" form Cargo.toml --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 56d0974b25371..656af7ec98e9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,7 +34,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-entity", ] @@ -42,7 +42,7 @@ dependencies = [ [[package]] name = "cranelift-codegen" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -58,7 +58,7 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -67,17 +67,17 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" [[package]] name = "cranelift-entity" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" [[package]] name = "cranelift-frontend" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen", "log", @@ -88,7 +88,7 @@ dependencies = [ [[package]] name = "cranelift-jit" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", @@ -105,7 +105,7 @@ dependencies = [ [[package]] name = "cranelift-module" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", @@ -116,7 +116,7 @@ dependencies = [ [[package]] name = "cranelift-native" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen", "libc", @@ -126,7 +126,7 @@ dependencies = [ [[package]] name = "cranelift-object" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", diff --git a/Cargo.toml b/Cargo.toml index ef68d7ee532dd..2e34717f419f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind", "all-arch"] } -cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } -cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } -cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } -cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", optional = true } -cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } +cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", features = ["unwind", "all-arch"] } +cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git" } +cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git" } +cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git" } +cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", optional = true } +cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git" } target-lexicon = "0.12.0" gimli = { version = "0.24.0", default-features = false, features = ["write"]} object = { version = "0.25.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } From e643b8b56123d81c30bda7c82d1b8a00e47a8c43 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 13 Jul 2021 00:41:10 +0200 Subject: [PATCH 10/58] fix cranelift --- src/constant.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/constant.rs b/src/constant.rs index 2a2573aad2950..c87309e22224f 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -193,20 +193,21 @@ pub(crate) fn codegen_const_value<'tcx>( place.to_cvalue(fx) } } - Scalar::Ptr(ptr) => { - let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id); + Scalar::Ptr(ptr, _size) => { + let (alloc_id, offset) = ptr.into_parts(); // we know the `offset` is relative + let alloc_kind = fx.tcx.get_global_alloc(alloc_id); let base_addr = match alloc_kind { Some(GlobalAlloc::Memory(alloc)) => { let data_id = data_id_for_alloc_id( &mut fx.constants_cx, fx.module, - ptr.alloc_id, + alloc_id, alloc.mutability, ); let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); if fx.clif_comments.enabled() { - fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id)); + fx.add_comment(local_data_id, format!("{:?}", alloc_id)); } fx.bcx.ins().global_value(fx.pointer_type, local_data_id) } @@ -226,10 +227,10 @@ pub(crate) fn codegen_const_value<'tcx>( } fx.bcx.ins().global_value(fx.pointer_type, local_data_id) } - None => bug!("missing allocation {:?}", ptr.alloc_id), + None => bug!("missing allocation {:?}", alloc_id), }; - let val = if ptr.offset.bytes() != 0 { - fx.bcx.ins().iadd_imm(base_addr, i64::try_from(ptr.offset.bytes()).unwrap()) + let val = if offset.bytes() != 0 { + fx.bcx.ins().iadd_imm(base_addr, i64::try_from(offset.bytes()).unwrap()) } else { base_addr }; @@ -406,7 +407,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec(); data_ctx.define(bytes.into_boxed_slice()); - for &(offset, (_tag, reloc)) in alloc.relocations().iter() { + for &(offset, alloc_id) in alloc.relocations().iter() { let addend = { let endianness = tcx.data_layout.endian; let offset = offset.bytes() as usize; @@ -417,7 +418,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant read_target_uint(endianness, bytes).unwrap() }; - let reloc_target_alloc = tcx.get_global_alloc(reloc).unwrap(); + let reloc_target_alloc = tcx.get_global_alloc(alloc_id).unwrap(); let data_id = match reloc_target_alloc { GlobalAlloc::Function(instance) => { assert_eq!(addend, 0); @@ -427,7 +428,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant continue; } GlobalAlloc::Memory(target_alloc) => { - data_id_for_alloc_id(cx, module, reloc, target_alloc.mutability) + data_id_for_alloc_id(cx, module, alloc_id, target_alloc.mutability) } GlobalAlloc::Static(def_id) => { if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) From b47198aaa1531fe8b470ca56d9cfa41dbbbc335d Mon Sep 17 00:00:00 2001 From: Richard Cobbe Date: Mon, 12 Jul 2021 12:46:27 -0700 Subject: [PATCH 11/58] Consider all fields when comparing DllImports, to remove nondetermininsm in multiple-definitions test --- src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cb1cb3c74dbb5..e32dae49131ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -221,9 +221,7 @@ impl CodegenBackend for CraneliftCodegenBackend { sess, &codegen_results, outputs, - ); - - Ok(()) + ) } } From 17eaf432b77f92b5033383a62a52b76be9ff196f Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 17 Jul 2021 14:34:40 +0200 Subject: [PATCH 12/58] Update Cranelift --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 656af7ec98e9e..afb4d986409ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,7 +34,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" dependencies = [ "cranelift-entity", ] @@ -42,7 +42,7 @@ dependencies = [ [[package]] name = "cranelift-codegen" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -58,7 +58,7 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -67,17 +67,17 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" [[package]] name = "cranelift-entity" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" [[package]] name = "cranelift-frontend" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" dependencies = [ "cranelift-codegen", "log", @@ -88,7 +88,7 @@ dependencies = [ [[package]] name = "cranelift-jit" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" dependencies = [ "anyhow", "cranelift-codegen", @@ -105,7 +105,7 @@ dependencies = [ [[package]] name = "cranelift-module" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" dependencies = [ "anyhow", "cranelift-codegen", @@ -116,7 +116,7 @@ dependencies = [ [[package]] name = "cranelift-native" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" dependencies = [ "cranelift-codegen", "libc", @@ -126,7 +126,7 @@ dependencies = [ [[package]] name = "cranelift-object" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" +source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" dependencies = [ "anyhow", "cranelift-codegen", From f7cfb9d6d5abee6c3774fa7530f3fbf4e174137a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 5 Jul 2021 18:02:12 +0200 Subject: [PATCH 13/58] Remove shl/shr special handling for 128bit ints Cranelift now natively supports 128bit int shifting --- src/codegen_i128.rs | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs index ffe1922ab9056..22d7f1da0b550 100644 --- a/src/codegen_i128.rs +++ b/src/codegen_i128.rs @@ -19,9 +19,6 @@ pub(crate) fn maybe_codegen<'tcx>( return None; } - let lhs_val = lhs.load_scalar(fx); - let rhs_val = rhs.load_scalar(fx); - let is_signed = type_sign(lhs.layout().ty); match bin_op { @@ -128,40 +125,6 @@ pub(crate) fn maybe_codegen<'tcx>( assert!(!checked); None } - BinOp::Shl | BinOp::Shr => { - let is_overflow = if checked { - // rhs >= 128 - - // FIXME support non 128bit rhs - /*let (rhs_lsb, rhs_msb) = fx.bcx.ins().isplit(rhs_val); - let rhs_msb_gt_0 = fx.bcx.ins().icmp_imm(IntCC::NotEqual, rhs_msb, 0); - let rhs_lsb_ge_128 = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThan, rhs_lsb, 127); - let is_overflow = fx.bcx.ins().bor(rhs_msb_gt_0, rhs_lsb_ge_128);*/ - let is_overflow = fx.bcx.ins().bconst(types::B1, false); - - Some(fx.bcx.ins().bint(types::I8, is_overflow)) - } else { - None - }; - - let truncated_rhs = clif_intcast(fx, rhs_val, types::I32, false); - let val = match bin_op { - BinOp::Shl => fx.bcx.ins().ishl(lhs_val, truncated_rhs), - BinOp::Shr => { - if is_signed { - fx.bcx.ins().sshr(lhs_val, truncated_rhs) - } else { - fx.bcx.ins().ushr(lhs_val, truncated_rhs) - } - } - _ => unreachable!(), - }; - if let Some(is_overflow) = is_overflow { - let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); - Some(CValue::by_val_pair(val, is_overflow, fx.layout_of(out_ty))) - } else { - Some(CValue::by_val(val, lhs.layout())) - } - } + BinOp::Shl | BinOp::Shr => None, } } From 6dc386e1923be6d6b57f2efca13777eed15ee0b7 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 5 Jul 2021 18:04:52 +0200 Subject: [PATCH 14/58] Don't truncate the shift amount It isn't actually necessary --- src/num.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/num.rs b/src/num.rs index b6d378a5fe10a..1a0cf939b2fa8 100644 --- a/src/num.rs +++ b/src/num.rs @@ -293,9 +293,8 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( } BinOp::Shl => { let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let actual_shift = clif_intcast(fx, actual_shift, types::I8, false); - let val = fx.bcx.ins().ishl(lhs, actual_shift); + let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); + let val = fx.bcx.ins().ishl(lhs, masked_shift); let ty = fx.bcx.func.dfg.value_type(val); let max_shift = i64::from(ty.bits()) - 1; let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); @@ -303,12 +302,11 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( } BinOp::Shr => { let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let actual_shift = clif_intcast(fx, actual_shift, types::I8, false); + let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); let val = if !signed { - fx.bcx.ins().ushr(lhs, actual_shift) + fx.bcx.ins().ushr(lhs, masked_shift) } else { - fx.bcx.ins().sshr(lhs, actual_shift) + fx.bcx.ins().sshr(lhs, masked_shift) }; let ty = fx.bcx.func.dfg.value_type(val); let max_shift = i64::from(ty.bits()) - 1; From ede41d1b984d51c6023eb7381930600fa3c143aa Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 17 Jul 2021 15:03:18 +0200 Subject: [PATCH 15/58] [CI] Update package list before installing packages --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f81ac87726052..f524b42c5eecd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,12 +49,14 @@ jobs: - name: Install MinGW toolchain and wine if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: | + sudo apt-get update sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable rustup target add x86_64-pc-windows-gnu - name: Install AArch64 toolchain and qemu if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu' run: | + sudo apt-get update sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user - name: Prepare dependencies From 60340d44d84dedd7112d2773bf949b606b40cb4a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 17 Jul 2021 16:07:27 +0200 Subject: [PATCH 16/58] Don't panic when the target is not supported by Cranelift --- src/lib.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cb1cb3c74dbb5..c7b3ad9604811 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,18 +217,17 @@ impl CodegenBackend for CraneliftCodegenBackend { ) -> Result<(), ErrorReported> { use rustc_codegen_ssa::back::link::link_binary; - link_binary::>( - sess, - &codegen_results, - outputs, - ); + link_binary::>(sess, &codegen_results, outputs); Ok(()) } } fn target_triple(sess: &Session) -> target_lexicon::Triple { - sess.target.llvm_target.parse().unwrap() + match sess.target.llvm_target.parse() { + Ok(triple) => triple, + Err(err) => sess.fatal(&format!("target not recognized: {}", err)), + } } fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box { @@ -278,15 +277,21 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box { let mut builder = - cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap(); + cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant) + .unwrap_or_else(|err| { + sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); + }); if let Err(_) = builder.enable(value) { - sess.fatal("The specified target cpu isn't currently supported by Cranelift."); + sess.fatal("the specified target cpu isn't currently supported by Cranelift."); } builder } None => { let mut builder = - cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant).unwrap(); + cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant) + .unwrap_or_else(|err| { + sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); + }); if target_triple.architecture == target_lexicon::Architecture::X86_64 { // Don't use "haswell" as the default, as it implies `has_lzcnt`. // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. From 80b9e36709019f98f6bdc33e632641861e470128 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 17 Jul 2021 16:32:55 +0200 Subject: [PATCH 17/58] Put all cg_clif specific options behind -Zunstable-features --- docs/usage.md | 4 ++-- scripts/cargo.rs | 12 ++++++++++-- scripts/filter_profile.rs | 2 +- scripts/tests.sh | 8 ++++---- src/lib.rs | 3 +++ 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 956d5905a97ad..87eec0e818bb2 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -36,7 +36,7 @@ $ $cg_clif_dir/build/cargo jit or ```bash -$ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs +$ $cg_clif_dir/build/bin/cg_clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs ``` There is also an experimental lazy jit mode. In this mode functions are only compiled once they are @@ -52,7 +52,7 @@ These are a few functions that allow you to easily run rust code from the shell ```bash function jit_naked() { - echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Cllvm-args=mode=jit -Cprefer-dynamic + echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic } function jit() { diff --git a/scripts/cargo.rs b/scripts/cargo.rs index b7e8dd4497479..89ec8da77d3ec 100644 --- a/scripts/cargo.rs +++ b/scripts/cargo.rs @@ -44,7 +44,11 @@ fn main() { ); std::array::IntoIter::new(["rustc".to_string()]) .chain(env::args().skip(2)) - .chain(["--".to_string(), "-Cllvm-args=mode=jit".to_string()]) + .chain([ + "--".to_string(), + "-Zunstable-features".to_string(), + "-Cllvm-args=mode=jit".to_string(), + ]) .collect() } Some("lazy-jit") => { @@ -54,7 +58,11 @@ fn main() { ); std::array::IntoIter::new(["rustc".to_string()]) .chain(env::args().skip(2)) - .chain(["--".to_string(), "-Cllvm-args=mode=jit-lazy".to_string()]) + .chain([ + "--".to_string(), + "-Zunstable-features".to_string(), + "-Cllvm-args=mode=jit-lazy".to_string(), + ]) .collect() } _ => env::args().skip(1).collect(), diff --git a/scripts/filter_profile.rs b/scripts/filter_profile.rs index 9e196afbe4f57..c4801a0a87b88 100755 --- a/scripts/filter_profile.rs +++ b/scripts/filter_profile.rs @@ -5,7 +5,7 @@ pushd $(dirname "$0")/../ source scripts/config.sh RUSTC="$(pwd)/build/bin/cg_clif" popd -PROFILE=$1 OUTPUT=$2 exec $RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic $0 +PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0 #*/ //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse diff --git a/scripts/tests.sh b/scripts/tests.sh index 5df04c533a70e..08c07dfad428e 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -16,10 +16,10 @@ function no_sysroot_tests() { if [[ "$JIT_SUPPORTED" = "1" ]]; then echo "[JIT] mini_core_hello_world" - CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE" + CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE" echo "[JIT-lazy] mini_core_hello_world" - CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE" + CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE" else echo "[JIT] mini_core_hello_world (skipped)" fi @@ -44,10 +44,10 @@ function base_sysroot_tests() { if [[ "$JIT_SUPPORTED" = "1" ]]; then echo "[JIT] std_example" - $MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" + $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" echo "[JIT-lazy] std_example" - $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" + $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" else echo "[JIT] std_example (skipped)" fi diff --git a/src/lib.rs b/src/lib.rs index c7b3ad9604811..366b9a7e24c5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,6 +184,9 @@ impl CodegenBackend for CraneliftCodegenBackend { let config = if let Some(config) = self.config.clone() { config } else { + if !tcx.sess.unstable_options() && !tcx.sess.opts.cg.llvm_args.is_empty() { + tcx.sess.fatal("`-Z unstable-options` must be passed to allow configuring cg_clif"); + } BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) .unwrap_or_else(|err| tcx.sess.fatal(&err)) }; From c2a9839686c538eb3cf850bb8947ebfe6f28141d Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 17 Jul 2021 16:40:54 +0200 Subject: [PATCH 18/58] Disable jit and inline-asm when building as part of rustc Both features are not yet ready. Inline-asm is only supported on Linux and requires explicitly specifying registers instead of register classes. The jit has usability issues and may require the cg_clif executable in the future. --- Cargo.toml | 3 ++- build_system/build_backend.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2e34717f419f7..02098b135f75b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,8 @@ smallvec = "1.6.1" #gimli = { path = "../" } [features] -default = ["jit", "inline_asm"] +# Enable features not ready to be enabled when compiling as part of rustc +unstable-features = ["jit", "inline_asm"] jit = ["cranelift-jit", "libloading"] inline_asm = [] diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index 1df2bcc4541ca..150b6d01a6b30 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -4,7 +4,7 @@ use std::process::Command; pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf { let mut cmd = Command::new("cargo"); - cmd.arg("build").arg("--target").arg(host_triple); + cmd.arg("build").arg("--target").arg(host_triple).arg("--features").arg("unstable-features"); match channel { "debug" => {} From 0ebb4839f673d911b148639009d264fb7ef02d24 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 19 Jul 2021 15:32:22 +0200 Subject: [PATCH 19/58] Rustup to rustc 1.55.0-nightly (59216858a 2021-07-18) --- build_sysroot/Cargo.lock | 4 ++-- rust-toolchain | 2 +- src/lib.rs | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index 431688abfa26c..5e5c481cd9a6b 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -40,9 +40,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "cc" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" +checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" [[package]] name = "cfg-if" diff --git a/rust-toolchain b/rust-toolchain index 586b05a071903..bc991acda6293 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-07-08" +channel = "nightly-2021-07-19" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/lib.rs b/src/lib.rs index 366b9a7e24c5a..4ef53663ca0d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -220,9 +220,7 @@ impl CodegenBackend for CraneliftCodegenBackend { ) -> Result<(), ErrorReported> { use rustc_codegen_ssa::back::link::link_binary; - link_binary::>(sess, &codegen_results, outputs); - - Ok(()) + link_binary::>(sess, &codegen_results, outputs) } } From 356360836e128e1d1eb11caf6ff5186efb211960 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 19 Jul 2021 15:34:33 +0200 Subject: [PATCH 20/58] Avoid call to pointer_ty --- src/intrinsics/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 3979886e10cfc..42483230fdc74 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1122,6 +1122,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( } let size = fx.layout_of(T).layout.size; + // FIXME add and use emit_small_memcmp let is_eq_value = if size == Size::ZERO { // No bytes means they're trivially equal @@ -1137,10 +1138,9 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( } else { // Just call `memcmp` (like slices do in core) when the // size is too large or it's not a power-of-two. - let ptr_ty = pointer_ty(fx.tcx); let signed_bytes = i64::try_from(size.bytes()).unwrap(); - let bytes_val = fx.bcx.ins().iconst(ptr_ty, signed_bytes); - let params = vec![AbiParam::new(ptr_ty); 3]; + let bytes_val = fx.bcx.ins().iconst(fx.pointer_type, signed_bytes); + let params = vec![AbiParam::new(fx.pointer_type); 3]; let returns = vec![AbiParam::new(types::I32)]; let args = &[lhs_ref, rhs_ref, bytes_val]; let cmp = fx.lib_call("memcmp", params, returns, args)[0]; From c42be7975ff50d38b577013fb367195829a92c11 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 23 Jul 2021 18:23:13 +0200 Subject: [PATCH 21/58] Support repr(simd) on ADTs containing a single array field This is the cg_clif half of rust PR 78863 --- src/intrinsics/mod.rs | 24 +++++++--------- src/intrinsics/simd.rs | 17 ++++++----- src/value_and_place.rs | 64 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 23 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 42483230fdc74..a6983749a26ab 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -175,12 +175,11 @@ fn simd_for_each_lane<'tcx>( assert_eq!(lane_count, ret_lane_count); for lane_idx in 0..lane_count { - let lane_idx = mir::Field::new(lane_idx.try_into().unwrap()); - let lane = val.value_field(fx, lane_idx).load_scalar(fx); + let lane = val.value_lane(fx, lane_idx).load_scalar(fx); let res_lane = f(fx, lane_layout, ret_lane_layout, lane); - ret.place_field(fx, lane_idx).write_cvalue(fx, res_lane); + ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane); } } @@ -206,14 +205,13 @@ fn simd_pair_for_each_lane<'tcx>( let ret_lane_layout = fx.layout_of(ret_lane_ty); assert_eq!(lane_count, ret_lane_count); - for lane in 0..lane_count { - let lane = mir::Field::new(lane.try_into().unwrap()); - let x_lane = x.value_field(fx, lane).load_scalar(fx); - let y_lane = y.value_field(fx, lane).load_scalar(fx); + for lane_idx in 0..lane_count { + let x_lane = x.value_lane(fx, lane_idx).load_scalar(fx); + let y_lane = y.value_lane(fx, lane_idx).load_scalar(fx); let res_lane = f(fx, lane_layout, ret_lane_layout, x_lane, y_lane); - ret.place_field(fx, lane).write_cvalue(fx, res_lane); + ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane); } } @@ -227,10 +225,9 @@ fn simd_reduce<'tcx>( let lane_layout = fx.layout_of(lane_ty); assert_eq!(lane_layout, ret.layout()); - let mut res_val = val.value_field(fx, mir::Field::new(0)).load_scalar(fx); + let mut res_val = val.value_lane(fx, 0).load_scalar(fx); for lane_idx in 1..lane_count { - let lane = - val.value_field(fx, mir::Field::new(lane_idx.try_into().unwrap())).load_scalar(fx); + let lane = val.value_lane(fx, lane_idx).load_scalar(fx); res_val = f(fx, lane_layout, res_val, lane); } let res = CValue::by_val(res_val, lane_layout); @@ -246,11 +243,10 @@ fn simd_reduce_bool<'tcx>( let (lane_count, _lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx); assert!(ret.layout().ty.is_bool()); - let res_val = val.value_field(fx, mir::Field::new(0)).load_scalar(fx); + let res_val = val.value_lane(fx, 0).load_scalar(fx); let mut res_val = fx.bcx.ins().band_imm(res_val, 1); // mask to boolean for lane_idx in 1..lane_count { - let lane = - val.value_field(fx, mir::Field::new(lane_idx.try_into().unwrap())).load_scalar(fx); + let lane = val.value_lane(fx, lane_idx).load_scalar(fx); let lane = fx.bcx.ins().band_imm(lane, 1); // mask to boolean res_val = f(fx, res_val, lane); } diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index c2f469fa021e1..e952942de8777 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -108,11 +108,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( for (out_idx, in_idx) in indexes.into_iter().enumerate() { let in_lane = if u64::from(in_idx) < lane_count { - x.value_field(fx, mir::Field::new(in_idx.into())) + x.value_lane(fx, in_idx.into()) } else { - y.value_field(fx, mir::Field::new(usize::from(in_idx) - usize::try_from(lane_count).unwrap())) + y.value_lane(fx, u64::from(in_idx) - lane_count) }; - let out_lane = ret.place_field(fx, mir::Field::new(out_idx)); + let out_lane = ret.place_lane(fx, u64::try_from(out_idx).unwrap()); out_lane.write_cvalue(fx, in_lane); } }; @@ -163,7 +163,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count)); } - let ret_lane = v.value_field(fx, mir::Field::new(idx.try_into().unwrap())); + let ret_lane = v.value_lane(fx, idx.try_into().unwrap()); ret.write_cvalue(fx, ret_lane); }; @@ -216,15 +216,14 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let ret_lane_layout = fx.layout_of(ret_lane_ty); for lane in 0..lane_count { - let lane = mir::Field::new(lane.try_into().unwrap()); - let a_lane = a.value_field(fx, lane).load_scalar(fx); - let b_lane = b.value_field(fx, lane).load_scalar(fx); - let c_lane = c.value_field(fx, lane).load_scalar(fx); + let a_lane = a.value_lane(fx, lane).load_scalar(fx); + let b_lane = b.value_lane(fx, lane).load_scalar(fx); + let c_lane = c.value_lane(fx, lane).load_scalar(fx); let mul_lane = fx.bcx.ins().fmul(a_lane, b_lane); let res_lane = CValue::by_val(fx.bcx.ins().fadd(mul_lane, c_lane), ret_lane_layout); - ret.place_field(fx, lane).write_cvalue(fx, res_lane); + ret.place_lane(fx, lane).write_cvalue(fx, res_lane); } }; diff --git a/src/value_and_place.rs b/src/value_and_place.rs index ae8ccc626b470..b1e00360d566a 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -206,6 +206,38 @@ impl<'tcx> CValue<'tcx> { } } + /// Like [`CValue::value_field`] except handling ADTs containing a single array field in a way + /// such that you can access individual lanes. + pub(crate) fn value_lane( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + lane_idx: u64, + ) -> CValue<'tcx> { + let layout = self.1; + assert!(layout.ty.is_simd()); + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + assert!(lane_idx < lane_count); + match self.0 { + CValueInner::ByVal(val) => match layout.abi { + Abi::Vector { element: _, count: _ } => { + assert!(lane_count <= u8::MAX.into(), "SIMD type with more than 255 lanes???"); + let lane_idx = u8::try_from(lane_idx).unwrap(); + let lane = fx.bcx.ins().extractlane(val, lane_idx); + CValue::by_val(lane, lane_layout) + } + _ => unreachable!("value_lane for ByVal with abi {:?}", layout.abi), + }, + CValueInner::ByValPair(_, _) => unreachable!(), + CValueInner::ByRef(ptr, None) => { + let field_offset = lane_layout.size * lane_idx; + let field_ptr = ptr.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()); + CValue::by_ref(field_ptr, lane_layout) + } + CValueInner::ByRef(_, Some(_)) => unreachable!(), + } + } + pub(crate) fn unsize_value(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) { crate::unsize::coerce_unsized_into(fx, self, dest); } @@ -610,6 +642,38 @@ impl<'tcx> CPlace<'tcx> { } } + /// Like [`CPlace::place_field`] except handling ADTs containing a single array field in a way + /// such that you can access individual lanes. + pub(crate) fn place_lane( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + lane_idx: u64, + ) -> CPlace<'tcx> { + let layout = self.layout(); + assert!(layout.ty.is_simd()); + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + assert!(lane_idx < lane_count); + + match self.inner { + CPlaceInner::Var(local, var) => { + assert!(matches!(layout.abi, Abi::Vector { .. })); + CPlace { + inner: CPlaceInner::VarLane(local, var, lane_idx.try_into().unwrap()), + layout: lane_layout, + } + } + CPlaceInner::VarPair(_, _, _) => unreachable!(), + CPlaceInner::VarLane(_, _, _) => unreachable!(), + CPlaceInner::Addr(ptr, None) => { + let field_offset = lane_layout.size * lane_idx; + let field_ptr = ptr.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()); + CPlace::for_ptr(field_ptr, lane_layout) + } + CPlaceInner::Addr(_, Some(_)) => unreachable!(), + } + } + pub(crate) fn place_index( self, fx: &mut FunctionCx<'_, '_, 'tcx>, From a7b06e81fc008750de32b9a57e292bb341d0b842 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 23 Jul 2021 18:29:47 +0200 Subject: [PATCH 22/58] Fix two type mismatch bugs --- src/intrinsics/mod.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index a6983749a26ab..42d1a53a2bb69 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -250,6 +250,11 @@ fn simd_reduce_bool<'tcx>( let lane = fx.bcx.ins().band_imm(lane, 1); // mask to boolean res_val = f(fx, res_val, lane); } + let res_val = if fx.bcx.func.dfg.value_type(res_val) != types::I8 { + fx.bcx.ins().ireduce(types::I8, res_val) + } else { + res_val + }; let res = CValue::by_val(res_val, ret.layout()); ret.write_cvalue(fx, res); } @@ -284,7 +289,11 @@ macro simd_cmp { if let Some(vector_ty) = vector_ty { let x = $x.load_scalar($fx); let y = $y.load_scalar($fx); - let val = $fx.bcx.ins().icmp(IntCC::$cc, x, y); + let val = if vector_ty.lane_type().is_float() { + $fx.bcx.ins().fcmp(FloatCC::$cc_f, x, y) + } else { + $fx.bcx.ins().icmp(IntCC::$cc, x, y) + }; // HACK This depends on the fact that icmp for vectors represents bools as 0 and !0, not 0 and 1. let val = $fx.bcx.ins().raw_bitcast(vector_ty, val); From 344cbac150d08d0931d03ab0651becc977baa64b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 24 Jul 2021 15:24:06 +0200 Subject: [PATCH 23/58] Fix simd_reduce_* intrinsics --- src/intrinsics/mod.rs | 6 ++++-- src/intrinsics/simd.rs | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 42d1a53a2bb69..6a818e2df1e83 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -218,6 +218,7 @@ fn simd_pair_for_each_lane<'tcx>( fn simd_reduce<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, val: CValue<'tcx>, + acc: Option, ret: CPlace<'tcx>, f: impl Fn(&mut FunctionCx<'_, '_, 'tcx>, TyAndLayout<'tcx>, Value, Value) -> Value, ) { @@ -225,8 +226,9 @@ fn simd_reduce<'tcx>( let lane_layout = fx.layout_of(lane_ty); assert_eq!(lane_layout, ret.layout()); - let mut res_val = val.value_lane(fx, 0).load_scalar(fx); - for lane_idx in 1..lane_count { + let (mut res_val, start_lane) = + if let Some(acc) = acc { (acc, 0) } else { (val.value_lane(fx, 0).load_scalar(fx), 1) }; + for lane_idx in start_lane..lane_count { let lane = val.value_lane(fx, lane_idx).load_scalar(fx); res_val = f(fx, lane_layout, res_val, lane); } diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index e952942de8777..db36437ab417a 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -236,9 +236,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_flt_binop!(fx, fmax(x, y) -> ret); }; - simd_reduce_add_ordered | simd_reduce_add_unordered, (c v) { + simd_reduce_add_ordered | simd_reduce_add_unordered, (c v, v acc) { validate_simd_type!(fx, intrinsic, span, v.layout().ty); - simd_reduce(fx, v, ret, |fx, lane_layout, a, b| { + simd_reduce(fx, v, Some(acc), ret, |fx, lane_layout, a, b| { if lane_layout.ty.is_floating_point() { fx.bcx.ins().fadd(a, b) } else { @@ -247,9 +247,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); }; - simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v) { + simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v, v acc) { validate_simd_type!(fx, intrinsic, span, v.layout().ty); - simd_reduce(fx, v, ret, |fx, lane_layout, a, b| { + simd_reduce(fx, v, Some(acc), ret, |fx, lane_layout, a, b| { if lane_layout.ty.is_floating_point() { fx.bcx.ins().fmul(a, b) } else { From 90e4493b98196e8825fcf18eff2a529a5b19d08f Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 24 Jul 2021 15:25:32 +0200 Subject: [PATCH 24/58] Implement more simd intrinsics --- src/intrinsics/simd.rs | 147 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 7 deletions(-) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index db36437ab417a..5a23e775712b8 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -167,6 +167,34 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ret.write_cvalue(fx, ret_lane); }; + simd_neg, (c a) { + validate_simd_type!(fx, intrinsic, span, a.layout().ty); + simd_for_each_lane(fx, a, ret, |fx, lane_layout, ret_lane_layout, lane| { + let ret_lane = match lane_layout.ty.kind() { + ty::Int(_) => fx.bcx.ins().ineg(lane), + ty::Float(_) => fx.bcx.ins().fneg(lane), + _ => unreachable!(), + }; + CValue::by_val(ret_lane, ret_lane_layout) + }); + }; + + simd_fabs, (c a) { + validate_simd_type!(fx, intrinsic, span, a.layout().ty); + simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { + let ret_lane = fx.bcx.ins().fabs(lane); + CValue::by_val(ret_lane, ret_lane_layout) + }); + }; + + simd_fsqrt, (c a) { + validate_simd_type!(fx, intrinsic, span, a.layout().ty); + simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { + let ret_lane = fx.bcx.ins().sqrt(lane); + CValue::by_val(ret_lane, ret_lane_layout) + }); + }; + simd_add, (c x, c y) { validate_simd_type!(fx, intrinsic, span, x.layout().ty); simd_int_flt_binop!(fx, iadd|fadd(x, y) -> ret); @@ -183,6 +211,29 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( validate_simd_type!(fx, intrinsic, span, x.layout().ty); simd_int_flt_binop!(fx, udiv|sdiv|fdiv(x, y) -> ret); }; + simd_rem, (c x, c y) { + validate_simd_type!(fx, intrinsic, span, x.layout().ty); + simd_pair_for_each_lane(fx, x, y, ret, |fx, lane_layout, ret_lane_layout, x_lane, y_lane| { + let res_lane = match lane_layout.ty.kind() { + ty::Uint(_) => fx.bcx.ins().urem(x_lane, y_lane), + ty::Int(_) => fx.bcx.ins().srem(x_lane, y_lane), + ty::Float(FloatTy::F32) => fx.lib_call( + "fmodf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + &[x_lane, y_lane], + )[0], + ty::Float(FloatTy::F64) => fx.lib_call( + "fmod", + vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], + vec![AbiParam::new(types::F64)], + &[x_lane, y_lane], + )[0], + _ => unreachable!("{:?}", lane_layout.ty), + }; + CValue::by_val(res_lane, ret_lane_layout) + }); + }; simd_shl, (c x, c y) { validate_simd_type!(fx, intrinsic, span, x.layout().ty); simd_int_binop!(fx, ishl(x, y) -> ret); @@ -236,6 +287,35 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_flt_binop!(fx, fmax(x, y) -> ret); }; + simd_round, (c a) { + validate_simd_type!(fx, intrinsic, span, a.layout().ty); + simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { + let ret_lane = fx.bcx.ins().nearest(lane); + CValue::by_val(ret_lane, ret_lane_layout) + }); + }; + simd_ceil, (c a) { + validate_simd_type!(fx, intrinsic, span, a.layout().ty); + simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { + let ret_lane = fx.bcx.ins().ceil(lane); + CValue::by_val(ret_lane, ret_lane_layout) + }); + }; + simd_floor, (c a) { + validate_simd_type!(fx, intrinsic, span, a.layout().ty); + simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { + let ret_lane = fx.bcx.ins().floor(lane); + CValue::by_val(ret_lane, ret_lane_layout) + }); + }; + simd_trunc, (c a) { + validate_simd_type!(fx, intrinsic, span, a.layout().ty); + simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { + let ret_lane = fx.bcx.ins().trunc(lane); + CValue::by_val(ret_lane, ret_lane_layout) + }); + }; + simd_reduce_add_ordered | simd_reduce_add_unordered, (c v, v acc) { validate_simd_type!(fx, intrinsic, span, v.layout().ty); simd_reduce(fx, v, Some(acc), ret, |fx, lane_layout, a, b| { @@ -268,13 +348,66 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().bor(a, b)); }; - // simd_fabs - // simd_saturating_add + simd_reduce_and, (c v) { + validate_simd_type!(fx, intrinsic, span, v.layout().ty); + simd_reduce(fx, v, None, ret, |fx, _layout, a, b| fx.bcx.ins().band(a, b)); + }; + + simd_reduce_or, (c v) { + validate_simd_type!(fx, intrinsic, span, v.layout().ty); + simd_reduce(fx, v, None, ret, |fx, _layout, a, b| fx.bcx.ins().bor(a, b)); + }; + + simd_reduce_xor, (c v) { + validate_simd_type!(fx, intrinsic, span, v.layout().ty); + simd_reduce(fx, v, None, ret, |fx, _layout, a, b| fx.bcx.ins().bxor(a, b)); + }; + + simd_reduce_min, (c v) { + validate_simd_type!(fx, intrinsic, span, v.layout().ty); + simd_reduce(fx, v, None, ret, |fx, layout, a, b| { + let lt = fx.bcx.ins().icmp(if layout.ty.is_signed() { + IntCC::SignedLessThan + } else { + IntCC::UnsignedLessThan + }, a, b); + fx.bcx.ins().select(lt, a, b) + }); + }; + + simd_reduce_max, (c v) { + validate_simd_type!(fx, intrinsic, span, v.layout().ty); + simd_reduce(fx, v, None, ret, |fx, layout, a, b| { + let gt = fx.bcx.ins().icmp(if layout.ty.is_signed() { + IntCC::SignedGreaterThan + } else { + IntCC::UnsignedGreaterThan + }, a, b); + fx.bcx.ins().select(gt, a, b) + }); + }; + + simd_select, (c m, c a, c b) { + validate_simd_type!(fx, intrinsic, span, m.layout().ty); + validate_simd_type!(fx, intrinsic, span, a.layout().ty); + assert_eq!(a.layout(), b.layout()); + + let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + + for lane in 0..lane_count { + let m_lane = m.value_lane(fx, lane).load_scalar(fx); + let a_lane = a.value_lane(fx, lane).load_scalar(fx); + let b_lane = b.value_lane(fx, lane).load_scalar(fx); + + let m_lane = fx.bcx.ins().icmp_imm(IntCC::Equal, m_lane, 0); + let res_lane = CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout); + + ret.place_lane(fx, lane).write_cvalue(fx, res_lane); + } + }; + + // simd_saturating_* // simd_bitmask - // simd_select - // simd_rem - // simd_neg - // simd_trunc - // simd_floor } } From 6d2221d1bb7978797589cc12a2cada8e9467b42d Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 25 Jul 2021 18:44:42 +0200 Subject: [PATCH 25/58] Fix simd_round implementation --- src/intrinsics/simd.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 5a23e775712b8..37906ab472d2e 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -289,9 +289,23 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_round, (c a) { validate_simd_type!(fx, intrinsic, span, a.layout().ty); - simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { - let ret_lane = fx.bcx.ins().nearest(lane); - CValue::by_val(ret_lane, ret_lane_layout) + simd_for_each_lane(fx, a, ret, |fx, lane_layout, ret_lane_layout, lane| { + let res_lane = match lane_layout.ty.kind() { + ty::Float(FloatTy::F32) => fx.lib_call( + "roundf", + vec![AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + &[lane], + )[0], + ty::Float(FloatTy::F64) => fx.lib_call( + "round", + vec![AbiParam::new(types::F64)], + vec![AbiParam::new(types::F64)], + &[lane], + )[0], + _ => unreachable!("{:?}", lane_layout.ty), + }; + CValue::by_val(res_lane, ret_lane_layout) }); }; simd_ceil, (c a) { @@ -409,5 +423,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // simd_saturating_* // simd_bitmask + // simd_scatter + // simd_gather } } From a0fb0facdca979b6f9d775650df6ff81d5b271ff Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 25 Jul 2021 18:45:56 +0200 Subject: [PATCH 26/58] Run stdsimd test suite --- build_system/prepare.rs | 13 +- ...01-stdsimd-Disable-unsupported-tests.patch | 181 ++++++++++++++++++ scripts/tests.sh | 5 + 3 files changed, 194 insertions(+), 5 deletions(-) create mode 100644 patches/0001-stdsimd-Disable-unsupported-tests.patch diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 401b8271abcc5..4b2051b605abd 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -27,6 +27,13 @@ pub(crate) fn prepare() { "341f207c1071f7290e3f228c710817c280c8dca1", ); + clone_repo( + "stdsimd", + "https://github.com/rust-lang/stdsimd", + "be96995d8ddec03fac9a0caf4d4c51c7fbc33507", + ); + apply_patches("stdsimd", Path::new("stdsimd")); + clone_repo( "simple-raytracer", "https://github.com/ebobby/simple-raytracer", @@ -60,11 +67,7 @@ fn prepare_sysroot() { copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library")); let rustc_version = get_rustc_version(); - fs::write( - Path::new("build_sysroot").join("rustc_version"), - &rustc_version, - ) - .unwrap(); + fs::write(Path::new("build_sysroot").join("rustc_version"), &rustc_version).unwrap(); eprintln!("[GIT] init"); let mut git_init_cmd = Command::new("git"); diff --git a/patches/0001-stdsimd-Disable-unsupported-tests.patch b/patches/0001-stdsimd-Disable-unsupported-tests.patch new file mode 100644 index 0000000000000..b24f67f3edc30 --- /dev/null +++ b/patches/0001-stdsimd-Disable-unsupported-tests.patch @@ -0,0 +1,181 @@ +From 6bfce5dc2cbf834c74dbccb7538adc08c6eb57e7 Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Sun, 25 Jul 2021 18:39:31 +0200 +Subject: [PATCH] Disable unsupported tests + +--- + crates/core_simd/src/array.rs | 2 ++ + crates/core_simd/src/lib.rs | 2 +- + crates/core_simd/src/math.rs | 4 ++++ + crates/core_simd/tests/masks.rs | 12 ------------ + crates/core_simd/tests/ops_macros.rs | 6 ++++++ + crates/core_simd/tests/round.rs | 2 ++ + 6 files changed, 15 insertions(+), 13 deletions(-) + +diff --git a/crates/core_simd/src/array.rs b/crates/core_simd/src/array.rs +index 25c5309..2b3d819 100644 +--- a/crates/core_simd/src/array.rs ++++ b/crates/core_simd/src/array.rs +@@ -22,6 +22,7 @@ where + #[must_use] + fn splat(val: Self::Scalar) -> Self; + ++ /* + /// SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices. + /// If an index is out of bounds, that lane instead selects the value from the "or" vector. + /// ``` +@@ -150,6 +151,7 @@ where + // Cleared ☢️ *mut T Zone + } + } ++ */ + } + + macro_rules! impl_simdarray_for { +diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs +index a64904d..299eb11 100644 +--- a/crates/core_simd/src/lib.rs ++++ b/crates/core_simd/src/lib.rs +@@ -1,7 +1,7 @@ + #![no_std] + #![allow(incomplete_features)] + #![feature( +- const_generics, ++ const_generics, + platform_intrinsics, + repr_simd, + simd_ffi, +diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs +index 7290a28..e394730 100644 +--- a/crates/core_simd/src/math.rs ++++ b/crates/core_simd/src/math.rs +@@ -2,6 +2,7 @@ macro_rules! impl_uint_arith { + ($(($name:ident, $n:ident)),+) => { + $( impl $name where Self: crate::LanesAtMost32 { + ++ /* + /// Lanewise saturating add. + /// + /// # Examples +@@ -38,6 +39,7 @@ macro_rules! impl_uint_arith { + pub fn saturating_sub(self, second: Self) -> Self { + unsafe { crate::intrinsics::simd_saturating_sub(self, second) } + } ++ */ + })+ + } + } +@@ -46,6 +48,7 @@ macro_rules! impl_int_arith { + ($(($name:ident, $n:ident)),+) => { + $( impl $name where Self: crate::LanesAtMost32 { + ++ /* + /// Lanewise saturating add. + /// + /// # Examples +@@ -141,6 +144,7 @@ macro_rules! impl_int_arith { + pub fn saturating_neg(self) -> Self { + Self::splat(0).saturating_sub(self) + } ++ */ + })+ + } + } +diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs +index 61d8e44..2bccae2 100644 +--- a/crates/core_simd/tests/masks.rs ++++ b/crates/core_simd/tests/masks.rs +@@ -67,18 +67,6 @@ macro_rules! test_mask_api { + assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); + assert_eq!(core_simd::$name::<8>::from_int(int), mask); + } +- +- #[test] +- fn roundtrip_bitmask_conversion() { +- let values = [ +- true, false, false, true, false, false, true, false, +- true, true, false, false, false, false, false, true, +- ]; +- let mask = core_simd::$name::<16>::from_array(values); +- let bitmask = mask.to_bitmask(); +- assert_eq!(bitmask, [0b01001001, 0b10000011]); +- assert_eq!(core_simd::$name::<16>::from_bitmask(bitmask), mask); +- } + } + } + } +diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs +index cb39e73..fc0ebe1 100644 +--- a/crates/core_simd/tests/ops_macros.rs ++++ b/crates/core_simd/tests/ops_macros.rs +@@ -435,6 +435,7 @@ macro_rules! impl_float_tests { + ) + } + ++ /* + fn mul_add() { + test_helpers::test_ternary_elementwise( + &Vector::::mul_add, +@@ -442,6 +443,7 @@ macro_rules! impl_float_tests { + &|_, _, _| true, + ) + } ++ */ + + fn sqrt() { + test_helpers::test_unary_elementwise( +@@ -491,6 +493,7 @@ macro_rules! impl_float_tests { + ) + } + ++ /* + fn min() { + // Regular conditions (both values aren't zero) + test_helpers::test_binary_elementwise( +@@ -536,6 +539,7 @@ macro_rules! impl_float_tests { + assert!(p_zero.max(n_zero).to_array().iter().all(|x| *x == 0.)); + assert!(n_zero.max(p_zero).to_array().iter().all(|x| *x == 0.)); + } ++ */ + + fn clamp() { + test_helpers::test_3(&|value: [Scalar; LANES], mut min: [Scalar; LANES], mut max: [Scalar; LANES]| { +@@ -581,6 +585,7 @@ macro_rules! impl_float_tests { + }); + } + ++ /* + fn horizontal_max() { + test_helpers::test_1(&|x| { + let vmax = Vector::::from_array(x).horizontal_max(); +@@ -604,6 +609,7 @@ macro_rules! impl_float_tests { + Ok(()) + }); + } ++ */ + } + } + } +diff --git a/crates/core_simd/tests/round.rs b/crates/core_simd/tests/round.rs +index 37044a7..4cdc6b7 100644 +--- a/crates/core_simd/tests/round.rs ++++ b/crates/core_simd/tests/round.rs +@@ -25,6 +25,7 @@ macro_rules! float_rounding_test { + ) + } + ++ /* + fn round() { + test_helpers::test_unary_elementwise( + &Vector::::round, +@@ -32,6 +33,7 @@ macro_rules! float_rounding_test { + &|_| true, + ) + } ++ */ + + fn trunc() { + test_helpers::test_unary_elementwise( +-- +2.26.2.7.g19db9cfb68 + diff --git a/scripts/tests.sh b/scripts/tests.sh index 08c07dfad428e..d689b9aad629e 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -136,6 +136,11 @@ function extended_sysroot_tests() { ../build/cargo build --tests --target $TARGET_TRIPLE fi popd + + pushd stdsimd + echo "[TEST] rust-lang/stdsimd" + ../build/cargo test -q + popd } case "$1" in From 581e38b97c8431be06e74a5c8c22c8e1e78cf368 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 25 Jul 2021 18:46:10 +0200 Subject: [PATCH 27/58] Add fixme --- scripts/tests.sh | 5 ++++- src/intrinsics/mod.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/tests.sh b/scripts/tests.sh index d689b9aad629e..1b8858eb4ab7c 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -139,7 +139,10 @@ function extended_sysroot_tests() { pushd stdsimd echo "[TEST] rust-lang/stdsimd" - ../build/cargo test -q + ../build/cargo build --all-targets --target $TARGET_TRIPLE + if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then + ../build/cargo test -q + fi popd } diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 6a818e2df1e83..17c79645eb24c 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -236,6 +236,7 @@ fn simd_reduce<'tcx>( ret.write_cvalue(fx, res); } +// FIXME move all uses to `simd_reduce` fn simd_reduce_bool<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, val: CValue<'tcx>, From 424a8c3a569e6a67afb3fafdae8d4e7568097b15 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 14:11:19 +0200 Subject: [PATCH 28/58] Implement "default_alloc_error_handler" feature Fixes #1182 --- src/allocator.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index d39486c2f1002..637d30f9344f9 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -5,7 +5,6 @@ use crate::prelude::*; use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; -use rustc_span::symbol::sym; /// Returns whether an allocator shim was created pub(crate) fn codegen( @@ -20,7 +19,7 @@ pub(crate) fn codegen( if any_dynamic_crate { false } else if let Some(kind) = tcx.allocator_kind(()) { - codegen_inner(module, unwind_context, kind); + codegen_inner(module, unwind_context, kind, tcx.lang_items().oom().is_some()); true } else { false @@ -31,6 +30,7 @@ fn codegen_inner( module: &mut impl Module, unwind_context: &mut UnwindContext, kind: AllocatorKind, + has_alloc_error_handler: bool, ) { let usize_ty = module.target_config().pointer_type(); @@ -65,7 +65,6 @@ fn codegen_inner( let caller_name = format!("__rust_{}", method.name); let callee_name = kind.fn_name(method.name); - //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns); let func_id = module.declare_function(&caller_name, Linkage::Export, &sig).unwrap(); @@ -104,13 +103,12 @@ fn codegen_inner( returns: vec![], }; - let callee_name = kind.fn_name(sym::oom); - //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns); + let callee_name = if has_alloc_error_handler { "__rg_oom" } else { "__rdl_oom" }; let func_id = module.declare_function("__rust_alloc_error_handler", Linkage::Export, &sig).unwrap(); - let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap(); + let callee_func_id = module.declare_function(callee_name, Linkage::Import, &sig).unwrap(); let mut ctx = Context::new(); ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig); From 02db151b0030794deb336e18f6bafab565456844 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 14:13:05 +0200 Subject: [PATCH 29/58] Add stdsimd to .gitignore and clean_all.sh --- .gitignore | 1 + clean_all.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 12e779fe7c7d7..25080488a88b5 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ perf.data.old /rand /regex /simple-raytracer +/stdsimd diff --git a/clean_all.sh b/clean_all.sh index f4f8c82d69f10..23e5bf2e0a8fd 100755 --- a/clean_all.sh +++ b/clean_all.sh @@ -3,4 +3,4 @@ set -e rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} rm -rf target/ build/ perf.data{,.old} -rm -rf rand/ regex/ simple-raytracer/ +rm -rf rand/ regex/ simple-raytracer/ stdsimd/ From 050b417a74a5f55a91ae25f0b841a6d04219ce34 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 14:40:27 +0200 Subject: [PATCH 30/58] Introduce the CallTarget enum --- src/abi/mod.rs | 52 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 54c8fb0e7b80b..a8596707c8e18 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::layout::FnAbiExt; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; -use cranelift_codegen::ir::AbiParam; +use cranelift_codegen::ir::{AbiParam, SigRef}; use smallvec::smallvec; use self::pass_mode::*; @@ -380,9 +380,11 @@ pub(crate) fn codegen_terminator_call<'tcx>( args.iter().map(|arg| codegen_operand(fx, arg)).collect::>() }; - // | indirect call target - // | | the first argument to be passed - // v v + enum CallTarget { + Direct(FuncRef), + Indirect(SigRef, Value), + } + let (func_ref, first_arg) = match instance { // Trait object call Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => { @@ -390,20 +392,27 @@ pub(crate) fn codegen_terminator_call<'tcx>( let nop_inst = fx.bcx.ins().nop(); fx.add_comment( nop_inst, - format!("virtual call; self arg pass mode: {:?}", &fn_abi.args[0],), + format!("virtual call; self arg pass mode: {:?}", &fn_abi.args[0]), ); } + let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0], idx); - (Some(method), smallvec![ptr]) + let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); + let sig = fx.bcx.import_signature(sig); + + (CallTarget::Indirect(sig, method), smallvec![ptr]) } // Normal call - Some(_) => ( - None, - args.get(0) - .map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0])) - .unwrap_or(smallvec![]), - ), + Some(instance) => { + let func_ref = fx.get_function_ref(instance); + ( + CallTarget::Direct(func_ref), + args.get(0) + .map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0])) + .unwrap_or(smallvec![]), + ) + } // Indirect call None => { @@ -411,9 +420,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( let nop_inst = fx.bcx.ins().nop(); fx.add_comment(nop_inst, "indirect call"); } + let func = codegen_operand(fx, func).load_scalar(fx); + let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); + let sig = fx.bcx.import_signature(sig); + ( - Some(func), + CallTarget::Indirect(sig, func), args.get(0) .map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0])) .unwrap_or(smallvec![]), @@ -452,14 +465,11 @@ pub(crate) fn codegen_terminator_call<'tcx>( assert_eq!(fn_abi.args.len(), regular_args_count); } - let call_inst = if let Some(func_ref) = func_ref { - let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); - let sig = fx.bcx.import_signature(sig); - fx.bcx.ins().call_indirect(sig, func_ref, &call_args) - } else { - let func_ref = - fx.get_function_ref(instance.expect("non-indirect call on non-FnDef type")); - fx.bcx.ins().call(func_ref, &call_args) + let call_inst = match func_ref { + CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), + CallTarget::Indirect(sig, func_ptr) => { + fx.bcx.ins().call_indirect(sig, func_ptr, &call_args) + } }; (call_inst, call_args) From 83da1e0d5abade2dda76bca0548b9431054c7d36 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 14:49:17 +0200 Subject: [PATCH 31/58] Simplify logic around first_arg --- src/abi/mod.rs | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index a8596707c8e18..c5c3b79992579 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -10,7 +10,6 @@ use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; use cranelift_codegen::ir::{AbiParam, SigRef}; -use smallvec::smallvec; use self::pass_mode::*; use crate::prelude::*; @@ -385,7 +384,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( Indirect(SigRef, Value), } - let (func_ref, first_arg) = match instance { + let (func_ref, first_arg_override) = match instance { // Trait object call Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => { if fx.clif_comments.enabled() { @@ -400,18 +399,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); let sig = fx.bcx.import_signature(sig); - (CallTarget::Indirect(sig, method), smallvec![ptr]) + (CallTarget::Indirect(sig, method), Some(ptr)) } // Normal call Some(instance) => { let func_ref = fx.get_function_ref(instance); - ( - CallTarget::Direct(func_ref), - args.get(0) - .map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0])) - .unwrap_or(smallvec![]), - ) + (CallTarget::Direct(func_ref), None) } // Indirect call @@ -425,12 +419,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); let sig = fx.bcx.import_signature(sig); - ( - CallTarget::Indirect(sig, func), - args.get(0) - .map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0])) - .unwrap_or(smallvec![]), - ) + (CallTarget::Indirect(sig, func), None) } }; @@ -443,11 +432,11 @@ pub(crate) fn codegen_terminator_call<'tcx>( let regular_args_count = args.len(); let mut call_args: Vec = return_ptr .into_iter() - .chain(first_arg.into_iter()) + .chain(first_arg_override.into_iter()) .chain( args.into_iter() .enumerate() - .skip(1) + .skip(if first_arg_override.is_some() { 1 } else { 0 }) .map(|(i, arg)| adjust_arg_for_abi(fx, arg, &fn_abi.args[i]).into_iter()) .flatten(), ) From 3361e349fa7c378c844458487b600dd57e566086 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 14:55:13 +0200 Subject: [PATCH 32/58] Don't return anything from codegen_with_call_return_arg --- src/abi/mod.rs | 113 +++++++++++++++++++++---------------------- src/abi/returning.rs | 10 ++-- 2 files changed, 60 insertions(+), 63 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index c5c3b79992579..ff7a7f819bcf7 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -424,66 +424,65 @@ pub(crate) fn codegen_terminator_call<'tcx>( }; let ret_place = destination.map(|(place, _)| place); - let (call_inst, call_args) = self::returning::codegen_with_call_return_arg( - fx, - &fn_abi.ret, - ret_place, - |fx, return_ptr| { - let regular_args_count = args.len(); - let mut call_args: Vec = return_ptr - .into_iter() - .chain(first_arg_override.into_iter()) - .chain( - args.into_iter() - .enumerate() - .skip(if first_arg_override.is_some() { 1 } else { 0 }) - .map(|(i, arg)| adjust_arg_for_abi(fx, arg, &fn_abi.args[i]).into_iter()) - .flatten(), - ) - .collect::>(); - - if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) { - // Pass the caller location for `#[track_caller]`. - let caller_location = fx.get_caller_location(span); - call_args.extend( - adjust_arg_for_abi(fx, caller_location, &fn_abi.args[regular_args_count]) - .into_iter(), - ); - assert_eq!(fn_abi.args.len(), regular_args_count + 1); - } else { - assert_eq!(fn_abi.args.len(), regular_args_count); - } - - let call_inst = match func_ref { - CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), - CallTarget::Indirect(sig, func_ptr) => { - fx.bcx.ins().call_indirect(sig, func_ptr, &call_args) - } - }; + self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| { + let regular_args_count = args.len(); + let mut call_args: Vec = return_ptr + .into_iter() + .chain(first_arg_override.into_iter()) + .chain( + args.into_iter() + .enumerate() + .skip(if first_arg_override.is_some() { 1 } else { 0 }) + .map(|(i, arg)| adjust_arg_for_abi(fx, arg, &fn_abi.args[i]).into_iter()) + .flatten(), + ) + .collect::>(); + + if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) { + // Pass the caller location for `#[track_caller]`. + let caller_location = fx.get_caller_location(span); + call_args.extend( + adjust_arg_for_abi(fx, caller_location, &fn_abi.args[regular_args_count]) + .into_iter(), + ); + assert_eq!(fn_abi.args.len(), regular_args_count + 1); + } else { + assert_eq!(fn_abi.args.len(), regular_args_count); + } - (call_inst, call_args) - }, - ); + let call_inst = match func_ref { + CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), + CallTarget::Indirect(sig, func_ptr) => { + fx.bcx.ins().call_indirect(sig, func_ptr, &call_args) + } + }; - // FIXME find a cleaner way to support varargs - if fn_sig.c_variadic { - if !matches!(fn_sig.abi, Abi::C { .. }) { - fx.tcx.sess.span_fatal(span, &format!("Variadic call for non-C abi {:?}", fn_sig.abi)); + // FIXME find a cleaner way to support varargs + if fn_sig.c_variadic { + if !matches!(fn_sig.abi, Abi::C { .. }) { + fx.tcx + .sess + .span_fatal(span, &format!("Variadic call for non-C abi {:?}", fn_sig.abi)); + } + let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap(); + let abi_params = call_args + .into_iter() + .map(|arg| { + let ty = fx.bcx.func.dfg.value_type(arg); + if !ty.is_int() { + // FIXME set %al to upperbound on float args once floats are supported + fx.tcx + .sess + .span_fatal(span, &format!("Non int ty {:?} for variadic call", ty)); + } + AbiParam::new(ty) + }) + .collect::>(); + fx.bcx.func.dfg.signatures[sig_ref].params = abi_params; } - let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap(); - let abi_params = call_args - .into_iter() - .map(|arg| { - let ty = fx.bcx.func.dfg.value_type(arg); - if !ty.is_int() { - // FIXME set %al to upperbound on float args once floats are supported - fx.tcx.sess.span_fatal(span, &format!("Non int ty {:?} for variadic call", ty)); - } - AbiParam::new(ty) - }) - .collect::>(); - fx.bcx.func.dfg.signatures[sig_ref].params = abi_params; - } + + call_inst + }); if let Some((_, dest)) = destination { let ret_block = fx.get_block(dest); diff --git a/src/abi/returning.rs b/src/abi/returning.rs index e1c53224b4f84..e5e06d1bd63c8 100644 --- a/src/abi/returning.rs +++ b/src/abi/returning.rs @@ -99,12 +99,12 @@ pub(super) fn codegen_return_param<'tcx>( /// Invokes the closure with if necessary a value representing the return pointer. When the closure /// returns the call return value(s) if any are written to the correct place. -pub(super) fn codegen_with_call_return_arg<'tcx, T>( +pub(super) fn codegen_with_call_return_arg<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, ret_arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, ret_place: Option>, - f: impl FnOnce(&mut FunctionCx<'_, '_, 'tcx>, Option) -> (Inst, T), -) -> (Inst, T) { + f: impl FnOnce(&mut FunctionCx<'_, '_, 'tcx>, Option) -> Inst, +) { let return_ptr = match ret_arg_abi.mode { PassMode::Ignore => None, PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => match ret_place { @@ -117,7 +117,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx, T>( PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => None, }; - let (call_inst, meta) = f(fx, return_ptr); + let call_inst = f(fx, return_ptr); match ret_arg_abi.mode { PassMode::Ignore => {} @@ -155,8 +155,6 @@ pub(super) fn codegen_with_call_return_arg<'tcx, T>( unreachable!("unsized return value") } } - - (call_inst, meta) } /// Codegen a return instruction with the right return value(s) if any. From 405642b853413705e660c011a5c7807f42e56479 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 15:01:50 +0200 Subject: [PATCH 33/58] Handle the extra argument for #[track_caller] earlier --- src/abi/mod.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index ff7a7f819bcf7..1c4be84f4e17f 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -359,7 +359,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } // Unpack arguments tuple for closures - let args = if fn_sig.abi == Abi::RustCall { + let mut args = if fn_sig.abi == Abi::RustCall { assert_eq!(args.len(), 2, "rust-call abi requires two arguments"); let self_arg = codegen_operand(fx, &args[0]); let pack_arg = codegen_operand(fx, &args[1]); @@ -379,6 +379,15 @@ pub(crate) fn codegen_terminator_call<'tcx>( args.iter().map(|arg| codegen_operand(fx, arg)).collect::>() }; + // Pass the caller location for `#[track_caller]`. + if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) { + let caller_location = fx.get_caller_location(span); + args.push(caller_location); + } + + let args = args; + assert_eq!(fn_abi.args.len(), args.len()); + enum CallTarget { Direct(FuncRef), Indirect(SigRef, Value), @@ -425,8 +434,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let ret_place = destination.map(|(place, _)| place); self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| { - let regular_args_count = args.len(); - let mut call_args: Vec = return_ptr + let call_args = return_ptr .into_iter() .chain(first_arg_override.into_iter()) .chain( @@ -436,19 +444,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( .map(|(i, arg)| adjust_arg_for_abi(fx, arg, &fn_abi.args[i]).into_iter()) .flatten(), ) - .collect::>(); - - if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) { - // Pass the caller location for `#[track_caller]`. - let caller_location = fx.get_caller_location(span); - call_args.extend( - adjust_arg_for_abi(fx, caller_location, &fn_abi.args[regular_args_count]) - .into_iter(), - ); - assert_eq!(fn_abi.args.len(), regular_args_count + 1); - } else { - assert_eq!(fn_abi.args.len(), regular_args_count); - } + .collect::>(); let call_inst = match func_ref { CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), From 2abc12daada0f7a12285902eb3faacd279316e11 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 16:11:24 +0200 Subject: [PATCH 34/58] Fix y.rs build --sysroot llvm --- build_system/build_sysroot.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 9fb88c279613f..642abc41f45a7 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -91,7 +91,9 @@ pub(crate) fn build_sysroot( { let file = file.unwrap().path(); let file_name_str = file.file_name().unwrap().to_str().unwrap(); - if file_name_str.contains("rustc_") + if (file_name_str.contains("rustc_") + && !file_name_str.contains("rustc_std_workspace_") + && !file_name_str.contains("rustc_demangle")) || file_name_str.contains("chalk") || file_name_str.contains("tracing") || file_name_str.contains("regex") From e387ec9cbf53af36228684b3d095228a1b351f16 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 18:17:22 +0200 Subject: [PATCH 35/58] Fix ABI for Indirect arguments In case of PassMode::Indirect, the ownership of the backing storage is transfered to the callee. This means that the caller must copy the argument if it wants to use it again later. Fixes #691 --- src/abi/mod.rs | 76 ++++++++++++++++++++++++++------------------ src/abi/pass_mode.rs | 20 +++++++++--- 2 files changed, 61 insertions(+), 35 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 1c4be84f4e17f..0478d4b198afc 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -235,27 +235,20 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ // not mutated by the current function, this is necessary to support unsized arguments. if let ArgKind::Normal(Some(val)) = arg_kind { if let Some((addr, meta)) = val.try_to_ptr() { - let local_decl = &fx.mir.local_decls[local]; - // v this ! is important - let internally_mutable = !val - .layout() - .ty - .is_freeze(fx.tcx.at(local_decl.source_info.span), ParamEnv::reveal_all()); - if local_decl.mutability == mir::Mutability::Not && !internally_mutable { - // We wont mutate this argument, so it is fine to borrow the backing storage - // of this argument, to prevent a copy. - - let place = if let Some(meta) = meta { - CPlace::for_ptr_with_extra(addr, meta, val.layout()) - } else { - CPlace::for_ptr(addr, val.layout()) - }; - - self::comments::add_local_place_comments(fx, place, local); - - assert_eq!(fx.local_map.push(place), local); - continue; - } + // Ownership of the value at the backing storage for an argument is passed to the + // callee per the ABI, so it is fine to borrow the backing storage of this argument + // to prevent a copy. + + let place = if let Some(meta) = meta { + CPlace::for_ptr_with_extra(addr, meta, val.layout()) + } else { + CPlace::for_ptr(addr, val.layout()) + }; + + self::comments::add_local_place_comments(fx, place, local); + + assert_eq!(fx.local_map.push(place), local); + continue; } } @@ -291,6 +284,22 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ fx.bcx.ins().jump(*fx.block_map.get(START_BLOCK).unwrap(), &[]); } +struct CallArgument<'tcx> { + value: CValue<'tcx>, + is_owned: bool, +} + +// FIXME avoid intermediate `CValue` before calling `adjust_arg_for_abi` +fn codegen_call_argument_operand<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + operand: &Operand<'tcx>, +) -> CallArgument<'tcx> { + CallArgument { + value: codegen_operand(fx, operand), + is_owned: matches!(operand, Operand::Move(_)), + } +} + pub(crate) fn codegen_terminator_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span, @@ -361,10 +370,10 @@ pub(crate) fn codegen_terminator_call<'tcx>( // Unpack arguments tuple for closures let mut args = if fn_sig.abi == Abi::RustCall { assert_eq!(args.len(), 2, "rust-call abi requires two arguments"); - let self_arg = codegen_operand(fx, &args[0]); - let pack_arg = codegen_operand(fx, &args[1]); + let self_arg = codegen_call_argument_operand(fx, &args[0]); + let pack_arg = codegen_call_argument_operand(fx, &args[1]); - let tupled_arguments = match pack_arg.layout().ty.kind() { + let tupled_arguments = match pack_arg.value.layout().ty.kind() { ty::Tuple(ref tupled_arguments) => tupled_arguments, _ => bug!("argument to function with \"rust-call\" ABI is not a tuple"), }; @@ -372,17 +381,20 @@ pub(crate) fn codegen_terminator_call<'tcx>( let mut args = Vec::with_capacity(1 + tupled_arguments.len()); args.push(self_arg); for i in 0..tupled_arguments.len() { - args.push(pack_arg.value_field(fx, mir::Field::new(i))); + args.push(CallArgument { + value: pack_arg.value.value_field(fx, mir::Field::new(i)), + is_owned: pack_arg.is_owned, + }); } args } else { - args.iter().map(|arg| codegen_operand(fx, arg)).collect::>() + args.iter().map(|arg| codegen_call_argument_operand(fx, arg)).collect::>() }; // Pass the caller location for `#[track_caller]`. if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) { let caller_location = fx.get_caller_location(span); - args.push(caller_location); + args.push(CallArgument { value: caller_location, is_owned: false }); } let args = args; @@ -404,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( ); } - let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0], idx); + let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0].value, idx); let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); let sig = fx.bcx.import_signature(sig); @@ -441,7 +453,9 @@ pub(crate) fn codegen_terminator_call<'tcx>( args.into_iter() .enumerate() .skip(if first_arg_override.is_some() { 1 } else { 0 }) - .map(|(i, arg)| adjust_arg_for_abi(fx, arg, &fn_abi.args[i]).into_iter()) + .map(|(i, arg)| { + adjust_arg_for_abi(fx, arg.value, &fn_abi.args[i], arg.is_owned).into_iter() + }) .flatten(), ) .collect::>(); @@ -529,7 +543,7 @@ pub(crate) fn codegen_drop<'tcx>( TypeAndMut { ty, mutbl: crate::rustc_hir::Mutability::Mut }, )), ); - let arg_value = adjust_arg_for_abi(fx, arg_value, &fn_abi.args[0]); + let arg_value = adjust_arg_for_abi(fx, arg_value, &fn_abi.args[0], true); let mut call_args: Vec = arg_value.into_iter().collect::>(); @@ -537,7 +551,7 @@ pub(crate) fn codegen_drop<'tcx>( // Pass the caller location for `#[track_caller]`. let caller_location = fx.get_caller_location(span); call_args.extend( - adjust_arg_for_abi(fx, caller_location, &fn_abi.args[1]).into_iter(), + adjust_arg_for_abi(fx, caller_location, &fn_abi.args[1], false).into_iter(), ); } diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 7c275965199e0..44eae706ea8f6 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -227,6 +227,7 @@ pub(super) fn adjust_arg_for_abi<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, arg: CValue<'tcx>, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, + is_owned: bool, ) -> SmallVec<[Value; 2]> { assert_assignable(fx, arg.layout().ty, arg_abi.layout.ty); match arg_abi.mode { @@ -237,10 +238,21 @@ pub(super) fn adjust_arg_for_abi<'tcx>( smallvec![a, b] } PassMode::Cast(cast) => to_casted_value(fx, arg, cast), - PassMode::Indirect { .. } => match arg.force_stack(fx) { - (ptr, None) => smallvec![ptr.get_addr(fx)], - (ptr, Some(meta)) => smallvec![ptr.get_addr(fx), meta], - }, + PassMode::Indirect { .. } => { + if is_owned { + match arg.force_stack(fx) { + (ptr, None) => smallvec![ptr.get_addr(fx)], + (ptr, Some(meta)) => smallvec![ptr.get_addr(fx), meta], + } + } else { + // Ownership of the value at the backing storage for an argument is passed to the + // callee per the ABI, so we must make a copy of the argument unless the argument + // local is moved. + let place = CPlace::new_stack_slot(fx, arg.layout()); + place.write_cvalue(fx, arg); + smallvec![place.to_ptr().get_addr(fx)] + } + } } } From 472f9f9d6294632bc2fe23e6a8726d526d296bbf Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 19:19:57 +0200 Subject: [PATCH 36/58] Update compiler_builtins version in setup_rust_fork.sh --- scripts/setup_rust_fork.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 52adaaa8de673..ca83e7096b86d 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -33,7 +33,7 @@ index d95b5b7f17f..00b6f0e3635 100644 [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "0.1.45", features = ['rustc-dep-of-std', 'no-asm'] } ++compiler_builtins = { version = "0.1.46", features = ['rustc-dep-of-std', 'no-asm'] } [dev-dependencies] rand = "0.7" From 641e13e0213ea09a2c9003369aaac1e842910c2a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 19:21:45 +0200 Subject: [PATCH 37/58] Replace pointer_ty() with fx.pointer_type where possible --- src/abi/returning.rs | 2 +- src/codegen_i128.rs | 16 ++++++++-------- src/trap.rs | 2 +- src/value_and_place.rs | 4 ++-- src/vtable.rs | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/abi/returning.rs b/src/abi/returning.rs index e5e06d1bd63c8..cb2beed2ca718 100644 --- a/src/abi/returning.rs +++ b/src/abi/returning.rs @@ -73,7 +73,7 @@ pub(super) fn codegen_return_param<'tcx>( } PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { let ret_param = block_params_iter.next().unwrap(); - assert_eq!(fx.bcx.func.dfg.value_type(ret_param), pointer_ty(fx.tcx)); + assert_eq!(fx.bcx.func.dfg.value_type(ret_param), fx.pointer_type); ( CPlace::for_ptr(Pointer::new(ret_param), fx.fn_abi.as_ref().unwrap().ret.layout), smallvec![ret_param], diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs index 22d7f1da0b550..4e50f4d6817ab 100644 --- a/src/codegen_i128.rs +++ b/src/codegen_i128.rs @@ -40,9 +40,9 @@ pub(crate) fn maybe_codegen<'tcx>( fx.lib_call( "__multi3", vec![ - AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), - AbiParam::new(pointer_ty(fx.tcx)), - AbiParam::new(pointer_ty(fx.tcx)), + AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), + AbiParam::new(fx.pointer_type), + AbiParam::new(fx.pointer_type), ], vec![], &args, @@ -63,16 +63,16 @@ pub(crate) fn maybe_codegen<'tcx>( assert!(rhs_extra.is_none()); ( vec![ - AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), - AbiParam::new(pointer_ty(fx.tcx)), - AbiParam::new(pointer_ty(fx.tcx)), + AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), + AbiParam::new(fx.pointer_type), + AbiParam::new(fx.pointer_type), ], [out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)], ) } else { ( vec![ - AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), AbiParam::new(types::I128), AbiParam::new(types::I128), ], @@ -109,7 +109,7 @@ pub(crate) fn maybe_codegen<'tcx>( let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; let ret = fx.lib_call( name, - vec![AbiParam::new(pointer_ty(fx.tcx)), AbiParam::new(pointer_ty(fx.tcx))], + vec![AbiParam::new(fx.pointer_type), AbiParam::new(fx.pointer_type)], vec![AbiParam::new(types::I64X2)], &args, )[0]; diff --git a/src/trap.rs b/src/trap.rs index 21d3e68dbc792..fe8d20fa39fc2 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -10,7 +10,7 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) { Linkage::Import, &Signature { call_conv: CallConv::triple_default(fx.triple()), - params: vec![AbiParam::new(pointer_ty(fx.tcx))], + params: vec![AbiParam::new(fx.pointer_type)], returns: vec![AbiParam::new(types::I32)], }, ) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index b1e00360d566a..d1b66ab02e107 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -34,10 +34,10 @@ fn codegen_field<'tcx>( let (_, unsized_align) = crate::unsize::size_and_align_of_dst(fx, field_layout, extra); - let one = fx.bcx.ins().iconst(pointer_ty(fx.tcx), 1); + let one = fx.bcx.ins().iconst(fx.pointer_type, 1); let align_sub_1 = fx.bcx.ins().isub(unsized_align, one); let and_lhs = fx.bcx.ins().iadd_imm(align_sub_1, unaligned_offset as i64); - let zero = fx.bcx.ins().iconst(pointer_ty(fx.tcx), 0); + let zero = fx.bcx.ins().iconst(fx.pointer_type, 0); let and_rhs = fx.bcx.ins().isub(zero, unsized_align); let offset = fx.bcx.ins().band(and_lhs, and_rhs); diff --git a/src/vtable.rs b/src/vtable.rs index 4a5f9f133a2bb..0004c9787be65 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -14,7 +14,7 @@ fn vtable_memflags() -> MemFlags { pub(crate) fn drop_fn_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value { let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; fx.bcx.ins().load( - pointer_ty(fx.tcx), + fx.pointer_type, vtable_memflags(), vtable, (ty::COMMON_VTABLE_ENTRIES_DROPINPLACE * usize_size) as i32, @@ -24,7 +24,7 @@ pub(crate) fn drop_fn_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> pub(crate) fn size_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value { let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; fx.bcx.ins().load( - pointer_ty(fx.tcx), + fx.pointer_type, vtable_memflags(), vtable, (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32, @@ -34,7 +34,7 @@ pub(crate) fn size_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Val pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value { let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; fx.bcx.ins().load( - pointer_ty(fx.tcx), + fx.pointer_type, vtable_memflags(), vtable, (ty::COMMON_VTABLE_ENTRIES_ALIGN * usize_size) as i32, @@ -55,7 +55,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes(); let func_ref = fx.bcx.ins().load( - pointer_ty(fx.tcx), + fx.pointer_type, vtable_memflags(), vtable, (idx * usize_size as usize) as i32, From a2b17e4e4fb538d1afb2fe3c164cd248fda593e4 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 19:34:23 +0200 Subject: [PATCH 38/58] Enable a working libcore test --- patches/0022-sysroot-Disable-not-compiling-tests.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/patches/0022-sysroot-Disable-not-compiling-tests.patch b/patches/0022-sysroot-Disable-not-compiling-tests.patch index ba0eaacd82870..25a315f666e27 100644 --- a/patches/0022-sysroot-Disable-not-compiling-tests.patch +++ b/patches/0022-sysroot-Disable-not-compiling-tests.patch @@ -51,14 +51,14 @@ index 1a6be3a..42dbd59 100644 #[test] #[allow(warnings)] // Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the -@@ -289,6 +290,7 @@ fn write_unaligned_drop() { - } - DROPS.with(|d| assert_eq!(*d.borrow(), [0])); +@@ -277,6 +277,7 @@ pub fn test_variadic_fnptr() { + let mut s = SipHasher::new(); + assert_eq!(p.hash(&mut s), q.hash(&mut s)); } +*/ #[test] - fn align_offset_zst() { + fn write_unaligned_drop() { diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 6609bc3..241b497 100644 --- a/library/core/tests/slice.rs From c2464ebeb04aaf8e36c98815b09a8660bd3065c3 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 27 Jul 2021 12:42:16 +0200 Subject: [PATCH 39/58] Update Cranelift, gimli and object --- Cargo.lock | 28 ++++++++++++++-------------- Cargo.toml | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index afb4d986409ff..82a8f26254c70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,7 +34,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" dependencies = [ "cranelift-entity", ] @@ -42,7 +42,7 @@ dependencies = [ [[package]] name = "cranelift-codegen" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -58,7 +58,7 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -67,17 +67,17 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" [[package]] name = "cranelift-entity" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" [[package]] name = "cranelift-frontend" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" dependencies = [ "cranelift-codegen", "log", @@ -88,7 +88,7 @@ dependencies = [ [[package]] name = "cranelift-jit" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" dependencies = [ "anyhow", "cranelift-codegen", @@ -105,7 +105,7 @@ dependencies = [ [[package]] name = "cranelift-module" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" dependencies = [ "anyhow", "cranelift-codegen", @@ -116,7 +116,7 @@ dependencies = [ [[package]] name = "cranelift-native" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" dependencies = [ "cranelift-codegen", "libc", @@ -126,7 +126,7 @@ dependencies = [ [[package]] name = "cranelift-object" version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#db5566dadb68b2697d51fc291ae0372cc4990f32" +source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" dependencies = [ "anyhow", "cranelift-codegen", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" dependencies = [ "indexmap", ] @@ -212,9 +212,9 @@ checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" [[package]] name = "object" -version = "0.25.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" +checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" dependencies = [ "crc32fast", "indexmap", diff --git a/Cargo.toml b/Cargo.toml index 02098b135f75b..32a41d3c7ef3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,8 +16,8 @@ cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git" } cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", optional = true } cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git" } target-lexicon = "0.12.0" -gimli = { version = "0.24.0", default-features = false, features = ["write"]} -object = { version = "0.25.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +gimli = { version = "0.25.0", default-features = false, features = ["write"]} +object = { version = "0.26.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } indexmap = "1.0.2" From bcf532ce1db14e940797f5821c741492ca6cf2aa Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 27 Jul 2021 12:54:58 +0200 Subject: [PATCH 40/58] Update dependencies --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82a8f26254c70..23c1fdc6ee425 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.38" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" +checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" [[package]] name = "ar" @@ -156,15 +156,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "indexmap" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", "hashbrown", @@ -172,9 +172,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.97" +version = "0.2.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" +checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" [[package]] name = "libloading" @@ -277,9 +277,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "target-lexicon" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" +checksum = "b0652da4c4121005e9ed22b79f6c5f2d9e2752906b53a33e9490489ba421a6fb" [[package]] name = "winapi" From f4ba61eee573888b9723df5d2c3c2f7a0143fe80 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 27 Jul 2021 15:22:50 +0200 Subject: [PATCH 41/58] Rustup to rustc 1.56.0-nightly (08095fc1f 2021-07-26) --- build_sysroot/Cargo.lock | 9 --------- rust-toolchain | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index 5e5c481cd9a6b..e068f084234bc 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -270,14 +270,6 @@ dependencies = [ "test", ] -[[package]] -name = "term" -version = "0.0.0" -dependencies = [ - "core", - "std", -] - [[package]] name = "test" version = "0.0.0" @@ -290,7 +282,6 @@ dependencies = [ "panic_unwind", "proc_macro", "std", - "term", ] [[package]] diff --git a/rust-toolchain b/rust-toolchain index bc991acda6293..d1611a75b09d6 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-07-19" +channel = "nightly-2021-07-27" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 8a6ff90a3a41e6ace18aeb089ea0a0eb3726dd08 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 28 Jul 2021 14:54:05 +0200 Subject: [PATCH 42/58] Use __muloti4 instead of __rust_i128_mulo Fixes #1126 --- src/codegen_i128.rs | 65 ++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs index 4e50f4d6817ab..638b2d573b5dd 100644 --- a/src/codegen_i128.rs +++ b/src/codegen_i128.rs @@ -27,29 +27,53 @@ pub(crate) fn maybe_codegen<'tcx>( None } BinOp::Add | BinOp::Sub if !checked => None, - BinOp::Mul if !checked => { - let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - if fx.tcx.sess.target.is_like_windows { - let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); - let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); - let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); - assert!(lhs_extra.is_none()); - assert!(rhs_extra.is_none()); - let args = - [ret_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; - fx.lib_call( - "__multi3", + BinOp::Mul if !checked || is_signed => { + if !checked { + let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; + if fx.tcx.sess.target.is_like_windows { + let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + let args = [ + ret_place.to_ptr().get_addr(fx), + lhs_ptr.get_addr(fx), + rhs_ptr.get_addr(fx), + ]; + fx.lib_call( + "__multi3", + vec![ + AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), + AbiParam::new(fx.pointer_type), + AbiParam::new(fx.pointer_type), + ], + vec![], + &args, + ); + Some(ret_place.to_cvalue(fx)) + } else { + Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) + } + } else { + let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); + let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); + let lhs = lhs.load_scalar(fx); + let rhs = rhs.load_scalar(fx); + let oflow_ptr = oflow.to_ptr().get_addr(fx); + let res = fx.lib_call( + "__muloti4", vec![ - AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), - AbiParam::new(fx.pointer_type), + AbiParam::new(types::I128), + AbiParam::new(types::I128), AbiParam::new(fx.pointer_type), ], - vec![], - &args, - ); - Some(ret_place.to_cvalue(fx)) - } else { - Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) + vec![AbiParam::new(types::I128)], + &[lhs, rhs, oflow_ptr], + )[0]; + let oflow = oflow.to_cvalue(fx).load_scalar(fx); + let oflow = fx.bcx.ins().ireduce(types::I8, oflow); + Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty))) } } BinOp::Add | BinOp::Sub | BinOp::Mul => { @@ -85,7 +109,6 @@ pub(crate) fn maybe_codegen<'tcx>( (BinOp::Sub, false) => "__rust_u128_subo", (BinOp::Sub, true) => "__rust_i128_subo", (BinOp::Mul, false) => "__rust_u128_mulo", - (BinOp::Mul, true) => "__rust_i128_mulo", _ => unreachable!(), }; fx.lib_call(name, param_types, vec![], &args); From 2e62516496b9b47bcf25a03195ba024fd326f162 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 28 Jul 2021 17:30:39 +0200 Subject: [PATCH 43/58] Remove workarounds for things unimplemented in Cranelift Many are now implemented, so it is much nicer to directly use the respective Cranelift instructions --- src/base.rs | 2 -- src/cast.rs | 19 ------------------- src/debuginfo/emit.rs | 2 +- src/debuginfo/mod.rs | 2 +- src/intrinsics/mod.rs | 39 ++------------------------------------ src/num.rs | 13 ------------- src/optimize/peephole.rs | 41 +--------------------------------------- 7 files changed, 5 insertions(+), 113 deletions(-) diff --git a/src/base.rs b/src/base.rs index 3d78eed77b94c..e99a227a3a6ea 100644 --- a/src/base.rs +++ b/src/base.rs @@ -334,8 +334,6 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr); let test_zero = if is_inverted { !test_zero } else { test_zero }; let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr); - let discr = - crate::optimize::peephole::make_branchable_value(&mut fx.bcx, discr); if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken( &fx.bcx, discr, test_zero, ) { diff --git a/src/cast.rs b/src/cast.rs index 74c5e09f08da0..e7e6afeb865bb 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -14,21 +14,6 @@ pub(crate) fn clif_intcast( (_, _) if from == to => val, // extend - (_, types::I128) => { - let lo = if from == types::I64 { - val - } else if signed { - fx.bcx.ins().sextend(types::I64, val) - } else { - fx.bcx.ins().uextend(types::I64, val) - }; - let hi = if signed { - fx.bcx.ins().sshr_imm(lo, 63) - } else { - fx.bcx.ins().iconst(types::I64, 0) - }; - fx.bcx.ins().iconcat(lo, hi) - } (_, _) if to.wider_or_equal(from) => { if signed { fx.bcx.ins().sextend(to, val) @@ -38,10 +23,6 @@ pub(crate) fn clif_intcast( } // reduce - (types::I128, _) => { - let (lsb, _msb) = fx.bcx.ins().isplit(val); - if to == types::I64 { lsb } else { fx.bcx.ins().ireduce(to, lsb) } - } (_, _) => fx.bcx.ins().ireduce(to, val), } } diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs index 6018eefcd42fb..fb6ccd7c53584 100644 --- a/src/debuginfo/emit.rs +++ b/src/debuginfo/emit.rs @@ -160,7 +160,7 @@ impl Writer for WriterRelocate { let val = match eh_pe.application() { gimli::DW_EH_PE_absptr => val, gimli::DW_EH_PE_pcrel => { - // TODO: better handling of sign + // FIXME better handling of sign let offset = self.len() as u64; offset.wrapping_sub(val) } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index c67336eb3f2c3..ceef65d54785f 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -46,7 +46,7 @@ impl<'tcx> DebugContext<'tcx> { pub(crate) fn new(tcx: TyCtxt<'tcx>, isa: &dyn TargetIsa) -> Self { let encoding = Encoding { format: Format::Dwarf32, - // TODO: this should be configurable + // FIXME this should be configurable // macOS doesn't seem to support DWARF > 3 // 5 version is required for md5 file hash version: if tcx.sess.target.is_like_osx { diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 17c79645eb24c..4f7f8e7ef6d75 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -611,9 +611,6 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( let (val, has_overflow) = checked_res.load_scalar_pair(fx); let clif_ty = fx.clif_type(T).unwrap(); - // `select.i8` is not implemented by Cranelift. - let has_overflow = fx.bcx.ins().uextend(types::I32, has_overflow); - let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed); let val = match (intrinsic, signed) { @@ -640,21 +637,11 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( }; rotate_left, (v x, v y) { let layout = fx.layout_of(T); - let y = if fx.bcx.func.dfg.value_type(y) == types::I128 { - fx.bcx.ins().ireduce(types::I64, y) - } else { - y - }; let res = fx.bcx.ins().rotl(x, y); ret.write_cvalue(fx, CValue::by_val(res, layout)); }; rotate_right, (v x, v y) { let layout = fx.layout_of(T); - let y = if fx.bcx.func.dfg.value_type(y) == types::I128 { - fx.bcx.ins().ireduce(types::I64, y) - } else { - y - }; let res = fx.bcx.ins().rotr(x, y); ret.write_cvalue(fx, CValue::by_val(res, layout)); }; @@ -692,35 +679,13 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( }; ctlz | ctlz_nonzero, (v arg) { // FIXME trap on `ctlz_nonzero` with zero arg. - let res = if T == fx.tcx.types.u128 || T == fx.tcx.types.i128 { - // FIXME verify this algorithm is correct - let (lsb, msb) = fx.bcx.ins().isplit(arg); - let lsb_lz = fx.bcx.ins().clz(lsb); - let msb_lz = fx.bcx.ins().clz(msb); - let msb_is_zero = fx.bcx.ins().icmp_imm(IntCC::Equal, msb, 0); - let lsb_lz_plus_64 = fx.bcx.ins().iadd_imm(lsb_lz, 64); - let res = fx.bcx.ins().select(msb_is_zero, lsb_lz_plus_64, msb_lz); - fx.bcx.ins().uextend(types::I128, res) - } else { - fx.bcx.ins().clz(arg) - }; + let res = fx.bcx.ins().clz(arg); let res = CValue::by_val(res, fx.layout_of(T)); ret.write_cvalue(fx, res); }; cttz | cttz_nonzero, (v arg) { // FIXME trap on `cttz_nonzero` with zero arg. - let res = if T == fx.tcx.types.u128 || T == fx.tcx.types.i128 { - // FIXME verify this algorithm is correct - let (lsb, msb) = fx.bcx.ins().isplit(arg); - let lsb_tz = fx.bcx.ins().ctz(lsb); - let msb_tz = fx.bcx.ins().ctz(msb); - let lsb_is_zero = fx.bcx.ins().icmp_imm(IntCC::Equal, lsb, 0); - let msb_tz_plus_64 = fx.bcx.ins().iadd_imm(msb_tz, 64); - let res = fx.bcx.ins().select(lsb_is_zero, msb_tz_plus_64, lsb_tz); - fx.bcx.ins().uextend(types::I128, res) - } else { - fx.bcx.ins().ctz(arg) - }; + let res = fx.bcx.ins().ctz(arg); let res = CValue::by_val(res, fx.layout_of(T)); ret.write_cvalue(fx, res); }; diff --git a/src/num.rs b/src/num.rs index 1a0cf939b2fa8..545d390e26995 100644 --- a/src/num.rs +++ b/src/num.rs @@ -67,19 +67,6 @@ pub(crate) fn codegen_binop<'tcx>( let lhs = in_lhs.load_scalar(fx); let rhs = in_rhs.load_scalar(fx); - let (lhs, rhs) = if (bin_op == BinOp::Eq || bin_op == BinOp::Ne) - && (in_lhs.layout().ty.kind() == fx.tcx.types.i8.kind() - || in_lhs.layout().ty.kind() == fx.tcx.types.i16.kind()) - { - // FIXME(CraneStation/cranelift#896) icmp_imm.i8/i16 with eq/ne for signed ints is implemented wrong. - ( - fx.bcx.ins().sextend(types::I32, lhs), - fx.bcx.ins().sextend(types::I32, rhs), - ) - } else { - (lhs, rhs) - }; - return codegen_compare_bin_op(fx, bin_op, signed, lhs, rhs); } _ => {} diff --git a/src/optimize/peephole.rs b/src/optimize/peephole.rs index b95e2d72877d9..d637b4d89293c 100644 --- a/src/optimize/peephole.rs +++ b/src/optimize/peephole.rs @@ -1,8 +1,6 @@ //! Peephole optimizations that can be performed while creating clif ir. -use cranelift_codegen::ir::{ - condcodes::IntCC, types, InstBuilder, InstructionData, Opcode, Value, ValueDef, -}; +use cranelift_codegen::ir::{condcodes::IntCC, InstructionData, Opcode, Value, ValueDef}; use cranelift_frontend::FunctionBuilder; /// If the given value was produced by a `bint` instruction, return it's input, otherwise return the @@ -37,43 +35,6 @@ pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) - } } -pub(crate) fn make_branchable_value(bcx: &mut FunctionBuilder<'_>, arg: Value) -> Value { - if bcx.func.dfg.value_type(arg).is_bool() { - return arg; - } - - (|| { - let arg_inst = if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) { - arg_inst - } else { - return None; - }; - - match bcx.func.dfg[arg_inst] { - // This is the lowering of Rvalue::Not - InstructionData::Load { opcode: Opcode::Load, arg: ptr, flags, offset } => { - // Using `load.i8 + uextend.i32` would legalize to `uload8 + ireduce.i8 + - // uextend.i32`. Just `uload8` is much faster. - match bcx.func.dfg.ctrl_typevar(arg_inst) { - types::I8 => Some(bcx.ins().uload8(types::I32, flags, ptr, offset)), - types::I16 => Some(bcx.ins().uload16(types::I32, flags, ptr, offset)), - _ => None, - } - } - _ => None, - } - })() - .unwrap_or_else(|| { - match bcx.func.dfg.value_type(arg) { - types::I8 | types::I16 => { - // WORKAROUND for brz.i8 and brnz.i8 not yet being implemented - bcx.ins().uextend(types::I32, arg) - } - _ => arg, - } - }) -} - /// Returns whether the branch is statically known to be taken or `None` if it isn't statically known. pub(crate) fn maybe_known_branch_taken( bcx: &FunctionBuilder<'_>, From bab224d254803f840aa7138f2712fbe9b2fbc87b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 28 Jul 2021 18:26:03 +0200 Subject: [PATCH 44/58] Remove outdated FIXME --- src/intrinsics/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 4f7f8e7ef6d75..12c8862879487 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -968,8 +968,6 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); }; - - // FIXME https://github.com/bytecodealliance/wasmtime/issues/2647 _ if intrinsic.as_str().starts_with("atomic_nand"), (v ptr, c src) { let layout = src.layout(); validate_atomic_type!(fx, intrinsic, span, layout.ty); From 8704a66922e9fbe3fafb4d27eeb13b34e8cebd82 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 28 Jul 2021 18:27:06 +0200 Subject: [PATCH 45/58] Allow returning PassMode::Cast directly to an ssa var --- src/abi/returning.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/abi/returning.rs b/src/abi/returning.rs index cb2beed2ca718..3b126938f14cf 100644 --- a/src/abi/returning.rs +++ b/src/abi/returning.rs @@ -44,9 +44,9 @@ pub(crate) fn can_return_to_ssa_var<'tcx>( FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args) }; match fn_abi.ret.mode { - PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => true, - // FIXME Make it possible to return Cast and Indirect to an ssa var. - PassMode::Cast(_) | PassMode::Indirect { .. } => false, + PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => true, + // FIXME Make it possible to return Indirect to an ssa var. + PassMode::Indirect { .. } => false, } } From b7881bb08d129a119c69ca79999cae54cef3efb4 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 28 Jul 2021 18:31:27 +0200 Subject: [PATCH 46/58] Remove CPlace::no_place It is never the right function --- src/abi/returning.rs | 3 +-- src/value_and_place.rs | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/abi/returning.rs b/src/abi/returning.rs index 3b126938f14cf..f9fc3992ae212 100644 --- a/src/abi/returning.rs +++ b/src/abi/returning.rs @@ -58,8 +58,7 @@ pub(super) fn codegen_return_param<'tcx>( block_params_iter: &mut impl Iterator, ) -> CPlace<'tcx> { let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.as_ref().unwrap().ret.mode { - PassMode::Ignore => (CPlace::no_place(fx.fn_abi.as_ref().unwrap().ret.layout), smallvec![]), - PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => { + PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => { let is_ssa = ssa_analyzed[RETURN_PLACE] == crate::analyze::SsaKind::Ssa; ( super::make_local_place( diff --git a/src/value_and_place.rs b/src/value_and_place.rs index d1b66ab02e107..364b3da92b888 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -318,17 +318,16 @@ impl<'tcx> CPlace<'tcx> { &self.inner } - pub(crate) fn no_place(layout: TyAndLayout<'tcx>) -> CPlace<'tcx> { - CPlace { inner: CPlaceInner::Addr(Pointer::dangling(layout.align.pref), None), layout } - } - pub(crate) fn new_stack_slot( fx: &mut FunctionCx<'_, '_, 'tcx>, layout: TyAndLayout<'tcx>, ) -> CPlace<'tcx> { assert!(!layout.is_unsized()); if layout.size.bytes() == 0 { - return CPlace::no_place(layout); + return CPlace { + inner: CPlaceInner::Addr(Pointer::dangling(layout.align.pref), None), + layout, + }; } let stack_slot = fx.bcx.create_stack_slot(StackSlotData { From e0b9f3b3cc3cdf3edcf0868e6c88e652455055fd Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 28 Jul 2021 18:54:21 +0200 Subject: [PATCH 47/58] Support storing return values in register places for all pass modes --- src/abi/mod.rs | 2 +- src/abi/returning.rs | 75 ++++++++++++++------------------------------ src/analyze.rs | 11 ------- 3 files changed, 24 insertions(+), 64 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 0478d4b198afc..13790409e59f6 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -14,7 +14,7 @@ use cranelift_codegen::ir::{AbiParam, SigRef}; use self::pass_mode::*; use crate::prelude::*; -pub(crate) use self::returning::{can_return_to_ssa_var, codegen_return}; +pub(crate) use self::returning::codegen_return; fn clif_sig_from_fn_abi<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/src/abi/returning.rs b/src/abi/returning.rs index f9fc3992ae212..c1bdba43e6ccb 100644 --- a/src/abi/returning.rs +++ b/src/abi/returning.rs @@ -2,54 +2,9 @@ use crate::prelude::*; -use rustc_middle::ty::layout::FnAbiExt; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; +use rustc_target::abi::call::{ArgAbi, PassMode}; use smallvec::{smallvec, SmallVec}; -/// Can the given type be returned into an ssa var or does it need to be returned on the stack. -pub(crate) fn can_return_to_ssa_var<'tcx>( - fx: &FunctionCx<'_, '_, 'tcx>, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], -) -> bool { - let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx)); - let fn_sig = - fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx)); - - // Handle special calls like instrinsics and empty drop glue. - let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() { - let instance = ty::Instance::resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs) - .unwrap() - .unwrap() - .polymorphize(fx.tcx); - - match instance.def { - InstanceDef::Intrinsic(_) | InstanceDef::DropGlue(_, _) => { - return true; - } - _ => Some(instance), - } - } else { - None - }; - - let extra_args = &args[fn_sig.inputs().len()..]; - let extra_args = extra_args - .iter() - .map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))) - .collect::>(); - let fn_abi = if let Some(instance) = instance { - FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args) - } else { - FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args) - }; - match fn_abi.ret.mode { - PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => true, - // FIXME Make it possible to return Indirect to an ssa var. - PassMode::Indirect { .. } => false, - } -} - /// Return a place where the return value of the current function can be written to. If necessary /// this adds an extra parameter pointing to where the return value needs to be stored. pub(super) fn codegen_return_param<'tcx>( @@ -104,16 +59,24 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( ret_place: Option>, f: impl FnOnce(&mut FunctionCx<'_, '_, 'tcx>, Option) -> Inst, ) { - let return_ptr = match ret_arg_abi.mode { - PassMode::Ignore => None, + let (ret_temp_place, return_ptr) = match ret_arg_abi.mode { + PassMode::Ignore => (None, None), PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => match ret_place { - Some(ret_place) => Some(ret_place.to_ptr().get_addr(fx)), - None => Some(fx.bcx.ins().iconst(fx.pointer_type, 43)), // FIXME allocate temp stack slot + Some(ret_place) if matches!(ret_place.inner(), CPlaceInner::Addr(_, None)) => { + // This is an optimization to prevent unnecessary copies of the return value when + // the return place is already a memory place as opposed to a register. + // This match arm can be safely removed. + (None, Some(ret_place.to_ptr().get_addr(fx))) + } + _ => { + let place = CPlace::new_stack_slot(fx, ret_arg_abi.layout); + (Some(place), Some(place.to_ptr().get_addr(fx))) + } }, PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { unreachable!("unsized return value") } - PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => None, + PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => (None, None), }; let call_inst = f(fx, return_ptr); @@ -149,7 +112,15 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( ret_place.write_cvalue(fx, result); } } - PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {} + PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { + if let (Some(ret_place), Some(ret_temp_place)) = (ret_place, ret_temp_place) { + // Both ret_place and ret_temp_place must be Some. If ret_place is None, this is + // a non-returning call. If ret_temp_place is None, it is not necessary to copy the + // return value. + let ret_temp_value = ret_temp_place.to_cvalue(fx); + ret_place.write_cvalue(fx, ret_temp_value); + } + } PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { unreachable!("unsized return value") } diff --git a/src/analyze.rs b/src/analyze.rs index efead25552f4d..35b89358b1984 100644 --- a/src/analyze.rs +++ b/src/analyze.rs @@ -38,17 +38,6 @@ pub(crate) fn analyze(fx: &FunctionCx<'_, '_, '_>) -> IndexVec { _ => {} } } - - match &bb.terminator().kind { - TerminatorKind::Call { destination, func, args, .. } => { - if let Some((dest_place, _dest_bb)) = destination { - if !crate::abi::can_return_to_ssa_var(fx, func, args) { - not_ssa(&mut flag_map, dest_place.local) - } - } - } - _ => {} - } } flag_map From c6564f814e39da74c6e551858e2040abc37e70f1 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 29 Jul 2021 15:20:37 +0200 Subject: [PATCH 48/58] Fix float min and max operations in presence of NaN Cranelift's fmin and fmax instructions propagate NaN, while Rust's min and max don't. Fixes #1049 --- ...01-stdsimd-Disable-unsupported-tests.patch | 16 -------- .../0023-sysroot-Ignore-failing-tests.patch | 40 ------------------- scripts/tests.sh | 1 + src/intrinsics/mod.rs | 24 +++++++++-- src/intrinsics/simd.rs | 2 + 5 files changed, 23 insertions(+), 60 deletions(-) diff --git a/patches/0001-stdsimd-Disable-unsupported-tests.patch b/patches/0001-stdsimd-Disable-unsupported-tests.patch index b24f67f3edc30..731c60fda58d6 100644 --- a/patches/0001-stdsimd-Disable-unsupported-tests.patch +++ b/patches/0001-stdsimd-Disable-unsupported-tests.patch @@ -124,22 +124,6 @@ index cb39e73..fc0ebe1 100644 fn sqrt() { test_helpers::test_unary_elementwise( -@@ -491,6 +493,7 @@ macro_rules! impl_float_tests { - ) - } - -+ /* - fn min() { - // Regular conditions (both values aren't zero) - test_helpers::test_binary_elementwise( -@@ -536,6 +539,7 @@ macro_rules! impl_float_tests { - assert!(p_zero.max(n_zero).to_array().iter().all(|x| *x == 0.)); - assert!(n_zero.max(p_zero).to_array().iter().all(|x| *x == 0.)); - } -+ */ - - fn clamp() { - test_helpers::test_3(&|value: [Scalar; LANES], mut min: [Scalar; LANES], mut max: [Scalar; LANES]| { @@ -581,6 +585,7 @@ macro_rules! impl_float_tests { }); } diff --git a/patches/0023-sysroot-Ignore-failing-tests.patch b/patches/0023-sysroot-Ignore-failing-tests.patch index 5d2c3049f60eb..50ef0bd9418c7 100644 --- a/patches/0023-sysroot-Ignore-failing-tests.patch +++ b/patches/0023-sysroot-Ignore-failing-tests.patch @@ -46,45 +46,5 @@ index 4bc44e9..8e3c7a4 100644 #[test] fn cell_allows_array_cycle() { -diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs -index a17c094..5bb11d2 100644 ---- a/library/core/tests/num/mod.rs -+++ b/library/core/tests/num/mod.rs -@@ -651,11 +651,12 @@ macro_rules! test_float { - assert_eq!((9.0 as $fty).min($neginf), $neginf); - assert_eq!(($neginf as $fty).min(-9.0), $neginf); - assert_eq!((-9.0 as $fty).min($neginf), $neginf); -- assert_eq!(($nan as $fty).min(9.0), 9.0); -- assert_eq!(($nan as $fty).min(-9.0), -9.0); -- assert_eq!((9.0 as $fty).min($nan), 9.0); -- assert_eq!((-9.0 as $fty).min($nan), -9.0); -- assert!(($nan as $fty).min($nan).is_nan()); -+ // Cranelift fmin has NaN propagation -+ //assert_eq!(($nan as $fty).min(9.0), 9.0); -+ //assert_eq!(($nan as $fty).min(-9.0), -9.0); -+ //assert_eq!((9.0 as $fty).min($nan), 9.0); -+ //assert_eq!((-9.0 as $fty).min($nan), -9.0); -+ //assert!(($nan as $fty).min($nan).is_nan()); - } - #[test] - fn max() { -@@ -673,11 +674,12 @@ macro_rules! test_float { - assert_eq!((9.0 as $fty).max($neginf), 9.0); - assert_eq!(($neginf as $fty).max(-9.0), -9.0); - assert_eq!((-9.0 as $fty).max($neginf), -9.0); -- assert_eq!(($nan as $fty).max(9.0), 9.0); -- assert_eq!(($nan as $fty).max(-9.0), -9.0); -- assert_eq!((9.0 as $fty).max($nan), 9.0); -- assert_eq!((-9.0 as $fty).max($nan), -9.0); -- assert!(($nan as $fty).max($nan).is_nan()); -+ // Cranelift fmax has NaN propagation -+ //assert_eq!(($nan as $fty).max(9.0), 9.0); -+ //assert_eq!(($nan as $fty).max(-9.0), -9.0); -+ //assert_eq!((9.0 as $fty).max($nan), 9.0); -+ //assert_eq!((-9.0 as $fty).max($nan), -9.0); -+ //assert!(($nan as $fty).max($nan).is_nan()); - } - #[test] - fn rem_euclid() { -- 2.21.0 (Apple Git-122) diff --git a/scripts/tests.sh b/scripts/tests.sh index 1b8858eb4ab7c..0eef710239bdd 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -139,6 +139,7 @@ function extended_sysroot_tests() { pushd stdsimd echo "[TEST] rust-lang/stdsimd" + ../build/cargo clean ../build/cargo build --all-targets --target $TARGET_TRIPLE if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then ../build/cargo test -q diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 12c8862879487..8669846074749 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1029,23 +1029,39 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); }; + // In Rust floating point min and max don't propagate NaN. In Cranelift they do however. + // For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for `minnumf*` + // and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing + // a float against itself. Only in case of NaN is it not equal to itself. minnumf32, (v a, v b) { - let val = fx.bcx.ins().fmin(a, b); + let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); + let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b); + let temp = fx.bcx.ins().select(a_ge_b, b, a); + let val = fx.bcx.ins().select(a_is_nan, b, temp); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); ret.write_cvalue(fx, val); }; minnumf64, (v a, v b) { - let val = fx.bcx.ins().fmin(a, b); + let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); + let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b); + let temp = fx.bcx.ins().select(a_ge_b, b, a); + let val = fx.bcx.ins().select(a_is_nan, b, temp); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); }; maxnumf32, (v a, v b) { - let val = fx.bcx.ins().fmax(a, b); + let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); + let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b); + let temp = fx.bcx.ins().select(a_le_b, b, a); + let val = fx.bcx.ins().select(a_is_nan, b, temp); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); ret.write_cvalue(fx, val); }; maxnumf64, (v a, v b) { - let val = fx.bcx.ins().fmax(a, b); + let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); + let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b); + let temp = fx.bcx.ins().select(a_le_b, b, a); + let val = fx.bcx.ins().select(a_is_nan, b, temp); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); }; diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 37906ab472d2e..43e68b4afa9ea 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -378,6 +378,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; simd_reduce_min, (c v) { + // FIXME support floats validate_simd_type!(fx, intrinsic, span, v.layout().ty); simd_reduce(fx, v, None, ret, |fx, layout, a, b| { let lt = fx.bcx.ins().icmp(if layout.ty.is_signed() { @@ -390,6 +391,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; simd_reduce_max, (c v) { + // FIXME support floats validate_simd_type!(fx, intrinsic, span, v.layout().ty); simd_reduce(fx, v, None, ret, |fx, layout, a, b| { let gt = fx.bcx.ins().icmp(if layout.ty.is_signed() { From 84961ef06acbb3e28354aa581454efce3972c0a2 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 29 Jul 2021 19:46:31 +0200 Subject: [PATCH 49/58] Re-enable a fixed rustc tests --- scripts/test_rustc_tests.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 2f5c2cf737b05..0ac49dd35740f 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -79,7 +79,6 @@ rm src/test/ui/type-alias-impl-trait/cross_crate_ice*.rs # requires removed aux rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition rm src/test/ui/cfg/cfg-panic.rs -rm src/test/ui/default-alloc-error-hook.rs rm -r src/test/ui/hygiene/ rm -r src/test/ui/polymorphization/ # polymorphization not yet supported From 966e54ee2ed1a329ae0e1fe28e9a7bcc75d96ab5 Mon Sep 17 00:00:00 2001 From: Jade Date: Tue, 27 Jul 2021 16:38:13 -0700 Subject: [PATCH 50/58] rfc3052: Remove authors field from Cargo manifests Since RFC 3052 soft deprecated the authors field anyway, hiding it from crates.io, docs.rs, and making Cargo not add it by default, and it is not generally up to date/useful information, we should remove it from crates in this repo. --- Cargo.toml | 1 - build_sysroot/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef68d7ee532dd..6593ac738fe84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "rustc_codegen_cranelift" version = "0.1.0" -authors = ["bjorn3 "] edition = "2018" [lib] diff --git a/build_sysroot/Cargo.toml b/build_sysroot/Cargo.toml index 04748d5dbab59..f25d87e60c0c1 100644 --- a/build_sysroot/Cargo.toml +++ b/build_sysroot/Cargo.toml @@ -1,5 +1,4 @@ [package] -authors = ["bjorn3 "] name = "sysroot" version = "0.0.0" From 6f682236c96f7f304ffda201ef80824765a50bd8 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Sat, 31 Jul 2021 22:46:23 +0800 Subject: [PATCH 51/58] Implement pointer casting. --- src/unsize.rs | 63 +++++++++++++++++++++++++++++++++++++++------------ src/vtable.rs | 2 +- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/unsize.rs b/src/unsize.rs index b9d379c6117c9..d594731b4dfce 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -25,39 +25,73 @@ pub(crate) fn unsized_info<'tcx>( .bcx .ins() .iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64), - (&ty::Dynamic(..), &ty::Dynamic(..)) => { - // For now, upcasts are limited to changes in marker - // traits, and hence never actually require an actual - // change to the vtable. - old_info.expect("unsized_info: missing old info for trait upcast") + (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { + let old_info = + old_info.expect("unsized_info: missing old info for trait upcasting coercion"); + if data_a.principal_def_id() == data_b.principal_def_id() { + return old_info; + } + // trait upcasting coercion + + // if both of the two `principal`s are `None`, this function would have returned early above. + // and if one of the two `principal`s is `None`, typechecking would have rejected this case. + let principal_a = data_a + .principal() + .expect("unsized_info: missing principal trait for trait upcasting coercion"); + let principal_b = data_b + .principal() + .expect("unsized_info: missing principal trait for trait upcasting coercion"); + + let vptr_entry_idx = fx.tcx.vtable_trait_upcasting_coercion_new_vptr_slot(( + principal_a.with_self_ty(fx.tcx, source), + principal_b.with_self_ty(fx.tcx, source), + )); + + if let Some(entry_idx) = vptr_entry_idx { + let entry_idx = u32::try_from(entry_idx).unwrap(); + let entry_offset = entry_idx * fx.pointer_type.bytes(); + let vptr_ptr = Pointer::new(old_info).offset_i64(fx, entry_offset.into()).load( + fx, + fx.pointer_type, + crate::vtable::vtable_memflags(), + ); + vptr_ptr + } else { + old_info + } } (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } -/// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer. -fn unsize_thin_ptr<'tcx>( +/// Coerce `src` to `dst_ty`. +fn unsize_ptr<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, src: Value, src_layout: TyAndLayout<'tcx>, dst_layout: TyAndLayout<'tcx>, + old_info: Option, ) -> (Value, Value) { match (&src_layout.ty.kind(), &dst_layout.ty.kind()) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _)) | (&ty::Ref(_, a, _), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { assert!(!fx.layout_of(a).is_unsized()); - (src, unsized_info(fx, a, b, None)) + (src, unsized_info(fx, a, b, old_info)) } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { let (a, b) = (src_layout.ty.boxed_ty(), dst_layout.ty.boxed_ty()); assert!(!fx.layout_of(a).is_unsized()); - (src, unsized_info(fx, a, b, None)) + (src, unsized_info(fx, a, b, old_info)) } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); + if src_layout == dst_layout { + return (src, old_info.unwrap()); + } + let mut result = None; for i in 0..src_layout.fields.count() { let src_f = src_layout.field(fx, i); @@ -71,11 +105,11 @@ fn unsize_thin_ptr<'tcx>( let dst_f = dst_layout.field(fx, i); assert_ne!(src_f.ty, dst_f.ty); assert_eq!(result, None); - result = Some(unsize_thin_ptr(fx, src, src_f, dst_f)); + result = Some(unsize_ptr(fx, src, src_f, dst_f, old_info)); } result.unwrap() } - _ => bug!("unsize_thin_ptr: called on bad types"), + _ => bug!("unsize_ptr: called on bad types"), } } @@ -91,12 +125,11 @@ pub(crate) fn coerce_unsized_into<'tcx>( let mut coerce_ptr = || { let (base, info) = if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty).is_unsized() { - // fat-ptr to fat-ptr unsize preserves the vtable - // i.e., &'a fmt::Debug+Send => &'a fmt::Debug - src.load_scalar_pair(fx) + let (old_base, old_info) = src.load_scalar_pair(fx); + unsize_ptr(fx, old_base, src.layout(), dst.layout(), Some(old_info)) } else { let base = src.load_scalar(fx); - unsize_thin_ptr(fx, base, src.layout(), dst.layout()) + unsize_ptr(fx, base, src.layout(), dst.layout(), None) }; dst.write_cvalue(fx, CValue::by_val_pair(base, info, dst.layout())); }; diff --git a/src/vtable.rs b/src/vtable.rs index 4a5f9f133a2bb..1b31587430887 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -5,7 +5,7 @@ use crate::constant::data_id_for_alloc_id; use crate::prelude::*; -fn vtable_memflags() -> MemFlags { +pub(crate) fn vtable_memflags() -> MemFlags { let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap. flags.set_readonly(); // A vtable is always read-only. flags From f9c5bbba6b3ecaac0f16f3268c85cb371e9be7e3 Mon Sep 17 00:00:00 2001 From: Gheorghe Anghelescu Date: Wed, 4 Aug 2021 10:23:27 +0300 Subject: [PATCH 52/58] change instructions for manually compiling y.rs (#1191) This prevents an error on windows where the `build_sysroot` function was trying to delete `y.exe`. --- y.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/y.rs b/y.rs index 43937588b481d..26605003c4200 100755 --- a/y.rs +++ b/y.rs @@ -15,8 +15,8 @@ exec ${0/.rs/.bin} $@ //! for example: //! //! ```shell -//! $ rustc y.rs -o build/y.bin -//! $ build/y.bin +//! $ rustc y.rs -o y.bin +//! $ ./y.bin //! ``` //! //! # Naming From 5ff06fb77f906b65b6a5301e84acc82a246af2b0 Mon Sep 17 00:00:00 2001 From: Hans Kratz Date: Wed, 4 Aug 2021 14:25:45 +0000 Subject: [PATCH 53/58] Fix overflow in rustc happening if the `err_count()` is reduced in a stage. This can happen if stashed diagnostics are removed or replaced with fewer errors. The semantics stay the same if built without overflow. Fixes #84219. --- compiler/rustc_session/src/session.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 9ab6dbb1ea906..ea2067aaa83f1 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -450,8 +450,7 @@ impl Session { { let old_count = self.err_count(); let result = f(); - let errors = self.err_count() - old_count; - if errors == 0 { Ok(result) } else { Err(ErrorReported) } + if self.err_count() == old_count { Ok(result) } else { Err(ErrorReported) } } pub fn span_warn>(&self, sp: S, msg: &str) { self.diagnostic().span_warn(sp, msg) From 7520ea9046de23d04829db40687a7fdde5034530 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Thu, 5 Aug 2021 17:42:27 +0800 Subject: [PATCH 54/58] Use `C-unwind` ABI for `__rust_start_panic` in `panic_abort` --- library/panic_abort/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index d95ea6530c204..4580f9a7758f3 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -15,6 +15,7 @@ #![feature(staged_api)] #![feature(rustc_attrs)] #![feature(asm)] +#![feature(c_unwind)] #[cfg(target_os = "android")] mod android; @@ -30,7 +31,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen // "Leak" the payload and shim to the relevant abort on the platform in question. #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { +pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { // Android has the ability to attach a message as part of the abort. #[cfg(target_os = "android")] android::android_set_abort_message(_payload); From 05677b6bd6c938ed760835d9b1f6514992654ae3 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 5 Aug 2021 15:32:02 +0200 Subject: [PATCH 55/58] Rustup to rustc 1.56.0-nightly (25b764849 2021-08-04) --- ...027-sysroot-128bit-atomic-operations.patch | 64 +++++++++---------- rust-toolchain | 2 +- src/unsize.rs | 2 - 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/patches/0027-sysroot-128bit-atomic-operations.patch b/patches/0027-sysroot-128bit-atomic-operations.patch index 32e5930969061..cda8153083c33 100644 --- a/patches/0027-sysroot-128bit-atomic-operations.patch +++ b/patches/0027-sysroot-128bit-atomic-operations.patch @@ -1,20 +1,44 @@ -From 894e07dfec2624ba539129b1c1d63e1d7d812bda Mon Sep 17 00:00:00 2001 +From 6a4e6f5dc8c8a529a822eb9b57f9e57519595439 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 18 Feb 2021 18:45:28 +0100 Subject: [PATCH] Disable 128bit atomic operations Cranelift doesn't support them yet --- - library/core/src/sync/atomic.rs | 38 --------------------------------- - library/core/tests/atomic.rs | 4 ---- - library/std/src/panic.rs | 6 ------ + library/core/src/panic/unwind_safe.rs | 6 ----- + library/core/src/sync/atomic.rs | 38 --------------------------- + library/core/tests/atomic.rs | 4 --- 3 files changed, 48 deletions(-) +diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs +index 092b7cf..158cf71 100644 +--- a/library/core/src/panic/unwind_safe.rs ++++ b/library/core/src/panic/unwind_safe.rs +@@ -216,9 +216,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} + #[cfg(target_has_atomic_load_store = "64")] + #[stable(feature = "integer_atomics_stable", since = "1.34.0")] + impl RefUnwindSafe for crate::sync::atomic::AtomicI64 {} +-#[cfg(target_has_atomic_load_store = "128")] +-#[unstable(feature = "integer_atomics", issue = "32976")] +-impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} + + #[cfg(target_has_atomic_load_store = "ptr")] + #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] +@@ -235,9 +232,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} + #[cfg(target_has_atomic_load_store = "64")] + #[stable(feature = "integer_atomics_stable", since = "1.34.0")] + impl RefUnwindSafe for crate::sync::atomic::AtomicU64 {} +-#[cfg(target_has_atomic_load_store = "128")] +-#[unstable(feature = "integer_atomics", issue = "32976")] +-impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} + + #[cfg(target_has_atomic_load_store = "8")] + #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs -index 81c9e1d..65c9503 100644 +index 0194c58..25a0038 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs -@@ -2228,44 +2228,6 @@ atomic_int! { +@@ -2229,44 +2229,6 @@ atomic_int! { "AtomicU64::new(0)", u64 AtomicU64 ATOMIC_U64_INIT } @@ -60,10 +84,10 @@ index 81c9e1d..65c9503 100644 macro_rules! atomic_int_ptr_sized { ( $($target_pointer_width:literal $align:literal)* ) => { $( diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs -index 2d1e449..cb6da5d 100644 +index b735957..ea728b6 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs -@@ -145,10 +145,6 @@ fn atomic_alignment() { +@@ -185,10 +185,6 @@ fn atomic_alignment() { assert_eq!(align_of::(), size_of::()); #[cfg(target_has_atomic = "64")] assert_eq!(align_of::(), size_of::()); @@ -74,30 +98,6 @@ index 2d1e449..cb6da5d 100644 #[cfg(target_has_atomic = "ptr")] assert_eq!(align_of::(), size_of::()); #[cfg(target_has_atomic = "ptr")] -diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs -index 89a822a..779fd88 100644 ---- a/library/std/src/panic.rs -+++ b/library/std/src/panic.rs -@@ -279,9 +279,6 @@ impl RefUnwindSafe for atomic::AtomicI32 {} - #[cfg(target_has_atomic_load_store = "64")] - #[stable(feature = "integer_atomics_stable", since = "1.34.0")] - impl RefUnwindSafe for atomic::AtomicI64 {} --#[cfg(target_has_atomic_load_store = "128")] --#[unstable(feature = "integer_atomics", issue = "32976")] --impl RefUnwindSafe for atomic::AtomicI128 {} - - #[cfg(target_has_atomic_load_store = "ptr")] - #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] -@@ -298,9 +295,6 @@ impl RefUnwindSafe for atomic::AtomicU32 {} - #[cfg(target_has_atomic_load_store = "64")] - #[stable(feature = "integer_atomics_stable", since = "1.34.0")] - impl RefUnwindSafe for atomic::AtomicU64 {} --#[cfg(target_has_atomic_load_store = "128")] --#[unstable(feature = "integer_atomics", issue = "32976")] --impl RefUnwindSafe for atomic::AtomicU128 {} - - #[cfg(target_has_atomic_load_store = "8")] - #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] -- 2.26.2.7.g19db9cfb68 diff --git a/rust-toolchain b/rust-toolchain index d1611a75b09d6..f074ebe7a42e0 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-07-27" +channel = "nightly-2021-08-05" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/unsize.rs b/src/unsize.rs index d594731b4dfce..d9c4647cba3a9 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -77,12 +77,10 @@ fn unsize_ptr<'tcx>( (&ty::Ref(_, a, _), &ty::Ref(_, b, _)) | (&ty::Ref(_, a, _), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { - assert!(!fx.layout_of(a).is_unsized()); (src, unsized_info(fx, a, b, old_info)) } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { let (a, b) = (src_layout.ty.boxed_ty(), dst_layout.ty.boxed_ty()); - assert!(!fx.layout_of(a).is_unsized()); (src, unsized_info(fx, a, b, old_info)) } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { From 89a8ba46b8a1ab4c857706ed375e91a0f3f64a86 Mon Sep 17 00:00:00 2001 From: Max Fan Date: Thu, 5 Aug 2021 22:50:56 -0400 Subject: [PATCH 56/58] Fix typo in the ptr documentation --- library/core/src/ptr/const_ptr.rs | 2 +- library/core/src/ptr/mut_ptr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index ac2e5ed256df3..95e86a688beb9 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -48,7 +48,7 @@ impl *const T { self as _ } - /// Decompose a (possibly wide) pointer into is address and metadata components. + /// Decompose a (possibly wide) pointer into its address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts`]. #[unstable(feature = "ptr_metadata", issue = "81513")] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 98a4cb59a6629..adc64cb2bd39a 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -47,7 +47,7 @@ impl *mut T { self as _ } - /// Decompose a (possibly wide) pointer into is address and metadata components. + /// Decompose a (possibly wide) pointer into its address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts_mut`]. #[unstable(feature = "ptr_metadata", issue = "81513")] From d0d49477755cead57aa20a4958562e7ca6e8f805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 4 Aug 2021 23:29:30 +0200 Subject: [PATCH 57/58] Add hint for unresolved associated trait items if the trait has a single item --- compiler/rustc_resolve/src/diagnostics.rs | 62 +++++++++++++------ .../rustc_resolve/src/late/diagnostics.rs | 52 +++++++++++++--- src/test/ui/associated-item/issue-87638.fixed | 22 +++++++ src/test/ui/associated-item/issue-87638.rs | 22 +++++++ .../ui/associated-item/issue-87638.stderr | 27 ++++++++ .../ui/associated-types/issue-22037.stderr | 7 ++- src/test/ui/issues/issue-19883.stderr | 8 ++- 7 files changed, 172 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/associated-item/issue-87638.fixed create mode 100644 src/test/ui/associated-item/issue-87638.rs create mode 100644 src/test/ui/associated-item/issue-87638.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7439cd9a0fe3d..0a5da653fab07 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -38,14 +38,25 @@ crate type Suggestion = (Vec<(Span, String)>, String, Applicability); /// similarly named label and whether or not it is reachable. crate type LabelSuggestion = (Ident, bool); +crate enum SuggestionTarget { + /// The target has a similar name as the name used by the programmer (probably a typo) + SimilarlyNamed, + /// The target is the only valid item that can be used in the corresponding context + SingleItem, +} + crate struct TypoSuggestion { pub candidate: Symbol, pub res: Res, + pub target: SuggestionTarget, } impl TypoSuggestion { - crate fn from_res(candidate: Symbol, res: Res) -> TypoSuggestion { - TypoSuggestion { candidate, res } + crate fn typo_from_res(candidate: Symbol, res: Res) -> TypoSuggestion { + Self { candidate, res, target: SuggestionTarget::SimilarlyNamed } + } + crate fn single_item_from_res(candidate: Symbol, res: Res) -> TypoSuggestion { + Self { candidate, res, target: SuggestionTarget::SingleItem } } } @@ -80,7 +91,7 @@ impl<'a> Resolver<'a> { if let Some(binding) = resolution.borrow().binding { let res = binding.res(); if filter_fn(res) { - names.push(TypoSuggestion::from_res(key.ident.name, res)); + names.push(TypoSuggestion::typo_from_res(key.ident.name, res)); } } } @@ -623,7 +634,7 @@ impl<'a> Resolver<'a> { .get(&expn_id) .into_iter() .flatten() - .map(|ident| TypoSuggestion::from_res(ident.name, res)), + .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)), ); } } @@ -642,7 +653,7 @@ impl<'a> Resolver<'a> { suggestions.extend( ext.helper_attrs .iter() - .map(|name| TypoSuggestion::from_res(*name, res)), + .map(|name| TypoSuggestion::typo_from_res(*name, res)), ); } } @@ -652,8 +663,10 @@ impl<'a> Resolver<'a> { if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() { let res = macro_rules_binding.binding.res(); if filter_fn(res) { - suggestions - .push(TypoSuggestion::from_res(macro_rules_binding.ident.name, res)) + suggestions.push(TypoSuggestion::typo_from_res( + macro_rules_binding.ident.name, + res, + )) } } } @@ -671,7 +684,7 @@ impl<'a> Resolver<'a> { suggestions.extend( this.registered_attrs .iter() - .map(|ident| TypoSuggestion::from_res(ident.name, res)), + .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)), ); } } @@ -679,7 +692,7 @@ impl<'a> Resolver<'a> { suggestions.extend(this.macro_use_prelude.iter().filter_map( |(name, binding)| { let res = binding.res(); - filter_fn(res).then_some(TypoSuggestion::from_res(*name, res)) + filter_fn(res).then_some(TypoSuggestion::typo_from_res(*name, res)) }, )); } @@ -689,14 +702,14 @@ impl<'a> Resolver<'a> { suggestions.extend( BUILTIN_ATTRIBUTES .iter() - .map(|(name, ..)| TypoSuggestion::from_res(*name, res)), + .map(|(name, ..)| TypoSuggestion::typo_from_res(*name, res)), ); } } Scope::ExternPrelude => { suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| { let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)); - filter_fn(res).then_some(TypoSuggestion::from_res(ident.name, res)) + filter_fn(res).then_some(TypoSuggestion::typo_from_res(ident.name, res)) })); } Scope::ToolPrelude => { @@ -704,7 +717,7 @@ impl<'a> Resolver<'a> { suggestions.extend( this.registered_tools .iter() - .map(|ident| TypoSuggestion::from_res(ident.name, res)), + .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)), ); } Scope::StdLibPrelude => { @@ -721,7 +734,7 @@ impl<'a> Resolver<'a> { Scope::BuiltinTypes => { suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| { let res = Res::PrimTy(*prim_ty); - filter_fn(res).then_some(TypoSuggestion::from_res(prim_ty.name(), res)) + filter_fn(res).then_some(TypoSuggestion::typo_from_res(prim_ty.name(), res)) })) } } @@ -993,20 +1006,31 @@ impl<'a> Resolver<'a> { // | ^ return false; } + let prefix = match suggestion.target { + SuggestionTarget::SimilarlyNamed => "similarly named ", + SuggestionTarget::SingleItem => "", + }; + err.span_label( self.session.source_map().guess_head_span(def_span), &format!( - "similarly named {} `{}` defined here", + "{}{} `{}` defined here", + prefix, suggestion.res.descr(), suggestion.candidate.as_str(), ), ); } - let msg = format!( - "{} {} with a similar name exists", - suggestion.res.article(), - suggestion.res.descr() - ); + let msg = match suggestion.target { + SuggestionTarget::SimilarlyNamed => format!( + "{} {} with a similar name exists", + suggestion.res.article(), + suggestion.res.descr() + ), + SuggestionTarget::SingleItem => { + format!("maybe you meant this {}", suggestion.res.descr()) + } + }; err.span_suggestion( span, &msg, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e3ab858541af4..7c97a17b45406 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -541,6 +541,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } _ => {} } + + // If the trait has a single item (which wasn't matched by Levenshtein), suggest it + let suggestion = self.get_single_associated_item(&path, span, &source, is_expected); + self.r.add_typo_suggestion(&mut err, suggestion, ident_span); } if fallback { // Fallback label. @@ -585,6 +589,40 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { (err, candidates) } + fn get_single_associated_item( + &mut self, + path: &[Segment], + span: Span, + source: &PathSource<'_>, + filter_fn: &impl Fn(Res) -> bool, + ) -> Option { + if let crate::PathSource::TraitItem(_) = source { + let mod_path = &path[..path.len() - 1]; + if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = + self.resolve_path(mod_path, None, false, span, CrateLint::No) + { + let resolutions = self.r.resolutions(module).borrow(); + let targets: Vec<_> = + resolutions + .iter() + .filter_map(|(key, resolution)| { + resolution.borrow().binding.map(|binding| binding.res()).and_then( + |res| if filter_fn(res) { Some((key, res)) } else { None }, + ) + }) + .collect(); + if targets.len() == 1 { + let target = targets[0]; + return Some(TypoSuggestion::single_item_from_res( + target.0.ident.name, + target.1, + )); + } + } + } + None + } + /// Given `where ::Baz: String`, suggest `where T: Bar`. fn restrict_assoc_type_in_where_clause( &mut self, @@ -1208,7 +1246,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Locals and type parameters for (ident, &res) in &rib.bindings { if filter_fn(res) { - names.push(TypoSuggestion::from_res(ident.name, res)); + names.push(TypoSuggestion::typo_from_res(ident.name, res)); } } // Items in scope @@ -1231,7 +1269,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ); if filter_fn(crate_mod) { - Some(TypoSuggestion::from_res(ident.name, crate_mod)) + Some(TypoSuggestion::typo_from_res( + ident.name, crate_mod, + )) } else { None } @@ -1249,11 +1289,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } // Add primitive types to the mix if filter_fn(Res::PrimTy(PrimTy::Bool)) { - names.extend( - PrimTy::ALL.iter().map(|prim_ty| { - TypoSuggestion::from_res(prim_ty.name(), Res::PrimTy(*prim_ty)) - }), - ) + names.extend(PrimTy::ALL.iter().map(|prim_ty| { + TypoSuggestion::typo_from_res(prim_ty.name(), Res::PrimTy(*prim_ty)) + })) } } else { // Search in module. diff --git a/src/test/ui/associated-item/issue-87638.fixed b/src/test/ui/associated-item/issue-87638.fixed new file mode 100644 index 0000000000000..b689777685f3d --- /dev/null +++ b/src/test/ui/associated-item/issue-87638.fixed @@ -0,0 +1,22 @@ +// run-rustfix + +trait Trait { + const FOO: usize; + + type Target; +} + +struct S; + +impl Trait for S { + const FOO: usize = 0; + type Target = (); +} + +fn main() { + let _: ::Target; //~ ERROR cannot find associated type `Output` in trait `Trait` + //~^ HELP maybe you meant this associated type + + let _ = ::FOO; //~ ERROR cannot find method or associated constant `BAR` in trait `Trait` + //~^ HELP maybe you meant this associated constant +} diff --git a/src/test/ui/associated-item/issue-87638.rs b/src/test/ui/associated-item/issue-87638.rs new file mode 100644 index 0000000000000..5a60b20fdf382 --- /dev/null +++ b/src/test/ui/associated-item/issue-87638.rs @@ -0,0 +1,22 @@ +// run-rustfix + +trait Trait { + const FOO: usize; + + type Target; +} + +struct S; + +impl Trait for S { + const FOO: usize = 0; + type Target = (); +} + +fn main() { + let _: ::Output; //~ ERROR cannot find associated type `Output` in trait `Trait` + //~^ HELP maybe you meant this associated type + + let _ = ::BAR; //~ ERROR cannot find method or associated constant `BAR` in trait `Trait` + //~^ HELP maybe you meant this associated constant +} diff --git a/src/test/ui/associated-item/issue-87638.stderr b/src/test/ui/associated-item/issue-87638.stderr new file mode 100644 index 0000000000000..cf6083444b0e6 --- /dev/null +++ b/src/test/ui/associated-item/issue-87638.stderr @@ -0,0 +1,27 @@ +error[E0576]: cannot find associated type `Output` in trait `Trait` + --> $DIR/issue-87638.rs:17:26 + | +LL | type Target; + | ------------ associated type `Target` defined here +... +LL | let _: ::Output; + | ^^^^^^ + | | + | not found in `Trait` + | help: maybe you meant this associated type: `Target` + +error[E0576]: cannot find method or associated constant `BAR` in trait `Trait` + --> $DIR/issue-87638.rs:20:27 + | +LL | const FOO: usize; + | ----------------- associated constant `FOO` defined here +... +LL | let _ = ::BAR; + | ^^^ + | | + | not found in `Trait` + | help: maybe you meant this associated constant: `FOO` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0576`. diff --git a/src/test/ui/associated-types/issue-22037.stderr b/src/test/ui/associated-types/issue-22037.stderr index 615628558f08b..0e019f10f37f2 100644 --- a/src/test/ui/associated-types/issue-22037.stderr +++ b/src/test/ui/associated-types/issue-22037.stderr @@ -1,8 +1,13 @@ error[E0576]: cannot find associated type `X` in trait `A` --> $DIR/issue-22037.rs:3:33 | +LL | type Output; + | ------------ associated type `Output` defined here LL | fn a(&self) -> ::X; - | ^ not found in `A` + | ^ + | | + | not found in `A` + | help: maybe you meant this associated type: `Output` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19883.stderr b/src/test/ui/issues/issue-19883.stderr index e370b2ec1cb42..bd6a86b742089 100644 --- a/src/test/ui/issues/issue-19883.stderr +++ b/src/test/ui/issues/issue-19883.stderr @@ -1,8 +1,14 @@ error[E0576]: cannot find associated type `Dst` in trait `From` --> $DIR/issue-19883.rs:9:30 | +LL | type Output; + | ------------ associated type `Output` defined here +... LL | >::Dst - | ^^^ not found in `From` + | ^^^ + | | + | not found in `From` + | help: maybe you meant this associated type: `Output` error: aborting due to previous error From a35d7f2bb32c35a5da3c7e7ba0d68af1e33f0619 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 4 Aug 2021 19:41:13 -0500 Subject: [PATCH 58/58] Remove special case for statement `NodeId` assignment We now let `noop_flat_map_stmt` assign `NodeId`s (via `visit_id`), just as we do for other AST nodes. --- compiler/rustc_expand/src/expand.rs | 9 ++------ compiler/rustc_expand/src/lib.rs | 1 + compiler/rustc_expand/src/placeholders.rs | 25 ++++------------------- 3 files changed, 7 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 09beda3348374..3629e668fa9f8 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -559,7 +559,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.force_mode = orig_force_mode; // Finally incorporate all the expanded macros into the input AST fragment. - let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); + let mut placeholder_expander = PlaceholderExpander::default(); while let Some(expanded_fragments) = expanded_fragments.pop() { for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { placeholder_expander @@ -1341,14 +1341,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - // The placeholder expander gives ids to statements, so we avoid folding the id here. // We don't use `assign_id!` - it will be called when we visit statement's contents // (e.g. an expression, item, or local) - let ast::Stmt { id, kind, span } = stmt; - let res = noop_flat_map_stmt_kind(kind, self) - .into_iter() - .map(|kind| ast::Stmt { id, kind, span }) - .collect(); + let res = noop_flat_map_stmt(stmt, self); self.cx.current_expansion.is_trailing_mac = false; res diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index efed41de23a89..43287984050d4 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -7,6 +7,7 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_blocks)] +#![recursion_limit = "256"] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 6586ba138fb99..8e78fcbb8dbc1 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -1,4 +1,3 @@ -use crate::base::ExtCtxt; use crate::expand::{AstFragment, AstFragmentKind}; use rustc_ast as ast; @@ -175,17 +174,12 @@ pub fn placeholder( } } -pub struct PlaceholderExpander<'a, 'b> { +#[derive(Default)] +pub struct PlaceholderExpander { expanded_fragments: FxHashMap, - cx: &'a mut ExtCtxt<'b>, - monotonic: bool, } -impl<'a, 'b> PlaceholderExpander<'a, 'b> { - pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { - PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic } - } - +impl PlaceholderExpander { pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); self.expanded_fragments.insert(id, fragment); @@ -196,7 +190,7 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } -impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { +impl MutVisitor for PlaceholderExpander { fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { if arm.is_placeholder { self.remove(arm.id).make_arms() @@ -360,15 +354,4 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { _ => noop_visit_ty(ty, self), } } - - fn visit_block(&mut self, block: &mut P) { - noop_visit_block(block, self); - - for stmt in block.stmts.iter_mut() { - if self.monotonic { - assert_eq!(stmt.id, ast::DUMMY_NODE_ID); - stmt.id = self.cx.resolver.next_node_id(); - } - } - } }