Auto merge of #107269 - bjorn3:sync_cg_clif-2023-01-24, r=bjorn3

Sync rustc_codegen_cranelift

For cg_clif itself there have been a couple of bug fixes since the last sync, a Cranelift update and implemented all remaining simd platform intrinsics used by `std::simd`. (`std::arch` still misses a lot though) Most of the diff is from reworking of the cg_clif build system though.

r? `@ghost`

`@rustbot` label +A-codegen +A-cranelift +T-compiler
This commit is contained in:
bors 2023-01-27 00:03:09 +00:00
commit 02d5f7fa4d
46 changed files with 1391 additions and 1109 deletions

View File

@ -1,13 +1,11 @@
task:
name: freebsd
freebsd_instance:
image: freebsd-12-1-release-amd64
image: freebsd-13-1-release-amd64
setup_rust_script:
- pkg install -y curl git bash
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh --default-toolchain none -y --profile=minimal
cargo_bin_cache:
folder: ~/.cargo/bin
target_cache:
folder: target
prepare_script:
@ -15,9 +13,4 @@ task:
- ./y.rs prepare
test_script:
- . $HOME/.cargo/env
- # 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
- ./y.rs test

View File

@ -25,6 +25,10 @@ jobs:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
@ -46,36 +50,31 @@ jobs:
- os: ubuntu-latest
env:
TARGET_TRIPLE: s390x-unknown-linux-gnu
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-msvc
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-gnu
steps:
- uses: actions/checkout@v3
- name: Cache cargo installed crates
uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v3
with:
path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Set MinGW as the default toolchain
if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: rustup set default-host x86_64-pc-windows-gnu
- name: Install MinGW toolchain and wine
if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
rustup target add x86_64-pc-windows-gnu
- name: Install AArch64 toolchain and qemu
if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu'
@ -89,6 +88,13 @@ jobs:
sudo apt-get update
sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
- name: Use sparse cargo registry
run: |
cat >> ~/.cargo/config.toml <<EOF
[unstable]
sparse-registry = true
EOF
- name: Prepare dependencies
run: ./y.rs prepare
@ -104,49 +110,47 @@ jobs:
- name: Test
env:
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
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.rs test
run: ./y.rs test
- name: Package prebuilt cg_clif
run: tar cvfJ cg_clif.tar.xz dist
- name: Upload prebuilt cg_clif
if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
uses: actions/upload-artifact@v2
if: matrix.os == 'windows-latest' || matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
uses: actions/upload-artifact@v3
with:
name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
path: cg_clif.tar.xz
- name: Upload prebuilt cg_clif (cross compile)
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
if: matrix.os != 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
uses: actions/upload-artifact@v3
with:
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
path: cg_clif.tar.xz
windows:
abi_cafe:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
defaults:
run:
shell: bash
strategy:
fail-fast: false
fail-fast: true
matrix:
include:
# Native Windows build with MSVC
- os: ubuntu-latest
env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu
- os: macos-latest
env:
TARGET_TRIPLE: x86_64-apple-darwin
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-msvc
# cross-compile from Windows to Windows MinGW
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-gnu
@ -154,20 +158,6 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Cache cargo installed crates
uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
- name: Cache cargo registry and index
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v3
with:
@ -178,50 +168,20 @@ jobs:
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: rustup set default-host x86_64-pc-windows-gnu
- name: Prepare dependencies
- name: Use sparse cargo registry
run: |
git config --global core.autocrlf false
rustc y.rs -o y.exe -g
./y.exe prepare
cat >> ~/.cargo/config.toml <<EOF
[unstable]
sparse-registry = true
EOF
- name: Build without unstable features
env:
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
# This is the config rust-lang/rust uses for builds
run: ./y.rs build --no-unstable-features
- name: Prepare dependencies
run: ./y.rs prepare
- name: Build
run: ./y.rs build --sysroot none
- name: Test
run: |
# Enable backtraces for easier debugging
$Env:RUST_BACKTRACE=1
# Reduce amount of benchmark runs as they are slow
$Env:COMPILE_RUNS=2
$Env:RUN_RUNS=2
# Enable extra checks
$Env:CG_CLIF_ENABLE_VERIFIER=1
# WIP Disable some tests
# This fails due to some weird argument handling by hyperfine, not an actual regression
# more of a build system issue
(Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' | Out-File config.txt
# This fails with a different output than expected
(Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' | Out-File config.txt
./y.exe test
- name: Package prebuilt cg_clif
# don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
run: tar cvf cg_clif.tar dist
- name: Upload prebuilt cg_clif
uses: actions/upload-artifact@v3
with:
name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
path: cg_clif.tar
- name: Test abi-cafe
env:
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
run: ./y.rs abi-cafe

View File

@ -1,59 +0,0 @@
name: Test nightly Cranelift
on:
push:
schedule:
- cron: '17 1 * * *' # At 01:17 UTC every day.
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v3
- name: Cache cargo installed crates
uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ubuntu-latest-cargo-installed-crates
- name: Prepare dependencies
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
./y.rs prepare
- name: Patch Cranelift
run: |
sed -i 's/cranelift-codegen = { version = "\w*.\w*.\w*", features = \["unwind", "all-arch"\] }/cranelift-codegen = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git", features = ["unwind", "all-arch"] }/' Cargo.toml
sed -i 's/cranelift-frontend = "\w*.\w*.\w*"/cranelift-frontend = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml
sed -i 's/cranelift-module = "\w*.\w*.\w*"/cranelift-module = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml
sed -i 's/cranelift-native = "\w*.\w*.\w*"/cranelift-native = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml
sed -i 's/cranelift-jit = { version = "\w*.\w*.\w*", optional = true }/cranelift-jit = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git", optional = true }/' Cargo.toml
sed -i 's/cranelift-object = "\w*.\w*.\w*"/cranelift-object = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml
sed -i 's/object = { version = "0.27.0"/object = { version = "0.28.0"/' Cargo.toml
cat Cargo.toml
- name: Build without unstable features
# This is the config rust-lang/rust uses for builds
run: ./y.rs build --no-unstable-features
- name: Build
run: ./y.rs build --sysroot none
- 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
./test.sh

View File

@ -10,73 +10,45 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Cache cargo installed crates
uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v3
with:
path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies
- name: Use sparse cargo registry
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
./y.rs prepare
cat >> ~/.cargo/config.toml <<EOF
[unstable]
sparse-registry = true
EOF
- name: Prepare dependencies
run: ./y.rs prepare
- name: Test
run: |
# Enable backtraces for easier debugging
export RUST_BACKTRACE=1
./scripts/test_bootstrap.sh
run: ./scripts/test_bootstrap.sh
rustc_test_suite:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Cache cargo installed crates
uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v3
with:
path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies
- name: Use sparse cargo registry
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
./y.rs prepare
cat >> ~/.cargo/config.toml <<EOF
[unstable]
sparse-registry = true
EOF
- name: Prepare dependencies
run: ./y.rs prepare
- name: Test
run: |
# Enable backtraces for easier debugging
export RUST_BACKTRACE=1
./scripts/test_rustc_tests.sh
run: ./scripts/test_rustc_tests.sh

5
.gitignore vendored
View File

@ -1,4 +1,4 @@
target
/target
**/*.rs.bk
*.rlib
*.o
@ -11,9 +11,6 @@ perf.data.old
/y.exe
/y.pdb
/build
/build_sysroot/sysroot_src
/build_sysroot/compiler-builtins
/build_sysroot/rustc_version
/dist
/rust
/download

View File

@ -1,4 +1,6 @@
{
"editor.formatOnSave": true,
// 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.imports.granularity.enforce": true,
@ -30,7 +32,7 @@
]
},
{
"sysroot_src": "./build_sysroot/sysroot_src/library",
"sysroot_src": "./download/sysroot/sysroot_src/library",
"crates": [
{
"root_module": "./example/std_example.rs",

109
Cargo.lock generated
View File

@ -57,28 +57,28 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cranelift-bforest"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62c772976416112fa4484cbd688cb6fb35fd430005c1c586224fc014018abad"
checksum = "2f3d54eab028f5805ae3b26fd60eca3f3a9cfb76b989d9bab173be3f61356cc3"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b40ed2dd13c2ac7e24f88a3090c68ad3414eb1d066a95f8f1f7b3b819cb4e46"
checksum = "2be1d5f2c3cca1efb691844bc1988b89c77291f13f778499a3f3c0cf49c0ed61"
dependencies = [
"arrayvec",
"bumpalo",
"cranelift-bforest",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
"cranelift-egraph",
"cranelift-entity",
"cranelift-isle",
"gimli",
"hashbrown",
"log",
"regalloc2",
"smallvec",
@ -87,44 +87,30 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb927a8f1c27c34ee3759b6b0ffa528d2330405d5cc4511f0cab33fe2279f4b5"
checksum = "3f9b1b1089750ce4005893af7ee00bb08a2cf1c9779999c0f7164cbc8ad2e0d2"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43dfa417b884a9ab488d95fd6b93b25e959321fe7bfd7a0a960ba5d7fb7ab927"
[[package]]
name = "cranelift-egraph"
version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a66b39785efd8513d2cca967ede56d6cc57c8d7986a595c7c47d0c78de8dce"
dependencies = [
"cranelift-entity",
"fxhash",
"hashbrown",
"indexmap",
"log",
"smallvec",
]
checksum = "cc5fbaec51de47297fd7304986fd53c8c0030abbe69728a60d72e1c63559318d"
[[package]]
name = "cranelift-entity"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0637ffde963cb5d759bc4d454cfa364b6509e6c74cdaa21298add0ed9276f346"
checksum = "dab984c94593f876090fae92e984bdcc74d9b1acf740ab5f79036001c65cba13"
[[package]]
name = "cranelift-frontend"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb72b8342685e850cb037350418f62cc4fc55d6c2eb9c7ca01b82f9f1a6f3d56"
checksum = "6e0cb3102d21a2fe5f3210af608748ddd0cd09825ac12d42dc56ed5ed8725fe0"
dependencies = [
"cranelift-codegen",
"log",
@ -134,15 +120,15 @@ dependencies = [
[[package]]
name = "cranelift-isle"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "850579cb9e4b448f7c301f1e6e6cbad99abe3f1f1d878a4994cb66e33c6db8cd"
checksum = "72101dd1f441d629735143c41e00b3428f9267738176983ef588ff43382af0a0"
[[package]]
name = "cranelift-jit"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9add822ad66dcbe152b5ab57de10240a2df4505099f2f6c27159acb711890bd4"
checksum = "6557f8ce44d498777f2495aa58d9692a4a37d6f84aa445750d666cef770b6a5c"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -159,9 +145,9 @@ dependencies = [
[[package]]
name = "cranelift-module"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "406b772626fc2664864cf947f3895a23b619895c7fff635f3622e2d857f4492f"
checksum = "88807e1c0c47ec02fe433333ccbe56b480425418b1470e333205e11650697d72"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -169,9 +155,9 @@ dependencies = [
[[package]]
name = "cranelift-native"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d0a279e5bcba3e0466c734d8d8eb6bfc1ad29e95c37f3e4955b492b5616335e"
checksum = "c22b0d9fcbe3fc5a1af9e7021b44ce42b930bcefac446ce22e02e8f9a0d67120"
dependencies = [
"cranelift-codegen",
"libc",
@ -180,9 +166,9 @@ dependencies = [
[[package]]
name = "cranelift-object"
version = "0.90.1"
version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39793c550f0c1d7db96c2fc1324583670c8143befe6edbfbaf1c68aba53be983"
checksum = "341375758d7c3fedc0b5315f552e6f0feac46baf87c450a15e9455ef47c2b261"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -317,9 +303,9 @@ checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "regalloc2"
version = "0.4.2"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5"
checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c"
dependencies = [
"fxhash",
"log",
@ -347,7 +333,6 @@ dependencies = [
"cranelift-frontend",
"cranelift-jit",
"cranelift-module",
"cranelift-native",
"cranelift-object",
"gimli",
"indexmap",
@ -396,9 +381,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "2.0.1"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6bbabb309c06cc238ee91b1455b748c45f0bdcab0dda2c2db85b0a1e69fcb66"
checksum = "08fcba5ebd96da2a9f0747ab6337fe9788adfb3f63fa2c180520d665562d257e"
dependencies = [
"cfg-if",
"libc",
@ -429,43 +414,57 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"

View File

@ -15,12 +15,14 @@ crate-type = ["dylib"]
[dependencies]
# These have to be in sync with each other
cranelift-codegen = { version = "0.90.1", features = ["unwind", "all-arch"] }
cranelift-frontend = "0.90.1"
cranelift-module = "0.90.1"
cranelift-native = "0.90.1"
cranelift-jit = { version = "0.90.1", optional = true }
cranelift-object = "0.90.1"
cranelift-codegen = { version = "0.92", features = ["unwind", "all-arch"] }
cranelift-frontend = { version = "0.92" }
cranelift-module = { version = "0.92" }
# NOTE vendored as src/cranelift_native.rs
# FIXME revert back to the external crate with Cranelift 0.93
#cranelift-native = { version = "0.92" }
cranelift-jit = { version = "0.92", optional = true }
cranelift-object = { version = "0.92" }
target-lexicon = "0.12.0"
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }

View File

@ -8,9 +8,9 @@ If not please open an issue.
## Building and testing
```bash
$ git clone https://github.com/bjorn3/rustc_codegen_cranelift.git
$ git clone https://github.com/bjorn3/rustc_codegen_cranelift
$ cd rustc_codegen_cranelift
$ ./y.rs prepare # download and patch sysroot src and install hyperfine for benchmarking
$ ./y.rs prepare
$ ./y.rs build
```
@ -20,13 +20,12 @@ To run the test suite replace the last command with:
$ ./test.sh
```
This will implicitly build cg_clif too. Both `y.rs build` and `test.sh` accept a `--debug` argument to
build in debug mode.
For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.rs`.
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 [Github Actions]. It is listed in the artifacts section
of workflow runs. Unfortunately due to GHA restrictions you need to be logged in to access it.
[GHA]: https://github.com/bjorn3/rustc_codegen_cranelift/actions?query=branch%3Amaster+event%3Apush+is%3Asuccess
[Github Actions]: https://github.com/bjorn3/rustc_codegen_cranelift/actions?query=branch%3Amaster+event%3Apush+is%3Asuccess
## Usage
@ -53,7 +52,8 @@ configuration options.
* Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041))
* On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`.
* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work)
* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported)
* Unwinding on panics ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1677), `-Cpanic=abort` is enabled by default)
## License

View File

@ -34,9 +34,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.77"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
@ -50,9 +50,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
version = "0.1.85"
version = "0.1.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
checksum = "5dae98c88e576098d7ab13ebcb40cc43e5114b2beafe61a87cda9200649ff205"
dependencies = [
"rustc-std-workspace-core",
]
@ -129,9 +129,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.138"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
dependencies = [
"rustc-std-workspace-core",
]

View File

@ -1,7 +1,6 @@
use std::path::Path;
use super::build_sysroot;
use super::config;
use super::path::Dirs;
use super::prepare::GitRepo;
use super::utils::{spawn_and_wait, CargoProject, Compiler};
@ -10,41 +9,31 @@ use super::SysrootKind;
pub(crate) static ABI_CAFE_REPO: GitRepo =
GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe");
pub(crate) static ABI_CAFE: CargoProject =
CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe");
pub(crate) fn run(
channel: &str,
sysroot_kind: SysrootKind,
dirs: &Dirs,
cg_clif_dylib: &Path,
host_triple: &str,
target_triple: &str,
bootstrap_host_compiler: &Compiler,
) {
if !config::get_bool("testsuite.abi-cafe") {
eprintln!("[SKIP] abi-cafe");
return;
}
if host_triple != target_triple {
eprintln!("[SKIP] abi-cafe (cross-compilation not supported)");
return;
}
eprintln!("Building sysroot for abi-cafe");
build_sysroot::build_sysroot(
dirs,
channel,
sysroot_kind,
cg_clif_dylib,
host_triple,
target_triple,
bootstrap_host_compiler,
bootstrap_host_compiler.triple.clone(),
);
eprintln!("Running abi-cafe");
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
let mut cmd = ABI_CAFE.run(&Compiler::host(), dirs);
let mut cmd = ABI_CAFE.run(bootstrap_host_compiler, dirs);
cmd.arg("--");
cmd.arg("--pairs");
cmd.args(pairs);

97
build_system/bench.rs Normal file
View File

@ -0,0 +1,97 @@
use std::env;
use std::fs;
use std::path::Path;
use super::path::{Dirs, RelPath};
use super::prepare::GitRepo;
use super::rustc_info::get_file_name;
use super::utils::{hyperfine_command, is_ci, spawn_and_wait, CargoProject, Compiler};
pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
"ebobby",
"simple-raytracer",
"804a7a21b9e673a482797aa289a18ed480e4d813",
"<none>",
);
// Use a separate target dir for the initial LLVM build to reduce unnecessary recompiles
pub(crate) static SIMPLE_RAYTRACER_LLVM: CargoProject =
CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer_llvm");
pub(crate) static SIMPLE_RAYTRACER: CargoProject =
CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
pub(crate) fn benchmark(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
benchmark_simple_raytracer(dirs, bootstrap_host_compiler);
}
fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
if std::process::Command::new("hyperfine").output().is_err() {
eprintln!("Hyperfine not installed");
eprintln!("Hint: Try `cargo install hyperfine` to install hyperfine");
std::process::exit(1);
}
eprintln!("[LLVM BUILD] simple-raytracer");
let build_cmd = SIMPLE_RAYTRACER_LLVM.build(bootstrap_host_compiler, dirs);
spawn_and_wait(build_cmd);
fs::copy(
SIMPLE_RAYTRACER_LLVM
.target_dir(dirs)
.join(&bootstrap_host_compiler.triple)
.join("debug")
.join(get_file_name("main", "bin")),
RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
)
.unwrap();
let run_runs = env::var("RUN_RUNS")
.unwrap_or(if is_ci() { "2" } else { "10" }.to_string())
.parse()
.unwrap();
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
let cargo_clif =
RelPath::DIST.to_path(dirs).join(get_file_name("cargo_clif", "bin").replace('_', "-"));
let manifest_path = SIMPLE_RAYTRACER.manifest_path(dirs);
let target_dir = SIMPLE_RAYTRACER.target_dir(dirs);
let clean_cmd = format!(
"cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
manifest_path = manifest_path.display(),
target_dir = target_dir.display(),
);
let llvm_build_cmd = format!(
"cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
manifest_path = manifest_path.display(),
target_dir = target_dir.display(),
);
let clif_build_cmd = format!(
"{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
cargo_clif = cargo_clif.display(),
manifest_path = manifest_path.display(),
target_dir = target_dir.display(),
);
let bench_compile =
hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
spawn_and_wait(bench_compile);
eprintln!("[BENCH RUN] ebobby/simple-raytracer");
fs::copy(
target_dir.join("debug").join(get_file_name("main", "bin")),
RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_clif", "bin")),
)
.unwrap();
let mut bench_run = hyperfine_command(
0,
run_runs,
None,
Path::new(".").join(get_file_name("raytracer_cg_llvm", "bin")).to_str().unwrap(),
Path::new(".").join(get_file_name("raytracer_cg_clif", "bin")).to_str().unwrap(),
);
bench_run.current_dir(RelPath::BUILD.to_path(dirs));
spawn_and_wait(bench_run);
}

View File

@ -5,15 +5,15 @@ use super::path::{Dirs, RelPath};
use super::rustc_info::get_file_name;
use super::utils::{is_ci, CargoProject, Compiler};
static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
pub(crate) static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
pub(crate) fn build_backend(
dirs: &Dirs,
channel: &str,
host_triple: &str,
bootstrap_host_compiler: &Compiler,
use_unstable_features: bool,
) -> PathBuf {
let mut cmd = CG_CLIF.build(&Compiler::host(), dirs);
let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs);
cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
@ -25,6 +25,8 @@ pub(crate) fn build_backend(
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
cmd.env("CARGO_BUILD_INCREMENTAL", "false");
cmd.env("CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS", "true");
}
if use_unstable_features {
@ -46,7 +48,7 @@ pub(crate) fn build_backend(
CG_CLIF
.target_dir(dirs)
.join(host_triple)
.join(&bootstrap_host_compiler.triple)
.join(channel)
.join(get_file_name("rustc_codegen_cranelift", "dylib"))
}

View File

@ -1,31 +1,32 @@
use std::fs;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::process::{self, Command};
use super::path::{Dirs, RelPath};
use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler};
use super::rustc_info::{get_file_name, get_rustc_version, get_toolchain_name};
use super::utils::{remove_dir_if_exists, spawn_and_wait, try_hard_link, CargoProject, Compiler};
use super::SysrootKind;
static DIST_DIR: RelPath = RelPath::DIST;
static BIN_DIR: RelPath = RelPath::DIST.join("bin");
static LIB_DIR: RelPath = RelPath::DIST.join("lib");
static RUSTLIB_DIR: RelPath = LIB_DIR.join("rustlib");
pub(crate) fn build_sysroot(
dirs: &Dirs,
channel: &str,
sysroot_kind: SysrootKind,
cg_clif_dylib_src: &Path,
host_triple: &str,
target_triple: &str,
) {
bootstrap_host_compiler: &Compiler,
target_triple: String,
) -> Compiler {
eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
DIST_DIR.ensure_fresh(dirs);
BIN_DIR.ensure_exists(dirs);
LIB_DIR.ensure_exists(dirs);
let is_native = bootstrap_host_compiler.triple == target_triple;
// Copy the backend
let cg_clif_dylib_path = if cfg!(windows) {
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
@ -35,129 +36,169 @@ pub(crate) fn build_sysroot(
LIB_DIR
}
.to_path(dirs)
.join(get_file_name("rustc_codegen_cranelift", "dylib"));
.join(cg_clif_dylib_src.file_name().unwrap());
try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
// Build and copy rustc and cargo wrappers
let wrapper_base_name = get_file_name("____", "bin");
let toolchain_name = get_toolchain_name();
for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
let wrapper_name = get_wrapper_file_name(wrapper, "bin");
let wrapper_name = wrapper_base_name.replace("____", wrapper);
let mut build_cargo_wrapper_cmd = Command::new("rustc");
let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc);
build_cargo_wrapper_cmd
.env("TOOLCHAIN_NAME", toolchain_name.clone())
.arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
.arg("-o")
.arg(DIST_DIR.to_path(dirs).join(wrapper_name))
.arg("-g");
.arg("-Cstrip=debuginfo");
spawn_and_wait(build_cargo_wrapper_cmd);
}
let default_sysroot = super::rustc_info::get_default_sysroot();
let host = build_sysroot_for_triple(
dirs,
channel,
bootstrap_host_compiler.clone(),
&cg_clif_dylib_path,
sysroot_kind,
);
host.install_into_sysroot(&DIST_DIR.to_path(dirs));
let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib");
let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).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"),
if !is_native {
build_sysroot_for_triple(
dirs,
channel,
{
let mut bootstrap_target_compiler = bootstrap_host_compiler.clone();
bootstrap_target_compiler.triple = target_triple.clone();
bootstrap_target_compiler.set_cross_linker_and_runner();
bootstrap_target_compiler
},
&cg_clif_dylib_path,
sysroot_kind,
)
.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()));
.install_into_sysroot(&DIST_DIR.to_path(dirs));
}
// Copy std for the host to the lib dir. This is necessary for the jit mode to find
// libstd.
for lib in host.libs {
let filename = lib.file_name().unwrap().to_str().unwrap();
if filename.contains("std-") && !filename.contains(".rlib") {
try_hard_link(&lib, LIB_DIR.to_path(dirs).join(lib.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("rustc_std_workspace_")
&& !file_name_str.contains("rustc_demangle"))
|| 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()));
}
let mut target_compiler = {
let dirs: &Dirs = &dirs;
let rustc_clif =
RelPath::DIST.to_path(&dirs).join(wrapper_base_name.replace("____", "rustc-clif"));
let rustdoc_clif =
RelPath::DIST.to_path(&dirs).join(wrapper_base_name.replace("____", "rustdoc-clif"));
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()));
}
}
Compiler {
cargo: bootstrap_host_compiler.cargo.clone(),
rustc: rustc_clif.clone(),
rustdoc: rustdoc_clif.clone(),
rustflags: String::new(),
rustdocflags: String::new(),
triple: target_triple,
runner: vec![],
}
SysrootKind::Clif => {
build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, None);
};
if !is_native {
target_compiler.set_cross_linker_and_runner();
}
target_compiler
}
if host_triple != target_triple {
// When cross-compiling it is often necessary to manually pick the right linker
let linker = match target_triple {
"aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"),
"s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"),
_ => None,
};
build_clif_sysroot_for_triple(
dirs,
channel,
target_triple,
&cg_clif_dylib_path,
linker,
);
}
struct SysrootTarget {
triple: String,
libs: Vec<PathBuf>,
}
// 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();
let filename = file.file_name().unwrap().to_str().unwrap();
if filename.contains("std-") && !filename.contains(".rlib") {
try_hard_link(&file, LIB_DIR.to_path(dirs).join(file.file_name().unwrap()));
}
}
impl SysrootTarget {
fn install_into_sysroot(&self, sysroot: &Path) {
if self.libs.is_empty() {
return;
}
let target_rustlib_lib = sysroot.join("lib").join("rustlib").join(&self.triple).join("lib");
fs::create_dir_all(&target_rustlib_lib).unwrap();
for lib in &self.libs {
try_hard_link(lib, target_rustlib_lib.join(lib.file_name().unwrap()));
}
}
}
// FIXME move to download/ or dist/
pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = RelPath::BUILD_SYSROOT.join("rustc_version");
pub(crate) static SYSROOT_SRC: RelPath = RelPath::BUILD_SYSROOT.join("sysroot_src");
static STANDARD_LIBRARY: CargoProject = CargoProject::new(&RelPath::BUILD_SYSROOT, "build_sysroot");
pub(crate) static ORIG_BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
pub(crate) static BUILD_SYSROOT: RelPath = RelPath::DOWNLOAD.join("sysroot");
pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = BUILD_SYSROOT.join("rustc_version");
pub(crate) static SYSROOT_SRC: RelPath = BUILD_SYSROOT.join("sysroot_src");
pub(crate) static STANDARD_LIBRARY: CargoProject =
CargoProject::new(&BUILD_SYSROOT, "build_sysroot");
pub(crate) static RTSTARTUP_SYSROOT: RelPath = RelPath::BUILD.join("rtstartup");
#[must_use]
fn build_sysroot_for_triple(
dirs: &Dirs,
channel: &str,
compiler: Compiler,
cg_clif_dylib_path: &Path,
sysroot_kind: SysrootKind,
) -> SysrootTarget {
match sysroot_kind {
SysrootKind::None => build_rtstartup(dirs, &compiler)
.unwrap_or(SysrootTarget { triple: compiler.triple, libs: vec![] }),
SysrootKind::Llvm => build_llvm_sysroot_for_triple(compiler),
SysrootKind::Clif => {
build_clif_sysroot_for_triple(dirs, channel, compiler, &cg_clif_dylib_path)
}
}
}
#[must_use]
fn build_llvm_sysroot_for_triple(compiler: Compiler) -> SysrootTarget {
let default_sysroot = super::rustc_info::get_default_sysroot(&compiler.rustc);
let mut target_libs = SysrootTarget { triple: compiler.triple, libs: vec![] };
for entry in fs::read_dir(
default_sysroot.join("lib").join("rustlib").join(&target_libs.triple).join("lib"),
)
.unwrap()
{
let entry = entry.unwrap();
if entry.file_type().unwrap().is_dir() {
continue;
}
let file = entry.path();
let file_name_str = file.file_name().unwrap().to_str().unwrap();
if (file_name_str.contains("rustc_")
&& !file_name_str.contains("rustc_std_workspace_")
&& !file_name_str.contains("rustc_demangle"))
|| file_name_str.contains("chalk")
|| file_name_str.contains("tracing")
|| file_name_str.contains("regex")
{
// These are large crates that are part of the rustc-dev component and are not
// necessary to run regular programs.
continue;
}
target_libs.libs.push(file);
}
target_libs
}
#[must_use]
fn build_clif_sysroot_for_triple(
dirs: &Dirs,
channel: &str,
triple: &str,
mut compiler: Compiler,
cg_clif_dylib_path: &Path,
linker: Option<&str>,
) {
) -> SysrootTarget {
match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) {
Err(e) => {
eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
@ -165,7 +206,7 @@ fn build_clif_sysroot_for_triple(
process::exit(1);
}
Ok(source_version) => {
let rustc_version = get_rustc_version();
let rustc_version = get_rustc_version(&compiler.rustc);
if source_version != rustc_version {
eprintln!("The patched sysroot source is outdated");
eprintln!("Source version: {}", source_version.trim());
@ -176,29 +217,32 @@ fn build_clif_sysroot_for_triple(
}
}
let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(triple).join(channel);
let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
if let Some(rtstartup_target_libs) = build_rtstartup(dirs, &compiler) {
rtstartup_target_libs.install_into_sysroot(&RTSTARTUP_SYSROOT.to_path(dirs));
target_libs.libs.extend(rtstartup_target_libs.libs);
}
let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(&compiler.triple).join(channel);
if !super::config::get_bool("keep_sysroot") {
// Cleanup the deps dir, but keep build scripts and the incremental cache for faster
// recompilation as they are not affected by changes in cg_clif.
if build_dir.join("deps").exists() {
fs::remove_dir_all(build_dir.join("deps")).unwrap();
}
remove_dir_if_exists(&build_dir.join("deps"));
}
// Build sysroot
let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
let mut rustflags = " -Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
rustflags.push_str(&format!(" --sysroot={}", DIST_DIR.to_path(dirs).to_str().unwrap()));
// Necessary for MinGW to find rsbegin.o and rsend.o
rustflags
.push_str(&format!(" --sysroot={}", RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap()));
if channel == "release" {
rustflags.push_str(" -Zmir-opt-level=3");
}
if let Some(linker) = linker {
use std::fmt::Write;
write!(rustflags, " -Clinker={}", linker).unwrap();
}
let mut compiler = Compiler::with_triple(triple.to_owned());
compiler.rustflags = rustflags;
compiler.rustflags += &rustflags;
let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
if channel == "release" {
build_cmd.arg("--release");
@ -206,7 +250,6 @@ fn build_clif_sysroot_for_triple(
build_cmd.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(build_dir.join("deps")).unwrap() {
let entry = entry.unwrap();
if let Some(ext) = entry.path().extension() {
@ -216,9 +259,35 @@ fn build_clif_sysroot_for_triple(
} else {
continue;
};
try_hard_link(
entry.path(),
RUSTLIB_DIR.to_path(dirs).join(triple).join("lib").join(entry.file_name()),
);
target_libs.libs.push(entry.path());
}
target_libs
}
fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
if !compiler.triple.ends_with("windows-gnu") {
return None;
}
RTSTARTUP_SYSROOT.ensure_fresh(dirs);
let rtstartup_src = SYSROOT_SRC.to_path(dirs).join("library").join("rtstartup");
let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
for file in ["rsbegin", "rsend"] {
let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o"));
let mut build_rtstartup_cmd = Command::new(&compiler.rustc);
build_rtstartup_cmd
.arg("--target")
.arg(&compiler.triple)
.arg("--emit=obj")
.arg("-o")
.arg(&obj)
.arg(rtstartup_src.join(format!("{file}.rs")));
spawn_and_wait(build_rtstartup_cmd);
target_libs.libs.push(obj.clone());
}
Some(target_libs)
}

View File

@ -2,9 +2,10 @@ use std::env;
use std::path::PathBuf;
use std::process;
use self::utils::is_ci;
use self::utils::{is_ci, Compiler};
mod abi_cafe;
mod bench;
mod build_backend;
mod build_sysroot;
mod config;
@ -14,31 +15,8 @@ mod rustc_info;
mod tests;
mod utils;
const USAGE: &str = r#"The build system of cg_clif.
USAGE:
./y.rs prepare [--out-dir DIR]
./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
OPTIONS:
--sysroot none|clif|llvm
Which sysroot libraries to use:
`none` will not include any standard library in the sysroot.
`clif` will build the standard library using Cranelift.
`llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
--out-dir DIR
Specify the directory in which the download, build and dist directories are stored.
By default this is the working directory.
--no-unstable-features
fSome features are not yet ready for production usage. This option will disable these
features. This includes the JIT mode and inline assembly support.
"#;
fn usage() {
eprintln!("{USAGE}");
eprintln!("{}", include_str!("usage.txt"));
}
macro_rules! arg_error {
@ -54,6 +32,8 @@ enum Command {
Prepare,
Build,
Test,
AbiCafe,
Bench,
}
#[derive(Copy, Clone, Debug)]
@ -64,12 +44,17 @@ pub(crate) enum SysrootKind {
}
pub fn main() {
env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
if env::var("RUST_BACKTRACE").is_err() {
env::set_var("RUST_BACKTRACE", "1");
}
env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
if is_ci() {
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
env::set_var("CARGO_BUILD_INCREMENTAL", "false");
// Enable the Cranelift verifier
env::set_var("CG_CLIF_ENABLE_VERIFIER", "1");
}
let mut args = env::args().skip(1);
@ -77,6 +62,8 @@ pub fn main() {
Some("prepare") => Command::Prepare,
Some("build") => Command::Build,
Some("test") => Command::Test,
Some("abi-cafe") => Command::AbiCafe,
Some("bench") => Command::Bench,
Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
Some(command) => arg_error!("Unknown command {}", command),
None => {
@ -112,24 +99,16 @@ pub fn main() {
}
}
let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
host_triple
} else if let Some(host_triple) = 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) = config::get_value("target") {
target_triple
} else {
host_triple.clone()
};
let bootstrap_host_compiler = Compiler::bootstrap_with_triple(
std::env::var("HOST_TRIPLE")
.ok()
.or_else(|| config::get_value("host"))
.unwrap_or_else(|| rustc_info::get_host_triple()),
);
let target_triple = std::env::var("TARGET_TRIPLE")
.ok()
.or_else(|| config::get_value("target"))
.unwrap_or_else(|| bootstrap_host_compiler.triple.clone());
// FIXME allow changing the location of these dirs using cli arguments
let current_dir = std::env::current_dir().unwrap();
@ -157,8 +136,15 @@ pub fn main() {
process::exit(0);
}
let cg_clif_dylib =
build_backend::build_backend(&dirs, channel, &host_triple, use_unstable_features);
env::set_var("RUSTC", "rustc_should_be_set_explicitly");
env::set_var("RUSTDOC", "rustdoc_should_be_set_explicitly");
let cg_clif_dylib = build_backend::build_backend(
&dirs,
channel,
&bootstrap_host_compiler,
use_unstable_features,
);
match command {
Command::Prepare => {
// Handled above
@ -169,28 +155,37 @@ pub fn main() {
channel,
sysroot_kind,
&cg_clif_dylib,
&host_triple,
&target_triple,
);
abi_cafe::run(
channel,
sysroot_kind,
&dirs,
&cg_clif_dylib,
&host_triple,
&target_triple,
&bootstrap_host_compiler,
target_triple.clone(),
);
}
Command::AbiCafe => {
if bootstrap_host_compiler.triple != target_triple {
eprintln!("Abi-cafe doesn't support cross-compilation");
process::exit(1);
}
abi_cafe::run(channel, sysroot_kind, &dirs, &cg_clif_dylib, &bootstrap_host_compiler);
}
Command::Build => {
build_sysroot::build_sysroot(
&dirs,
channel,
sysroot_kind,
&cg_clif_dylib,
&host_triple,
&target_triple,
&bootstrap_host_compiler,
target_triple,
);
}
Command::Bench => {
build_sysroot::build_sysroot(
&dirs,
channel,
sysroot_kind,
&cg_clif_dylib,
&bootstrap_host_compiler,
target_triple,
);
bench::benchmark(&dirs, &bootstrap_host_compiler);
}
}
}

View File

@ -1,6 +1,8 @@
use std::fs;
use std::path::PathBuf;
use super::utils::remove_dir_if_exists;
#[derive(Debug, Clone)]
pub(crate) struct Dirs {
pub(crate) source_dir: PathBuf,
@ -42,7 +44,6 @@ impl RelPath {
pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist);
pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts");
pub(crate) const BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches");
pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath {
@ -62,9 +63,7 @@ impl RelPath {
pub(crate) fn ensure_fresh(&self, dirs: &Dirs) {
let path = self.to_path(dirs);
if path.exists() {
fs::remove_dir_all(&path).unwrap();
}
remove_dir_if_exists(&path);
fs::create_dir_all(path).unwrap();
}
}

View File

@ -3,73 +3,55 @@ use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
use super::build_sysroot::{SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
use super::build_sysroot::{BUILD_SYSROOT, ORIG_BUILD_SYSROOT, SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
use super::path::{Dirs, RelPath};
use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
use super::utils::{copy_dir_recursively, spawn_and_wait, Compiler};
use super::rustc_info::{get_default_sysroot, get_rustc_version};
use super::utils::{copy_dir_recursively, git_command, retry_spawn_and_wait, spawn_and_wait};
pub(crate) fn prepare(dirs: &Dirs) {
if RelPath::DOWNLOAD.to_path(dirs).exists() {
std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
}
std::fs::create_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
RelPath::DOWNLOAD.ensure_fresh(dirs);
spawn_and_wait(super::build_backend::CG_CLIF.fetch("cargo", dirs));
prepare_sysroot(dirs);
// FIXME maybe install this only locally?
eprintln!("[INSTALL] hyperfine");
Command::new("cargo")
.arg("install")
.arg("hyperfine")
.env_remove("CARGO_TARGET_DIR")
.spawn()
.unwrap()
.wait()
.unwrap();
spawn_and_wait(super::build_sysroot::STANDARD_LIBRARY.fetch("cargo", dirs));
spawn_and_wait(super::tests::LIBCORE_TESTS.fetch("cargo", dirs));
super::abi_cafe::ABI_CAFE_REPO.fetch(dirs);
spawn_and_wait(super::abi_cafe::ABI_CAFE.fetch("cargo", dirs));
super::tests::RAND_REPO.fetch(dirs);
spawn_and_wait(super::tests::RAND.fetch("cargo", dirs));
super::tests::REGEX_REPO.fetch(dirs);
spawn_and_wait(super::tests::REGEX.fetch("cargo", dirs));
super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs);
eprintln!("[LLVM BUILD] simple-raytracer");
let host_compiler = Compiler::host();
let build_cmd = super::tests::SIMPLE_RAYTRACER.build(&host_compiler, dirs);
spawn_and_wait(build_cmd);
fs::copy(
super::tests::SIMPLE_RAYTRACER
.target_dir(dirs)
.join(&host_compiler.triple)
.join("debug")
.join(get_file_name("main", "bin")),
RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
)
.unwrap();
spawn_and_wait(super::tests::PORTABLE_SIMD.fetch("cargo", dirs));
super::bench::SIMPLE_RAYTRACER_REPO.fetch(dirs);
spawn_and_wait(super::bench::SIMPLE_RAYTRACER.fetch("cargo", dirs));
}
fn prepare_sysroot(dirs: &Dirs) {
let rustc_path = get_rustc_path();
let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
let sysroot_src = SYSROOT_SRC;
let sysroot_src_orig = get_default_sysroot(Path::new("rustc")).join("lib/rustlib/src/rust");
assert!(sysroot_src_orig.exists());
sysroot_src.ensure_fresh(dirs);
fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap();
eprintln!("[COPY] sysroot src");
// FIXME ensure builds error out or update the copy if any of the files copied here change
BUILD_SYSROOT.ensure_fresh(dirs);
copy_dir_recursively(&ORIG_BUILD_SYSROOT.to_path(dirs), &BUILD_SYSROOT.to_path(dirs));
fs::create_dir_all(SYSROOT_SRC.to_path(dirs).join("library")).unwrap();
copy_dir_recursively(
&sysroot_src_orig.join("library"),
&sysroot_src.to_path(dirs).join("library"),
&SYSROOT_SRC.to_path(dirs).join("library"),
);
let rustc_version = get_rustc_version();
let rustc_version = get_rustc_version(Path::new("rustc"));
fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &rustc_version).unwrap();
eprintln!("[GIT] init");
init_git_repo(&sysroot_src.to_path(dirs));
init_git_repo(&SYSROOT_SRC.to_path(dirs));
apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs));
apply_patches(dirs, "sysroot", &SYSROOT_SRC.to_path(dirs));
}
pub(crate) struct GitRepo {
@ -118,14 +100,14 @@ impl GitRepo {
fn clone_repo(download_dir: &Path, 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(&download_dir).spawn().unwrap().wait().unwrap();
git_command(None, "clone").arg(repo).arg(download_dir).spawn().unwrap().wait().unwrap();
let mut clean_cmd = Command::new("git");
clean_cmd.arg("checkout").arg("--").arg(".").current_dir(&download_dir);
let mut clean_cmd = git_command(download_dir, "checkout");
clean_cmd.arg("--").arg(".");
spawn_and_wait(clean_cmd);
let mut checkout_cmd = Command::new("git");
checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir);
let mut checkout_cmd = git_command(download_dir, "checkout");
checkout_cmd.arg("-q").arg(rev);
spawn_and_wait(checkout_cmd);
}
@ -149,8 +131,22 @@ fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo:
// Download zip archive
let mut download_cmd = Command::new("curl");
download_cmd.arg("--location").arg("--output").arg(&archive_file).arg(archive_url);
spawn_and_wait(download_cmd);
download_cmd
.arg("--max-time")
.arg("600")
.arg("-y")
.arg("30")
.arg("-Y")
.arg("10")
.arg("--connect-timeout")
.arg("30")
.arg("--continue-at")
.arg("-")
.arg("--location")
.arg("--output")
.arg(&archive_file)
.arg(archive_url);
retry_spawn_and_wait(5, download_cmd);
// Unpack tar archive
let mut unpack_cmd = Command::new("tar");
@ -167,25 +163,16 @@ fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo:
}
fn init_git_repo(repo_dir: &Path) {
let mut git_init_cmd = Command::new("git");
git_init_cmd.arg("init").arg("-q").current_dir(repo_dir);
let mut git_init_cmd = git_command(repo_dir, "init");
git_init_cmd.arg("-q");
spawn_and_wait(git_init_cmd);
let mut git_add_cmd = Command::new("git");
git_add_cmd.arg("add").arg(".").current_dir(repo_dir);
let mut git_add_cmd = git_command(repo_dir, "add");
git_add_cmd.arg(".");
spawn_and_wait(git_add_cmd);
let mut git_commit_cmd = Command::new("git");
git_commit_cmd
.arg("-c")
.arg("user.name=Dummy")
.arg("-c")
.arg("user.email=dummy@example.com")
.arg("commit")
.arg("-m")
.arg("Initial commit")
.arg("-q")
.current_dir(repo_dir);
let mut git_commit_cmd = git_command(repo_dir, "commit");
git_commit_cmd.arg("-m").arg("Initial commit").arg("-q");
spawn_and_wait(git_commit_cmd);
}
@ -220,16 +207,8 @@ fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) {
target_dir.file_name().unwrap(),
patch.file_name().unwrap()
);
let mut apply_patch_cmd = Command::new("git");
apply_patch_cmd
.arg("-c")
.arg("user.name=Dummy")
.arg("-c")
.arg("user.email=dummy@example.com")
.arg("am")
.arg(patch)
.arg("-q")
.current_dir(target_dir);
let mut apply_patch_cmd = git_command(target_dir, "am");
apply_patch_cmd.arg(patch).arg("-q");
spawn_and_wait(apply_patch_cmd);
}
}

View File

@ -1,9 +1,9 @@
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
pub(crate) fn get_rustc_version() -> String {
pub(crate) fn get_rustc_version(rustc: &Path) -> String {
let version_info =
Command::new("rustc").stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout;
Command::new(rustc).stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout;
String::from_utf8(version_info).unwrap()
}
@ -23,6 +23,16 @@ pub(crate) fn get_host_triple() -> String {
.to_owned()
}
pub(crate) fn get_toolchain_name() -> String {
let active_toolchain = Command::new("rustup")
.stderr(Stdio::inherit())
.args(&["show", "active-toolchain"])
.output()
.unwrap()
.stdout;
String::from_utf8(active_toolchain).unwrap().trim().split_once(' ').unwrap().0.to_owned()
}
pub(crate) fn get_cargo_path() -> PathBuf {
let cargo_path = Command::new("rustup")
.stderr(Stdio::inherit())
@ -53,8 +63,8 @@ pub(crate) fn get_rustdoc_path() -> PathBuf {
Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
}
pub(crate) fn get_default_sysroot() -> PathBuf {
let default_sysroot = Command::new("rustc")
pub(crate) fn get_default_sysroot(rustc: &Path) -> PathBuf {
let default_sysroot = Command::new(rustc)
.stderr(Stdio::inherit())
.args(&["--print", "sysroot"])
.output()
@ -83,12 +93,3 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String {
assert!(file_name.contains(crate_name));
file_name
}
/// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to
/// underscores (`_`). This is specially made for the rustc and cargo wrappers
/// which have a dash in the name, and that is not allowed in a crate name.
pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str) -> String {
let crate_name = crate_name.replace('-', "_");
let wrapper_name = get_file_name(&crate_name, crate_type);
wrapper_name.replace('_', "-")
}

View File

@ -1,11 +1,10 @@
use super::build_sysroot;
use super::bench::SIMPLE_RAYTRACER;
use super::build_sysroot::{self, SYSROOT_SRC};
use super::config;
use super::path::{Dirs, RelPath};
use super::prepare::GitRepo;
use super::rustc_info::{get_cargo_path, get_wrapper_file_name};
use super::utils::{
hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler,
};
use super::rustc_info::get_host_triple;
use super::utils::{spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler};
use super::SysrootKind;
use std::env;
use std::ffi::OsStr;
@ -17,256 +16,111 @@ static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
struct TestCase {
config: &'static str,
func: &'static dyn Fn(&TestRunner),
cmd: TestCaseCmd,
}
enum TestCaseCmd {
Custom { func: &'static dyn Fn(&TestRunner) },
BuildLib { source: &'static str, crate_types: &'static str },
BuildBinAndRun { source: &'static str, args: &'static [&'static str] },
JitBin { source: &'static str, args: &'static str },
}
impl TestCase {
const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
Self { config, func }
// FIXME reduce usage of custom test case commands
const fn custom(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
Self { config, cmd: TestCaseCmd::Custom { func } }
}
const fn build_lib(
config: &'static str,
source: &'static str,
crate_types: &'static str,
) -> Self {
Self { config, cmd: TestCaseCmd::BuildLib { source, crate_types } }
}
const fn build_bin_and_run(
config: &'static str,
source: &'static str,
args: &'static [&'static str],
) -> Self {
Self { config, cmd: TestCaseCmd::BuildBinAndRun { source, args } }
}
const fn jit_bin(config: &'static str, source: &'static str, args: &'static str) -> Self {
Self { config, cmd: TestCaseCmd::JitBin { source, args } }
}
}
const NO_SYSROOT_SUITE: &[TestCase] = &[
TestCase::new("build.mini_core", &|runner| {
runner.run_rustc([
"example/mini_core.rs",
"--crate-name",
"mini_core",
"--crate-type",
"lib,dylib",
"--target",
&runner.target_compiler.triple,
]);
}),
TestCase::new("build.example", &|runner| {
runner.run_rustc([
"example/example.rs",
"--crate-type",
"lib",
"--target",
&runner.target_compiler.triple,
]);
}),
TestCase::new("jit.mini_core_hello_world", &|runner| {
let mut jit_cmd = runner.rustc_command([
"-Zunstable-options",
"-Cllvm-args=mode=jit",
"-Cprefer-dynamic",
"example/mini_core_hello_world.rs",
"--cfg",
"jit",
"--target",
&runner.target_compiler.triple,
]);
jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
spawn_and_wait(jit_cmd);
eprintln!("[JIT-lazy] mini_core_hello_world");
let mut jit_cmd = runner.rustc_command([
"-Zunstable-options",
"-Cllvm-args=mode=jit-lazy",
"-Cprefer-dynamic",
"example/mini_core_hello_world.rs",
"--cfg",
"jit",
"--target",
&runner.target_compiler.triple,
]);
jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
spawn_and_wait(jit_cmd);
}),
TestCase::new("aot.mini_core_hello_world", &|runner| {
runner.run_rustc([
"example/mini_core_hello_world.rs",
"--crate-name",
"mini_core_hello_world",
"--crate-type",
"bin",
"-g",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
}),
TestCase::build_lib("build.mini_core", "example/mini_core.rs", "lib,dylib"),
TestCase::build_lib("build.example", "example/example.rs", "lib"),
TestCase::jit_bin("jit.mini_core_hello_world", "example/mini_core_hello_world.rs", "abc bcd"),
TestCase::build_bin_and_run(
"aot.mini_core_hello_world",
"example/mini_core_hello_world.rs",
&["abc", "bcd"],
),
];
const BASE_SYSROOT_SUITE: &[TestCase] = &[
TestCase::new("aot.arbitrary_self_types_pointers_and_wrappers", &|runner| {
runner.run_rustc([
"example/arbitrary_self_types_pointers_and_wrappers.rs",
"--crate-name",
"arbitrary_self_types_pointers_and_wrappers",
"--crate-type",
"bin",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
}),
TestCase::new("aot.issue_91827_extern_types", &|runner| {
runner.run_rustc([
"example/issue-91827-extern-types.rs",
"--crate-name",
"issue_91827_extern_types",
"--crate-type",
"bin",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("issue_91827_extern_types", []);
}),
TestCase::new("build.alloc_system", &|runner| {
runner.run_rustc([
"example/alloc_system.rs",
"--crate-type",
"lib",
"--target",
&runner.target_compiler.triple,
]);
}),
TestCase::new("aot.alloc_example", &|runner| {
runner.run_rustc([
"example/alloc_example.rs",
"--crate-type",
"bin",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("alloc_example", []);
}),
TestCase::new("jit.std_example", &|runner| {
runner.run_rustc([
"-Zunstable-options",
"-Cllvm-args=mode=jit",
"-Cprefer-dynamic",
"example/std_example.rs",
"--target",
&runner.target_compiler.triple,
]);
eprintln!("[JIT-lazy] std_example");
runner.run_rustc([
"-Zunstable-options",
"-Cllvm-args=mode=jit-lazy",
"-Cprefer-dynamic",
"example/std_example.rs",
"--target",
&runner.target_compiler.triple,
]);
}),
TestCase::new("aot.std_example", &|runner| {
runner.run_rustc([
"example/std_example.rs",
"--crate-type",
"bin",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("std_example", ["arg"]);
}),
TestCase::new("aot.dst_field_align", &|runner| {
runner.run_rustc([
"example/dst-field-align.rs",
"--crate-name",
"dst_field_align",
"--crate-type",
"bin",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("dst_field_align", []);
}),
TestCase::new("aot.subslice-patterns-const-eval", &|runner| {
runner.run_rustc([
"example/subslice-patterns-const-eval.rs",
"--crate-type",
"bin",
"-Cpanic=abort",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("subslice-patterns-const-eval", []);
}),
TestCase::new("aot.track-caller-attribute", &|runner| {
runner.run_rustc([
"example/track-caller-attribute.rs",
"--crate-type",
"bin",
"-Cpanic=abort",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("track-caller-attribute", []);
}),
TestCase::new("aot.float-minmax-pass", &|runner| {
runner.run_rustc([
"example/float-minmax-pass.rs",
"--crate-type",
"bin",
"-Cpanic=abort",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("float-minmax-pass", []);
}),
TestCase::new("aot.mod_bench", &|runner| {
runner.run_rustc([
"example/mod_bench.rs",
"--crate-type",
"bin",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("mod_bench", []);
}),
TestCase::new("aot.issue-72793", &|runner| {
runner.run_rustc([
"example/issue-72793.rs",
"--crate-type",
"bin",
"--target",
&runner.target_compiler.triple,
]);
runner.run_out_command("issue-72793", []);
}),
TestCase::build_bin_and_run(
"aot.arbitrary_self_types_pointers_and_wrappers",
"example/arbitrary_self_types_pointers_and_wrappers.rs",
&[],
),
TestCase::build_bin_and_run(
"aot.issue_91827_extern_types",
"example/issue-91827-extern-types.rs",
&[],
),
TestCase::build_lib("build.alloc_system", "example/alloc_system.rs", "lib"),
TestCase::build_bin_and_run("aot.alloc_example", "example/alloc_example.rs", &[]),
TestCase::jit_bin("jit.std_example", "example/std_example.rs", ""),
TestCase::build_bin_and_run("aot.std_example", "example/std_example.rs", &["arg"]),
TestCase::build_bin_and_run("aot.dst_field_align", "example/dst-field-align.rs", &[]),
TestCase::build_bin_and_run(
"aot.subslice-patterns-const-eval",
"example/subslice-patterns-const-eval.rs",
&[],
),
TestCase::build_bin_and_run(
"aot.track-caller-attribute",
"example/track-caller-attribute.rs",
&[],
),
TestCase::build_bin_and_run("aot.float-minmax-pass", "example/float-minmax-pass.rs", &[]),
TestCase::build_bin_and_run("aot.mod_bench", "example/mod_bench.rs", &[]),
TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]),
];
pub(crate) static RAND_REPO: GitRepo =
GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
pub(crate) static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
pub(crate) static REGEX_REPO: GitRepo =
GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex");
pub(crate) static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex");
pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
"rust-lang",
"portable-simd",
"d5cd4a8112d958bd3a252327e0d069a6363249bd",
"582239ac3b32007613df04d7ffa78dc30f4c5645",
"portable-simd",
);
static PORTABLE_SIMD: CargoProject =
pub(crate) static PORTABLE_SIMD: CargoProject =
CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd");
pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
"ebobby",
"simple-raytracer",
"804a7a21b9e673a482797aa289a18ed480e4d813",
"<none>",
);
pub(crate) static SIMPLE_RAYTRACER: CargoProject =
CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
static LIBCORE_TESTS: CargoProject =
CargoProject::new(&RelPath::BUILD_SYSROOT.join("sysroot_src/library/core/tests"), "core_tests");
pub(crate) static LIBCORE_TESTS: CargoProject =
CargoProject::new(&SYSROOT_SRC.join("library/core/tests"), "core_tests");
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
TestCase::new("test.rust-random/rand", &|runner| {
spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs));
TestCase::custom("test.rust-random/rand", &|runner| {
RAND.clean(&runner.dirs);
if runner.is_native {
eprintln!("[TEST] rust-random/rand");
@ -280,60 +134,12 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
spawn_and_wait(build_cmd);
}
}),
TestCase::new("bench.simple-raytracer", &|runner| {
let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
if runner.is_native {
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
let cargo_clif = RelPath::DIST
.to_path(&runner.dirs)
.join(get_wrapper_file_name("cargo-clif", "bin"));
let manifest_path = SIMPLE_RAYTRACER.manifest_path(&runner.dirs);
let target_dir = SIMPLE_RAYTRACER.target_dir(&runner.dirs);
let clean_cmd = format!(
"cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
manifest_path = manifest_path.display(),
target_dir = target_dir.display(),
);
let llvm_build_cmd = format!(
"cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
manifest_path = manifest_path.display(),
target_dir = target_dir.display(),
);
let clif_build_cmd = format!(
"{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
cargo_clif = cargo_clif.display(),
manifest_path = manifest_path.display(),
target_dir = target_dir.display(),
);
let bench_compile =
hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
spawn_and_wait(bench_compile);
eprintln!("[BENCH RUN] ebobby/simple-raytracer");
fs::copy(
target_dir.join("debug").join("main"),
RelPath::BUILD.to_path(&runner.dirs).join("raytracer_cg_clif"),
)
.unwrap();
let mut bench_run =
hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif");
bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs));
spawn_and_wait(bench_run);
} else {
spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs));
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
eprintln!("[COMPILE] ebobby/simple-raytracer");
spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
}
TestCase::custom("test.simple-raytracer", &|runner| {
SIMPLE_RAYTRACER.clean(&runner.dirs);
spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
}),
TestCase::new("test.libcore", &|runner| {
spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs));
TestCase::custom("test.libcore", &|runner| {
LIBCORE_TESTS.clean(&runner.dirs);
if runner.is_native {
spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs));
@ -344,8 +150,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
spawn_and_wait(build_cmd);
}
}),
TestCase::new("test.regex-shootout-regex-dna", &|runner| {
spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs));
TestCase::custom("test.regex-shootout-regex-dna", &|runner| {
REGEX.clean(&runner.dirs);
// newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
@ -364,9 +170,10 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"),
)
.unwrap();
let expected_path =
REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt");
let expected = fs::read_to_string(&expected_path).unwrap();
let expected = fs::read_to_string(
REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt"),
)
.unwrap();
let output = spawn_and_wait_with_input(run_cmd, input);
// Make sure `[codegen mono items] start` doesn't poison the diff
@ -379,27 +186,16 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
let output_matches = expected.lines().eq(output.lines());
if !output_matches {
let res_path = REGEX.source_dir(&runner.dirs).join("res.txt");
fs::write(&res_path, &output).unwrap();
if cfg!(windows) {
println!("Output files don't match!");
println!("Expected Output:\n{}", expected);
println!("Actual Output:\n{}", output);
} else {
let mut diff = Command::new("diff");
diff.arg("-u");
diff.arg(res_path);
diff.arg(expected_path);
spawn_and_wait(diff);
}
println!("Output files don't match!");
println!("Expected Output:\n{}", expected);
println!("Actual Output:\n{}", output);
std::process::exit(1);
}
}
}),
TestCase::new("test.regex", &|runner| {
spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs));
TestCase::custom("test.regex", &|runner| {
REGEX.clean(&runner.dirs);
// newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
@ -425,8 +221,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
spawn_and_wait(build_cmd);
}
}),
TestCase::new("test.portable-simd", &|runner| {
spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs));
TestCase::custom("test.portable-simd", &|runner| {
PORTABLE_SIMD.clean(&runner.dirs);
let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
build_cmd.arg("--all-targets");
@ -445,21 +241,22 @@ pub(crate) fn run_tests(
channel: &str,
sysroot_kind: SysrootKind,
cg_clif_dylib: &Path,
host_triple: &str,
target_triple: &str,
bootstrap_host_compiler: &Compiler,
target_triple: String,
) {
let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string());
if config::get_bool("testsuite.no_sysroot") {
build_sysroot::build_sysroot(
let target_compiler = build_sysroot::build_sysroot(
dirs,
channel,
SysrootKind::None,
cg_clif_dylib,
&host_triple,
&target_triple,
bootstrap_host_compiler,
target_triple.clone(),
);
let runner =
TestRunner::new(dirs.clone(), target_compiler, get_host_triple() == target_triple);
BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
runner.run_testsuite(NO_SYSROOT_SUITE);
} else {
@ -470,26 +267,29 @@ pub(crate) fn run_tests(
let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot");
if run_base_sysroot || run_extended_sysroot {
build_sysroot::build_sysroot(
let target_compiler = build_sysroot::build_sysroot(
dirs,
channel,
sysroot_kind,
cg_clif_dylib,
&host_triple,
&target_triple,
bootstrap_host_compiler,
target_triple.clone(),
);
}
if run_base_sysroot {
runner.run_testsuite(BASE_SYSROOT_SUITE);
} else {
eprintln!("[SKIP] base_sysroot tests");
}
let runner =
TestRunner::new(dirs.clone(), target_compiler, get_host_triple() == target_triple);
if run_extended_sysroot {
runner.run_testsuite(EXTENDED_SYSROOT_SUITE);
} else {
eprintln!("[SKIP] extended_sysroot tests");
if run_base_sysroot {
runner.run_testsuite(BASE_SYSROOT_SUITE);
} else {
eprintln!("[SKIP] base_sysroot tests");
}
if run_extended_sysroot {
runner.run_testsuite(EXTENDED_SYSROOT_SUITE);
} else {
eprintln!("[SKIP] extended_sysroot tests");
}
}
}
@ -497,84 +297,34 @@ struct TestRunner {
is_native: bool,
jit_supported: bool,
dirs: Dirs,
host_compiler: Compiler,
target_compiler: Compiler,
}
impl TestRunner {
pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self {
let is_native = host_triple == target_triple;
let jit_supported =
target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
let rustc_clif =
RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustc-clif", "bin"));
let rustdoc_clif =
RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustdoc-clif", "bin"));
let mut rustflags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
let mut runner = vec![];
if !is_native {
match target_triple.as_str() {
"aarch64-unknown-linux-gnu" => {
// We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags);
runner = vec![
"qemu-aarch64".to_owned(),
"-L".to_owned(),
"/usr/aarch64-linux-gnu".to_owned(),
];
}
"s390x-unknown-linux-gnu" => {
// We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
rustflags = format!("-Clinker=s390x-linux-gnu-gcc{}", rustflags);
runner = vec![
"qemu-s390x".to_owned(),
"-L".to_owned(),
"/usr/s390x-linux-gnu".to_owned(),
];
}
"x86_64-pc-windows-gnu" => {
// We are cross-compiling for Windows. Run tests in wine.
runner = vec!["wine".to_owned()];
}
_ => {
println!("Unknown non-native platform");
}
}
pub fn new(dirs: Dirs, mut target_compiler: Compiler, is_native: bool) -> Self {
if let Ok(rustflags) = env::var("RUSTFLAGS") {
target_compiler.rustflags.push(' ');
target_compiler.rustflags.push_str(&rustflags);
}
if let Ok(rustdocflags) = env::var("RUSTDOCFLAGS") {
target_compiler.rustdocflags.push(' ');
target_compiler.rustdocflags.push_str(&rustdocflags);
}
// FIXME fix `#[linkage = "extern_weak"]` without this
if target_triple.contains("darwin") {
rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags);
if target_compiler.triple.contains("darwin") {
target_compiler.rustflags.push_str(" -Clink-arg=-undefined -Clink-arg=dynamic_lookup");
}
let host_compiler = Compiler {
cargo: get_cargo_path(),
rustc: rustc_clif.clone(),
rustdoc: rustdoc_clif.clone(),
rustflags: String::new(),
rustdocflags: String::new(),
triple: host_triple,
runner: vec![],
};
let jit_supported = is_native
&& target_compiler.triple.contains("x86_64")
&& !target_compiler.triple.contains("windows");
let target_compiler = Compiler {
cargo: get_cargo_path(),
rustc: rustc_clif,
rustdoc: rustdoc_clif,
rustflags: rustflags.clone(),
rustdocflags: rustflags,
triple: target_triple,
runner,
};
Self { is_native, jit_supported, dirs, host_compiler, target_compiler }
Self { is_native, jit_supported, dirs, target_compiler }
}
pub fn run_testsuite(&self, tests: &[TestCase]) {
for &TestCase { config, func } in tests {
for TestCase { config, cmd } in tests {
let (tag, testname) = config.split_once('.').unwrap();
let tag = tag.to_uppercase();
let is_jit_test = tag == "JIT";
@ -586,7 +336,47 @@ impl TestRunner {
eprintln!("[{tag}] {testname}");
}
func(self);
match *cmd {
TestCaseCmd::Custom { func } => func(self),
TestCaseCmd::BuildLib { source, crate_types } => {
self.run_rustc([source, "--crate-type", crate_types]);
}
TestCaseCmd::BuildBinAndRun { source, args } => {
self.run_rustc([source]);
self.run_out_command(
source.split('/').last().unwrap().split('.').next().unwrap(),
args,
);
}
TestCaseCmd::JitBin { source, args } => {
let mut jit_cmd = self.rustc_command([
"-Zunstable-options",
"-Cllvm-args=mode=jit",
"-Cprefer-dynamic",
source,
"--cfg",
"jit",
]);
if !args.is_empty() {
jit_cmd.env("CG_CLIF_JIT_ARGS", args);
}
spawn_and_wait(jit_cmd);
eprintln!("[JIT-lazy] {testname}");
let mut jit_cmd = self.rustc_command([
"-Zunstable-options",
"-Cllvm-args=mode=jit-lazy",
"-Cprefer-dynamic",
source,
"--cfg",
"jit",
]);
if !args.is_empty() {
jit_cmd.env("CG_CLIF_JIT_ARGS", args);
}
spawn_and_wait(jit_cmd);
}
}
}
}
@ -603,6 +393,9 @@ impl TestRunner {
cmd.arg("--out-dir");
cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
cmd.arg("-Cdebuginfo=2");
cmd.arg("--target");
cmd.arg(&self.target_compiler.triple);
cmd.arg("-Cpanic=abort");
cmd.args(args);
cmd
}
@ -615,10 +408,7 @@ impl TestRunner {
spawn_and_wait(self.rustc_command(args));
}
fn run_out_command<'a, I>(&self, name: &str, args: I)
where
I: IntoIterator<Item = &'a str>,
{
fn run_out_command<'a>(&self, name: &str, args: &[&str]) {
let mut full_cmd = vec![];
// Prepend the RUN_WRAPPER's
@ -630,7 +420,7 @@ impl TestRunner {
BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(),
);
for arg in args.into_iter() {
for arg in args {
full_cmd.push(arg.to_string());
}

35
build_system/usage.txt Normal file
View File

@ -0,0 +1,35 @@
The build system of cg_clif.
USAGE:
./y.rs prepare [--out-dir DIR]
./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
./y.rs abi-cafe [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
./y.rs bench [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
OPTIONS:
--debug
Build cg_clif and the standard library in debug mode rather than release mode.
Warning: An unoptimized cg_clif is very slow.
--sysroot none|clif|llvm
Which sysroot libraries to use:
`none` will not include any standard library in the sysroot.
`clif` will build the standard library using Cranelift.
`llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
--out-dir DIR
Specify the directory in which the download, build and dist directories are stored.
By default this is the working directory.
--no-unstable-features
Some features are not yet ready for production usage. This option will disable these
features. This includes the JIT mode and inline assembly support.
REQUIREMENTS:
* Rustup: The build system has a hard coded dependency on rustup to install the right nightly
version and make sure it is used where necessary.
* Git: `./y.rs prepare` uses git for applying patches and on Windows for downloading test repos.
* Curl and tar (non-Windows only): Used by `./y.rs prepare` to download a single commit for
repos. Git will be used to clone the whole repo when using Windows.
* [Hyperfine](https://github.com/sharkdp/hyperfine/): Used for benchmarking with `./y.rs bench`.

View File

@ -1,12 +1,13 @@
use std::env;
use std::fs;
use std::io::Write;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
use super::path::{Dirs, RelPath};
use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path};
use super::rustc_info::{get_cargo_path, get_rustc_path, get_rustdoc_path};
#[derive(Clone, Debug)]
pub(crate) struct Compiler {
pub(crate) cargo: PathBuf,
pub(crate) rustc: PathBuf,
@ -18,19 +19,7 @@ pub(crate) struct Compiler {
}
impl Compiler {
pub(crate) fn host() -> Compiler {
Compiler {
cargo: get_cargo_path(),
rustc: get_rustc_path(),
rustdoc: get_rustdoc_path(),
rustflags: String::new(),
rustdocflags: String::new(),
triple: get_host_triple(),
runner: vec![],
}
}
pub(crate) fn with_triple(triple: String) -> Compiler {
pub(crate) fn bootstrap_with_triple(triple: String) -> Compiler {
Compiler {
cargo: get_cargo_path(),
rustc: get_rustc_path(),
@ -41,6 +30,38 @@ impl Compiler {
runner: vec![],
}
}
pub(crate) fn set_cross_linker_and_runner(&mut self) {
match self.triple.as_str() {
"aarch64-unknown-linux-gnu" => {
// We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
self.rustflags += " -Clinker=aarch64-linux-gnu-gcc";
self.rustdocflags += " -Clinker=aarch64-linux-gnu-gcc";
self.runner = vec![
"qemu-aarch64".to_owned(),
"-L".to_owned(),
"/usr/aarch64-linux-gnu".to_owned(),
];
}
"s390x-unknown-linux-gnu" => {
// We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
self.rustflags += " -Clinker=s390x-linux-gnu-gcc";
self.rustdocflags += " -Clinker=s390x-linux-gnu-gcc";
self.runner = vec![
"qemu-s390x".to_owned(),
"-L".to_owned(),
"/usr/s390x-linux-gnu".to_owned(),
];
}
"x86_64-pc-windows-gnu" => {
// We are cross-compiling for Windows. Run tests in wine.
self.runner = vec!["wine".to_owned()];
}
_ => {
println!("Unknown non-native platform");
}
}
}
}
pub(crate) struct CargoProject {
@ -65,6 +86,7 @@ impl CargoProject {
RelPath::BUILD.join(self.target).to_path(dirs)
}
#[must_use]
fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command {
let mut cmd = Command::new(cargo);
@ -72,11 +94,13 @@ impl CargoProject {
.arg("--manifest-path")
.arg(self.manifest_path(dirs))
.arg("--target-dir")
.arg(self.target_dir(dirs));
.arg(self.target_dir(dirs))
.arg("--frozen");
cmd
}
#[must_use]
fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command {
let mut cmd = self.base_cmd(command, &compiler.cargo, dirs);
@ -105,9 +129,8 @@ impl CargoProject {
cmd
}
#[must_use]
pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command {
self.base_cmd("clean", cargo, dirs)
pub(crate) fn clean(&self, dirs: &Dirs) {
let _ = fs::remove_dir_all(self.target_dir(dirs));
}
#[must_use]
@ -153,6 +176,23 @@ pub(crate) fn hyperfine_command(
bench
}
#[must_use]
pub(crate) fn git_command<'a>(repo_dir: impl Into<Option<&'a Path>>, cmd: &str) -> Command {
let mut git_cmd = Command::new("git");
git_cmd
.arg("-c")
.arg("user.name=Dummy")
.arg("-c")
.arg("user.email=dummy@example.com")
.arg("-c")
.arg("core.autocrlf=false")
.arg(cmd);
if let Some(repo_dir) = repo_dir.into() {
git_cmd.current_dir(repo_dir);
}
git_cmd
}
#[track_caller]
pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
let src = src.as_ref();
@ -169,6 +209,22 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) {
}
}
// Based on the retry function in rust's src/ci/shared.sh
#[track_caller]
pub(crate) fn retry_spawn_and_wait(tries: u64, mut cmd: Command) {
for i in 1..tries + 1 {
if i != 1 {
println!("Command failed. Attempt {i}/{tries}:");
}
if cmd.spawn().unwrap().wait().unwrap().success() {
return;
}
std::thread::sleep(std::time::Duration::from_secs(i * 5));
}
println!("The command has failed after {tries} attempts.");
process::exit(1);
}
#[track_caller]
pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> String {
let mut child = cmd
@ -190,6 +246,14 @@ pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> Stri
String::from_utf8(output.stdout).unwrap()
}
pub(crate) fn remove_dir_if_exists(path: &Path) {
match fs::remove_dir_all(&path) {
Ok(()) => {}
Err(err) if err.kind() == io::ErrorKind::NotFound => {}
Err(err) => panic!("Failed to remove {path}: {err}", path = path.display()),
}
}
pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
for entry in fs::read_dir(from).unwrap() {
let entry = entry.unwrap();

View File

@ -1,10 +1,9 @@
#!/usr/bin/env bash
set -e
rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
rm -rf target/ build/ dist/ perf.data{,.old} y.bin
rm -rf download/
rm -rf target/ download/ build/ dist/ y.bin y.bin.dSYM y.exe y.pdb
# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
# FIXME remove at some point in the future
rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ abi-cafe/
rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}

View File

@ -44,10 +44,8 @@ aot.issue-72793
testsuite.extended_sysroot
test.rust-random/rand
bench.simple-raytracer
test.simple-raytracer
test.libcore
test.regex-shootout-regex-dna
test.regex
test.portable-simd
testsuite.abi-cafe

View File

@ -1,35 +0,0 @@
From b742f03694b920cc14400727d54424e8e1b60928 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Thu, 18 Nov 2021 19:28:40 +0100
Subject: [PATCH] Disable unsupported tests
---
crates/core_simd/src/elements/int.rs | 8 ++++++++
crates/core_simd/src/elements/uint.rs | 4 ++++
crates/core_simd/src/masks/full_masks.rs | 6 ++++++
crates/core_simd/src/vector.rs | 2 ++
crates/core_simd/tests/masks.rs | 3 ---
5 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs
index e8e8f68..7173c24 100644
--- a/crates/core_simd/src/vector.rs
+++ b/crates/core_simd/src/vector.rs
@@ -250,6 +250,7 @@ where
unsafe { intrinsics::simd_cast(self) }
}
+ /*
/// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
/// If an index is out-of-bounds, the lane is instead selected from the `or` vector.
///
@@ -473,6 +474,7 @@ where
// Cleared ☢️ *mut T Zone
}
}
+ */
}
impl<T, const LANES: usize> Copy for Simd<T, LANES>
--
2.25.1

View File

@ -18,7 +18,7 @@ new file mode 100644
index 0000000..46fd999
--- /dev/null
+++ b/library/core/tests/Cargo.toml
@@ -0,0 +1,11 @@
@@ -0,0 +1,12 @@
+[package]
+name = "core"
+version = "0.0.0"
@ -29,6 +29,7 @@ index 0000000..46fd999
+path = "lib.rs"
+
+[dependencies]
+rand = "0.7"
+rand = { version = "0.8.5", default-features = false }
+rand_xorshift = { version = "0.3.0", default-features = false }
--
2.21.0 (Apple Git-122)

View File

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2022-12-13"
channel = "nightly-2023-01-20"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View File

@ -26,7 +26,7 @@ fn main() {
env::set_var("RUSTDOCFLAGS", env::var("RUSTDOCFLAGS").unwrap_or(String::new()) + &rustflags);
// Ensure that the right toolchain is used
env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME"));
let args: Vec<_> = match env::args().nth(1).as_deref() {
Some("jit") => {

View File

@ -24,7 +24,7 @@ fn main() {
}
// Ensure that the right toolchain is used
env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME"));
#[cfg(unix)]
Command::new("rustc").args(args).exec();

View File

@ -24,7 +24,7 @@ fn main() {
}
// Ensure that the right toolchain is used
env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME"));
#[cfg(unix)]
Command::new("rustdoc").args(args).exec();

View File

@ -17,10 +17,10 @@ case $1 in
done
./clean_all.sh
./y.rs prepare
(cd build_sysroot && cargo update)
(cd download/sysroot && cargo update && cargo fetch && cp Cargo.lock ../../build_sysroot/)
;;
"commit")
git add rust-toolchain build_sysroot/Cargo.lock

View File

@ -10,7 +10,7 @@ git fetch
git checkout -- .
git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')"
git am ../patches/*-sysroot-*.patch
git -c user.name=Dummy -c user.email=dummy@example.com am ../patches/*-sysroot-*.patch
git apply - <<EOF
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
@ -25,8 +25,8 @@ index d95b5b7f17f..00b6f0e3635 100644
+compiler_builtins = { version = "0.1.66", features = ['rustc-dep-of-std', 'no-asm'] }
[dev-dependencies]
rand = "0.7"
rand_xorshift = "0.2"
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
rand_xorshift = "0.3.0"
EOF
cat > config.toml <<EOF
@ -51,7 +51,7 @@ popd
# FIXME remove once inline asm is fully supported
export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd build_sysroot/sysroot_src; pwd)"
export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd download/sysroot/sysroot_src; pwd)"
# Allow the testsuite to use llvm tools
host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")

View File

@ -11,7 +11,7 @@ pushd rust
command -v rg >/dev/null 2>&1 || cargo install ripgrep
rm -r tests/ui/{extern/,unsized-locals/,lto/,linkage*} || true
for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" tests/{ui,incremental}); do
for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" tests/{codegen-units,ui,incremental}); do
rm $test
done
@ -32,20 +32,13 @@ rm tests/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort
# requires compiling with -Cpanic=unwind
rm -r tests/ui/macros/rfc-2011-nicer-assert-messages/
rm -r tests/run-make/test-benches
rm tests/ui/test-attrs/test-type.rs
# vendor intrinsics
rm tests/ui/sse2.rs # cpuid not supported, so sse2 not detected
rm tests/ui/intrinsics/const-eval-select-x86_64.rs # requires x86_64 vendor intrinsics
rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant"
rm tests/ui/simd/intrinsic/generic-bitmask-pass.rs # simd_bitmask unimplemented
rm tests/ui/simd/intrinsic/generic-as.rs # simd_as unimplemented
rm tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs # simd_saturating_add unimplemented
rm tests/ui/simd/intrinsic/float-math-pass.rs # simd_fcos unimplemented
rm tests/ui/simd/intrinsic/generic-gather-pass.rs # simd_gather unimplemented
rm tests/ui/simd/intrinsic/generic-select-pass.rs # simd_select_bitmask unimplemented
rm tests/ui/simd/issue-85915-simd-ptrs.rs # simd_gather unimplemented
rm tests/ui/simd/issue-89193.rs # simd_gather unimplemented
rm tests/ui/simd/simd-bitmask.rs # simd_bitmask unimplemented
# exotic linkages
rm tests/ui/issues/issue-33992.rs # unsupported linkages
@ -64,10 +57,7 @@ rm tests/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and near
rm tests/ui/target-feature/missing-plusminus.rs # error not implemented
rm tests/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
rm -r tests/run-make/emit-named-files # requires full --emit support
rm tests/ui/abi/stack-probes.rs # stack probes not yet implemented
rm tests/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
rm -r tests/run-make/repr128-dwarf # debuginfo test
rm tests/codegen-units/item-collection/asm-sym.rs # requires support for sym in asm!()
# optimization tests
# ==================
@ -88,6 +78,20 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same
rm tests/ui/consts/issue-33537.rs # same
rm tests/ui/layout/valid_range_oob.rs # different ICE message
rm tests/ui/consts/issue-miri-1910.rs # different error message
rm tests/ui/consts/offset_ub.rs # same
rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same
rm tests/ui/lint/lint-const-item-mutation.rs # same
rm tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs # same
rm tests/ui/suggestions/derive-trait-for-method-call.rs # same
rm tests/ui/typeck/issue-46112.rs # same
rm tests/ui/proc-macro/crt-static.rs # extra warning about -Cpanic=abort for proc macros
rm tests/ui/proc-macro/proc-macro-deprecated-attr.rs # same
rm tests/ui/proc-macro/quote-debug.rs # same
rm tests/ui/proc-macro/no-missing-docs.rs # same
rm tests/ui/rust-2018/proc-macro-crate-in-paths.rs # same
# doesn't work due to the way the rustc test suite is invoked.
# should work when using ./x.py test the way it is intended
# ============================================================
@ -102,23 +106,20 @@ rm -r tests/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to b
# ============
rm tests/incremental/spike-neg1.rs # errors out for some reason
rm tests/incremental/spike-neg2.rs # same
rm tests/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs
rm tests/ui/mir/ssa-analysis-regression-50041.rs # produces ICE
rm tests/ui/type-alias-impl-trait/assoc-projection-ice.rs # produces ICE
rm tests/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
rm tests/ui/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301)
rm tests/ui/simd/intrinsic/generic-as.rs # crash when accessing vector type filed (#1318)
rm tests/ui/simd/simd-bitmask.rs # crash
rm tests/ui/dyn-star/dyn-star-to-dyn.rs
rm tests/ui/dyn-star/dispatch-on-pin-mut.rs
# bugs in the test suite
# ======================
rm tests/ui/backtrace.rs # TODO warning
rm tests/ui/simple_global_asm.rs # TODO add needs-asm-support
rm tests/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
# not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason
rm -r tests/run-make/native-link-modifier-bundle
rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
rm tests/ui/dyn-star/dispatch-on-pin-mut.rs # TODO failed assertion in vtable::get_ptr_and_method_ref
rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd

View File

@ -7,6 +7,7 @@ mod returning;
use cranelift_module::ModuleError;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_session::Session;
use rustc_target::abi::call::{Conv, FnAbi};
use rustc_target::spec::abi::Abi;
@ -22,7 +23,7 @@ fn clif_sig_from_fn_abi<'tcx>(
default_call_conv: CallConv,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> Signature {
let call_conv = conv_to_call_conv(fn_abi.conv, default_call_conv);
let call_conv = conv_to_call_conv(tcx.sess, fn_abi.conv, default_call_conv);
let inputs = fn_abi.args.iter().map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()).flatten();
@ -33,24 +34,32 @@ fn clif_sig_from_fn_abi<'tcx>(
Signature { params, returns, call_conv }
}
pub(crate) fn conv_to_call_conv(c: Conv, default_call_conv: CallConv) -> CallConv {
pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: CallConv) -> CallConv {
match c {
Conv::Rust | Conv::C => default_call_conv,
Conv::RustCold => CallConv::Cold,
Conv::X86_64SysV => CallConv::SystemV,
Conv::X86_64Win64 => CallConv::WindowsFastcall,
Conv::ArmAapcs
| Conv::CCmseNonSecureCall
| Conv::Msp430Intr
// Should already get a back compat warning
Conv::X86Fastcall | Conv::X86Stdcall | Conv::X86ThisCall | Conv::X86VectorCall => {
default_call_conv
}
Conv::X86Intr => sess.fatal("x86-interrupt call conv not yet implemented"),
Conv::ArmAapcs => sess.fatal("aapcs call conv not yet implemented"),
Conv::CCmseNonSecureCall => {
sess.fatal("C-cmse-nonsecure-call call conv is not yet implemented");
}
Conv::Msp430Intr
| Conv::PtxKernel
| Conv::X86Fastcall
| Conv::X86Intr
| Conv::X86Stdcall
| Conv::X86ThisCall
| Conv::X86VectorCall
| Conv::AmdGpuKernel
| Conv::AvrInterrupt
| Conv::AvrNonBlockingInterrupt => todo!("{:?}", c),
| Conv::AvrNonBlockingInterrupt => {
unreachable!("tried to use {c:?} call conv which only exists on an unsupported target");
}
}
}
@ -161,6 +170,12 @@ fn make_local_place<'tcx>(
layout: TyAndLayout<'tcx>,
is_ssa: bool,
) -> CPlace<'tcx> {
if layout.is_unsized() {
fx.tcx.sess.span_fatal(
fx.mir.local_decls[local].source_info.span,
"unsized locals are not yet supported",
);
}
let place = if is_ssa {
if let rustc_target::abi::Abi::ScalarPair(_, _) = layout.abi {
CPlace::new_var_pair(fx, local, layout)

View File

@ -113,6 +113,8 @@ pub(crate) fn codegen_fn<'tcx>(
};
tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block));
fx.bcx.seal_all_blocks();
fx.bcx.finalize();
// Recover all necessary data from fx, before accessing func will prevent future access to it.
let symbol_name = fx.symbol_name;
@ -303,6 +305,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
let source_info = bb_data.terminator().source_info;
fx.set_debug_loc(source_info);
let _print_guard =
crate::PrintOnPanic(|| format!("terminator {:?}", bb_data.terminator().kind));
match &bb_data.terminator().kind {
TerminatorKind::Goto { target } => {
if let TerminatorKind::Return = fx.mir[*target].terminator().kind {
@ -464,7 +469,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
*destination,
);
}
TerminatorKind::Resume | TerminatorKind::Abort => {
TerminatorKind::Abort => {
codegen_panic_cannot_unwind(fx, source_info);
}
TerminatorKind::Resume => {
// FIXME implement unwinding
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
@ -487,9 +495,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
}
};
}
fx.bcx.seal_all_blocks();
fx.bcx.finalize();
}
fn codegen_stmt<'tcx>(
@ -932,7 +937,28 @@ pub(crate) fn codegen_panic<'tcx>(
codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, source_info.span);
}
pub(crate) fn codegen_panic_inner<'tcx>(
pub(crate) fn codegen_panic_nounwind<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
msg_str: &str,
source_info: mir::SourceInfo,
) {
let msg_ptr = fx.anonymous_str(msg_str);
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
let args = [msg_ptr, msg_len];
codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span);
}
pub(crate) fn codegen_panic_cannot_unwind<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
source_info: mir::SourceInfo,
) {
let args = [];
codegen_panic_inner(fx, rustc_hir::LangItem::PanicCannotUnwind, &args, source_info.span);
}
fn codegen_panic_inner<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
lang_item: rustc_hir::LangItem,
args: &[Value],
@ -949,11 +975,7 @@ pub(crate) fn codegen_panic_inner<'tcx>(
fx.lib_call(
&*symbol_name,
vec![
AbiParam::new(fx.pointer_type),
AbiParam::new(fx.pointer_type),
AbiParam::new(fx.pointer_type),
],
args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(),
vec![],
args,
);

View File

@ -168,6 +168,15 @@ pub(crate) fn codegen_icmp_imm(
}
}
pub(crate) fn codegen_bitcast(fx: &mut FunctionCx<'_, '_, '_>, dst_ty: Type, val: Value) -> Value {
let mut flags = MemFlags::new();
flags.set_endianness(match fx.tcx.data_layout.endian {
rustc_target::abi::Endian::Big => cranelift_codegen::ir::Endianness::Big,
rustc_target::abi::Endian::Little => cranelift_codegen::ir::Endianness::Little,
});
fx.bcx.ins().bitcast(dst_ty, flags, val)
}
pub(crate) fn type_zero_value(bcx: &mut FunctionBuilder<'_>, ty: Type) -> Value {
if ty == types::I128 {
let zero = bcx.ins().iconst(types::I64, 0);

248
src/cranelift_native.rs Normal file
View File

@ -0,0 +1,248 @@
// Vendored from https://github.com/bytecodealliance/wasmtime/blob/b58a197d33f044193c3d608010f5e6ec394ac07e/cranelift/native/src/lib.rs
// which is licensed as
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// unlike rustc_codegen_cranelift itself. Also applies a small change to remove #![cfg_attr] that
// rust's CI complains about and to fix formatting to match rustc.
// FIXME revert back to the external crate with Cranelift 0.93
#![allow(warnings)]
//! Performs autodetection of the host for the purposes of running
//! Cranelift to generate code to run on the same machine.
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates, unstable_features)]
#![warn(unused_import_braces)]
use cranelift_codegen::isa;
use target_lexicon::Triple;
/// Return an `isa` builder configured for the current host
/// machine, or `Err(())` if the host machine is not supported
/// in the current configuration.
pub fn builder() -> Result<isa::Builder, &'static str> {
builder_with_options(true)
}
/// Return an `isa` builder configured for the current host
/// machine, or `Err(())` if the host machine is not supported
/// in the current configuration.
///
/// Selects the given backend variant specifically; this is
/// useful when more than oen backend exists for a given target
/// (e.g., on x86-64).
pub fn builder_with_options(infer_native_flags: bool) -> Result<isa::Builder, &'static str> {
let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err {
isa::LookupError::SupportDisabled => "support for architecture disabled at compile time",
isa::LookupError::Unsupported => "unsupported architecture",
})?;
#[cfg(target_arch = "x86_64")]
{
use cranelift_codegen::settings::Configurable;
if !std::is_x86_feature_detected!("sse2") {
return Err("x86 support requires SSE2");
}
if !infer_native_flags {
return Ok(isa_builder);
}
// These are temporarily enabled by default (see #3810 for
// more) so that a default-constructed `Flags` can work with
// default Wasmtime features. Otherwise, the user must
// explicitly use native flags or turn these on when on x86-64
// platforms to avoid a configuration panic. In order for the
// "enable if detected" logic below to work, we must turn them
// *off* (differing from the default) and then re-enable below
// if present.
isa_builder.set("has_sse3", "false").unwrap();
isa_builder.set("has_ssse3", "false").unwrap();
isa_builder.set("has_sse41", "false").unwrap();
isa_builder.set("has_sse42", "false").unwrap();
if std::is_x86_feature_detected!("sse3") {
isa_builder.enable("has_sse3").unwrap();
}
if std::is_x86_feature_detected!("ssse3") {
isa_builder.enable("has_ssse3").unwrap();
}
if std::is_x86_feature_detected!("sse4.1") {
isa_builder.enable("has_sse41").unwrap();
}
if std::is_x86_feature_detected!("sse4.2") {
isa_builder.enable("has_sse42").unwrap();
}
if std::is_x86_feature_detected!("popcnt") {
isa_builder.enable("has_popcnt").unwrap();
}
if std::is_x86_feature_detected!("avx") {
isa_builder.enable("has_avx").unwrap();
}
if std::is_x86_feature_detected!("avx2") {
isa_builder.enable("has_avx2").unwrap();
}
if std::is_x86_feature_detected!("fma") {
isa_builder.enable("has_fma").unwrap();
}
if std::is_x86_feature_detected!("bmi1") {
isa_builder.enable("has_bmi1").unwrap();
}
if std::is_x86_feature_detected!("bmi2") {
isa_builder.enable("has_bmi2").unwrap();
}
if std::is_x86_feature_detected!("avx512bitalg") {
isa_builder.enable("has_avx512bitalg").unwrap();
}
if std::is_x86_feature_detected!("avx512dq") {
isa_builder.enable("has_avx512dq").unwrap();
}
if std::is_x86_feature_detected!("avx512f") {
isa_builder.enable("has_avx512f").unwrap();
}
if std::is_x86_feature_detected!("avx512vl") {
isa_builder.enable("has_avx512vl").unwrap();
}
if std::is_x86_feature_detected!("avx512vbmi") {
isa_builder.enable("has_avx512vbmi").unwrap();
}
if std::is_x86_feature_detected!("lzcnt") {
isa_builder.enable("has_lzcnt").unwrap();
}
}
#[cfg(target_arch = "aarch64")]
{
use cranelift_codegen::settings::Configurable;
if !infer_native_flags {
return Ok(isa_builder);
}
if std::arch::is_aarch64_feature_detected!("lse") {
isa_builder.enable("has_lse").unwrap();
}
if std::arch::is_aarch64_feature_detected!("paca") {
isa_builder.enable("has_pauth").unwrap();
}
if cfg!(target_os = "macos") {
// Pointer authentication is always available on Apple Silicon.
isa_builder.enable("sign_return_address").unwrap();
// macOS enforces the use of the B key for return addresses.
isa_builder.enable("sign_return_address_with_bkey").unwrap();
}
}
// There is no is_s390x_feature_detected macro yet, so for now
// we use getauxval from the libc crate directly.
#[cfg(all(target_arch = "s390x", target_os = "linux"))]
{
use cranelift_codegen::settings::Configurable;
if !infer_native_flags {
return Ok(isa_builder);
}
let v = unsafe { libc::getauxval(libc::AT_HWCAP) };
const HWCAP_S390X_VXRS_EXT2: libc::c_ulong = 32768;
if (v & HWCAP_S390X_VXRS_EXT2) != 0 {
isa_builder.enable("has_vxrs_ext2").unwrap();
// There is no separate HWCAP bit for mie2, so assume
// that any machine with vxrs_ext2 also has mie2.
isa_builder.enable("has_mie2").unwrap();
}
}
// `is_riscv_feature_detected` is nightly only for now, use
// getauxval from the libc crate directly as a temporary measure.
#[cfg(all(target_arch = "riscv64", target_os = "linux"))]
{
use cranelift_codegen::settings::Configurable;
if !infer_native_flags {
return Ok(isa_builder);
}
let v = unsafe { libc::getauxval(libc::AT_HWCAP) };
const HWCAP_RISCV_EXT_A: libc::c_ulong = 1 << (b'a' - b'a');
const HWCAP_RISCV_EXT_C: libc::c_ulong = 1 << (b'c' - b'a');
const HWCAP_RISCV_EXT_D: libc::c_ulong = 1 << (b'd' - b'a');
const HWCAP_RISCV_EXT_F: libc::c_ulong = 1 << (b'f' - b'a');
const HWCAP_RISCV_EXT_M: libc::c_ulong = 1 << (b'm' - b'a');
const HWCAP_RISCV_EXT_V: libc::c_ulong = 1 << (b'v' - b'a');
if (v & HWCAP_RISCV_EXT_A) != 0 {
isa_builder.enable("has_a").unwrap();
}
if (v & HWCAP_RISCV_EXT_C) != 0 {
isa_builder.enable("has_c").unwrap();
}
if (v & HWCAP_RISCV_EXT_D) != 0 {
isa_builder.enable("has_d").unwrap();
}
if (v & HWCAP_RISCV_EXT_F) != 0 {
isa_builder.enable("has_f").unwrap();
// TODO: There doesn't seem to be a bit associated with this extension
// rust enables it with the `f` extension:
// https://github.com/rust-lang/stdarch/blob/790411f93c4b5eada3c23abb4c9a063fb0b24d99/crates/std_detect/src/detect/os/linux/riscv.rs#L43
isa_builder.enable("has_zicsr").unwrap();
}
if (v & HWCAP_RISCV_EXT_M) != 0 {
isa_builder.enable("has_m").unwrap();
}
if (v & HWCAP_RISCV_EXT_V) != 0 {
isa_builder.enable("has_v").unwrap();
}
// TODO: ZiFencei does not have a bit associated with it
// TODO: Zbkb does not have a bit associated with it
}
// squelch warnings about unused mut/variables on some platforms.
drop(&mut isa_builder);
drop(infer_native_flags);
Ok(isa_builder)
}
#[cfg(test)]
mod tests {
use super::builder;
use cranelift_codegen::isa::CallConv;
use cranelift_codegen::settings;
#[test]
fn test() {
if let Ok(isa_builder) = builder() {
let flag_builder = settings::builder();
let isa = isa_builder.finish(settings::Flags::new(flag_builder)).unwrap();
if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
assert_eq!(isa.default_call_conv(), CallConv::AppleAarch64);
} else if cfg!(any(unix, target_os = "nebulet")) {
assert_eq!(isa.default_call_conv(), CallConv::SystemV);
} else if cfg!(windows) {
assert_eq!(isa.default_call_conv(), CallConv::WindowsFastcall);
}
if cfg!(target_pointer_width = "64") {
assert_eq!(isa.pointer_bits(), 64);
} else if cfg!(target_pointer_width = "32") {
assert_eq!(isa.pointer_bits(), 32);
} else if cfg!(target_pointer_width = "16") {
assert_eq!(isa.pointer_bits(), 16);
}
}
}
}
/// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

View File

@ -20,6 +20,14 @@ use indexmap::IndexSet;
pub(crate) use emit::{DebugReloc, DebugRelocName};
pub(crate) use unwind::UnwindContext;
pub(crate) fn producer() -> String {
format!(
"cg_clif (rustc {}, cranelift {})",
rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
cranelift_codegen::VERSION,
)
}
pub(crate) struct DebugContext {
endian: RunTimeEndian,
@ -57,11 +65,7 @@ impl DebugContext {
let mut dwarf = DwarfUnit::new(encoding);
let producer = format!(
"cg_clif (rustc {}, cranelift {})",
rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
cranelift_codegen::VERSION,
);
let producer = producer();
let comp_dir = tcx
.sess
.opts

View File

@ -108,6 +108,8 @@ impl OngoingCodegen {
self.concurrency_limiter.finished();
sess.abort_if_errors();
(
CodegenResults {
modules,
@ -169,10 +171,22 @@ fn emit_cgu(
fn emit_module(
output_filenames: &OutputFilenames,
prof: &SelfProfilerRef,
object: cranelift_object::object::write::Object<'_>,
mut object: cranelift_object::object::write::Object<'_>,
kind: ModuleKind,
name: String,
) -> Result<CompiledModule, String> {
if object.format() == cranelift_object::object::BinaryFormat::Elf {
let comment_section = object.add_section(
Vec::new(),
b".comment".to_vec(),
cranelift_object::object::SectionKind::OtherString,
);
let mut producer = vec![0];
producer.extend(crate::debuginfo::producer().as_bytes());
producer.push(0);
object.set_section_data(comment_section, producer, 1);
}
let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name));
let mut file = match File::create(&tmp_file) {
Ok(file) => file,
@ -399,8 +413,6 @@ pub(crate) fn run_aot(
.collect::<Vec<_>>()
});
tcx.sess.abort_if_errors();
let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string());
let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true);
let created_alloc_shim =

View File

@ -33,8 +33,8 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
// cast float to int
let a_lane = match lane_ty {
types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
types::F32 => codegen_bitcast(fx, types::I32, a_lane),
types::F64 => codegen_bitcast(fx, types::I64, a_lane),
_ => a_lane,
};

View File

@ -201,7 +201,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
let mut res = fx.bcx.ins().bmask(int_ty, val);
if ty.is_float() {
res = fx.bcx.ins().bitcast(ty, res);
res = codegen_bitcast(fx, ty, res);
}
res
@ -241,10 +241,9 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
substs,
args,
destination,
target,
source_info.span,
);
let ret_block = fx.get_block(target);
fx.bcx.ins().jump(ret_block, &[]);
} else if codegen_float_intrinsic_call(fx, intrinsic, args, destination) {
let ret_block = fx.get_block(target);
fx.bcx.ins().jump(ret_block, &[]);
@ -651,7 +650,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
let layout = fx.layout_of(substs.type_at(0));
if layout.abi.is_uninhabited() {
with_no_trimmed_paths!({
crate::base::codegen_panic(
crate::base::codegen_panic_nounwind(
fx,
&format!("attempted to instantiate uninhabited type `{}`", layout.ty),
source_info,
@ -664,7 +663,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
&& !fx.tcx.permits_zero_init(fx.param_env().and(layout))
{
with_no_trimmed_paths!({
crate::base::codegen_panic(
crate::base::codegen_panic_nounwind(
fx,
&format!(
"attempted to zero-initialize type `{}`, which is invalid",
@ -680,7 +679,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
&& !fx.tcx.permits_uninit_init(fx.param_env().and(layout))
{
with_no_trimmed_paths!({
crate::base::codegen_panic(
crate::base::codegen_panic_nounwind(
fx,
&format!(
"attempted to leave type `{}` uninitialized, which is invalid",

View File

@ -24,6 +24,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
_substs: SubstsRef<'tcx>,
args: &[mir::Operand<'tcx>],
ret: CPlace<'tcx>,
target: BasicBlock,
span: Span,
) {
match intrinsic {
@ -277,16 +278,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
} else {
fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant");
let trap_block = fx.bcx.create_block();
let dummy_block = fx.bcx.create_block();
let true_ = fx.bcx.ins().iconst(types::I8, 1);
fx.bcx.ins().brnz(true_, trap_block, &[]);
fx.bcx.ins().jump(dummy_block, &[]);
let ret_block = fx.get_block(target);
fx.bcx.ins().jump(ret_block, &[]);
fx.bcx.switch_to_block(trap_block);
crate::trap::trap_unimplemented(
fx,
"Index argument for `simd_extract` is not a constant",
);
fx.bcx.switch_to_block(dummy_block);
return;
};
@ -770,11 +770,119 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
});
}
// simd_arith_offset
// simd_scatter
// simd_gather
sym::simd_expose_addr | sym::simd_from_exposed_addr | sym::simd_cast_ptr => {
intrinsic_args!(fx, args => (arg); intrinsic);
ret.write_cvalue_transmute(fx, arg);
}
sym::simd_arith_offset => {
intrinsic_args!(fx, args => (ptr, offset); intrinsic);
let (lane_count, ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap().ty;
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
let ret_lane_layout = fx.layout_of(ret_lane_ty);
assert_eq!(lane_count, ret_lane_count);
for lane_idx in 0..lane_count {
let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx);
let offset_lane = offset.value_lane(fx, lane_idx).load_scalar(fx);
let ptr_diff = if pointee_size != 1 {
fx.bcx.ins().imul_imm(offset_lane, pointee_size as i64)
} else {
offset_lane
};
let res_lane = fx.bcx.ins().iadd(ptr_lane, ptr_diff);
let res_lane = CValue::by_val(res_lane, ret_lane_layout);
ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane);
}
}
sym::simd_gather => {
intrinsic_args!(fx, args => (val, ptr, mask); intrinsic);
let (val_lane_count, val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
let (mask_lane_count, _mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx);
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
assert_eq!(val_lane_count, ptr_lane_count);
assert_eq!(val_lane_count, mask_lane_count);
assert_eq!(val_lane_count, ret_lane_count);
let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap();
let ret_lane_layout = fx.layout_of(ret_lane_ty);
for lane_idx in 0..ptr_lane_count {
let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx);
let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
let if_enabled = fx.bcx.create_block();
let if_disabled = fx.bcx.create_block();
let next = fx.bcx.create_block();
let res_lane = fx.bcx.append_block_param(next, lane_clif_ty);
fx.bcx.ins().brnz(mask_lane, if_enabled, &[]);
fx.bcx.ins().jump(if_disabled, &[]);
fx.bcx.seal_block(if_enabled);
fx.bcx.seal_block(if_disabled);
fx.bcx.switch_to_block(if_enabled);
let res = fx.bcx.ins().load(lane_clif_ty, MemFlags::trusted(), ptr_lane, 0);
fx.bcx.ins().jump(next, &[res]);
fx.bcx.switch_to_block(if_disabled);
fx.bcx.ins().jump(next, &[val_lane]);
fx.bcx.seal_block(next);
fx.bcx.switch_to_block(next);
fx.bcx.ins().nop();
ret.place_lane(fx, lane_idx)
.write_cvalue(fx, CValue::by_val(res_lane, ret_lane_layout));
}
}
sym::simd_scatter => {
intrinsic_args!(fx, args => (val, ptr, mask); intrinsic);
let (val_lane_count, _val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
let (mask_lane_count, _mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx);
assert_eq!(val_lane_count, ptr_lane_count);
assert_eq!(val_lane_count, mask_lane_count);
for lane_idx in 0..ptr_lane_count {
let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx);
let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
let if_enabled = fx.bcx.create_block();
let next = fx.bcx.create_block();
fx.bcx.ins().brnz(mask_lane, if_enabled, &[]);
fx.bcx.ins().jump(next, &[]);
fx.bcx.seal_block(if_enabled);
fx.bcx.switch_to_block(if_enabled);
fx.bcx.ins().store(MemFlags::trusted(), val_lane, ptr_lane, 0);
fx.bcx.ins().jump(next, &[]);
fx.bcx.seal_block(next);
fx.bcx.switch_to_block(next);
}
}
_ => {
fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic));
fx.tcx.sess.span_err(span, &format!("Unknown SIMD intrinsic {}", intrinsic));
// Prevent verifier error
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
}
let ret_block = fx.get_block(target);
fx.bcx.ins().jump(ret_block, &[]);
}

View File

@ -57,6 +57,8 @@ mod compiler_builtins;
mod concurrency_limiter;
mod config;
mod constant;
// FIXME revert back to the external crate with Cranelift 0.93
mod cranelift_native;
mod debuginfo;
mod discriminant;
mod driver;
@ -278,12 +280,14 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
}
}
if target_triple.architecture == target_lexicon::Architecture::X86_64 {
if let target_lexicon::Architecture::Aarch64(_) | target_lexicon::Architecture::X86_64 =
target_triple.architecture
{
// Windows depends on stack probes to grow the committed part of the stack
flags_builder.enable("enable_probestack").unwrap();
flags_builder.set("probestack_strategy", "inline").unwrap();
} else {
// __cranelift_probestack is not provided and inline stack probes are only supported on x86_64
// __cranelift_probestack is not provided and inline stack probes are only supported on AArch64 and x86_64
flags_builder.set("enable_probestack", "false").unwrap();
}

View File

@ -64,13 +64,20 @@ pub(crate) fn maybe_create_entry_wrapper(
],
returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
call_conv: crate::conv_to_call_conv(
tcx.sess,
tcx.sess.target.options.entry_abi,
m.target_config().default_call_conv,
),
};
let entry_name = tcx.sess.target.options.entry_name.as_ref();
let cmain_func_id = m.declare_function(entry_name, Linkage::Export, &cmain_sig).unwrap();
let cmain_func_id = match m.declare_function(entry_name, Linkage::Export, &cmain_sig) {
Ok(func_id) => func_id,
Err(err) => {
tcx.sess
.fatal(&format!("entry symbol `{entry_name}` declared multiple times: {err}"));
}
};
let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
@ -162,7 +169,11 @@ pub(crate) fn maybe_create_entry_wrapper(
bcx.seal_all_blocks();
bcx.finalize();
}
m.define_function(cmain_func_id, &mut ctx).unwrap();
if let Err(err) = m.define_function(cmain_func_id, &mut ctx) {
tcx.sess.fatal(&format!("entry symbol `{entry_name}` defined multiple times: {err}"));
}
unwind_context.add_function(cmain_func_id, &ctx, m.isa());
}
}

View File

@ -7,7 +7,7 @@ use cranelift_frontend::FunctionBuilder;
/// otherwise return the given value and false.
pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) {
if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
match bcx.func.dfg[arg_inst] {
match bcx.func.dfg.insts[arg_inst] {
// This is the lowering of `Rvalue::Not`
InstructionData::IntCompareImm {
opcode: Opcode::IcmpImm,
@ -34,7 +34,7 @@ pub(crate) fn maybe_known_branch_taken(
return None;
};
match bcx.func.dfg[arg_inst] {
match bcx.func.dfg.insts[arg_inst] {
InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
if test_zero {
Some(imm.bits() == 0)

View File

@ -514,8 +514,8 @@ impl<'tcx> CPlace<'tcx> {
(types::I32, types::F32)
| (types::F32, types::I32)
| (types::I64, types::F64)
| (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data),
_ if src_ty.is_vector() && dst_ty.is_vector() => fx.bcx.ins().bitcast(dst_ty, data),
| (types::F64, types::I64) => codegen_bitcast(fx, dst_ty, data),
_ if src_ty.is_vector() && dst_ty.is_vector() => codegen_bitcast(fx, dst_ty, data),
_ if src_ty.is_vector() || dst_ty.is_vector() => {
// FIXME do something more efficient for transmutes between vectors and integers.
let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {

2
y.rs
View File

@ -3,7 +3,7 @@
# This block is ignored by rustc
set -e
echo "[BUILD] y.rs" 1>&2
rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021
rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021 -Cpanic=abort
exec ${0/.rs/.bin} $@
*/