diff --git a/compiler/rustc_codegen_cranelift/.cirrus.yml b/compiler/rustc_codegen_cranelift/.cirrus.yml index e173df423a765..61da6a2491c52 100644 --- a/compiler/rustc_codegen_cranelift/.cirrus.yml +++ b/compiler/rustc_codegen_cranelift/.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/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index 4d45e36c956c9..f81ac87726052 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.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/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml index e01a92598bab7..1c08e5ece33d2 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml +++ b/compiler/rustc_codegen_cranelift/.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/compiler/rustc_codegen_cranelift/.gitignore b/compiler/rustc_codegen_cranelift/.gitignore index b241bef9d1e7f..12e779fe7c7d7 100644 --- a/compiler/rustc_codegen_cranelift/.gitignore +++ b/compiler/rustc_codegen_cranelift/.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/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json index 9009a532c54dc..f62e59cefc241 100644 --- a/compiler/rustc_codegen_cranelift/.vscode/settings.json +++ b/compiler/rustc_codegen_cranelift/.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/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index a6f5925149b92..56d0974b25371 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index fd149af454735..ef68d7ee532dd 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 08f9373be6262..dad8ed90b53b8 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build.sh b/compiler/rustc_codegen_cranelift/build.sh deleted file mode 100755 index 76bc1884334af..0000000000000 --- a/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock index 923deb9aec4c0..46f661107e73b 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh deleted file mode 100755 index 0354304e55bf7..0000000000000 --- a/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh deleted file mode 100755 index 54b7a94750c52..0000000000000 --- a/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs new file mode 100644 index 0000000000000..1df2bcc4541ca --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs new file mode 100644 index 0000000000000..9fb88c279613f --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_system/config.rs b/compiler/rustc_codegen_cranelift/build_system/config.rs new file mode 100644 index 0000000000000..ef540cf1f822b --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs new file mode 100644 index 0000000000000..401b8271abcc5 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs new file mode 100644 index 0000000000000..9206bb02bd3da --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs new file mode 100644 index 0000000000000..12b5d70fad853 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh index a7bbeb05cac5a..f4f8c82d69f10 100755 --- a/compiler/rustc_codegen_cranelift/clean_all.sh +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt new file mode 100644 index 0000000000000..b14db27d6206f --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/docs/usage.md b/compiler/rustc_codegen_cranelift/docs/usage.md index 3eee3b554e3b6..956d5905a97ad 100644 --- a/compiler/rustc_codegen_cranelift/docs/usage.md +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 6570f2bf9f297..d997ce6d1b379 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index 7d608df9253df..5bc51a541b58c 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch rename to compiler/rustc_codegen_cranelift/patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch b/compiler/rustc_codegen_cranelift/patches/0001-rand-Enable-c2-chacha-simd-feature.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch rename to compiler/rustc_codegen_cranelift/patches/0001-rand-Enable-c2-chacha-simd-feature.patch diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0002-rand-Disable-failing-test.patch b/compiler/rustc_codegen_cranelift/patches/0002-rand-Disable-failing-test.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/crate_patches/0002-rand-Disable-failing-test.patch rename to compiler/rustc_codegen_cranelift/patches/0002-rand-Disable-failing-test.patch diff --git a/compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch rename to compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch diff --git a/compiler/rustc_codegen_cranelift/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/patches/0023-core-Ignore-failing-tests.patch rename to compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch diff --git a/compiler/rustc_codegen_cranelift/patches/0027-Disable-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/patches/0027-Disable-128bit-atomic-operations.patch rename to compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch diff --git a/compiler/rustc_codegen_cranelift/prepare.sh b/compiler/rustc_codegen_cranelift/prepare.sh deleted file mode 100755 index 64c097261c908..0000000000000 --- a/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 9fe6e093a7b81..f806f7bdcd98a 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/cargo.rs b/compiler/rustc_codegen_cranelift/scripts/cargo.rs new file mode 100644 index 0000000000000..b7e8dd4497479 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/cargo.sh b/compiler/rustc_codegen_cranelift/scripts/cargo.sh deleted file mode 100755 index 1daa5a78f7bd2..0000000000000 --- a/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/config.sh b/compiler/rustc_codegen_cranelift/scripts/config.sh index 99b302ee1d94b..53ada369b089a 100644 --- a/compiler/rustc_codegen_cranelift/scripts/config.sh +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/ext_config.sh b/compiler/rustc_codegen_cranelift/scripts/ext_config.sh index 3f98d77d76cad..11d6c4c831867 100644 --- a/compiler/rustc_codegen_cranelift/scripts/ext_config.sh +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs index 15388926ec9ec..9e196afbe4f57 100755 --- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index fa7557653d879..cc34c08088665 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index 43c4887669cf6..52adaaa8de673 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 347fb40e6f9e7..2f5c2cf737b05 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/scripts/tests.sh b/compiler/rustc_codegen_cranelift/scripts/tests.sh index 0d99d2c507c95..5df04c533a70e 100755 --- a/compiler/rustc_codegen_cranelift/scripts/tests.sh +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index ec3e17e5b758d..3d78eed77b94c 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs index 2643fae0a810a..a044b43b86470 100644 --- a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index a8a0bb52a246e..892ccf27f6df8 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index a87b3703949f9..2a2573aad2950 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs index 9eb067706309e..c7e15f81e0301 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 61e54a76f29ba..c67336eb3f2c3 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 50fd53481f745..a8b802f449437 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 04ec01ad28148..76fbc9ad51e8e 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index ba4ed2162cd5d..be3704ca2768e 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index ebf98e8694b78..cb1cb3c74dbb5 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/optimize/mod.rs b/compiler/rustc_codegen_cranelift/src/optimize/mod.rs index 137fb5f77313c..61033d85a1274 100644 --- a/compiler/rustc_codegen_cranelift/src/optimize/mod.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index cd8c5b5160836..05db74745a1c0 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index 12f7092d935a3..4a5f9f133a2bb 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/test.sh b/compiler/rustc_codegen_cranelift/test.sh index e222adc7b8058..a10924628bb0e 100755 --- a/compiler/rustc_codegen_cranelift/test.sh +++ b/compiler/rustc_codegen_cranelift/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/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs new file mode 100755 index 0000000000000..43937588b481d --- /dev/null +++ b/compiler/rustc_codegen_cranelift/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, + ); +} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index ea587210b4f4e..799d685ce5ca1 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -254,6 +254,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "libloading", "log", "mach", + "memchr", "object", "regalloc", "region",