1
Fork 0

Merge commit '3a31c6d827' into sync_cg_clif-2021-07-07

This commit is contained in:
bjorn3 2021-07-07 11:14:20 +02:00
commit d531f3d6ee
55 changed files with 1285 additions and 448 deletions

View file

@ -14,7 +14,7 @@ task:
- . $HOME/.cargo/env - . $HOME/.cargo/env
- git config --global user.email "user@example.com" - git config --global user.email "user@example.com"
- git config --global user.name "User" - git config --global user.name "User"
- ./prepare.sh - ./y.rs prepare
test_script: test_script:
- . $HOME/.cargo/env - . $HOME/.cargo/env
- # Enable backtraces for easier debugging - # Enable backtraces for easier debugging

View file

@ -19,6 +19,9 @@ jobs:
- os: ubuntu-latest - os: ubuntu-latest
env: env:
TARGET_TRIPLE: x86_64-pc-windows-gnu TARGET_TRIPLE: x86_64-pc-windows-gnu
- os: ubuntu-latest
env:
TARGET_TRIPLE: aarch64-unknown-linux-gnu
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -49,11 +52,19 @@ jobs:
sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
rustup target add x86_64-pc-windows-gnu 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 - name: Prepare dependencies
run: | run: |
git config --global user.email "user@example.com" git config --global user.email "user@example.com"
git config --global user.name "User" git config --global user.name "User"
./prepare.sh ./y.rs prepare
- name: Build
run: ./y.rs build --sysroot none
- name: Test - name: Test
env: env:
@ -87,3 +98,63 @@ jobs:
with: with:
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
path: cg_clif.tar.xz 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

View file

@ -34,7 +34,7 @@ jobs:
run: | run: |
git config --global user.email "user@example.com" git config --global user.email "user@example.com"
git config --global user.name "User" git config --global user.name "User"
./prepare.sh ./y.rs prepare
- name: Test - name: Test
run: | run: |
@ -72,7 +72,7 @@ jobs:
run: | run: |
git config --global user.email "user@example.com" git config --global user.email "user@example.com"
git config --global user.name "User" git config --global user.name "User"
./prepare.sh ./y.rs prepare
- name: Test - name: Test
run: | run: |

View file

@ -6,9 +6,11 @@ perf.data
perf.data.old perf.data.old
*.events *.events
*.string* *.string*
/y.bin
/build /build
/build_sysroot/sysroot_src /build_sysroot/sysroot_src
/build_sysroot/compiler-builtins /build_sysroot/compiler-builtins
/build_sysroot/rustc_version
/rust /rust
/rand /rand
/regex /regex

View file

@ -1,7 +1,9 @@
{ {
// source for rustc_* is not included in the rust-src component; disable the errors about this // 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.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.cargo.runBuildScripts": true,
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
"./Cargo.toml", "./Cargo.toml",
@ -49,6 +51,23 @@
"cfg": [], "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": [],
},
]
} }
] ]
} }

View file

@ -33,16 +33,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "cranelift-bforest" name = "cranelift-bforest"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [ dependencies = [
"cranelift-entity", "cranelift-entity",
] ]
[[package]] [[package]]
name = "cranelift-codegen" name = "cranelift-codegen"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [ dependencies = [
"cranelift-bforest", "cranelift-bforest",
"cranelift-codegen-meta", "cranelift-codegen-meta",
@ -57,8 +57,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-meta" name = "cranelift-codegen-meta"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [ dependencies = [
"cranelift-codegen-shared", "cranelift-codegen-shared",
"cranelift-entity", "cranelift-entity",
@ -66,18 +66,18 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-shared" name = "cranelift-codegen-shared"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
[[package]] [[package]]
name = "cranelift-entity" name = "cranelift-entity"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
[[package]] [[package]]
name = "cranelift-frontend" name = "cranelift-frontend"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"log", "log",
@ -87,8 +87,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-jit" name = "cranelift-jit"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -104,8 +104,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-module" name = "cranelift-module"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -115,17 +115,18 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-native" name = "cranelift-native"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"libc",
"target-lexicon", "target-lexicon",
] ]
[[package]] [[package]]
name = "cranelift-object" name = "cranelift-object"
version = "0.74.0" version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -171,9 +172,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.86" version = "0.2.97"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
[[package]] [[package]]
name = "libloading" name = "libloading"
@ -204,13 +205,20 @@ dependencies = [
] ]
[[package]] [[package]]
name = "object" name = "memchr"
version = "0.24.0" version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "object"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"indexmap", "indexmap",
"memchr",
] ]
[[package]] [[package]]

View file

@ -9,7 +9,7 @@ crate-type = ["dylib"]
[dependencies] [dependencies]
# These have to be in sync with each other # 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-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } cranelift-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" } cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
target-lexicon = "0.12.0" target-lexicon = "0.12.0"
gimli = { version = "0.24.0", default-features = false, features = ["write"]} 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" } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.0.2" indexmap = "1.0.2"

View file

@ -10,8 +10,8 @@ If not please open an issue.
```bash ```bash
$ git clone https://github.com/bjorn3/rustc_codegen_cranelift.git $ git clone https://github.com/bjorn3/rustc_codegen_cranelift.git
$ cd rustc_codegen_cranelift $ cd rustc_codegen_cranelift
$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking $ ./y.rs prepare # download and patch sysroot src and install hyperfine for benchmarking
$ ./build.sh $ ./y.rs build
``` ```
To run the test suite replace the last command with: 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 $ ./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. build in debug mode.
Alternatively you can download a pre built version from [GHA]. It is listed in the artifacts section 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. 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: In the directory with your project (where you can do the usual `cargo build`), run:
```bash ```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. This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.

View file

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

View file

@ -56,7 +56,7 @@ dependencies = [
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.43" version = "0.1.46"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -121,9 +121,9 @@ dependencies = [
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.18" version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"libc", "libc",
@ -132,9 +132,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.95" version = "0.2.97"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -195,9 +195,9 @@ dependencies = [
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.19" version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce" checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"rustc-std-workspace-core", "rustc-std-workspace-core",

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,55 @@
use std::{fs, process};
fn load_config_file() -> Vec<(String, Option<String>)> {
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::<Vec<_>>();
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<String> {
let values = load_config_file()
.into_iter()
.filter(|(key, _)| key == name)
.map(|(_, val)| val)
.collect::<Vec<_>>();
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);
}
}

View file

@ -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<OsString> {
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);
}
}

View file

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

View file

@ -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<Path>, dst: impl AsRef<Path>) {
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();
}
}
}

View file

@ -1,5 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e 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/ rm -rf rand/ regex/ simple-raytracer/

View file

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

View file

@ -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. 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 ## Cargo
In the directory with your project (where you can do the usual `cargo build`), run: In the directory with your project (where you can do the usual `cargo build`), run:
```bash ```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. 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. > The jit mode will probably need cargo integration to make this possible.
```bash ```bash
$ $cg_clif_dir/build/cargo.sh jit $ $cg_clif_dir/build/cargo jit
``` ```
or 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 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 first called.
function is called from another thread than the main thread, you will get an ICE.
```bash ```bash
$ $cg_clif_dir/build/cargo.sh lazy-jit $ $cg_clif_dir/build/cargo lazy-jit
``` ```
## Shell ## Shell

View file

@ -292,7 +292,7 @@ fn main() {
#[cfg(not(any(jit, windows)))] #[cfg(not(any(jit, windows)))]
test_tls(); test_tls();
#[cfg(all(not(jit), target_os = "linux"))] #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
unsafe { unsafe {
global_asm_test(); global_asm_test();
} }
@ -303,12 +303,12 @@ fn main() {
assert_eq!(*REF1, *REF2); assert_eq!(*REF1, *REF2);
} }
#[cfg(all(not(jit), target_os = "linux"))] #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
extern "C" { extern "C" {
fn global_asm_test(); 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_asm! {
" "
.global global_asm_test .global global_asm_test

View file

@ -15,8 +15,6 @@ fn main() {
let stderr = ::std::io::stderr(); let stderr = ::std::io::stderr();
let mut stderr = stderr.lock(); let mut stderr = stderr.lock();
// FIXME support lazy jit when multi threading
#[cfg(not(lazy_jit))]
std::thread::spawn(move || { std::thread::spawn(move || {
println!("Hello from another thread!"); println!("Hello from another thread!");
}); });

View file

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

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly-2021-05-26" channel = "nightly-2021-07-07"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"] components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -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),
);
}

View file

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

View file

@ -2,26 +2,5 @@
set -e set -e
dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -) export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH"
export DYLD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$DYLD_LIBRARY_PATH"
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

View file

@ -1,6 +1,6 @@
# Note to people running shellcheck: this file should only be sourced, not executed directly. # 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 set -e
@ -25,3 +25,8 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
echo "Unknown non-native platform" echo "Unknown non-native platform"
fi fi
fi fi
# FIXME fix `#[linkage = "extern_weak"]` without this
if [[ "$(uname)" == 'Darwin' ]]; then
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
fi

View file

@ -2,9 +2,10 @@
#![forbid(unsafe_code)]/* This line is ignored by bash #![forbid(unsafe_code)]/* This line is ignored by bash
# This block is ignored by rustc # This block is ignored by rustc
pushd $(dirname "$0")/../ pushd $(dirname "$0")/../
source build/config.sh source scripts/config.sh
RUSTC="$(pwd)/build/bin/cg_clif"
popd 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 //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse

View file

@ -17,7 +17,7 @@ case $1 in
done done
./clean_all.sh ./clean_all.sh
./prepare.sh ./y.rs prepare
(cd build_sysroot && cargo update) (cd build_sysroot && cargo update)

View file

@ -1,8 +1,8 @@
#!/bin/bash #!/bin/bash
set -e set -e
./build.sh ./y.rs build
source build/config.sh source scripts/config.sh
echo "[SETUP] Rust fork" echo "[SETUP] Rust fork"
git clone https://github.com/rust-lang/rust.git || true git clone https://github.com/rust-lang/rust.git || true
@ -33,7 +33,7 @@ index d95b5b7f17f..00b6f0e3635 100644
[dependencies] [dependencies]
core = { path = "../core" } core = { path = "../core" }
-compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] } -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] [dev-dependencies]
rand = "0.7" rand = "0.7"

View file

@ -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/numbers-arithmetic/int-abs-overflow.rs
rm src/test/ui/drop/drop-trait-enum.rs rm src/test/ui/drop/drop-trait-enum.rs
rm src/test/ui/numbers-arithmetic/issue-8460.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/issues/issue-28950.rs # depends on stack size optimizations
rm src/test/ui/init-large-type.rs # same 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/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/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/asm.rs # inline asm
rm src/test/pretty/raw-str-nonexpr.rs # same rm src/test/pretty/raw-str-nonexpr.rs # same

View file

@ -2,9 +2,10 @@
set -e set -e
source build/config.sh source scripts/config.sh
source scripts/ext_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() { function no_sysroot_tests() {
echo "[BUILD] mini_core" 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" $MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE"
echo "[JIT-lazy] std_example" 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 else
echo "[JIT] std_example (skipped)" echo "[JIT] std_example (skipped)"
fi fi
@ -75,63 +76,64 @@ function base_sysroot_tests() {
function extended_sysroot_tests() { function extended_sysroot_tests() {
pushd rand pushd rand
cargo clean ../build/cargo clean
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[TEST] rust-random/rand" echo "[TEST] rust-random/rand"
../build/cargo.sh test --workspace ../build/cargo test --workspace
else else
echo "[AOT] rust-random/rand" echo "[AOT] rust-random/rand"
../build/cargo.sh build --workspace --target $TARGET_TRIPLE --tests ../build/cargo build --workspace --target $TARGET_TRIPLE --tests
fi fi
popd popd
pushd simple-raytracer pushd simple-raytracer
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[BENCH COMPILE] ebobby/simple-raytracer" 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" \ "RUSTC=rustc RUSTFLAGS='' cargo build" \
"../build/cargo.sh build" "../build/cargo build"
echo "[BENCH RUN] ebobby/simple-raytracer" echo "[BENCH RUN] ebobby/simple-raytracer"
cp ./target/debug/main ./raytracer_cg_clif cp ./target/debug/main ./raytracer_cg_clif
hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif
else else
../build/cargo clean
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
echo "[COMPILE] ebobby/simple-raytracer" 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)" echo "[BENCH RUN] ebobby/simple-raytracer (skipped)"
fi fi
popd popd
pushd build_sysroot/sysroot_src/library/core/tests pushd build_sysroot/sysroot_src/library/core/tests
echo "[TEST] libcore" echo "[TEST] libcore"
cargo clean ../../../../../build/cargo clean
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
../../../../../build/cargo.sh test ../../../../../build/cargo test
else else
../../../../../build/cargo.sh build --target $TARGET_TRIPLE --tests ../../../../../build/cargo build --target $TARGET_TRIPLE --tests
fi fi
popd popd
pushd regex pushd regex
echo "[TEST] rust-lang/regex example shootout-regex-dna" 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 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 # 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 if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
cat examples/regexdna-input.txt \ 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 | grep -v "Spawned thread" > res.txt
diff -u res.txt examples/regexdna-output.txt diff -u res.txt examples/regexdna-output.txt
fi fi
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[TEST] rust-lang/regex tests" 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 else
echo "[AOT] rust-lang/regex tests" echo "[AOT] rust-lang/regex tests"
../build/cargo.sh build --tests --target $TARGET_TRIPLE ../build/cargo build --tests --target $TARGET_TRIPLE
fi fi
popd popd
} }

View file

@ -21,6 +21,11 @@ pub(crate) fn codegen_fn<'tcx>(
debug_assert!(!instance.substs.needs_infer()); debug_assert!(!instance.substs.needs_infer());
let mir = tcx.instance_mir(instance.def); 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 // Declare function
let symbol_name = tcx.symbol_name(instance); let symbol_name = tcx.symbol_name(instance);
@ -52,7 +57,6 @@ pub(crate) fn codegen_fn<'tcx>(
module, module,
tcx, tcx,
pointer_type, pointer_type,
vtables: FxHashMap::default(),
constants_cx: ConstantCx::new(), constants_cx: ConstantCx::new(),
instance, instance,
@ -105,7 +109,14 @@ pub(crate) fn codegen_fn<'tcx>(
let context = &mut cx.cached_context; let context = &mut cx.cached_context;
context.func = func; 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 function
verify_func(tcx, &clif_comments, &context.func); verify_func(tcx, &clif_comments, &context.func);
@ -122,7 +133,13 @@ pub(crate) fn codegen_fn<'tcx>(
// Perform rust specific optimizations // Perform rust specific optimizations
tcx.sess.time("optimize clif ir", || { 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 // Define function
@ -137,7 +154,7 @@ pub(crate) fn codegen_fn<'tcx>(
crate::pretty_clif::write_clif_file( crate::pretty_clif::write_clif_file(
tcx, tcx,
"opt", "opt",
Some(module.isa()), module.isa(),
instance, instance,
&context, &context,
&clif_comments, &clif_comments,

View file

@ -6,8 +6,8 @@ extern crate rustc_interface;
extern crate rustc_session; extern crate rustc_session;
extern crate rustc_target; extern crate rustc_target;
use std::panic;
use std::lazy::SyncLazy; use std::lazy::SyncLazy;
use std::panic;
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_interface::interface; use rustc_interface::interface;

View file

@ -233,7 +233,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
pub(crate) module: &'m mut dyn Module, pub(crate) module: &'m mut dyn Module,
pub(crate) tcx: TyCtxt<'tcx>, pub(crate) tcx: TyCtxt<'tcx>,
pub(crate) pointer_type: Type, // Cached from module pub(crate) pointer_type: Type, // Cached from module
pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Pointer>,
pub(crate) constants_cx: ConstantCx, pub(crate) constants_cx: ConstantCx,
pub(crate) instance: Instance<'tcx>, pub(crate) instance: Instance<'tcx>,

View file

@ -1,16 +1,13 @@
//! Handling of `static`s, `const`s and promoted allocations //! 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_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::ErrorReported; use rustc_errors::ErrorReported;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{ use rustc_middle::mir::interpret::{
alloc_range, read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
Scalar,
}; };
use rustc_middle::ty::ConstKind; use rustc_middle::ty::ConstKind;
use rustc_span::DUMMY_SP;
use cranelift_codegen::ir::GlobalValueData; use cranelift_codegen::ir::GlobalValueData;
use cranelift_module::*; use cranelift_module::*;
@ -171,66 +168,74 @@ pub(crate) fn codegen_const_value<'tcx>(
} }
match const_val { match const_val {
ConstValue::Scalar(x) => { ConstValue::Scalar(x) => match x {
if fx.clif_type(layout.ty).is_none() { Scalar::Int(int) => {
let (size, align) = (layout.size, layout.align.pref); if fx.clif_type(layout.ty).is_some() {
let mut alloc = Allocation::from_bytes( return CValue::const_val(fx, layout, int);
std::iter::repeat(0).take(size.bytes_usize()).collect::<Vec<u8>>(), } else {
align, let raw_val = int.to_bits(int.size()).unwrap();
Mutability::Not, let val = match int.size().bytes() {
); 1 => fx.bcx.ins().iconst(types::I8, raw_val as i64),
alloc.write_scalar(fx, alloc_range(Size::ZERO, size), x.into()).unwrap(); 2 => fx.bcx.ins().iconst(types::I16, raw_val as i64),
let alloc = fx.tcx.intern_const_alloc(alloc); 4 => fx.bcx.ins().iconst(types::I32, raw_val as i64),
return CValue::by_ref(pointer_for_allocation(fx, alloc), layout); 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)
}
_ => unreachable!(),
};
match x { let place = CPlace::new_stack_slot(fx, layout);
Scalar::Int(int) => CValue::const_val(fx, layout, int), place.to_ptr().store(fx, val, MemFlags::trusted());
Scalar::Ptr(ptr) => { place.to_cvalue(fx)
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)
}
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)
} }
} }
} 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( ConstValue::ByRef { alloc, offset } => CValue::by_ref(
pointer_for_allocation(fx, alloc) pointer_for_allocation(fx, alloc)
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()), .offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
@ -254,7 +259,6 @@ pub(crate) fn pointer_for_allocation<'tcx>(
alloc: &'tcx Allocation, alloc: &'tcx Allocation,
) -> crate::pointer::Pointer { ) -> crate::pointer::Pointer {
let alloc_id = fx.tcx.create_memory_alloc(alloc); let alloc_id = fx.tcx.create_memory_alloc(alloc);
fx.constants_cx.todo.push(TodoItem::Alloc(alloc_id));
let data_id = let data_id =
data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, alloc.mutability); 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) crate::pointer::Pointer::new(global_ptr)
} }
fn data_id_for_alloc_id( pub(crate) fn data_id_for_alloc_id(
cx: &mut ConstantCx, cx: &mut ConstantCx,
module: &mut dyn Module, module: &mut dyn Module,
alloc_id: AllocId, alloc_id: AllocId,
mutability: rustc_hir::Mutability, mutability: rustc_hir::Mutability,
) -> DataId { ) -> DataId {
cx.todo.push(TodoItem::Alloc(alloc_id));
*cx.anon_allocs.entry(alloc_id).or_insert_with(|| { *cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
module.declare_anonymous_data(mutability == rustc_hir::Mutability::Mut, false).unwrap() 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::Memory(alloc) => alloc,
GlobalAlloc::Function(_) | GlobalAlloc::Static(_) => unreachable!(), 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) (data_id, alloc, None)
} }
TodoItem::Static(def_id) => { TodoItem::Static(def_id) => {
@ -415,7 +427,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
continue; continue;
} }
GlobalAlloc::Memory(target_alloc) => { GlobalAlloc::Memory(target_alloc) => {
cx.todo.push(TodoItem::Alloc(reloc));
data_id_for_alloc_id(cx, module, reloc, target_alloc.mutability) data_id_for_alloc_id(cx, module, reloc, target_alloc.mutability)
} }
GlobalAlloc::Static(def_id) => { GlobalAlloc::Static(def_id) => {

View file

@ -10,7 +10,7 @@ use rustc_span::{
}; };
use cranelift_codegen::binemit::CodeOffset; use cranelift_codegen::binemit::CodeOffset;
use cranelift_codegen::machinst::MachSrcLoc; use cranelift_codegen::MachSrcLoc;
use gimli::write::{ use gimli::write::{
Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable, Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable,

View file

@ -61,9 +61,11 @@ impl<'tcx> DebugContext<'tcx> {
let mut dwarf = DwarfUnit::new(encoding); let mut dwarf = DwarfUnit::new(encoding);
// FIXME: how to get version when building out of tree? let producer = format!(
// Normally this would use option_env!("CFG_VERSION"). "cg_clif (rustc {}, cranelift {})",
let producer = format!("cg_clif (rustc {})", "unknown version"); 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 comp_dir = tcx.sess.working_dir.to_string_lossy(false).into_owned();
let (name, file_info) = match tcx.sess.local_crate_source_file.clone() { let (name, file_info) = match tcx.sess.local_crate_source_file.clone() {
Some(path) => { Some(path) => {

View file

@ -289,13 +289,16 @@ pub(crate) fn run_aot(
None 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(( Box::new((
CodegenResults { CodegenResults {
modules, modules,
allocator_module, allocator_module,
metadata_module, metadata_module,
metadata, metadata,
crate_info: CrateInfo::new(tcx, crate::target_triple(tcx.sess).to_string()), crate_info: CrateInfo::new(tcx, target_cpu),
}, },
work_products, work_products,
)) ))

View file

@ -3,11 +3,14 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::ffi::CString; use std::ffi::CString;
use std::lazy::{Lazy, SyncOnceCell};
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use std::sync::{mpsc, Mutex};
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_codegen_ssa::CrateInfo; use rustc_codegen_ssa::CrateInfo;
use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::MonoItem;
use rustc_session::Session;
use cranelift_jit::{JITBuilder, JITModule}; use cranelift_jit::{JITBuilder, JITModule};
@ -23,12 +26,48 @@ thread_local! {
static LAZY_JIT_STATE: RefCell<Option<JitState>> = RefCell::new(None); static LAZY_JIT_STATE: RefCell<Option<JitState>> = RefCell::new(None);
} }
/// The Sender owned by the rustc thread
static GLOBAL_MESSAGE_SENDER: SyncOnceCell<Mutex<mpsc::Sender<UnsafeMessage>>> =
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<UnsafeMessage>> {
thread_local! {
/// The Sender owned by the local thread
static LOCAL_MESSAGE_SENDER: Lazy<mpsc::Sender<UnsafeMessage>> = Lazy::new(||
GLOBAL_MESSAGE_SENDER
.get().unwrap()
.lock().unwrap()
.clone()
);
}
LOCAL_MESSAGE_SENDER.with(|sender| sender.send(self))
}
}
fn create_jit_module<'tcx>( fn create_jit_module<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
backend_config: &BackendConfig, backend_config: &BackendConfig,
hotswap: bool, hotswap: bool,
) -> (JITModule, CodegenCx<'tcx>) { ) -> (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 isa = crate::build_isa(tcx.sess, backend_config);
let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); 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)) .chain(backend_config.jit_args.iter().map(|arg| &**arg))
.map(|arg| CString::new(arg).unwrap()) .map(|arg| CString::new(arg).unwrap())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
// 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 { let start_sig = Signature {
params: vec![ params: vec![
@ -128,7 +162,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
AbiParam::new(jit_module.target_config().pointer_type()), AbiParam::new(jit_module.target_config().pointer_type()),
], ],
returns: vec![AbiParam::new(jit_module.target_config().pointer_type() /*isize*/)], 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 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); 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 = let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
unsafe { ::std::mem::transmute(finalized_start) }; 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::<Vec<_>>();
// 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] #[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| { rustc_middle::ty::tls::with(|tcx| {
// lift is used to ensure the correct lifetime for instance. // lift is used to ensure the correct lifetime for instance.
let instance = tcx.lift(unsafe { *instance_ptr }).unwrap(); 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 name = tcx.symbol_name(instance).name;
let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance); 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 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(); jit_module.prepare_for_function_redefine(func_id).unwrap();
let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module.isa(), false); 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; use rustc_middle::middle::dependency_format::Linkage;
let mut dylib_paths = Vec::new(); let mut dylib_paths = Vec::new();
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); let data = &crate_info
let formats = tcx.dependency_formats(()); .dependency_formats
let data = &formats
.iter() .iter()
.find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable) .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable)
.unwrap() .unwrap()
@ -190,9 +276,8 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
match data[cnum.as_usize() - 1] { match data[cnum.as_usize() - 1] {
Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::NotLinked | Linkage::IncludedFromDylib => {}
Linkage::Static => { Linkage::Static => {
let name = tcx.crate_name(cnum); let name = &crate_info.crate_name[&cnum];
let mut err = let mut err = sess.struct_err(&format!("Can't load static lib {}", name.as_str()));
tcx.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.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
err.emit(); err.emit();
} }
@ -232,7 +317,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
std::mem::forget(lib) std::mem::forget(lib)
} }
tcx.sess.abort_if_errors(); sess.abort_if_errors();
imported_symbols imported_symbols
} }
@ -254,7 +339,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
Linkage::Import, Linkage::Import,
&Signature { &Signature {
call_conv: module.target_config().default_call_conv, 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)], 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 builder_ctx = FunctionBuilderContext::new();
let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx); 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 jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func);
let sig_ref = trampoline_builder.func.import_signature(sig); 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); trampoline_builder.switch_to_block(entry_block);
let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64); 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 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 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(); let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();

View file

@ -106,6 +106,26 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout()); let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
dest.write_cvalue(fx, a); 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 { 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.pshuf.b
// llvm.x86.avx2.psrli.w // llvm.x86.avx2.psrli.w
// llvm.x86.sse2.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);
}

View file

@ -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(rust_2018_idioms)]
#![warn(unused_lifetimes)] #![warn(unused_lifetimes)]
#![warn(unreachable_pub)] #![warn(unreachable_pub)]
@ -14,7 +14,9 @@ extern crate rustc_fs_util;
extern crate rustc_hir; extern crate rustc_hir;
extern crate rustc_incremental; extern crate rustc_incremental;
extern crate rustc_index; extern crate rustc_index;
extern crate rustc_interface;
extern crate rustc_metadata; extern crate rustc_metadata;
extern crate rustc_mir;
extern crate rustc_session; extern crate rustc_session;
extern crate rustc_span; extern crate rustc_span;
extern crate rustc_target; extern crate rustc_target;
@ -284,10 +286,12 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
} }
None => { None => {
let mut builder = let mut builder =
cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap(); cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant).unwrap();
// Don't use "haswell" as the default, as it implies `has_lzcnt`. if target_triple.architecture == target_lexicon::Architecture::X86_64 {
// macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. // Don't use "haswell" as the default, as it implies `has_lzcnt`.
builder.enable("nehalem").unwrap(); // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
builder.enable("nehalem").unwrap();
}
builder builder
} }
}; };

View file

@ -1,17 +1,20 @@
//! Various optimizations specific to cg_clif //! Various optimizations specific to cg_clif
use cranelift_codegen::isa::TargetIsa;
use crate::prelude::*; use crate::prelude::*;
pub(crate) mod peephole; pub(crate) mod peephole;
pub(crate) fn optimize_function<'tcx>( pub(crate) fn optimize_function<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
isa: &dyn TargetIsa,
instance: Instance<'tcx>, instance: Instance<'tcx>,
ctx: &mut Context, ctx: &mut Context,
clif_comments: &mut crate::pretty_clif::CommentWriter, clif_comments: &mut crate::pretty_clif::CommentWriter,
) { ) {
// FIXME classify optimizations over opt levels once we have more // 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); crate::base::verify_func(tcx, &*clif_comments, &ctx.func);
} }

View file

@ -233,7 +233,7 @@ pub(crate) fn write_ir_file(
pub(crate) fn write_clif_file<'tcx>( pub(crate) fn write_clif_file<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
postfix: &str, postfix: &str,
isa: Option<&dyn cranelift_codegen::isa::TargetIsa>, isa: &dyn cranelift_codegen::isa::TargetIsa,
instance: Instance<'tcx>, instance: Instance<'tcx>,
context: &cranelift_codegen::Context, context: &cranelift_codegen::Context,
mut clif_comments: &CommentWriter, mut clif_comments: &CommentWriter,
@ -242,22 +242,23 @@ pub(crate) fn write_clif_file<'tcx>(
tcx, tcx,
|| format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix), || format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix),
|file| { |file| {
let value_ranges = isa
.map(|isa| context.build_value_labels_ranges(isa).expect("value location ranges"));
let mut clif = String::new(); let mut clif = String::new();
cranelift_codegen::write::decorate_function( cranelift_codegen::write::decorate_function(
&mut clif_comments, &mut clif_comments,
&mut clif, &mut clif,
&context.func, &context.func,
&DisplayFunctionAnnotations { isa, value_ranges: value_ranges.as_ref() }, &DisplayFunctionAnnotations { isa: Some(isa), value_ranges: None },
) )
.unwrap(); .unwrap();
writeln!(file, "test compile")?; for flag in isa.flags().iter() {
writeln!(file, "set is_pic")?; writeln!(file, "set {}", flag)?;
writeln!(file, "set enable_simd")?; }
writeln!(file, "target {} haswell", crate::target_triple(tcx.sess))?; 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)?; writeln!(file)?;
file.write_all(clif.as_bytes())?; file.write_all(clif.as_bytes())?;
Ok(()) Ok(())

View file

@ -1,10 +1,9 @@
//! Codegen vtables and vtable accesses. //! Codegen vtables and vtable accesses.
//! //!
//! See `rustc_codegen_ssa/src/meth.rs` for reference. //! 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 crate::prelude::*;
use super::constant::pointer_for_allocation;
fn vtable_memflags() -> MemFlags { fn vtable_memflags() -> MemFlags {
let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap. 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), pointer_ty(fx.tcx),
vtable_memflags(), vtable_memflags(),
vtable, 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>, ty: Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> Value { ) -> Value {
let vtable_ptr = if let Some(vtable_ptr) = fx.vtables.get(&(ty, trait_ref)) { let alloc_id = fx.tcx.vtable_allocation(ty, trait_ref);
*vtable_ptr let data_id =
} else { data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not);
let vtable_alloc_id = fx.tcx.vtable_allocation(ty, trait_ref); let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
let vtable_allocation = fx.tcx.global_alloc(vtable_alloc_id).unwrap_memory(); if fx.clif_comments.enabled() {
let vtable_ptr = pointer_for_allocation(fx, vtable_allocation); fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id));
}
fx.vtables.insert((ty, trait_ref), vtable_ptr); fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
vtable_ptr
};
vtable_ptr.get_addr(fx)
} }

View file

@ -1,13 +1,13 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
./build.sh --sysroot none "$@" ./y.rs build --sysroot none "$@"
rm -r target/out || true rm -r target/out || true
scripts/tests.sh no_sysroot scripts/tests.sh no_sysroot
./build.sh "$@" ./y.rs build "$@"
scripts/tests.sh base_sysroot scripts/tests.sh base_sysroot
scripts/tests.sh extended_sysroot scripts/tests.sh extended_sysroot

View file

@ -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,
);
}