Merge commit '2bb3996244cf1b89878da9e39841e9f6bf061602' into sync_cg_clif-2022-12-14

This commit is contained in:
bjorn3 2022-12-14 19:30:46 +01:00
parent f7c76ad662
commit 98a276b589
53 changed files with 1675 additions and 1012 deletions

View File

@ -12,8 +12,6 @@ task:
folder: target folder: target
prepare_script: prepare_script:
- . $HOME/.cargo/env - . $HOME/.cargo/env
- git config --global user.email "user@example.com"
- git config --global user.name "User"
- ./y.rs prepare - ./y.rs prepare
test_script: test_script:
- . $HOME/.cargo/env - . $HOME/.cargo/env

View File

@ -19,6 +19,7 @@ jobs:
- name: Rustfmt - name: Rustfmt
run: | run: |
cargo fmt --check cargo fmt --check
rustfmt --check build_system/mod.rs
build: build:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -28,7 +29,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: ubuntu-latest - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed
env: env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu TARGET_TRIPLE: x86_64-unknown-linux-gnu
- os: macos-latest - os: macos-latest
@ -41,18 +42,22 @@ jobs:
- os: ubuntu-latest - os: ubuntu-latest
env: env:
TARGET_TRIPLE: aarch64-unknown-linux-gnu TARGET_TRIPLE: aarch64-unknown-linux-gnu
# s390x requires QEMU 6.1 or greater, we could build it from source, but ubuntu 22.04 comes with 6.2 by default
- os: ubuntu-latest
env:
TARGET_TRIPLE: s390x-unknown-linux-gnu
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Cache cargo installed crates - name: Cache cargo installed crates
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: ~/.cargo/bin path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index - name: Cache cargo registry and index
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@ -60,9 +65,9 @@ jobs:
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir - name: Cache cargo target dir
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: target path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Install MinGW toolchain and wine - name: Install MinGW toolchain and wine
@ -78,11 +83,14 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user
- name: Prepare dependencies - name: Install s390x toolchain and qemu
if: matrix.env.TARGET_TRIPLE == 's390x-unknown-linux-gnu'
run: | run: |
git config --global user.email "user@example.com" sudo apt-get update
git config --global user.name "User" sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
./y.rs prepare
- name: Prepare dependencies
run: ./y.rs prepare
- name: Build without unstable features - name: Build without unstable features
env: env:
@ -110,7 +118,7 @@ jobs:
./y.rs test ./y.rs test
- name: Package prebuilt cg_clif - name: Package prebuilt cg_clif
run: tar cvfJ cg_clif.tar.xz build run: tar cvfJ cg_clif.tar.xz dist
- name: Upload prebuilt cg_clif - name: Upload prebuilt cg_clif
if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
@ -121,7 +129,7 @@ jobs:
- name: Upload prebuilt cg_clif (cross compile) - name: Upload prebuilt cg_clif (cross compile)
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
path: cg_clif.tar.xz path: cg_clif.tar.xz
@ -147,13 +155,13 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Cache cargo installed crates - name: Cache cargo installed crates
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: ~/.cargo/bin path: ~/.cargo/bin
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
- name: Cache cargo registry and index - name: Cache cargo registry and index
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@ -161,9 +169,9 @@ jobs:
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir - name: Cache cargo target dir
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: target path: build/cg_clif
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-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 - name: Set MinGW as the default toolchain
@ -172,8 +180,6 @@ jobs:
- name: Prepare dependencies - name: Prepare dependencies
run: | run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
git config --global core.autocrlf false git config --global core.autocrlf false
rustc y.rs -o y.exe -g rustc y.rs -o y.exe -g
./y.exe prepare ./y.exe prepare
@ -212,10 +218,10 @@ jobs:
- name: Package prebuilt cg_clif - name: Package prebuilt cg_clif
# don't use compression as xzip isn't supported by tar on windows and bzip2 hangs # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
run: tar cvf cg_clif.tar build run: tar cvf cg_clif.tar dist
- name: Upload prebuilt cg_clif - name: Upload prebuilt cg_clif
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: cg_clif-${{ matrix.env.TARGET_TRIPLE }} name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
path: cg_clif.tar path: cg_clif.tar

View File

@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Cache cargo installed crates - name: Cache cargo installed crates
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: ~/.cargo/bin path: ~/.cargo/bin
key: ubuntu-latest-cargo-installed-crates key: ubuntu-latest-cargo-installed-crates

View File

@ -11,13 +11,13 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Cache cargo installed crates - name: Cache cargo installed crates
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: ~/.cargo/bin path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index - name: Cache cargo registry and index
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@ -25,9 +25,9 @@ jobs:
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir - name: Cache cargo target dir
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: target path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies - name: Prepare dependencies
@ -49,13 +49,13 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Cache cargo installed crates - name: Cache cargo installed crates
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: ~/.cargo/bin path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index - name: Cache cargo registry and index
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@ -63,9 +63,9 @@ jobs:
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir - name: Cache cargo target dir
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: target path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies - name: Prepare dependencies

1
.gitignore vendored
View File

@ -14,5 +14,6 @@ perf.data.old
/build_sysroot/sysroot_src /build_sysroot/sysroot_src
/build_sysroot/compiler-builtins /build_sysroot/compiler-builtins
/build_sysroot/rustc_version /build_sysroot/rustc_version
/dist
/rust /rust
/download /download

35
.vscode/settings.json vendored
View File

@ -4,16 +4,10 @@
"rust-analyzer.imports.granularity.enforce": true, "rust-analyzer.imports.granularity.enforce": true,
"rust-analyzer.imports.granularity.group": "module", "rust-analyzer.imports.granularity.group": "module",
"rust-analyzer.imports.prefix": "crate", "rust-analyzer.imports.prefix": "crate",
"rust-analyzer.cargo.features": ["unstable-features"], "rust-analyzer.cargo.features": ["unstable-features", "__check_build_system_using_ra"],
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
"./Cargo.toml", "./Cargo.toml",
//"./build_sysroot/sysroot_src/library/std/Cargo.toml",
{ {
"roots": [
"./example/mini_core.rs",
"./example/mini_core_hello_world.rs",
"./example/mod_bench.rs"
],
"crates": [ "crates": [
{ {
"root_module": "./example/mini_core.rs", "root_module": "./example/mini_core.rs",
@ -36,34 +30,11 @@
] ]
}, },
{ {
"roots": ["./example/std_example.rs"], "sysroot_src": "./build_sysroot/sysroot_src/library",
"crates": [ "crates": [
{ {
"root_module": "./example/std_example.rs", "root_module": "./example/std_example.rs",
"edition": "2018", "edition": "2015",
"deps": [{ "crate": 1, "name": "std" }],
"cfg": [],
},
{
"root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
"edition": "2018",
"deps": [],
"cfg": [],
},
]
},
{
"roots": ["./y.rs"],
"crates": [
{
"root_module": "./y.rs",
"edition": "2018",
"deps": [{ "crate": 1, "name": "std" }],
"cfg": [],
},
{
"root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
"edition": "2018",
"deps": [], "deps": [],
"cfg": [], "cfg": [],
}, },

125
Cargo.lock generated
View File

@ -15,9 +15,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.60" version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142" checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
@ -39,9 +39,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.11.0" version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -57,24 +57,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "cranelift-bforest" name = "cranelift-bforest"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a" checksum = "b62c772976416112fa4484cbd688cb6fb35fd430005c1c586224fc014018abad"
dependencies = [ dependencies = [
"cranelift-entity", "cranelift-entity",
] ]
[[package]] [[package]]
name = "cranelift-codegen" name = "cranelift-codegen"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf" checksum = "9b40ed2dd13c2ac7e24f88a3090c68ad3414eb1d066a95f8f1f7b3b819cb4e46"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bumpalo", "bumpalo",
"cranelift-bforest", "cranelift-bforest",
"cranelift-codegen-meta", "cranelift-codegen-meta",
"cranelift-codegen-shared", "cranelift-codegen-shared",
"cranelift-egraph",
"cranelift-entity", "cranelift-entity",
"cranelift-isle", "cranelift-isle",
"gimli", "gimli",
@ -86,30 +87,44 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-meta" name = "cranelift-codegen-meta"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5" checksum = "bb927a8f1c27c34ee3759b6b0ffa528d2330405d5cc4511f0cab33fe2279f4b5"
dependencies = [ dependencies = [
"cranelift-codegen-shared", "cranelift-codegen-shared",
] ]
[[package]] [[package]]
name = "cranelift-codegen-shared" name = "cranelift-codegen-shared"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e" 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",
]
[[package]] [[package]]
name = "cranelift-entity" name = "cranelift-entity"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103" checksum = "0637ffde963cb5d759bc4d454cfa364b6509e6c74cdaa21298add0ed9276f346"
[[package]] [[package]]
name = "cranelift-frontend" name = "cranelift-frontend"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc" checksum = "fb72b8342685e850cb037350418f62cc4fc55d6c2eb9c7ca01b82f9f1a6f3d56"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"log", "log",
@ -119,15 +134,15 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-isle" name = "cranelift-isle"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293" checksum = "850579cb9e4b448f7c301f1e6e6cbad99abe3f1f1d878a4994cb66e33c6db8cd"
[[package]] [[package]]
name = "cranelift-jit" name = "cranelift-jit"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015" checksum = "9add822ad66dcbe152b5ab57de10240a2df4505099f2f6c27159acb711890bd4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -138,14 +153,15 @@ dependencies = [
"log", "log",
"region", "region",
"target-lexicon", "target-lexicon",
"wasmtime-jit-icache-coherence",
"windows-sys", "windows-sys",
] ]
[[package]] [[package]]
name = "cranelift-module" name = "cranelift-module"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49" checksum = "406b772626fc2664864cf947f3895a23b619895c7fff635f3622e2d857f4492f"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -153,9 +169,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-native" name = "cranelift-native"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4" checksum = "2d0a279e5bcba3e0466c734d8d8eb6bfc1ad29e95c37f3e4955b492b5616335e"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"libc", "libc",
@ -164,9 +180,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-object" name = "cranelift-object"
version = "0.88.1" version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b" checksum = "39793c550f0c1d7db96c2fc1324583670c8143befe6edbfbaf1c68aba53be983"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -185,6 +201,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]] [[package]]
name = "fxhash" name = "fxhash"
version = "0.2.1" version = "0.2.1"
@ -196,9 +218,9 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.7" version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
@ -211,7 +233,9 @@ version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [ dependencies = [
"fallible-iterator",
"indexmap", "indexmap",
"stable_deref_trait",
] ]
[[package]] [[package]]
@ -225,9 +249,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.1" version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown", "hashbrown",
@ -235,15 +259,15 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.127" version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]] [[package]]
name = "libloading" name = "libloading"
version = "0.7.3" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"winapi", "winapi",
@ -287,15 +311,15 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.13.0" version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]] [[package]]
name = "regalloc2" name = "regalloc2"
version = "0.3.2" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779" checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5"
dependencies = [ dependencies = [
"fxhash", "fxhash",
"log", "log",
@ -342,15 +366,21 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.12.4" version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
[[package]] [[package]]
name = "version_check" name = "version_check"
@ -364,6 +394,17 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6bbabb309c06cc238ee91b1455b748c45f0bdcab0dda2c2db85b0a1e69fcb66"
dependencies = [
"cfg-if",
"libc",
"windows-sys",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@ -3,17 +3,24 @@ name = "rustc_codegen_cranelift"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[[bin]]
# This is used just to teach rust-analyzer how to check the build system. required-features is used
# to disable it for regular builds.
name = "y"
path = "./y.rs"
required-features = ["__check_build_system_using_ra"]
[lib] [lib]
crate-type = ["dylib"] crate-type = ["dylib"]
[dependencies] [dependencies]
# These have to be in sync with each other # These have to be in sync with each other
cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] } cranelift-codegen = { version = "0.90.1", features = ["unwind", "all-arch"] }
cranelift-frontend = "0.88.1" cranelift-frontend = "0.90.1"
cranelift-module = "0.88.1" cranelift-module = "0.90.1"
cranelift-native = "0.88.1" cranelift-native = "0.90.1"
cranelift-jit = { version = "0.88.1", optional = true } cranelift-jit = { version = "0.90.1", optional = true }
cranelift-object = "0.88.1" cranelift-object = "0.90.1"
target-lexicon = "0.12.0" target-lexicon = "0.12.0"
gimli = { version = "0.26.0", default-features = false, features = ["write"]} 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"] } object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
@ -39,6 +46,7 @@ smallvec = "1.8.1"
unstable-features = ["jit", "inline_asm"] unstable-features = ["jit", "inline_asm"]
jit = ["cranelift-jit", "libloading"] jit = ["cranelift-jit", "libloading"]
inline_asm = [] inline_asm = []
__check_build_system_using_ra = []
[package.metadata.rust-analyzer] [package.metadata.rust-analyzer]
rustc_private = true rustc_private = true

View File

@ -37,7 +37,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
In the directory with your project (where you can do the usual `cargo build`), run: In the directory with your project (where you can do the usual `cargo build`), run:
```bash ```bash
$ $cg_clif_dir/build/cargo-clif build $ $cg_clif_dir/dist/cargo-clif build
``` ```
This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.

View File

@ -4,9 +4,9 @@ version = 3
[[package]] [[package]]
name = "addr2line" name = "addr2line"
version = "0.16.0" version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"gimli", "gimli",
@ -32,27 +32,11 @@ dependencies = [
"core", "core",
] ]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.73" version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -66,9 +50,9 @@ dependencies = [
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.82" version = "0.1.85"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603" checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -111,9 +95,9 @@ dependencies = [
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.25.0" version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"rustc-std-workspace-alloc", "rustc-std-workspace-alloc",
@ -145,9 +129,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.135" version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -164,12 +148,11 @@ dependencies = [
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.4" version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [ dependencies = [
"adler", "adler",
"autocfg",
"compiler_builtins", "compiler_builtins",
"rustc-std-workspace-alloc", "rustc-std-workspace-alloc",
"rustc-std-workspace-core", "rustc-std-workspace-core",
@ -177,9 +160,9 @@ dependencies = [
[[package]] [[package]]
name = "object" name = "object"
version = "0.26.2" version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"memchr", "memchr",
@ -192,7 +175,7 @@ name = "panic_abort"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"alloc", "alloc",
"cfg-if 0.1.10", "cfg-if",
"compiler_builtins", "compiler_builtins",
"core", "core",
"libc", "libc",
@ -203,7 +186,7 @@ name = "panic_unwind"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"alloc", "alloc",
"cfg-if 0.1.10", "cfg-if",
"compiler_builtins", "compiler_builtins",
"core", "core",
"libc", "libc",
@ -255,7 +238,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"alloc", "alloc",
"cfg-if 1.0.0", "cfg-if",
"compiler_builtins", "compiler_builtins",
"core", "core",
"dlmalloc", "dlmalloc",
@ -277,7 +260,7 @@ dependencies = [
name = "std_detect" name = "std_detect"
version = "0.1.5" version = "0.1.5"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"compiler_builtins", "compiler_builtins",
"libc", "libc",
"rustc-std-workspace-alloc", "rustc-std-workspace-alloc",
@ -299,7 +282,7 @@ dependencies = [
name = "test" name = "test"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if",
"core", "core",
"getopts", "getopts",
"libc", "libc",
@ -325,7 +308,7 @@ name = "unwind"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"cc", "cc",
"cfg-if 0.1.10", "cfg-if",
"compiler_builtins", "compiler_builtins",
"core", "core",
"libc", "libc",

View File

@ -1,16 +1,21 @@
use std::env;
use std::path::Path; use std::path::Path;
use super::build_sysroot; use super::build_sysroot;
use super::config; use super::config;
use super::prepare; use super::path::Dirs;
use super::utils::{cargo_command, spawn_and_wait}; use super::prepare::GitRepo;
use super::utils::{spawn_and_wait, CargoProject, Compiler};
use super::SysrootKind; 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) fn run( pub(crate) fn run(
channel: &str, channel: &str,
sysroot_kind: SysrootKind, sysroot_kind: SysrootKind,
target_dir: &Path, dirs: &Dirs,
cg_clif_dylib: &Path, cg_clif_dylib: &Path,
host_triple: &str, host_triple: &str,
target_triple: &str, target_triple: &str,
@ -27,26 +32,25 @@ pub(crate) fn run(
eprintln!("Building sysroot for abi-cafe"); eprintln!("Building sysroot for abi-cafe");
build_sysroot::build_sysroot( build_sysroot::build_sysroot(
dirs,
channel, channel,
sysroot_kind, sysroot_kind,
target_dir,
cg_clif_dylib, cg_clif_dylib,
host_triple, host_triple,
target_triple, target_triple,
); );
eprintln!("Running abi-cafe"); eprintln!("Running abi-cafe");
let abi_cafe_path = prepare::ABI_CAFE.source_dir();
env::set_current_dir(abi_cafe_path.clone()).unwrap();
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"]; let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path); let mut cmd = ABI_CAFE.run(&Compiler::host(), dirs);
cmd.arg("--"); cmd.arg("--");
cmd.arg("--pairs"); cmd.arg("--pairs");
cmd.args(pairs); cmd.args(pairs);
cmd.arg("--add-rustc-codegen-backend"); cmd.arg("--add-rustc-codegen-backend");
cmd.arg(format!("cgclif:{}", cg_clif_dylib.display())); cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
cmd.current_dir(ABI_CAFE.source_dir(dirs));
spawn_and_wait(cmd); spawn_and_wait(cmd);
} }

View File

@ -1,16 +1,19 @@
use std::env; use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use super::path::{Dirs, RelPath};
use super::rustc_info::get_file_name; use super::rustc_info::get_file_name;
use super::utils::{cargo_command, is_ci}; use super::utils::{is_ci, CargoProject, Compiler};
static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
pub(crate) fn build_backend( pub(crate) fn build_backend(
dirs: &Dirs,
channel: &str, channel: &str,
host_triple: &str, host_triple: &str,
use_unstable_features: bool, use_unstable_features: bool,
) -> PathBuf { ) -> PathBuf {
let source_dir = std::env::current_dir().unwrap(); let mut cmd = CG_CLIF.build(&Compiler::host(), dirs);
let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
@ -41,8 +44,8 @@ pub(crate) fn build_backend(
eprintln!("[BUILD] rustc_codegen_cranelift"); eprintln!("[BUILD] rustc_codegen_cranelift");
super::utils::spawn_and_wait(cmd); super::utils::spawn_and_wait(cmd);
source_dir CG_CLIF
.join("target") .target_dir(dirs)
.join(host_triple) .join(host_triple)
.join(channel) .join(channel)
.join(get_file_name("rustc_codegen_cranelift", "dylib")) .join(get_file_name("rustc_codegen_cranelift", "dylib"))

View File

@ -1,57 +1,60 @@
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::Path;
use std::process::{self, Command}; 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::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
use super::utils::{cargo_command, spawn_and_wait, try_hard_link}; use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler};
use super::SysrootKind; 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( pub(crate) fn build_sysroot(
dirs: &Dirs,
channel: &str, channel: &str,
sysroot_kind: SysrootKind, sysroot_kind: SysrootKind,
target_dir: &Path,
cg_clif_dylib_src: &Path, cg_clif_dylib_src: &Path,
host_triple: &str, host_triple: &str,
target_triple: &str, target_triple: &str,
) { ) {
eprintln!("[BUILD] sysroot {:?}", sysroot_kind); eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
if target_dir.exists() { DIST_DIR.ensure_fresh(dirs);
fs::remove_dir_all(target_dir).unwrap(); BIN_DIR.ensure_exists(dirs);
} LIB_DIR.ensure_exists(dirs);
fs::create_dir_all(target_dir.join("bin")).unwrap();
fs::create_dir_all(target_dir.join("lib")).unwrap();
// Copy the backend // Copy the backend
let cg_clif_dylib_path = target_dir let cg_clif_dylib_path = if cfg!(windows) {
.join(if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the // binaries.
// binaries. BIN_DIR
"bin" } else {
} else { LIB_DIR
"lib" }
}) .to_path(dirs)
.join(get_file_name("rustc_codegen_cranelift", "dylib")); .join(get_file_name("rustc_codegen_cranelift", "dylib"));
try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path); try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
// Build and copy rustc and cargo wrappers // Build and copy rustc and cargo wrappers
for wrapper in ["rustc-clif", "cargo-clif"] { for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
let wrapper_name = get_wrapper_file_name(wrapper, "bin"); let wrapper_name = get_wrapper_file_name(wrapper, "bin");
let mut build_cargo_wrapper_cmd = Command::new("rustc"); let mut build_cargo_wrapper_cmd = Command::new("rustc");
build_cargo_wrapper_cmd build_cargo_wrapper_cmd
.arg(PathBuf::from("scripts").join(format!("{wrapper}.rs"))) .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
.arg("-o") .arg("-o")
.arg(target_dir.join(wrapper_name)) .arg(DIST_DIR.to_path(dirs).join(wrapper_name))
.arg("-g"); .arg("-g");
spawn_and_wait(build_cargo_wrapper_cmd); spawn_and_wait(build_cargo_wrapper_cmd);
} }
let default_sysroot = super::rustc_info::get_default_sysroot(); let default_sysroot = super::rustc_info::get_default_sysroot();
let rustlib = target_dir.join("lib").join("rustlib"); let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib");
let host_rustlib_lib = rustlib.join(host_triple).join("lib"); let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(target_triple).join("lib");
let target_rustlib_lib = rustlib.join(target_triple).join("lib");
fs::create_dir_all(&host_rustlib_lib).unwrap(); fs::create_dir_all(&host_rustlib_lib).unwrap();
fs::create_dir_all(&target_rustlib_lib).unwrap(); fs::create_dir_all(&target_rustlib_lib).unwrap();
@ -112,24 +115,18 @@ pub(crate) fn build_sysroot(
} }
} }
SysrootKind::Clif => { SysrootKind::Clif => {
build_clif_sysroot_for_triple( build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, None);
channel,
target_dir,
host_triple,
&cg_clif_dylib_path,
None,
);
if host_triple != target_triple { if host_triple != target_triple {
// When cross-compiling it is often necessary to manually pick the right linker // When cross-compiling it is often necessary to manually pick the right linker
let linker = if target_triple == "aarch64-unknown-linux-gnu" { let linker = match target_triple {
Some("aarch64-linux-gnu-gcc") "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"),
} else { "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"),
None _ => None,
}; };
build_clif_sysroot_for_triple( build_clif_sysroot_for_triple(
dirs,
channel, channel,
target_dir,
target_triple, target_triple,
&cg_clif_dylib_path, &cg_clif_dylib_path,
linker, linker,
@ -142,21 +139,26 @@ pub(crate) fn build_sysroot(
let file = file.unwrap().path(); let file = file.unwrap().path();
let filename = file.file_name().unwrap().to_str().unwrap(); let filename = file.file_name().unwrap().to_str().unwrap();
if filename.contains("std-") && !filename.contains(".rlib") { if filename.contains("std-") && !filename.contains(".rlib") {
try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap())); try_hard_link(&file, LIB_DIR.to_path(dirs).join(file.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");
fn build_clif_sysroot_for_triple( fn build_clif_sysroot_for_triple(
dirs: &Dirs,
channel: &str, channel: &str,
target_dir: &Path,
triple: &str, triple: &str,
cg_clif_dylib_path: &Path, cg_clif_dylib_path: &Path,
linker: Option<&str>, linker: Option<&str>,
) { ) {
match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) { match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) {
Err(e) => { Err(e) => {
eprintln!("Failed to get rustc version for patched sysroot source: {}", e); eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source"); eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
@ -174,7 +176,7 @@ fn build_clif_sysroot_for_triple(
} }
} }
let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel); let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(triple).join(channel);
if !super::config::get_bool("keep_sysroot") { if !super::config::get_bool("keep_sysroot") {
// Cleanup the deps dir, but keep build scripts and the incremental cache for faster // Cleanup the deps dir, but keep build scripts and the incremental cache for faster
@ -185,27 +187,27 @@ fn build_clif_sysroot_for_triple(
} }
// Build sysroot // Build sysroot
let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("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!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap())); rustflags.push_str(&format!(" --sysroot={}", DIST_DIR.to_path(dirs).to_str().unwrap()));
if channel == "release" { if channel == "release" {
build_cmd.arg("--release");
rustflags.push_str(" -Zmir-opt-level=3"); rustflags.push_str(" -Zmir-opt-level=3");
} }
if let Some(linker) = linker { if let Some(linker) = linker {
use std::fmt::Write; use std::fmt::Write;
write!(rustflags, " -Clinker={}", linker).unwrap(); write!(rustflags, " -Clinker={}", linker).unwrap();
} }
build_cmd.env("RUSTFLAGS", rustflags); let mut compiler = Compiler::with_triple(triple.to_owned());
compiler.rustflags = rustflags;
let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
if channel == "release" {
build_cmd.arg("--release");
}
build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
spawn_and_wait(build_cmd); spawn_and_wait(build_cmd);
// Copy all relevant files to the sysroot // Copy all relevant files to the sysroot
for entry in for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps"))
.unwrap()
{
let entry = entry.unwrap(); let entry = entry.unwrap();
if let Some(ext) = entry.path().extension() { if let Some(ext) = entry.path().extension() {
if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" { if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
@ -216,7 +218,7 @@ fn build_clif_sysroot_for_triple(
}; };
try_hard_link( try_hard_link(
entry.path(), entry.path(),
target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()), RUSTLIB_DIR.to_path(dirs).join(triple).join("lib").join(entry.file_name()),
); );
} }
} }

View File

@ -8,20 +8,37 @@ mod abi_cafe;
mod build_backend; mod build_backend;
mod build_sysroot; mod build_sysroot;
mod config; mod config;
mod path;
mod prepare; mod prepare;
mod rustc_info; mod rustc_info;
mod tests; mod tests;
mod utils; 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() { fn usage() {
eprintln!("Usage:"); eprintln!("{USAGE}");
eprintln!(" ./y.rs prepare");
eprintln!(
" ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
);
eprintln!(
" ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
);
} }
macro_rules! arg_error { macro_rules! arg_error {
@ -34,6 +51,7 @@ macro_rules! arg_error {
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
enum Command { enum Command {
Prepare,
Build, Build,
Test, Test,
} }
@ -48,8 +66,6 @@ pub(crate) enum SysrootKind {
pub fn main() { pub fn main() {
env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1"); env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1"); env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
// The target dir is expected in the default location. Guard against the user changing it.
env::set_var("CARGO_TARGET_DIR", "target");
if is_ci() { if is_ci() {
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
@ -58,13 +74,7 @@ pub fn main() {
let mut args = env::args().skip(1); let mut args = env::args().skip(1);
let command = match args.next().as_deref() { let command = match args.next().as_deref() {
Some("prepare") => { Some("prepare") => Command::Prepare,
if args.next().is_some() {
arg_error!("./y.rs prepare doesn't expect arguments");
}
prepare::prepare();
process::exit(0);
}
Some("build") => Command::Build, Some("build") => Command::Build,
Some("test") => Command::Test, Some("test") => Command::Test,
Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
@ -75,15 +85,15 @@ pub fn main() {
} }
}; };
let mut target_dir = PathBuf::from("build"); let mut out_dir = PathBuf::from(".");
let mut channel = "release"; let mut channel = "release";
let mut sysroot_kind = SysrootKind::Clif; let mut sysroot_kind = SysrootKind::Clif;
let mut use_unstable_features = true; let mut use_unstable_features = true;
while let Some(arg) = args.next().as_deref() { while let Some(arg) = args.next().as_deref() {
match arg { match arg {
"--target-dir" => { "--out-dir" => {
target_dir = PathBuf::from(args.next().unwrap_or_else(|| { out_dir = PathBuf::from(args.next().unwrap_or_else(|| {
arg_error!("--target-dir requires argument"); arg_error!("--out-dir requires argument");
})) }))
} }
"--debug" => channel = "debug", "--debug" => channel = "debug",
@ -101,7 +111,6 @@ pub fn main() {
arg => arg_error!("Unexpected argument {}", arg), arg => arg_error!("Unexpected argument {}", arg),
} }
} }
target_dir = std::env::current_dir().unwrap().join(target_dir);
let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
host_triple host_triple
@ -122,13 +131,43 @@ pub fn main() {
host_triple.clone() host_triple.clone()
}; };
let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features); // FIXME allow changing the location of these dirs using cli arguments
let current_dir = std::env::current_dir().unwrap();
out_dir = current_dir.join(out_dir);
let dirs = path::Dirs {
source_dir: current_dir.clone(),
download_dir: out_dir.join("download"),
build_dir: out_dir.join("build"),
dist_dir: out_dir.join("dist"),
};
path::RelPath::BUILD.ensure_exists(&dirs);
{
// Make sure we always explicitly specify the target dir
let target =
path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs);
env::set_var("CARGO_TARGET_DIR", &target);
let _ = std::fs::remove_file(&target);
std::fs::File::create(target).unwrap();
}
if command == Command::Prepare {
prepare::prepare(&dirs);
process::exit(0);
}
let cg_clif_dylib =
build_backend::build_backend(&dirs, channel, &host_triple, use_unstable_features);
match command { match command {
Command::Prepare => {
// Handled above
}
Command::Test => { Command::Test => {
tests::run_tests( tests::run_tests(
&dirs,
channel, channel,
sysroot_kind, sysroot_kind,
&target_dir,
&cg_clif_dylib, &cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
@ -137,7 +176,7 @@ pub fn main() {
abi_cafe::run( abi_cafe::run(
channel, channel,
sysroot_kind, sysroot_kind,
&target_dir, &dirs,
&cg_clif_dylib, &cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
@ -145,9 +184,9 @@ pub fn main() {
} }
Command::Build => { Command::Build => {
build_sysroot::build_sysroot( build_sysroot::build_sysroot(
&dirs,
channel, channel,
sysroot_kind, sysroot_kind,
&target_dir,
&cg_clif_dylib, &cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,

70
build_system/path.rs Normal file
View File

@ -0,0 +1,70 @@
use std::fs;
use std::path::PathBuf;
#[derive(Debug, Clone)]
pub(crate) struct Dirs {
pub(crate) source_dir: PathBuf,
pub(crate) download_dir: PathBuf,
pub(crate) build_dir: PathBuf,
pub(crate) dist_dir: PathBuf,
}
#[doc(hidden)]
#[derive(Debug, Copy, Clone)]
pub(crate) enum PathBase {
Source,
Download,
Build,
Dist,
}
impl PathBase {
fn to_path(self, dirs: &Dirs) -> PathBuf {
match self {
PathBase::Source => dirs.source_dir.clone(),
PathBase::Download => dirs.download_dir.clone(),
PathBase::Build => dirs.build_dir.clone(),
PathBase::Dist => dirs.dist_dir.clone(),
}
}
}
#[derive(Debug, Copy, Clone)]
pub(crate) enum RelPath {
Base(PathBase),
Join(&'static RelPath, &'static str),
}
impl RelPath {
pub(crate) const SOURCE: RelPath = RelPath::Base(PathBase::Source);
pub(crate) const DOWNLOAD: RelPath = RelPath::Base(PathBase::Download);
pub(crate) const BUILD: RelPath = RelPath::Base(PathBase::Build);
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 {
RelPath::Join(self, suffix)
}
pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf {
match self {
RelPath::Base(base) => base.to_path(dirs),
RelPath::Join(base, suffix) => base.to_path(dirs).join(suffix),
}
}
pub(crate) fn ensure_exists(&self, dirs: &Dirs) {
fs::create_dir_all(self.to_path(dirs)).unwrap();
}
pub(crate) fn ensure_fresh(&self, dirs: &Dirs) {
let path = self.to_path(dirs);
if path.exists() {
fs::remove_dir_all(&path).unwrap();
}
fs::create_dir_all(path).unwrap();
}
}

View File

@ -1,92 +1,75 @@
use std::env;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use super::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::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait}; use super::utils::{copy_dir_recursively, spawn_and_wait, Compiler};
pub(crate) const ABI_CAFE: GitRepo = pub(crate) fn prepare(dirs: &Dirs) {
GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe"); if RelPath::DOWNLOAD.to_path(dirs).exists() {
std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
pub(crate) const RAND: GitRepo =
GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
pub(crate) const REGEX: GitRepo =
GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
"rust-lang",
"portable-simd",
"d5cd4a8112d958bd3a252327e0d069a6363249bd",
"portable-simd",
);
pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
"ebobby",
"simple-raytracer",
"804a7a21b9e673a482797aa289a18ed480e4d813",
"<none>",
);
pub(crate) fn prepare() {
if Path::new("download").exists() {
std::fs::remove_dir_all(Path::new("download")).unwrap();
} }
std::fs::create_dir_all(Path::new("download")).unwrap(); std::fs::create_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
prepare_sysroot(); prepare_sysroot(dirs);
// FIXME maybe install this only locally? // FIXME maybe install this only locally?
eprintln!("[INSTALL] hyperfine"); eprintln!("[INSTALL] hyperfine");
Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap(); Command::new("cargo")
.arg("install")
.arg("hyperfine")
.env_remove("CARGO_TARGET_DIR")
.spawn()
.unwrap()
.wait()
.unwrap();
ABI_CAFE.fetch(); super::abi_cafe::ABI_CAFE_REPO.fetch(dirs);
RAND.fetch(); super::tests::RAND_REPO.fetch(dirs);
REGEX.fetch(); super::tests::REGEX_REPO.fetch(dirs);
PORTABLE_SIMD.fetch(); super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
SIMPLE_RAYTRACER.fetch(); super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs);
eprintln!("[LLVM BUILD] simple-raytracer"); eprintln!("[LLVM BUILD] simple-raytracer");
let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir()); let host_compiler = Compiler::host();
let build_cmd = super::tests::SIMPLE_RAYTRACER.build(&host_compiler, dirs);
spawn_and_wait(build_cmd); spawn_and_wait(build_cmd);
fs::copy( fs::copy(
SIMPLE_RAYTRACER super::tests::SIMPLE_RAYTRACER
.source_dir() .target_dir(dirs)
.join("target") .join(&host_compiler.triple)
.join("debug") .join("debug")
.join(get_file_name("main", "bin")), .join(get_file_name("main", "bin")),
SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")), RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
) )
.unwrap(); .unwrap();
} }
fn prepare_sysroot() { fn prepare_sysroot(dirs: &Dirs) {
let rustc_path = get_rustc_path(); let rustc_path = get_rustc_path();
let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust"); let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src"); let sysroot_src = SYSROOT_SRC;
assert!(sysroot_src_orig.exists()); assert!(sysroot_src_orig.exists());
if sysroot_src.exists() { sysroot_src.ensure_fresh(dirs);
fs::remove_dir_all(&sysroot_src).unwrap(); fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap();
}
fs::create_dir_all(sysroot_src.join("library")).unwrap();
eprintln!("[COPY] sysroot src"); eprintln!("[COPY] sysroot src");
copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library")); copy_dir_recursively(
&sysroot_src_orig.join("library"),
&sysroot_src.to_path(dirs).join("library"),
);
let rustc_version = get_rustc_version(); let rustc_version = get_rustc_version();
fs::write(Path::new("build_sysroot").join("rustc_version"), &rustc_version).unwrap(); fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &rustc_version).unwrap();
eprintln!("[GIT] init"); eprintln!("[GIT] init");
let mut git_init_cmd = Command::new("git"); init_git_repo(&sysroot_src.to_path(dirs));
git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src);
spawn_and_wait(git_init_cmd);
init_git_repo(&sysroot_src); apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs));
apply_patches("sysroot", &sysroot_src);
} }
pub(crate) struct GitRepo { pub(crate) struct GitRepo {
@ -100,7 +83,7 @@ enum GitRepoUrl {
} }
impl GitRepo { impl GitRepo {
const fn github( pub(crate) const fn github(
user: &'static str, user: &'static str,
repo: &'static str, repo: &'static str,
rev: &'static str, rev: &'static str,
@ -109,21 +92,25 @@ impl GitRepo {
GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name } GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
} }
pub(crate) fn source_dir(&self) -> PathBuf { pub(crate) const fn source_dir(&self) -> RelPath {
match self.url { match self.url {
GitRepoUrl::Github { user: _, repo } => { GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo),
std::env::current_dir().unwrap().join("download").join(repo)
}
} }
} }
fn fetch(&self) { fn fetch(&self, dirs: &Dirs) {
match self.url { match self.url {
GitRepoUrl::Github { user, repo } => { GitRepoUrl::Github { user, repo } => {
clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev); clone_repo_shallow_github(
dirs,
&self.source_dir().to_path(dirs),
user,
repo,
self.rev,
);
} }
} }
apply_patches(self.patch_name, &self.source_dir()); apply_patches(dirs, self.patch_name, &self.source_dir().to_path(dirs));
} }
} }
@ -142,18 +129,16 @@ fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
spawn_and_wait(checkout_cmd); spawn_and_wait(checkout_cmd);
} }
fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) { fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo: &str, rev: &str) {
if cfg!(windows) { if cfg!(windows) {
// Older windows doesn't have tar or curl by default. Fall back to using git. // Older windows doesn't have tar or curl by default. Fall back to using git.
clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev); clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
return; return;
} }
let downloads_dir = std::env::current_dir().unwrap().join("download");
let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev); let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
let archive_file = downloads_dir.join(format!("{}.tar.gz", rev)); let archive_file = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}.tar.gz", rev));
let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev)); let archive_dir = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}-{}", repo, rev));
eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url); eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
@ -169,7 +154,7 @@ fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &
// Unpack tar archive // Unpack tar archive
let mut unpack_cmd = Command::new("tar"); let mut unpack_cmd = Command::new("tar");
unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir); unpack_cmd.arg("xf").arg(&archive_file).current_dir(RelPath::DOWNLOAD.to_path(dirs));
spawn_and_wait(unpack_cmd); spawn_and_wait(unpack_cmd);
// Rename unpacked dir to the expected name // Rename unpacked dir to the expected name
@ -191,12 +176,21 @@ fn init_git_repo(repo_dir: &Path) {
spawn_and_wait(git_add_cmd); spawn_and_wait(git_add_cmd);
let mut git_commit_cmd = Command::new("git"); let mut git_commit_cmd = Command::new("git");
git_commit_cmd.arg("commit").arg("-m").arg("Initial commit").arg("-q").current_dir(repo_dir); 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);
spawn_and_wait(git_commit_cmd); spawn_and_wait(git_commit_cmd);
} }
fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> { fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> {
let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches")) let mut patches: Vec<_> = fs::read_dir(RelPath::PATCHES.to_path(dirs))
.unwrap() .unwrap()
.map(|entry| entry.unwrap().path()) .map(|entry| entry.unwrap().path())
.filter(|path| path.extension() == Some(OsStr::new("patch"))) .filter(|path| path.extension() == Some(OsStr::new("patch")))
@ -215,19 +209,27 @@ fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
patches patches
} }
fn apply_patches(crate_name: &str, target_dir: &Path) { fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) {
if crate_name == "<none>" { if crate_name == "<none>" {
return; return;
} }
for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) { for patch in get_patches(dirs, crate_name) {
eprintln!( eprintln!(
"[PATCH] {:?} <- {:?}", "[PATCH] {:?} <- {:?}",
target_dir.file_name().unwrap(), target_dir.file_name().unwrap(),
patch.file_name().unwrap() patch.file_name().unwrap()
); );
let mut apply_patch_cmd = Command::new("git"); let mut apply_patch_cmd = Command::new("git");
apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir); 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);
spawn_and_wait(apply_patch_cmd); spawn_and_wait(apply_patch_cmd);
} }
} }

View File

@ -23,6 +23,16 @@ pub(crate) fn get_host_triple() -> String {
.to_owned() .to_owned()
} }
pub(crate) fn get_cargo_path() -> PathBuf {
let cargo_path = Command::new("rustup")
.stderr(Stdio::inherit())
.args(&["which", "cargo"])
.output()
.unwrap()
.stdout;
Path::new(String::from_utf8(cargo_path).unwrap().trim()).to_owned()
}
pub(crate) fn get_rustc_path() -> PathBuf { pub(crate) fn get_rustc_path() -> PathBuf {
let rustc_path = Command::new("rustup") let rustc_path = Command::new("rustup")
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
@ -33,6 +43,16 @@ pub(crate) fn get_rustc_path() -> PathBuf {
Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned() Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
} }
pub(crate) fn get_rustdoc_path() -> PathBuf {
let rustc_path = Command::new("rustup")
.stderr(Stdio::inherit())
.args(&["which", "rustdoc"])
.output()
.unwrap()
.stdout;
Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
}
pub(crate) fn get_default_sysroot() -> PathBuf { pub(crate) fn get_default_sysroot() -> PathBuf {
let default_sysroot = Command::new("rustc") let default_sysroot = Command::new("rustc")
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())

View File

@ -1,15 +1,20 @@
use super::build_sysroot; use super::build_sysroot;
use super::config; use super::config;
use super::prepare; use super::path::{Dirs, RelPath};
use super::rustc_info::get_wrapper_file_name; use super::prepare::GitRepo;
use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input}; use super::rustc_info::{get_cargo_path, get_wrapper_file_name};
use build_system::SysrootKind; use super::utils::{
hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler,
};
use super::SysrootKind;
use std::env; use std::env;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::Path;
use std::process::Command; use std::process::Command;
static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
struct TestCase { struct TestCase {
config: &'static str, config: &'static str,
func: &'static dyn Fn(&TestRunner), func: &'static dyn Fn(&TestRunner),
@ -30,7 +35,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"lib,dylib", "lib,dylib",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
}), }),
TestCase::new("build.example", &|runner| { TestCase::new("build.example", &|runner| {
@ -39,7 +44,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"lib", "lib",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
}), }),
TestCase::new("jit.mini_core_hello_world", &|runner| { TestCase::new("jit.mini_core_hello_world", &|runner| {
@ -51,7 +56,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
"--cfg", "--cfg",
"jit", "jit",
"--target", "--target",
&runner.host_triple, &runner.target_compiler.triple,
]); ]);
jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
spawn_and_wait(jit_cmd); spawn_and_wait(jit_cmd);
@ -65,7 +70,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
"--cfg", "--cfg",
"jit", "jit",
"--target", "--target",
&runner.host_triple, &runner.target_compiler.triple,
]); ]);
jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
spawn_and_wait(jit_cmd); spawn_and_wait(jit_cmd);
@ -79,7 +84,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
"bin", "bin",
"-g", "-g",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]); runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
}), }),
@ -94,7 +99,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"bin", "bin",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []); runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
}), }),
@ -106,7 +111,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"bin", "bin",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("issue_91827_extern_types", []); runner.run_out_command("issue_91827_extern_types", []);
}), }),
@ -116,7 +121,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"lib", "lib",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
}), }),
TestCase::new("aot.alloc_example", &|runner| { TestCase::new("aot.alloc_example", &|runner| {
@ -125,7 +130,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"bin", "bin",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("alloc_example", []); runner.run_out_command("alloc_example", []);
}), }),
@ -136,7 +141,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"-Cprefer-dynamic", "-Cprefer-dynamic",
"example/std_example.rs", "example/std_example.rs",
"--target", "--target",
&runner.host_triple, &runner.target_compiler.triple,
]); ]);
eprintln!("[JIT-lazy] std_example"); eprintln!("[JIT-lazy] std_example");
@ -146,7 +151,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"-Cprefer-dynamic", "-Cprefer-dynamic",
"example/std_example.rs", "example/std_example.rs",
"--target", "--target",
&runner.host_triple, &runner.target_compiler.triple,
]); ]);
}), }),
TestCase::new("aot.std_example", &|runner| { TestCase::new("aot.std_example", &|runner| {
@ -155,7 +160,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"bin", "bin",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("std_example", ["arg"]); runner.run_out_command("std_example", ["arg"]);
}), }),
@ -167,7 +172,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"bin", "bin",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("dst_field_align", []); runner.run_out_command("dst_field_align", []);
}), }),
@ -178,7 +183,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"bin", "bin",
"-Cpanic=abort", "-Cpanic=abort",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("subslice-patterns-const-eval", []); runner.run_out_command("subslice-patterns-const-eval", []);
}), }),
@ -189,7 +194,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"bin", "bin",
"-Cpanic=abort", "-Cpanic=abort",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("track-caller-attribute", []); runner.run_out_command("track-caller-attribute", []);
}), }),
@ -200,7 +205,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"bin", "bin",
"-Cpanic=abort", "-Cpanic=abort",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("float-minmax-pass", []); runner.run_out_command("float-minmax-pass", []);
}), }),
@ -210,205 +215,252 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
"--crate-type", "--crate-type",
"bin", "bin",
"--target", "--target",
&runner.target_triple, &runner.target_compiler.triple,
]); ]);
runner.run_out_command("mod_bench", []); 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", []);
}),
]; ];
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 REGEX_REPO: GitRepo =
GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex");
pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
"rust-lang",
"portable-simd",
"d5cd4a8112d958bd3a252327e0d069a6363249bd",
"portable-simd",
);
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");
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
TestCase::new("test.rust-random/rand", &|runner| { TestCase::new("test.rust-random/rand", &|runner| {
runner.in_dir(prepare::RAND.source_dir(), |runner| { spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs));
runner.run_cargo("clean", []);
if runner.host_triple == runner.target_triple { if runner.is_native {
eprintln!("[TEST] rust-random/rand"); eprintln!("[TEST] rust-random/rand");
runner.run_cargo("test", ["--workspace"]); let mut test_cmd = RAND.test(&runner.target_compiler, &runner.dirs);
} else { test_cmd.arg("--workspace");
eprintln!("[AOT] rust-random/rand"); spawn_and_wait(test_cmd);
runner.run_cargo("build", ["--workspace", "--tests"]); } else {
} eprintln!("[AOT] rust-random/rand");
}); let mut build_cmd = RAND.build(&runner.target_compiler, &runner.dirs);
build_cmd.arg("--workspace").arg("--tests");
spawn_and_wait(build_cmd);
}
}), }),
TestCase::new("bench.simple-raytracer", &|runner| { TestCase::new("bench.simple-raytracer", &|runner| {
runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| { let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
if runner.host_triple == runner.target_triple { if runner.is_native {
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer"); eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
let prepare = runner.cargo_command("clean", []); 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 llvm_build_cmd = cargo_command("cargo", "build", None, Path::new(".")); 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 cargo_clif = runner let bench_compile =
.root_dir hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
.clone()
.join("build")
.join(get_wrapper_file_name("cargo-clif", "bin"));
let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
let bench_compile = spawn_and_wait(bench_compile);
hyperfine_command(1, run_runs, Some(prepare), 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();
eprintln!("[BENCH RUN] ebobby/simple-raytracer"); let mut bench_run =
fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif")) hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif");
.unwrap(); bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs));
spawn_and_wait(bench_run);
let bench_run = hyperfine_command( } else {
0, spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs));
run_runs, eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
None, eprintln!("[COMPILE] ebobby/simple-raytracer");
Command::new("./raytracer_cg_llvm"), spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
Command::new("./raytracer_cg_clif"), eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
); }
spawn_and_wait(bench_run);
} else {
runner.run_cargo("clean", []);
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
eprintln!("[COMPILE] ebobby/simple-raytracer");
runner.run_cargo("build", []);
eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
}
});
}), }),
TestCase::new("test.libcore", &|runner| { TestCase::new("test.libcore", &|runner| {
runner.in_dir( spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs));
std::env::current_dir()
.unwrap()
.join("build_sysroot")
.join("sysroot_src")
.join("library")
.join("core")
.join("tests"),
|runner| {
runner.run_cargo("clean", []);
if runner.host_triple == runner.target_triple { if runner.is_native {
runner.run_cargo("test", []); spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs));
} else { } else {
eprintln!("Cross-Compiling: Not running tests"); eprintln!("Cross-Compiling: Not running tests");
runner.run_cargo("build", ["--tests"]); let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs);
} build_cmd.arg("--tests");
}, spawn_and_wait(build_cmd);
); }
}), }),
TestCase::new("test.regex-shootout-regex-dna", &|runner| { TestCase::new("test.regex-shootout-regex-dna", &|runner| {
runner.in_dir(prepare::REGEX.source_dir(), |runner| { spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs));
runner.run_cargo("clean", []);
// newer aho_corasick versions throw a deprecation warning // newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]); let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); build_cmd.arg("--example").arg("shootout-regex-dna");
spawn_and_wait(build_cmd); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
spawn_and_wait(build_cmd);
if runner.host_triple == runner.target_triple { if runner.is_native {
let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]); let mut run_cmd = REGEX.run(&runner.target_compiler, &runner.dirs);
run_cmd.env("RUSTFLAGS", lint_rust_flags); run_cmd.arg("--example").arg("shootout-regex-dna");
run_cmd.env("RUSTFLAGS", lint_rust_flags);
let input = let input = fs::read_to_string(
fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"),
let expected_path = PathBuf::from("examples/regexdna-output.txt"); )
let expected = fs::read_to_string(&expected_path).unwrap(); .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 output = spawn_and_wait_with_input(run_cmd, input); let output = spawn_and_wait_with_input(run_cmd, input);
// Make sure `[codegen mono items] start` doesn't poison the diff // Make sure `[codegen mono items] start` doesn't poison the diff
let output = output let output = output
.lines() .lines()
.filter(|line| !line.contains("codegen mono items")) .filter(|line| !line.contains("codegen mono items"))
.chain(Some("")) // This just adds the trailing newline .chain(Some("")) // This just adds the trailing newline
.collect::<Vec<&str>>() .collect::<Vec<&str>>()
.join("\r\n"); .join("\r\n");
let output_matches = expected.lines().eq(output.lines()); let output_matches = expected.lines().eq(output.lines());
if !output_matches { if !output_matches {
let res_path = PathBuf::from("res.txt"); let res_path = REGEX.source_dir(&runner.dirs).join("res.txt");
fs::write(&res_path, &output).unwrap(); fs::write(&res_path, &output).unwrap();
if cfg!(windows) { if cfg!(windows) {
println!("Output files don't match!"); println!("Output files don't match!");
println!("Expected Output:\n{}", expected); println!("Expected Output:\n{}", expected);
println!("Actual Output:\n{}", output); println!("Actual Output:\n{}", output);
} else { } else {
let mut diff = Command::new("diff"); let mut diff = Command::new("diff");
diff.arg("-u"); diff.arg("-u");
diff.arg(res_path); diff.arg(res_path);
diff.arg(expected_path); diff.arg(expected_path);
spawn_and_wait(diff); spawn_and_wait(diff);
}
std::process::exit(1);
} }
std::process::exit(1);
} }
}); }
}), }),
TestCase::new("test.regex", &|runner| { TestCase::new("test.regex", &|runner| {
runner.in_dir(prepare::REGEX.source_dir(), |runner| { spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs));
runner.run_cargo("clean", []);
// newer aho_corasick versions throw a deprecation warning // newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
if runner.host_triple == runner.target_triple { if runner.is_native {
let mut run_cmd = runner.cargo_command( let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs);
"test", run_cmd.args([
[ "--tests",
"--tests", "--",
"--", "--exclude-should-panic",
"--exclude-should-panic", "--test-threads",
"--test-threads", "1",
"1", "-Zunstable-options",
"-Zunstable-options", "-q",
"-q", ]);
], run_cmd.env("RUSTFLAGS", lint_rust_flags);
); spawn_and_wait(run_cmd);
run_cmd.env("RUSTFLAGS", lint_rust_flags); } else {
spawn_and_wait(run_cmd); eprintln!("Cross-Compiling: Not running tests");
} else { let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
eprintln!("Cross-Compiling: Not running tests"); build_cmd.arg("--tests");
let mut build_cmd = build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]); spawn_and_wait(build_cmd);
build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); }
spawn_and_wait(build_cmd);
}
});
}), }),
TestCase::new("test.portable-simd", &|runner| { TestCase::new("test.portable-simd", &|runner| {
runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| { spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs));
runner.run_cargo("clean", []);
runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
if runner.host_triple == runner.target_triple { let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
runner.run_cargo("test", ["-q"]); build_cmd.arg("--all-targets");
} spawn_and_wait(build_cmd);
});
if runner.is_native {
let mut test_cmd = PORTABLE_SIMD.test(&runner.target_compiler, &runner.dirs);
test_cmd.arg("-q");
spawn_and_wait(test_cmd);
}
}), }),
]; ];
pub(crate) fn run_tests( pub(crate) fn run_tests(
dirs: &Dirs,
channel: &str, channel: &str,
sysroot_kind: SysrootKind, sysroot_kind: SysrootKind,
target_dir: &Path,
cg_clif_dylib: &Path, cg_clif_dylib: &Path,
host_triple: &str, host_triple: &str,
target_triple: &str, target_triple: &str,
) { ) {
let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string()); let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string());
if config::get_bool("testsuite.no_sysroot") { if config::get_bool("testsuite.no_sysroot") {
build_sysroot::build_sysroot( build_sysroot::build_sysroot(
dirs,
channel, channel,
SysrootKind::None, SysrootKind::None,
&target_dir,
cg_clif_dylib, cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
); );
let _ = fs::remove_dir_all(Path::new("target").join("out")); BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
runner.run_testsuite(NO_SYSROOT_SUITE); runner.run_testsuite(NO_SYSROOT_SUITE);
} else { } else {
eprintln!("[SKIP] no_sysroot tests"); eprintln!("[SKIP] no_sysroot tests");
@ -419,9 +471,9 @@ pub(crate) fn run_tests(
if run_base_sysroot || run_extended_sysroot { if run_base_sysroot || run_extended_sysroot {
build_sysroot::build_sysroot( build_sysroot::build_sysroot(
dirs,
channel, channel,
sysroot_kind, sysroot_kind,
&target_dir,
cg_clif_dylib, cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
@ -442,40 +494,50 @@ pub(crate) fn run_tests(
} }
struct TestRunner { struct TestRunner {
root_dir: PathBuf, is_native: bool,
out_dir: PathBuf,
jit_supported: bool, jit_supported: bool,
rust_flags: String, dirs: Dirs,
run_wrapper: Vec<String>, host_compiler: Compiler,
host_triple: String, target_compiler: Compiler,
target_triple: String,
} }
impl TestRunner { impl TestRunner {
pub fn new(host_triple: String, target_triple: String) -> Self { pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self {
let root_dir = env::current_dir().unwrap();
let mut out_dir = root_dir.clone();
out_dir.push("target");
out_dir.push("out");
let is_native = host_triple == target_triple; let is_native = host_triple == target_triple;
let jit_supported = let jit_supported =
target_triple.contains("x86_64") && is_native && !host_triple.contains("windows"); target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); let rustc_clif =
let mut run_wrapper = Vec::new(); 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 { if !is_native {
match target_triple.as_str() { match target_triple.as_str() {
"aarch64-unknown-linux-gnu" => { "aarch64-unknown-linux-gnu" => {
// We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags); rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags);
run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]; 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" => { "x86_64-pc-windows-gnu" => {
// We are cross-compiling for Windows. Run tests in wine. // We are cross-compiling for Windows. Run tests in wine.
run_wrapper = vec!["wine"]; runner = vec!["wine".to_owned()];
} }
_ => { _ => {
println!("Unknown non-native platform"); println!("Unknown non-native platform");
@ -484,19 +546,31 @@ impl TestRunner {
} }
// FIXME fix `#[linkage = "extern_weak"]` without this // FIXME fix `#[linkage = "extern_weak"]` without this
if host_triple.contains("darwin") { if target_triple.contains("darwin") {
rust_flags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rust_flags); rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags);
} }
Self { let host_compiler = Compiler {
root_dir, cargo: get_cargo_path(),
out_dir, rustc: rustc_clif.clone(),
jit_supported, rustdoc: rustdoc_clif.clone(),
rust_flags, rustflags: String::new(),
run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(), rustdocflags: String::new(),
host_triple, triple: host_triple,
target_triple, runner: vec![],
} };
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 }
} }
pub fn run_testsuite(&self, tests: &[TestCase]) { pub fn run_testsuite(&self, tests: &[TestCase]) {
@ -516,29 +590,18 @@ impl TestRunner {
} }
} }
fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) { #[must_use]
let current = env::current_dir().unwrap();
env::set_current_dir(new).unwrap();
callback(self);
env::set_current_dir(current).unwrap();
}
fn rustc_command<I, S>(&self, args: I) -> Command fn rustc_command<I, S>(&self, args: I) -> Command
where where
I: IntoIterator<Item = S>, I: IntoIterator<Item = S>,
S: AsRef<OsStr>, S: AsRef<OsStr>,
{ {
let mut rustc_clif = self.root_dir.clone(); let mut cmd = Command::new(&self.target_compiler.rustc);
rustc_clif.push("build"); cmd.args(self.target_compiler.rustflags.split_whitespace());
rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin"));
let mut cmd = Command::new(rustc_clif);
cmd.args(self.rust_flags.split_whitespace());
cmd.arg("-L"); cmd.arg("-L");
cmd.arg(format!("crate={}", self.out_dir.display())); cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
cmd.arg("--out-dir"); cmd.arg("--out-dir");
cmd.arg(format!("{}", self.out_dir.display())); cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
cmd.arg("-Cdebuginfo=2"); cmd.arg("-Cdebuginfo=2");
cmd.args(args); cmd.args(args);
cmd cmd
@ -559,15 +622,13 @@ impl TestRunner {
let mut full_cmd = vec![]; let mut full_cmd = vec![];
// Prepend the RUN_WRAPPER's // Prepend the RUN_WRAPPER's
if !self.run_wrapper.is_empty() { if !self.target_compiler.runner.is_empty() {
full_cmd.extend(self.run_wrapper.iter().cloned()); full_cmd.extend(self.target_compiler.runner.iter().cloned());
} }
full_cmd.push({ full_cmd.push(
let mut out_path = self.out_dir.clone(); BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(),
out_path.push(name); );
out_path.to_str().unwrap().to_string()
});
for arg in args.into_iter() { for arg in args.into_iter() {
full_cmd.push(arg.to_string()); full_cmd.push(arg.to_string());
@ -581,30 +642,4 @@ impl TestRunner {
spawn_and_wait(cmd); spawn_and_wait(cmd);
} }
fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
where
I: IntoIterator<Item = &'a str>,
{
let mut cargo_clif = self.root_dir.clone();
cargo_clif.push("build");
cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
let mut cmd = cargo_command(
cargo_clif,
subcommand,
if subcommand == "clean" { None } else { Some(&self.target_triple) },
Path::new("."),
);
cmd.args(args);
cmd.env("RUSTFLAGS", &self.rust_flags);
cmd
}
fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
where
I: IntoIterator<Item = &'a str>,
{
spawn_and_wait(self.cargo_command(subcommand, args));
}
} }

View File

@ -1,35 +1,138 @@
use std::env; use std::env;
use std::fs; use std::fs;
use std::io::Write; use std::io::Write;
use std::path::Path; use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio}; use std::process::{self, Command, Stdio};
pub(crate) fn cargo_command( use super::path::{Dirs, RelPath};
cargo: impl AsRef<Path>, use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path};
subcommand: &str,
triple: Option<&str>,
source_dir: &Path,
) -> Command {
let mut cmd = Command::new(cargo.as_ref());
cmd.arg(subcommand)
.arg("--manifest-path")
.arg(source_dir.join("Cargo.toml"))
.arg("--target-dir")
.arg(source_dir.join("target"));
if let Some(triple) = triple { pub(crate) struct Compiler {
cmd.arg("--target").arg(triple); pub(crate) cargo: PathBuf,
} pub(crate) rustc: PathBuf,
pub(crate) rustdoc: PathBuf,
cmd pub(crate) rustflags: String,
pub(crate) rustdocflags: String,
pub(crate) triple: String,
pub(crate) runner: Vec<String>,
} }
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 {
Compiler {
cargo: get_cargo_path(),
rustc: get_rustc_path(),
rustdoc: get_rustdoc_path(),
rustflags: String::new(),
rustdocflags: String::new(),
triple,
runner: vec![],
}
}
}
pub(crate) struct CargoProject {
source: &'static RelPath,
target: &'static str,
}
impl CargoProject {
pub(crate) const fn new(path: &'static RelPath, target: &'static str) -> CargoProject {
CargoProject { source: path, target }
}
pub(crate) fn source_dir(&self, dirs: &Dirs) -> PathBuf {
self.source.to_path(dirs)
}
pub(crate) fn manifest_path(&self, dirs: &Dirs) -> PathBuf {
self.source_dir(dirs).join("Cargo.toml")
}
pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf {
RelPath::BUILD.join(self.target).to_path(dirs)
}
fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command {
let mut cmd = Command::new(cargo);
cmd.arg(command)
.arg("--manifest-path")
.arg(self.manifest_path(dirs))
.arg("--target-dir")
.arg(self.target_dir(dirs));
cmd
}
fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command {
let mut cmd = self.base_cmd(command, &compiler.cargo, dirs);
cmd.arg("--target").arg(&compiler.triple);
cmd.env("RUSTC", &compiler.rustc);
cmd.env("RUSTDOC", &compiler.rustdoc);
cmd.env("RUSTFLAGS", &compiler.rustflags);
cmd.env("RUSTDOCFLAGS", &compiler.rustdocflags);
if !compiler.runner.is_empty() {
cmd.env(
format!("CARGO_TARGET_{}_RUNNER", compiler.triple.to_uppercase().replace('-', "_")),
compiler.runner.join(" "),
);
}
cmd
}
#[must_use]
pub(crate) fn fetch(&self, cargo: impl AsRef<Path>, dirs: &Dirs) -> Command {
let mut cmd = Command::new(cargo.as_ref());
cmd.arg("fetch").arg("--manifest-path").arg(self.manifest_path(dirs));
cmd
}
#[must_use]
pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command {
self.base_cmd("clean", cargo, dirs)
}
#[must_use]
pub(crate) fn build(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
self.build_cmd("build", compiler, dirs)
}
#[must_use]
pub(crate) fn test(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
self.build_cmd("test", compiler, dirs)
}
#[must_use]
pub(crate) fn run(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
self.build_cmd("run", compiler, dirs)
}
}
#[must_use]
pub(crate) fn hyperfine_command( pub(crate) fn hyperfine_command(
warmup: u64, warmup: u64,
runs: u64, runs: u64,
prepare: Option<Command>, prepare: Option<&str>,
a: Command, a: &str,
b: Command, b: &str,
) -> Command { ) -> Command {
let mut bench = Command::new("hyperfine"); let mut bench = Command::new("hyperfine");
@ -42,10 +145,10 @@ pub(crate) fn hyperfine_command(
} }
if let Some(prepare) = prepare { if let Some(prepare) = prepare {
bench.arg("--prepare").arg(format!("{:?}", prepare)); bench.arg("--prepare").arg(prepare);
} }
bench.arg(format!("{:?}", a)).arg(format!("{:?}", b)); bench.arg(a).arg(b);
bench bench
} }

View File

@ -2,7 +2,7 @@
set -e set -e
rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
rm -rf target/ build/ perf.data{,.old} y.bin rm -rf target/ build/ dist/ perf.data{,.old} y.bin
rm -rf download/ rm -rf download/
# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh # Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh

View File

@ -40,6 +40,7 @@ aot.subslice-patterns-const-eval
aot.track-caller-attribute aot.track-caller-attribute
aot.float-minmax-pass aot.float-minmax-pass
aot.mod_bench aot.mod_bench
aot.issue-72793
testsuite.extended_sysroot testsuite.extended_sysroot
test.rust-random/rand test.rust-random/rand

View File

@ -9,7 +9,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
In the directory with your project (where you can do the usual `cargo build`), run: In the directory with your project (where you can do the usual `cargo build`), run:
```bash ```bash
$ $cg_clif_dir/build/cargo-clif build $ $cg_clif_dir/dist/cargo-clif build
``` ```
This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
@ -19,7 +19,7 @@ This will build your project with rustc_codegen_cranelift instead of the usual L
> You should prefer using the Cargo method. > You should prefer using the Cargo method.
```bash ```bash
$ $cg_clif_dir/build/rustc-clif my_crate.rs $ $cg_clif_dir/dist/rustc-clif my_crate.rs
``` ```
## Jit mode ## Jit mode
@ -32,20 +32,20 @@ In jit mode cg_clif will immediately execute your code without creating an execu
> The jit mode will probably need cargo integration to make this possible. > The jit mode will probably need cargo integration to make this possible.
```bash ```bash
$ $cg_clif_dir/build/cargo-clif jit $ $cg_clif_dir/dist/cargo-clif jit
``` ```
or or
```bash ```bash
$ $cg_clif_dir/build/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs $ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
``` ```
There is also an experimental lazy jit mode. In this mode functions are only compiled once they are There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
first called. first called.
```bash ```bash
$ $cg_clif_dir/build/cargo-clif lazy-jit $ $cg_clif_dir/dist/cargo-clif lazy-jit
``` ```
## Shell ## Shell
@ -54,7 +54,7 @@ These are a few functions that allow you to easily run rust code from the shell
```bash ```bash
function jit_naked() { function jit_naked() {
echo "$@" | $cg_clif_dir/build/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
} }
function jit() { function jit() {

24
example/issue-72793.rs Normal file
View File

@ -0,0 +1,24 @@
// Adapted from rustc ui test suite (ui/type-alias-impl-trait/issue-72793.rs)
#![feature(type_alias_impl_trait)]
trait T { type Item; }
type Alias<'a> = impl T<Item = &'a ()>;
struct S;
impl<'a> T for &'a S {
type Item = &'a ();
}
fn filter_positive<'a>() -> Alias<'a> {
&S
}
fn with_positive(fun: impl Fn(Alias<'_>)) {
fun(filter_positive());
}
fn main() {
with_positive(|_| ());
}

View File

@ -19,6 +19,9 @@ pub trait Sized {}
#[lang = "destruct"] #[lang = "destruct"]
pub trait Destruct {} pub trait Destruct {}
#[lang = "tuple_trait"]
pub trait Tuple {}
#[lang = "unsize"] #[lang = "unsize"]
pub trait Unsize<T: ?Sized> {} pub trait Unsize<T: ?Sized> {}
@ -443,7 +446,7 @@ pub struct PhantomData<T: ?Sized>;
#[lang = "fn_once"] #[lang = "fn_once"]
#[rustc_paren_sugar] #[rustc_paren_sugar]
pub trait FnOnce<Args> { pub trait FnOnce<Args: Tuple> {
#[lang = "fn_once_output"] #[lang = "fn_once_output"]
type Output; type Output;
@ -452,7 +455,7 @@ pub trait FnOnce<Args> {
#[lang = "fn_mut"] #[lang = "fn_mut"]
#[rustc_paren_sugar] #[rustc_paren_sugar]
pub trait FnMut<Args>: FnOnce<Args> { pub trait FnMut<Args: Tuple>: FnOnce<Args> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
} }

View File

@ -171,8 +171,6 @@ fn main() {
assert_eq!(slice_ptr as usize % 4, 0); assert_eq!(slice_ptr as usize % 4, 0);
//return;
unsafe { unsafe {
printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8); printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8);

View File

@ -164,6 +164,8 @@ unsafe fn test_simd() {
let cmp_eq = _mm_cmpeq_epi8(y, y); let cmp_eq = _mm_cmpeq_epi8(y, y);
let cmp_lt = _mm_cmplt_epi8(y, y); let cmp_lt = _mm_cmplt_epi8(y, y);
let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x);
assert_eq!((zero0, zero1), (0, 0));
assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]); assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]); assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]);
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]); assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);

View File

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

View File

@ -1,3 +1,5 @@
ignore = ["y.rs"]
# Matches rustfmt.toml of rustc # Matches rustfmt.toml of rustc
version = "Two" version = "Two"
use_small_heuristics = "Max" use_small_heuristics = "Max"

View File

@ -2,7 +2,7 @@
#![forbid(unsafe_code)]/* This line is ignored by bash #![forbid(unsafe_code)]/* This line is ignored by bash
# This block is ignored by rustc # This block is ignored by rustc
pushd $(dirname "$0")/../ pushd $(dirname "$0")/../
RUSTC="$(pwd)/build/rustc-clif" RUSTC="$(pwd)/dist/rustc-clif"
popd popd
PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0 PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
#*/ #*/

36
scripts/rustdoc-clif.rs Normal file
View File

@ -0,0 +1,36 @@
use std::env;
use std::ffi::OsString;
#[cfg(unix)]
use std::os::unix::process::CommandExt;
use std::path::PathBuf;
use std::process::Command;
fn main() {
let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap());
let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join(
env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
);
let mut args = std::env::args_os().skip(1).collect::<Vec<_>>();
args.push(OsString::from("-Cpanic=abort"));
args.push(OsString::from("-Zpanic-abort-tests"));
let mut codegen_backend_arg = OsString::from("-Zcodegen-backend=");
codegen_backend_arg.push(cg_clif_dylib_path);
args.push(codegen_backend_arg);
if !args.contains(&OsString::from("--sysroot")) {
args.push(OsString::from("--sysroot"));
args.push(OsString::from(sysroot.to_str().unwrap()));
}
// Ensure that the right toolchain is used
env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
#[cfg(unix)]
Command::new("rustdoc").args(args).exec();
#[cfg(not(unix))]
std::process::exit(
Command::new("rustdoc").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
);
}

View File

@ -27,24 +27,6 @@ index d95b5b7f17f..00b6f0e3635 100644
[dev-dependencies] [dev-dependencies]
rand = "0.7" rand = "0.7"
rand_xorshift = "0.2" rand_xorshift = "0.2"
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 8431aa7b818..a3ff7e68ce5 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3489,12 +3489,7 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
let compiler_src_dir = base_dir.join("compiler");
normalize_path(&compiler_src_dir, "$(echo '$COMPILER_DIR')");
- if let Some(virtual_rust_source_base_dir) =
- option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from)
- {
- normalize_path(&virtual_rust_source_base_dir.join("library"), "$(echo '$SRC_DIR')");
- normalize_path(&virtual_rust_source_base_dir.join("compiler"), "$(echo '$COMPILER_DIR')");
- }
+ normalize_path(&Path::new("$(cd ../build_sysroot/sysroot_src/library; pwd)"), "$(echo '$SRC_DIR')");
// Paths into the build directory
let test_build_dir = &self.config.build_base;
EOF EOF
cat > config.toml <<EOF cat > config.toml <<EOF
@ -54,7 +36,7 @@ changelog-seen = 2
ninja = false ninja = false
[build] [build]
rustc = "$(pwd)/../build/rustc-clif" rustc = "$(pwd)/../dist/rustc-clif"
cargo = "$(rustup which cargo)" cargo = "$(rustup which cargo)"
full-bootstrap = true full-bootstrap = true
local-rebuild = true local-rebuild = true
@ -69,6 +51,8 @@ popd
# FIXME remove once inline asm is fully supported # FIXME remove once inline asm is fully supported
export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc" export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd build_sysroot/sysroot_src; pwd)"
# Allow the testsuite to use llvm tools # Allow the testsuite to use llvm tools
host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ") host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin" export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin"

View File

@ -20,6 +20,7 @@ for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|// error-pat
done done
git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
git checkout -- src/test/ui/proc-macro/pretty-print-hack/
# missing features # missing features
# ================ # ================
@ -30,6 +31,7 @@ rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abo
# requires compiling with -Cpanic=unwind # requires compiling with -Cpanic=unwind
rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/ rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
rm -r src/test/run-make/test-benches
# vendor intrinsics # vendor intrinsics
rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected
@ -64,6 +66,8 @@ rm src/test/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
rm -r src/test/run-make/emit-named-files # requires full --emit support rm -r src/test/run-make/emit-named-files # requires full --emit support
rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented
rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
rm -r src/test/run-make/repr128-dwarf # debuginfo test
rm src/test/codegen-units/item-collection/asm-sym.rs # requires support for sym in asm!()
# optimization tests # optimization tests
# ================== # ==================
@ -82,20 +86,20 @@ rm src/test/ui/abi/stack-protector.rs # requires stack protector support
rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
rm src/test/ui/mir/mir_raw_fat_ptr.rs # same rm src/test/ui/mir/mir_raw_fat_ptr.rs # same
rm src/test/ui/consts/issue-33537.rs # same rm src/test/ui/consts/issue-33537.rs # same
rm src/test/ui/layout/valid_range_oob.rs # different ICE message
# doesn't work due to the way the rustc test suite is invoked. # 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 # should work when using ./x.py test the way it is intended
# ============================================================ # ============================================================
rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/ rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in dist/bin/
rm -r src/test/run-make/unstable-flag-required # same rm -r src/test/run-make/unstable-flag-required # same
rm -r src/test/run-make/rustdoc-* # same rm -r src/test/run-make/rustdoc-* # same
rm -r src/test/run-make/issue-88756-default-output # same rm -r src/test/run-make/issue-88756-default-output # same
rm -r src/test/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump rm -r src/test/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
rm -r src/test/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere
# genuine bugs # genuine bugs
# ============ # ============
rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition
rm src/test/incremental/spike-neg1.rs # errors out for some reason rm src/test/incremental/spike-neg1.rs # errors out for some reason
rm src/test/incremental/spike-neg2.rs # same rm src/test/incremental/spike-neg2.rs # same
rm src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs rm src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs
@ -104,6 +108,8 @@ rm src/test/ui/type-alias-impl-trait/assoc-projection-ice.rs # produces ICE
rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
rm src/test/ui/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301)
# bugs in the test suite # bugs in the test suite
# ====================== # ======================
rm src/test/ui/backtrace.rs # TODO warning rm src/test/ui/backtrace.rs # TODO warning
@ -111,6 +117,8 @@ rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout rm src/test/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 # 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 src/test/run-make/native-link-modifier-bundle rm -r src/test/run-make/native-link-modifier-bundle
rm src/test/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
rm src/test/ui/dyn-star/dispatch-on-pin-mut.rs # TODO failed assertion in vtable::get_ptr_and_method_ref
rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd

View File

@ -56,13 +56,13 @@ pub(crate) fn conv_to_call_conv(c: Conv, default_call_conv: CallConv) -> CallCon
pub(crate) fn get_function_sig<'tcx>( pub(crate) fn get_function_sig<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
triple: &target_lexicon::Triple, default_call_conv: CallConv,
inst: Instance<'tcx>, inst: Instance<'tcx>,
) -> Signature { ) -> Signature {
assert!(!inst.substs.needs_infer()); assert!(!inst.substs.needs_infer());
clif_sig_from_fn_abi( clif_sig_from_fn_abi(
tcx, tcx,
CallConv::triple_default(triple), default_call_conv,
&RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()), &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
) )
} }
@ -74,7 +74,7 @@ pub(crate) fn import_function<'tcx>(
inst: Instance<'tcx>, inst: Instance<'tcx>,
) -> FuncId { ) -> FuncId {
let name = tcx.symbol_name(inst).name; let name = tcx.symbol_name(inst).name;
let sig = get_function_sig(tcx, module.isa().triple(), inst); let sig = get_function_sig(tcx, module.target_config().default_call_conv, inst);
match module.declare_function(name, Linkage::Import, &sig) { match module.declare_function(name, Linkage::Import, &sig) {
Ok(func_id) => func_id, Ok(func_id) => func_id,
Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!( Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
@ -341,14 +341,13 @@ pub(crate) fn codegen_terminator_call<'tcx>(
destination: Place<'tcx>, destination: Place<'tcx>,
target: Option<BasicBlock>, target: Option<BasicBlock>,
) { ) {
let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx)); let func = codegen_operand(fx, func);
let fn_sig = let fn_sig = func.layout().ty.fn_sig(fx.tcx);
fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
let ret_place = codegen_place(fx, destination); let ret_place = codegen_place(fx, destination);
// Handle special calls like intrinsics and empty drop glue. // Handle special calls like intrinsics and empty drop glue.
let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() { let instance = if let ty::FnDef(def_id, substs) = *func.layout().ty.kind() {
let instance = let instance =
ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs) ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
.polymorphize(fx.tcx); .polymorphize(fx.tcx);
@ -390,17 +389,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
None None
}; };
let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
let extra_args = fx let extra_args = fx
.tcx .tcx
.mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx)))); .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
let fn_abi = if let Some(instance) = instance { let fn_abi = if let Some(instance) = instance {
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args) RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
} else { } else {
RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args) RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_sig, extra_args)
}; };
let is_cold = if fn_sig.abi == Abi::RustCold { let is_cold = if fn_sig.abi() == Abi::RustCold {
true true
} else { } else {
instance instance
@ -417,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
} }
// Unpack arguments tuple for closures // Unpack arguments tuple for closures
let mut args = if fn_sig.abi == Abi::RustCall { let mut args = if fn_sig.abi() == Abi::RustCall {
assert_eq!(args.len(), 2, "rust-call abi requires two arguments"); assert_eq!(args.len(), 2, "rust-call abi requires two arguments");
let self_arg = codegen_call_argument_operand(fx, &args[0]); let self_arg = codegen_call_argument_operand(fx, &args[0]);
let pack_arg = codegen_call_argument_operand(fx, &args[1]); let pack_arg = codegen_call_argument_operand(fx, &args[1]);
@ -485,7 +484,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
fx.add_comment(nop_inst, "indirect call"); fx.add_comment(nop_inst, "indirect call");
} }
let func = codegen_operand(fx, func).load_scalar(fx); let func = func.load_scalar(fx);
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
let sig = fx.bcx.import_signature(sig); let sig = fx.bcx.import_signature(sig);
@ -516,11 +515,11 @@ pub(crate) fn codegen_terminator_call<'tcx>(
}; };
// FIXME find a cleaner way to support varargs // FIXME find a cleaner way to support varargs
if fn_sig.c_variadic { if fn_sig.c_variadic() {
if !matches!(fn_sig.abi, Abi::C { .. }) { if !matches!(fn_sig.abi(), Abi::C { .. }) {
fx.tcx.sess.span_fatal( fx.tcx.sess.span_fatal(
source_info.span, source_info.span,
&format!("Variadic call for non-C abi {:?}", fn_sig.abi), &format!("Variadic call for non-C abi {:?}", fn_sig.abi()),
); );
} }
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap(); let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();

View File

@ -66,7 +66,7 @@ fn codegen_inner(
}; };
let sig = Signature { let sig = Signature {
call_conv: CallConv::triple_default(module.isa().triple()), call_conv: module.target_config().default_call_conv,
params: arg_tys.iter().cloned().map(AbiParam::new).collect(), params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
returns: output.into_iter().map(AbiParam::new).collect(), returns: output.into_iter().map(AbiParam::new).collect(),
}; };
@ -104,7 +104,7 @@ fn codegen_inner(
} }
let sig = Signature { let sig = Signature {
call_conv: CallConv::triple_default(module.isa().triple()), call_conv: module.target_config().default_call_conv,
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)], params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
returns: vec![], returns: vec![],
}; };

View File

@ -59,7 +59,7 @@ pub(crate) fn codegen_fn<'tcx>(
// Declare function // Declare function
let symbol_name = tcx.symbol_name(instance).name.to_string(); let symbol_name = tcx.symbol_name(instance).name.to_string();
let sig = get_function_sig(tcx, module.isa().triple(), instance); let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap(); let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
// Make the FunctionBuilder // Make the FunctionBuilder
@ -390,11 +390,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
_ => unreachable!("{:?}", targets), _ => unreachable!("{:?}", targets),
}; };
let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
let (discr, is_inverted) = let (discr, is_inverted) =
crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr); crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr);
let test_zero = if is_inverted { !test_zero } else { test_zero }; let test_zero = if is_inverted { !test_zero } else { test_zero };
let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken( if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken(
&fx.bcx, discr, test_zero, &fx.bcx, discr, test_zero,
) { ) {
@ -571,7 +569,7 @@ fn codegen_stmt<'tcx>(
UnOp::Not => match layout.ty.kind() { UnOp::Not => match layout.ty.kind() {
ty::Bool => { ty::Bool => {
let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0); let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
CValue::by_val(fx.bcx.ins().bint(types::I8, res), layout) CValue::by_val(res, layout)
} }
ty::Uint(_) | ty::Int(_) => { ty::Uint(_) | ty::Int(_) => {
CValue::by_val(fx.bcx.ins().bnot(val), layout) CValue::by_val(fx.bcx.ins().bnot(val), layout)
@ -579,12 +577,6 @@ fn codegen_stmt<'tcx>(
_ => unreachable!("un op Not for {:?}", layout.ty), _ => unreachable!("un op Not for {:?}", layout.ty),
}, },
UnOp::Neg => match layout.ty.kind() { UnOp::Neg => match layout.ty.kind() {
ty::Int(IntTy::I128) => {
// FIXME remove this case once ineg.i128 works
let zero =
CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
crate::num::codegen_int_binop(fx, BinOp::Sub, zero, operand)
}
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout), ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout), ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
_ => unreachable!("un op Neg for {:?}", layout.ty), _ => unreachable!("un op Neg for {:?}", layout.ty),

View File

@ -149,7 +149,7 @@ pub(crate) fn clif_int_or_float_cast(
} }
let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from); let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
let zero = fx.bcx.ins().iconst(to_ty, 0); let zero = type_zero_value(&mut fx.bcx, to_ty);
fx.bcx.ins().select(is_not_nan, val, zero) fx.bcx.ins().select(is_not_nan, val, zero)
} else if from_ty.is_float() && to_ty.is_float() { } else if from_ty.is_float() && to_ty.is_float() {
// float -> float // float -> float

View File

@ -162,11 +162,20 @@ pub(crate) fn codegen_icmp_imm(
} }
} }
} else { } else {
let rhs = i64::try_from(rhs).expect("codegen_icmp_imm rhs out of range for <128bit int"); let rhs = rhs as i64; // Truncates on purpose in case rhs is actually an unsigned value
fx.bcx.ins().icmp_imm(intcc, lhs, rhs) fx.bcx.ins().icmp_imm(intcc, lhs, rhs)
} }
} }
pub(crate) fn type_zero_value(bcx: &mut FunctionBuilder<'_>, ty: Type) -> Value {
if ty == types::I128 {
let zero = bcx.ins().iconst(types::I64, 0);
bcx.ins().iconcat(zero, zero)
} else {
bcx.ins().iconst(ty, 0)
}
}
pub(crate) fn type_min_max_value( pub(crate) fn type_min_max_value(
bcx: &mut FunctionBuilder<'_>, bcx: &mut FunctionBuilder<'_>,
ty: Type, ty: Type,

View File

@ -28,9 +28,7 @@ impl ConstantCx {
} }
pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) { pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
//println!("todo {:?}", self.todo);
define_all_allocs(tcx, module, &mut self); define_all_allocs(tcx, module, &mut self);
//println!("done {:?}", self.done);
self.done.clear(); self.done.clear();
} }
} }
@ -268,16 +266,7 @@ fn data_id_for_static(
def_id: DefId, def_id: DefId,
definition: bool, definition: bool,
) -> DataId { ) -> DataId {
let rlinkage = tcx.codegen_fn_attrs(def_id).linkage; let attrs = tcx.codegen_fn_attrs(def_id);
let linkage = if definition {
crate::linkage::get_static_linkage(tcx, def_id)
} else if rlinkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
|| rlinkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
{
Linkage::Preemptible
} else {
Linkage::Import
};
let instance = Instance::mono(tcx, def_id).polymorphize(tcx); let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
let symbol_name = tcx.symbol_name(instance).name; let symbol_name = tcx.symbol_name(instance).name;
@ -289,22 +278,30 @@ fn data_id_for_static(
}; };
let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes(); let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
let attrs = tcx.codegen_fn_attrs(def_id); if let Some(import_linkage) = attrs.import_linkage {
assert!(!definition);
let data_id = match module.declare_data( let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
&*symbol_name, || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
linkage, {
is_mutable, Linkage::Preemptible
attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL), } else {
) { Linkage::Import
Ok(data_id) => data_id, };
Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
"attempt to declare `{symbol_name}` as static, but it was already declared as function" let data_id = match module.declare_data(
)), &*symbol_name,
Err(err) => Err::<_, _>(err).unwrap(), linkage,
}; is_mutable,
attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
) {
Ok(data_id) => data_id,
Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
"attempt to declare `{symbol_name}` as static, but it was already declared as function"
)),
Err(err) => Err::<_, _>(err).unwrap(),
};
if rlinkage.is_some() {
// Comment copied from https://github.com/rust-lang/rust/blob/45060c2a66dfd667f88bd8b94261b28a58d85bd5/src/librustc_codegen_llvm/consts.rs#L141 // Comment copied from https://github.com/rust-lang/rust/blob/45060c2a66dfd667f88bd8b94261b28a58d85bd5/src/librustc_codegen_llvm/consts.rs#L141
// Declare an internal global `extern_with_linkage_foo` which // Declare an internal global `extern_with_linkage_foo` which
// is initialized with the address of `foo`. If `foo` is // is initialized with the address of `foo`. If `foo` is
@ -326,10 +323,34 @@ fn data_id_for_static(
Err(ModuleError::DuplicateDefinition(_)) => {} Err(ModuleError::DuplicateDefinition(_)) => {}
res => res.unwrap(), res => res.unwrap(),
} }
ref_data_id
} else { return ref_data_id;
data_id
} }
let linkage = if definition {
crate::linkage::get_static_linkage(tcx, def_id)
} else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
|| attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
{
Linkage::Preemptible
} else {
Linkage::Import
};
let data_id = match module.declare_data(
&*symbol_name,
linkage,
is_mutable,
attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
) {
Ok(data_id) => data_id,
Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
"attempt to declare `{symbol_name}` as static, but it was already declared as function"
)),
Err(err) => Err::<_, _>(err).unwrap(),
};
data_id
} }
fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) { fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) {
@ -348,8 +369,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
(data_id, alloc, None) (data_id, alloc, None)
} }
TodoItem::Static(def_id) => { TodoItem::Static(def_id) => {
//println!("static {:?}", def_id);
let section_name = tcx.codegen_fn_attrs(def_id).link_section; let section_name = tcx.codegen_fn_attrs(def_id).link_section;
let alloc = tcx.eval_static_initializer(def_id).unwrap(); let alloc = tcx.eval_static_initializer(def_id).unwrap();
@ -359,7 +378,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
} }
}; };
//("data_id {}", data_id);
if cx.done.contains(&data_id) { if cx.done.contains(&data_id) {
continue; continue;
} }

View File

@ -39,7 +39,9 @@ impl UnwindContext {
} }
pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) { pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) {
let unwind_info = if let Some(unwind_info) = context.create_unwind_info(isa).unwrap() { let unwind_info = if let Some(unwind_info) =
context.compiled_code().unwrap().create_unwind_info(isa).unwrap()
{
unwind_info unwind_info
} else { } else {
return; return;

View File

@ -1,6 +1,7 @@
//! Handling of enum discriminants //! Handling of enum discriminants
//! //!
//! Adapted from <https://github.com/rust-lang/rust/blob/d760df5aea483aae041c9a241e7acacf48f75035/src/librustc_codegen_ssa/mir/place.rs> //! Adapted from <https://github.com/rust-lang/rust/blob/31c0645b9d2539f47eecb096142474b29dc542f7/compiler/rustc_codegen_ssa/src/mir/place.rs>
//! (<https://github.com/rust-lang/rust/pull/104535>)
use rustc_target::abi::{Int, TagEncoding, Variants}; use rustc_target::abi::{Int, TagEncoding, Variants};
@ -47,13 +48,19 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
} => { } => {
if variant_index != untagged_variant { if variant_index != untagged_variant {
let niche = place.place_field(fx, mir::Field::new(tag_field)); let niche = place.place_field(fx, mir::Field::new(tag_field));
let niche_type = fx.clif_type(niche.layout().ty).unwrap();
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
let niche_value = ty::ScalarInt::try_from_uint( let niche_value = (niche_value as u128).wrapping_add(niche_start);
u128::from(niche_value).wrapping_add(niche_start), let niche_value = match niche_type {
niche.layout().size, types::I128 => {
) let lsb = fx.bcx.ins().iconst(types::I64, niche_value as u64 as i64);
.unwrap(); let msb =
let niche_llval = CValue::const_val(fx, niche.layout(), niche_value); fx.bcx.ins().iconst(types::I64, (niche_value >> 64) as u64 as i64);
fx.bcx.ins().iconcat(lsb, msb)
}
ty => fx.bcx.ins().iconst(ty, niche_value as i64),
};
let niche_llval = CValue::by_val(niche_value, niche.layout());
niche.write_cvalue(fx, niche_llval); niche.write_cvalue(fx, niche_llval);
} }
} }
@ -96,6 +103,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
} }
}; };
let cast_to_size = dest_layout.layout.size();
let cast_to = fx.clif_type(dest_layout.ty).unwrap(); let cast_to = fx.clif_type(dest_layout.ty).unwrap();
// Read the tag/niche-encoded discriminant from memory. // Read the tag/niche-encoded discriminant from memory.
@ -114,21 +122,128 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
dest.write_cvalue(fx, res); dest.write_cvalue(fx, res);
} }
TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
// Rebase from niche values to discriminants, and check let tag_size = tag_scalar.size(fx);
// whether the result is in range for the niche variants. let max_unsigned = tag_size.unsigned_int_max();
let max_signed = tag_size.signed_int_max() as u128;
let min_signed = max_signed + 1;
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
let niche_end = niche_start.wrapping_add(relative_max as u128) & max_unsigned;
let range = tag_scalar.valid_range(fx);
// We first compute the "relative discriminant" (wrt `niche_variants`), let sle = |lhs: u128, rhs: u128| -> bool {
// that is, if `n = niche_variants.end() - niche_variants.start()`, // Signed and unsigned comparisons give the same results,
// we remap `niche_start..=niche_start + n` (which may wrap around) // except that in signed comparisons an integer with the
// to (non-wrap-around) `0..=n`, to be able to check whether the // sign bit set is less than one with the sign bit clear.
// discriminant corresponds to a niche variant with one comparison. // Toggle the sign bit to do a signed comparison.
// We also can't go directly to the (variant index) discriminant (lhs ^ min_signed) <= (rhs ^ min_signed)
// and check that it is in the range `niche_variants`, because };
// that might not fit in the same type, on top of needing an extra
// comparison (see also the comment on `let niche_discr`). // We have a subrange `niche_start..=niche_end` inside `range`.
let relative_discr = if niche_start == 0 { // If the value of the tag is inside this subrange, it's a
tag // "niche value", an increment of the discriminant. Otherwise it
// indicates the untagged variant.
// A general algorithm to extract the discriminant from the tag
// is:
// relative_tag = tag - niche_start
// is_niche = relative_tag <= (ule) relative_max
// discr = if is_niche {
// cast(relative_tag) + niche_variants.start()
// } else {
// untagged_variant
// }
// However, we will likely be able to emit simpler code.
// Find the least and greatest values in `range`, considered
// both as signed and unsigned.
let (low_unsigned, high_unsigned) =
if range.start <= range.end { (range.start, range.end) } else { (0, max_unsigned) };
let (low_signed, high_signed) = if sle(range.start, range.end) {
(range.start, range.end)
} else { } else {
(min_signed, max_signed)
};
let niches_ule = niche_start <= niche_end;
let niches_sle = sle(niche_start, niche_end);
let cast_smaller = cast_to_size <= tag_size;
// In the algorithm above, we can change
// cast(relative_tag) + niche_variants.start()
// into
// cast(tag + (niche_variants.start() - niche_start))
// if either the casted type is no larger than the original
// type, or if the niche values are contiguous (in either the
// signed or unsigned sense).
let can_incr = cast_smaller || niches_ule || niches_sle;
let data_for_boundary_niche = || -> Option<(IntCC, u128)> {
if !can_incr {
None
} else if niche_start == low_unsigned {
Some((IntCC::UnsignedLessThanOrEqual, niche_end))
} else if niche_end == high_unsigned {
Some((IntCC::UnsignedGreaterThanOrEqual, niche_start))
} else if niche_start == low_signed {
Some((IntCC::SignedLessThanOrEqual, niche_end))
} else if niche_end == high_signed {
Some((IntCC::SignedGreaterThanOrEqual, niche_start))
} else {
None
}
};
let (is_niche, tagged_discr, delta) = if relative_max == 0 {
// Best case scenario: only one tagged variant. This will
// likely become just a comparison and a jump.
// The algorithm is:
// is_niche = tag == niche_start
// discr = if is_niche {
// niche_start
// } else {
// untagged_variant
// }
let is_niche = codegen_icmp_imm(fx, IntCC::Equal, tag, niche_start as i128);
let tagged_discr =
fx.bcx.ins().iconst(cast_to, niche_variants.start().as_u32() as i64);
(is_niche, tagged_discr, 0)
} else if let Some((predicate, constant)) = data_for_boundary_niche() {
// The niche values are either the lowest or the highest in
// `range`. We can avoid the first subtraction in the
// algorithm.
// The algorithm is now this:
// is_niche = tag <= niche_end
// discr = if is_niche {
// cast(tag + (niche_variants.start() - niche_start))
// } else {
// untagged_variant
// }
// (the first line may instead be tag >= niche_start,
// and may be a signed or unsigned comparison)
// The arithmetic must be done before the cast, so we can
// have the correct wrapping behavior. See issue #104519 for
// the consequences of getting this wrong.
let is_niche = codegen_icmp_imm(fx, predicate, tag, constant as i128);
let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start);
let incr_tag = if delta == 0 {
tag
} else {
let delta = match fx.bcx.func.dfg.value_type(tag) {
types::I128 => {
let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
fx.bcx.ins().iconcat(lsb, msb)
}
ty => fx.bcx.ins().iconst(ty, delta as i64),
};
fx.bcx.ins().iadd(tag, delta)
};
let cast_tag = clif_intcast(fx, incr_tag, cast_to, !niches_ule);
(is_niche, cast_tag, 0)
} else {
// The special cases don't apply, so we'll have to go with
// the general algorithm.
let niche_start = match fx.bcx.func.dfg.value_type(tag) { let niche_start = match fx.bcx.func.dfg.value_type(tag) {
types::I128 => { types::I128 => {
let lsb = fx.bcx.ins().iconst(types::I64, niche_start as u64 as i64); let lsb = fx.bcx.ins().iconst(types::I64, niche_start as u64 as i64);
@ -138,40 +253,40 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
} }
ty => fx.bcx.ins().iconst(ty, niche_start as i64), ty => fx.bcx.ins().iconst(ty, niche_start as i64),
}; };
fx.bcx.ins().isub(tag, niche_start) let relative_discr = fx.bcx.ins().isub(tag, niche_start);
}; let cast_tag = clif_intcast(fx, relative_discr, cast_to, false);
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); let is_niche = crate::common::codegen_icmp_imm(
let is_niche = {
codegen_icmp_imm(
fx, fx,
IntCC::UnsignedLessThanOrEqual, IntCC::UnsignedLessThanOrEqual,
relative_discr, relative_discr,
i128::from(relative_max), i128::from(relative_max),
) );
(is_niche, cast_tag, niche_variants.start().as_u32() as u128)
}; };
// NOTE(eddyb) this addition needs to be performed on the final let tagged_discr = if delta == 0 {
// type, in case the niche itself can't represent all variant tagged_discr
// indices (e.g. `u8` niche with more than `256` variants, } else {
// but enough uninhabited variants so that the remaining variants let delta = match cast_to {
// fit in the niche). types::I128 => {
// In other words, `niche_variants.end - niche_variants.start` let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
// is representable in the niche, but `niche_variants.end` let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
// might not be, in extreme cases. fx.bcx.ins().iconcat(lsb, msb)
let niche_discr = { }
let relative_discr = if relative_max == 0 { ty => fx.bcx.ins().iconst(ty, delta as i64),
// HACK(eddyb) since we have only one niche, we know which
// one it is, and we can avoid having a dynamic value here.
fx.bcx.ins().iconst(cast_to, 0)
} else {
clif_intcast(fx, relative_discr, cast_to, false)
}; };
fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32())) fx.bcx.ins().iadd(tagged_discr, delta)
}; };
let untagged_variant = let untagged_variant = if cast_to == types::I128 {
fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32())); let zero = fx.bcx.ins().iconst(types::I64, 0);
let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant); let untagged_variant =
fx.bcx.ins().iconst(types::I64, i64::from(untagged_variant.as_u32()));
fx.bcx.ins().iconcat(untagged_variant, zero)
} else {
fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()))
};
let discr = fx.bcx.ins().select(is_niche, tagged_discr, untagged_variant);
let res = CValue::by_val(discr, dest_layout); let res = CValue::by_val(discr, dest_layout);
dest.write_cvalue(fx, res); dest.write_cvalue(fx, res);
} }

View File

@ -159,7 +159,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
tcx.sess.abort_if_errors(); tcx.sess.abort_if_errors();
jit_module.finalize_definitions(); jit_module.finalize_definitions().unwrap();
unsafe { cx.unwind_context.register_jit(&jit_module) }; unsafe { cx.unwind_context.register_jit(&jit_module) };
println!( println!(
@ -245,7 +245,11 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
let backend_config = lazy_jit_state.backend_config.clone(); let backend_config = lazy_jit_state.backend_config.clone();
let name = tcx.symbol_name(instance).name; let name = tcx.symbol_name(instance).name;
let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance); let sig = crate::abi::get_function_sig(
tcx,
jit_module.target_config().default_call_conv,
instance,
);
let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap(); let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
let current_ptr = jit_module.read_got_entry(func_id); let current_ptr = jit_module.read_got_entry(func_id);
@ -278,7 +282,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
}); });
assert!(cx.global_asm.is_empty()); assert!(cx.global_asm.is_empty());
jit_module.finalize_definitions(); jit_module.finalize_definitions().unwrap();
unsafe { cx.unwind_context.register_jit(&jit_module) }; unsafe { cx.unwind_context.register_jit(&jit_module) };
jit_module.get_finalized_function(func_id) jit_module.get_finalized_function(func_id)
}) })
@ -344,7 +348,7 @@ fn codegen_shim<'tcx>(
let pointer_type = module.target_config().pointer_type(); let pointer_type = module.target_config().pointer_type();
let name = tcx.symbol_name(inst).name; let name = tcx.symbol_name(inst).name;
let sig = crate::abi::get_function_sig(tcx, module.isa().triple(), inst); let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap(); let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
let instance_ptr = Box::into_raw(Box::new(inst)); let instance_ptr = Box::into_raw(Box::new(inst));

View File

@ -24,7 +24,8 @@ fn predefine_mono_items<'tcx>(
MonoItem::Fn(instance) => { MonoItem::Fn(instance) => {
let name = tcx.symbol_name(instance).name; let name = tcx.symbol_name(instance).name;
let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name)); let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name));
let sig = get_function_sig(tcx, module.isa().triple(), instance); let sig =
get_function_sig(tcx, module.target_config().default_call_conv, instance);
let linkage = crate::linkage::get_clif_linkage( let linkage = crate::linkage::get_clif_linkage(
mono_item, mono_item,
linkage, linkage,

View File

@ -8,135 +8,37 @@ use rustc_middle::ty::subst::SubstsRef;
pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>, fx: &mut FunctionCx<'_, '_, 'tcx>,
intrinsic: &str, intrinsic: &str,
_substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
args: &[mir::Operand<'tcx>], args: &[mir::Operand<'tcx>],
ret: CPlace<'tcx>, ret: CPlace<'tcx>,
target: Option<BasicBlock>, target: Option<BasicBlock>,
) { ) {
match intrinsic { if intrinsic.starts_with("llvm.aarch64") {
"llvm.x86.sse2.pause" | "llvm.aarch64.isb" => { return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(
// Spin loop hint fx, intrinsic, substs, args, ret, target,
} );
}
if intrinsic.starts_with("llvm.x86") {
return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, substs, args, ret, target);
}
// Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8` match intrinsic {
"llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => { _ if intrinsic.starts_with("llvm.ctlz.v") => {
intrinsic_args!(fx, args => (a); intrinsic); intrinsic_args!(fx, args => (a); intrinsic);
let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
let lane_ty = fx.clif_type(lane_ty).unwrap(); fx.bcx.ins().clz(lane)
assert!(lane_count <= 32);
let mut res = fx.bcx.ins().iconst(types::I32, 0);
for lane in (0..lane_count).rev() {
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
// 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),
_ => a_lane,
};
// extract sign bit of an int
let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
// shift sign bit into result
let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
res = fx.bcx.ins().ishl_imm(res, 1);
res = fx.bcx.ins().bor(res, a_lane_sign);
}
let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
ret.write_cvalue(fx, res);
}
"llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
let (x, y, kind) = match args {
[x, y, kind] => (x, y, kind),
_ => bug!("wrong number of args for intrinsic {intrinsic}"),
};
let x = codegen_operand(fx, x);
let y = codegen_operand(fx, y);
let kind = crate::constant::mir_operand_get_const_val(fx, kind)
.expect("llvm.x86.sse2.cmp.* kind not const");
let flt_cc = match kind
.try_to_bits(Size::from_bytes(1))
.unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
{
0 => FloatCC::Equal,
1 => FloatCC::LessThan,
2 => FloatCC::LessThanOrEqual,
7 => FloatCC::Ordered,
3 => FloatCC::Unordered,
4 => FloatCC::NotEqual,
5 => FloatCC::UnorderedOrGreaterThanOrEqual,
6 => FloatCC::UnorderedOrGreaterThan,
kind => unreachable!("kind {:?}", kind),
};
simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
let res_lane = match lane_ty.kind() {
ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
_ => unreachable!("{:?}", lane_ty),
};
bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
}); });
} }
"llvm.x86.sse2.psrli.d" => {
let (a, imm8) = match args {
[a, imm8] => (a, imm8),
_ => bug!("wrong number of args for intrinsic {intrinsic}"),
};
let a = codegen_operand(fx, a);
let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
.expect("llvm.x86.sse2.psrli.d imm8 not const");
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8 _ if intrinsic.starts_with("llvm.ctpop.v") => {
.try_to_bits(Size::from_bytes(4)) intrinsic_args!(fx, args => (a); intrinsic);
.unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
{ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)), fx.bcx.ins().popcnt(lane)
_ => fx.bcx.ins().iconst(types::I32, 0),
}); });
} }
"llvm.x86.sse2.pslli.d" => {
let (a, imm8) = match args {
[a, imm8] => (a, imm8),
_ => bug!("wrong number of args for intrinsic {intrinsic}"),
};
let a = codegen_operand(fx, a);
let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
.expect("llvm.x86.sse2.psrli.d imm8 not const");
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
.try_to_bits(Size::from_bytes(4))
.unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
{
imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
_ => fx.bcx.ins().iconst(types::I32, 0),
});
}
"llvm.x86.sse2.storeu.dq" => {
intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
let mem_addr = mem_addr.load_scalar(fx);
// FIXME correctly handle the unalignment
let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
dest.write_cvalue(fx, a);
}
"llvm.x86.addcarry.64" => {
intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
let c_in = c_in.load_scalar(fx);
llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
}
"llvm.x86.subborrow.64" => {
intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
let b_in = b_in.load_scalar(fx);
llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
}
_ => { _ => {
fx.tcx fx.tcx
.sess .sess
@ -150,47 +52,3 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
let ret_block = fx.get_block(dest); let ret_block = fx.get_block(dest);
fx.bcx.ins().jump(ret_block, &[]); fx.bcx.ins().jump(ret_block, &[]);
} }
// llvm.x86.avx2.vperm2i128
// llvm.x86.ssse3.pshuf.b.128
// llvm.x86.avx2.pshuf.b
// llvm.x86.avx2.psrli.w
// llvm.x86.sse2.psrli.w
fn llvm_add_sub<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
bin_op: BinOp,
ret: CPlace<'tcx>,
cb_in: Value,
a: CValue<'tcx>,
b: CValue<'tcx>,
) {
assert_eq!(
a.layout().ty,
fx.tcx.types.u64,
"llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
);
assert_eq!(
b.layout().ty,
fx.tcx.types.u64,
"llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
);
// c + carry -> c + first intermediate carry or borrow respectively
let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
let c = int0.value_field(fx, mir::Field::new(0));
let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
// c + carry -> c + second intermediate carry or borrow respectively
let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
let (c, cb1) = int1.load_scalar_pair(fx);
// carry0 | carry1 -> carry or borrow respectively
let cb_out = fx.bcx.ins().bor(cb0, cb1);
let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
let val = CValue::by_val_pair(cb_out, c, layout);
ret.write_cvalue(fx, val);
}

View File

@ -0,0 +1,222 @@
//! Emulate AArch64 LLVM intrinsics
use crate::intrinsics::*;
use crate::prelude::*;
use rustc_middle::ty::subst::SubstsRef;
pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
intrinsic: &str,
_substs: SubstsRef<'tcx>,
args: &[mir::Operand<'tcx>],
ret: CPlace<'tcx>,
target: Option<BasicBlock>,
) {
// llvm.aarch64.neon.sqshl.v*i*
match intrinsic {
"llvm.aarch64.isb" => {
fx.bcx.ins().fence();
}
_ if intrinsic.starts_with("llvm.aarch64.neon.abs.v") => {
intrinsic_args!(fx, args => (a); intrinsic);
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
fx.bcx.ins().iabs(lane)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.cls.v") => {
intrinsic_args!(fx, args => (a); intrinsic);
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
fx.bcx.ins().cls(lane)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.rbit.v") => {
intrinsic_args!(fx, args => (a); intrinsic);
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
fx.bcx.ins().bitrev(lane)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") => {
intrinsic_args!(fx, args => (x, y); intrinsic);
simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
crate::num::codegen_saturating_int_binop(fx, BinOp::Add, x_lane, y_lane)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") => {
intrinsic_args!(fx, args => (x, y); intrinsic);
simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
crate::num::codegen_saturating_int_binop(fx, BinOp::Sub, x_lane, y_lane)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.smax.v") => {
intrinsic_args!(fx, args => (x, y); intrinsic);
simd_pair_for_each_lane(
fx,
x,
y,
ret,
&|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, x_lane, y_lane);
fx.bcx.ins().select(gt, x_lane, y_lane)
},
);
}
_ if intrinsic.starts_with("llvm.aarch64.neon.umax.v") => {
intrinsic_args!(fx, args => (x, y); intrinsic);
simd_pair_for_each_lane(
fx,
x,
y,
ret,
&|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, x_lane, y_lane);
fx.bcx.ins().select(gt, x_lane, y_lane)
},
);
}
_ if intrinsic.starts_with("llvm.aarch64.neon.smaxv.i") => {
intrinsic_args!(fx, args => (v); intrinsic);
simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b);
fx.bcx.ins().select(gt, a, b)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.umaxv.i") => {
intrinsic_args!(fx, args => (v); intrinsic);
simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b);
fx.bcx.ins().select(gt, a, b)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.smin.v") => {
intrinsic_args!(fx, args => (x, y); intrinsic);
simd_pair_for_each_lane(
fx,
x,
y,
ret,
&|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane);
fx.bcx.ins().select(gt, x_lane, y_lane)
},
);
}
_ if intrinsic.starts_with("llvm.aarch64.neon.umin.v") => {
intrinsic_args!(fx, args => (x, y); intrinsic);
simd_pair_for_each_lane(
fx,
x,
y,
ret,
&|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, x_lane, y_lane);
fx.bcx.ins().select(gt, x_lane, y_lane)
},
);
}
_ if intrinsic.starts_with("llvm.aarch64.neon.sminv.i") => {
intrinsic_args!(fx, args => (v); intrinsic);
simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b);
fx.bcx.ins().select(gt, a, b)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.uminv.i") => {
intrinsic_args!(fx, args => (v); intrinsic);
simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b);
fx.bcx.ins().select(gt, a, b)
});
}
/*
_ if intrinsic.starts_with("llvm.aarch64.neon.sshl.v")
|| intrinsic.starts_with("llvm.aarch64.neon.sqshl.v")
// FIXME split this one out once saturating is implemented
|| intrinsic.starts_with("llvm.aarch64.neon.sqshlu.v") =>
{
intrinsic_args!(fx, args => (a, b); intrinsic);
simd_pair_for_each_lane(fx, a, b, ret, &|fx, _lane_ty, _res_lane_ty, a, b| {
// FIXME saturate?
fx.bcx.ins().ishl(a, b)
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.sqshrn.v") => {
let (a, imm32) = match args {
[a, imm32] => (a, imm32),
_ => bug!("wrong number of args for intrinsic {intrinsic}"),
};
let a = codegen_operand(fx, a);
let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
.expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
.try_to_bits(Size::from_bytes(4))
.unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
{
imm32 if imm32 < 32 => fx.bcx.ins().sshr_imm(lane, i64::from(imm32 as u8)),
_ => fx.bcx.ins().iconst(types::I32, 0),
});
}
_ if intrinsic.starts_with("llvm.aarch64.neon.sqshrun.v") => {
let (a, imm32) = match args {
[a, imm32] => (a, imm32),
_ => bug!("wrong number of args for intrinsic {intrinsic}"),
};
let a = codegen_operand(fx, a);
let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
.expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
.try_to_bits(Size::from_bytes(4))
.unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
{
imm32 if imm32 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm32 as u8)),
_ => fx.bcx.ins().iconst(types::I32, 0),
});
}
*/
_ => {
fx.tcx.sess.warn(&format!(
"unsupported AArch64 llvm intrinsic {}; replacing with trap",
intrinsic
));
crate::trap::trap_unimplemented(fx, intrinsic);
return;
}
}
let dest = target.expect("all llvm intrinsics used by stdlib should return");
let ret_block = fx.get_block(dest);
fx.bcx.ins().jump(ret_block, &[]);
}

197
src/intrinsics/llvm_x86.rs Normal file
View File

@ -0,0 +1,197 @@
//! Emulate x86 LLVM intrinsics
use crate::intrinsics::*;
use crate::prelude::*;
use rustc_middle::ty::subst::SubstsRef;
pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
intrinsic: &str,
_substs: SubstsRef<'tcx>,
args: &[mir::Operand<'tcx>],
ret: CPlace<'tcx>,
target: Option<BasicBlock>,
) {
match intrinsic {
"llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
// Spin loop hint
}
// Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
"llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
intrinsic_args!(fx, args => (a); intrinsic);
let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
let lane_ty = fx.clif_type(lane_ty).unwrap();
assert!(lane_count <= 32);
let mut res = fx.bcx.ins().iconst(types::I32, 0);
for lane in (0..lane_count).rev() {
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
// 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),
_ => a_lane,
};
// extract sign bit of an int
let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
// shift sign bit into result
let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
res = fx.bcx.ins().ishl_imm(res, 1);
res = fx.bcx.ins().bor(res, a_lane_sign);
}
let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
ret.write_cvalue(fx, res);
}
"llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
let (x, y, kind) = match args {
[x, y, kind] => (x, y, kind),
_ => bug!("wrong number of args for intrinsic {intrinsic}"),
};
let x = codegen_operand(fx, x);
let y = codegen_operand(fx, y);
let kind = crate::constant::mir_operand_get_const_val(fx, kind)
.expect("llvm.x86.sse2.cmp.* kind not const");
let flt_cc = match kind
.try_to_bits(Size::from_bytes(1))
.unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
{
0 => FloatCC::Equal,
1 => FloatCC::LessThan,
2 => FloatCC::LessThanOrEqual,
7 => FloatCC::Ordered,
3 => FloatCC::Unordered,
4 => FloatCC::NotEqual,
5 => FloatCC::UnorderedOrGreaterThanOrEqual,
6 => FloatCC::UnorderedOrGreaterThan,
kind => unreachable!("kind {:?}", kind),
};
simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
let res_lane = match lane_ty.kind() {
ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
_ => unreachable!("{:?}", lane_ty),
};
bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
});
}
"llvm.x86.sse2.psrli.d" => {
let (a, imm8) = match args {
[a, imm8] => (a, imm8),
_ => bug!("wrong number of args for intrinsic {intrinsic}"),
};
let a = codegen_operand(fx, a);
let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
.expect("llvm.x86.sse2.psrli.d imm8 not const");
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
.try_to_bits(Size::from_bytes(4))
.unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
{
imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
_ => fx.bcx.ins().iconst(types::I32, 0),
});
}
"llvm.x86.sse2.pslli.d" => {
let (a, imm8) = match args {
[a, imm8] => (a, imm8),
_ => bug!("wrong number of args for intrinsic {intrinsic}"),
};
let a = codegen_operand(fx, a);
let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
.expect("llvm.x86.sse2.psrli.d imm8 not const");
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
.try_to_bits(Size::from_bytes(4))
.unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
{
imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
_ => fx.bcx.ins().iconst(types::I32, 0),
});
}
"llvm.x86.sse2.storeu.dq" => {
intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
let mem_addr = mem_addr.load_scalar(fx);
// FIXME correctly handle the unalignment
let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
dest.write_cvalue(fx, a);
}
"llvm.x86.addcarry.64" => {
intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
let c_in = c_in.load_scalar(fx);
llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
}
"llvm.x86.subborrow.64" => {
intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
let b_in = b_in.load_scalar(fx);
llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
}
_ => {
fx.tcx.sess.warn(&format!(
"unsupported x86 llvm intrinsic {}; replacing with trap",
intrinsic
));
crate::trap::trap_unimplemented(fx, intrinsic);
return;
}
}
let dest = target.expect("all llvm intrinsics used by stdlib should return");
let ret_block = fx.get_block(dest);
fx.bcx.ins().jump(ret_block, &[]);
}
// llvm.x86.avx2.vperm2i128
// llvm.x86.ssse3.pshuf.b.128
// llvm.x86.avx2.pshuf.b
// llvm.x86.avx2.psrli.w
// llvm.x86.sse2.psrli.w
fn llvm_add_sub<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
bin_op: BinOp,
ret: CPlace<'tcx>,
cb_in: Value,
a: CValue<'tcx>,
b: CValue<'tcx>,
) {
assert_eq!(
a.layout().ty,
fx.tcx.types.u64,
"llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
);
assert_eq!(
b.layout().ty,
fx.tcx.types.u64,
"llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
);
// c + carry -> c + first intermediate carry or borrow respectively
let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
let c = int0.value_field(fx, mir::Field::new(0));
let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
// c + carry -> c + second intermediate carry or borrow respectively
let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
let (c, cb1) = int1.load_scalar_pair(fx);
// carry0 | carry1 -> carry or borrow respectively
let cb_out = fx.bcx.ins().bor(cb0, cb1);
let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
let val = CValue::by_val_pair(cb_out, c, layout);
ret.write_cvalue(fx, val);
}

View File

@ -14,6 +14,8 @@ macro_rules! intrinsic_args {
mod cpuid; mod cpuid;
mod llvm; mod llvm;
mod llvm_aarch64;
mod llvm_x86;
mod simd; mod simd;
pub(crate) use cpuid::codegen_cpuid_call; pub(crate) use cpuid::codegen_cpuid_call;
@ -195,8 +197,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
ty => ty, ty => ty,
}; };
let val = fx.bcx.ins().bint(int_ty, val); let mut res = fx.bcx.ins().bmask(int_ty, val);
let mut res = fx.bcx.ins().ineg(val);
if ty.is_float() { if ty.is_float() {
res = fx.bcx.ins().bitcast(ty, res); res = fx.bcx.ins().bitcast(ty, res);
@ -632,85 +633,15 @@ fn codegen_regular_intrinsic_call<'tcx>(
ret.write_cvalue(fx, res); ret.write_cvalue(fx, res);
} }
sym::bswap => { sym::bswap => {
// FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift
fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
match bcx.func.dfg.value_type(v) {
types::I8 => v,
// https://code.woboq.org/gcc/include/bits/byteswap.h.html
types::I16 => {
let tmp1 = bcx.ins().ishl_imm(v, 8);
let n1 = bcx.ins().band_imm(tmp1, 0xFF00);
let tmp2 = bcx.ins().ushr_imm(v, 8);
let n2 = bcx.ins().band_imm(tmp2, 0x00FF);
bcx.ins().bor(n1, n2)
}
types::I32 => {
let tmp1 = bcx.ins().ishl_imm(v, 24);
let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000);
let tmp2 = bcx.ins().ishl_imm(v, 8);
let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000);
let tmp3 = bcx.ins().ushr_imm(v, 8);
let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00);
let tmp4 = bcx.ins().ushr_imm(v, 24);
let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF);
let or_tmp1 = bcx.ins().bor(n1, n2);
let or_tmp2 = bcx.ins().bor(n3, n4);
bcx.ins().bor(or_tmp1, or_tmp2)
}
types::I64 => {
let tmp1 = bcx.ins().ishl_imm(v, 56);
let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000_0000_0000u64 as i64);
let tmp2 = bcx.ins().ishl_imm(v, 40);
let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000_0000_0000u64 as i64);
let tmp3 = bcx.ins().ishl_imm(v, 24);
let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00_0000_0000u64 as i64);
let tmp4 = bcx.ins().ishl_imm(v, 8);
let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF_0000_0000u64 as i64);
let tmp5 = bcx.ins().ushr_imm(v, 8);
let n5 = bcx.ins().band_imm(tmp5, 0x0000_0000_FF00_0000u64 as i64);
let tmp6 = bcx.ins().ushr_imm(v, 24);
let n6 = bcx.ins().band_imm(tmp6, 0x0000_0000_00FF_0000u64 as i64);
let tmp7 = bcx.ins().ushr_imm(v, 40);
let n7 = bcx.ins().band_imm(tmp7, 0x0000_0000_0000_FF00u64 as i64);
let tmp8 = bcx.ins().ushr_imm(v, 56);
let n8 = bcx.ins().band_imm(tmp8, 0x0000_0000_0000_00FFu64 as i64);
let or_tmp1 = bcx.ins().bor(n1, n2);
let or_tmp2 = bcx.ins().bor(n3, n4);
let or_tmp3 = bcx.ins().bor(n5, n6);
let or_tmp4 = bcx.ins().bor(n7, n8);
let or_tmp5 = bcx.ins().bor(or_tmp1, or_tmp2);
let or_tmp6 = bcx.ins().bor(or_tmp3, or_tmp4);
bcx.ins().bor(or_tmp5, or_tmp6)
}
types::I128 => {
let (lo, hi) = bcx.ins().isplit(v);
let lo = swap(bcx, lo);
let hi = swap(bcx, hi);
bcx.ins().iconcat(hi, lo)
}
ty => unreachable!("bswap {}", ty),
}
}
intrinsic_args!(fx, args => (arg); intrinsic); intrinsic_args!(fx, args => (arg); intrinsic);
let val = arg.load_scalar(fx); let val = arg.load_scalar(fx);
let res = CValue::by_val(swap(&mut fx.bcx, val), arg.layout()); let res = if fx.bcx.func.dfg.value_type(val) == types::I8 {
val
} else {
fx.bcx.ins().bswap(val)
};
let res = CValue::by_val(res, arg.layout());
ret.write_cvalue(fx, res); ret.write_cvalue(fx, res);
} }
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
@ -936,8 +867,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
let old = fx.bcx.ins().atomic_cas(MemFlags::trusted(), ptr, test_old, new); let old = fx.bcx.ins().atomic_cas(MemFlags::trusted(), ptr, test_old, new);
let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old); let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old);
let ret_val = let ret_val = CValue::by_val_pair(old, is_eq, ret.layout());
CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout());
ret.write_cvalue(fx, ret_val) ret.write_cvalue(fx, ret_val)
} }
@ -1259,8 +1189,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
flags.set_notrap(); flags.set_notrap();
let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0);
let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0);
let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val); fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val)
fx.bcx.ins().bint(types::I8, eq)
} else { } else {
// Just call `memcmp` (like slices do in core) when the // Just call `memcmp` (like slices do in core) when the
// size is too large or it's not a power-of-two. // size is too large or it's not a power-of-two.
@ -1270,8 +1199,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
let returns = vec![AbiParam::new(types::I32)]; let returns = vec![AbiParam::new(types::I32)];
let args = &[lhs_ref, rhs_ref, bytes_val]; let args = &[lhs_ref, rhs_ref, bytes_val];
let cmp = fx.lib_call("memcmp", params, returns, args)[0]; let cmp = fx.lib_call("memcmp", params, returns, args)[0];
let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0); fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0)
fx.bcx.ins().bint(types::I8, eq)
}; };
ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout())); ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
} }

View File

@ -112,10 +112,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
_ => unreachable!(), _ => unreachable!(),
}; };
let ty = fx.clif_type(res_lane_ty).unwrap(); bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
let res_lane = fx.bcx.ins().bint(ty, res_lane);
fx.bcx.ins().ineg(res_lane)
}); });
} }
@ -716,7 +713,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let res_type = let res_type =
Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap(); Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
let mut res = fx.bcx.ins().iconst(res_type, 0); let mut res = type_zero_value(&mut fx.bcx, res_type);
let lanes = match fx.tcx.sess.target.endian { let lanes = match fx.tcx.sess.target.endian {
Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>, Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,

View File

@ -65,7 +65,7 @@ pub(crate) fn maybe_create_entry_wrapper(
returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)], returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
call_conv: crate::conv_to_call_conv( call_conv: crate::conv_to_call_conv(
tcx.sess.target.options.entry_abi, tcx.sess.target.options.entry_abi,
CallConv::triple_default(m.isa().triple()), m.target_config().default_call_conv,
), ),
}; };
@ -75,7 +75,7 @@ pub(crate) fn maybe_create_entry_wrapper(
let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx); let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
let main_name = tcx.symbol_name(instance).name; let main_name = tcx.symbol_name(instance).name;
let main_sig = get_function_sig(tcx, m.isa().triple(), instance); let main_sig = get_function_sig(tcx, m.target_config().default_call_conv, instance);
let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap(); let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();
let mut ctx = Context::new(); let mut ctx = Context::new();
@ -119,7 +119,7 @@ pub(crate) fn maybe_create_entry_wrapper(
.polymorphize(tcx); .polymorphize(tcx);
let report_name = tcx.symbol_name(report).name; let report_name = tcx.symbol_name(report).name;
let report_sig = get_function_sig(tcx, m.isa().triple(), report); let report_sig = get_function_sig(tcx, m.target_config().default_call_conv, report);
let report_func_id = let report_func_id =
m.declare_function(report_name, Linkage::Import, &report_sig).unwrap(); m.declare_function(report_name, Linkage::Import, &report_sig).unwrap();
let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func); let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func);

View File

@ -49,7 +49,6 @@ fn codegen_compare_bin_op<'tcx>(
) -> CValue<'tcx> { ) -> CValue<'tcx> {
let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap(); let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
let val = fx.bcx.ins().icmp(intcc, lhs, rhs); let val = fx.bcx.ins().icmp(intcc, lhs, rhs);
let val = fx.bcx.ins().bint(types::I8, val);
CValue::by_val(val, fx.layout_of(fx.tcx.types.bool)) CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
} }
@ -290,8 +289,6 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
_ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs), _ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs),
}; };
let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter())); let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
CValue::by_val_pair(res, has_overflow, out_layout) CValue::by_val_pair(res, has_overflow, out_layout)
} }
@ -368,7 +365,6 @@ pub(crate) fn codegen_float_binop<'tcx>(
_ => unreachable!(), _ => unreachable!(),
}; };
let val = fx.bcx.ins().fcmp(fltcc, lhs, rhs); let val = fx.bcx.ins().fcmp(fltcc, lhs, rhs);
let val = fx.bcx.ins().bint(types::I8, val);
return CValue::by_val(val, fx.layout_of(fx.tcx.types.bool)); return CValue::by_val(val, fx.layout_of(fx.tcx.types.bool));
} }
_ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs), _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs),
@ -440,7 +436,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
_ => panic!("bin_op {:?} on ptr", bin_op), _ => panic!("bin_op {:?} on ptr", bin_op),
}; };
CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool)) CValue::by_val(res, fx.layout_of(fx.tcx.types.bool))
} }
} }

View File

@ -3,19 +3,6 @@
use cranelift_codegen::ir::{condcodes::IntCC, InstructionData, Opcode, Value, ValueDef}; use cranelift_codegen::ir::{condcodes::IntCC, InstructionData, Opcode, Value, ValueDef};
use cranelift_frontend::FunctionBuilder; use cranelift_frontend::FunctionBuilder;
/// If the given value was produced by a `bint` instruction, return it's input, otherwise return the
/// given value.
pub(crate) fn maybe_unwrap_bint(bcx: &mut FunctionBuilder<'_>, arg: Value) -> Value {
if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
match bcx.func.dfg[arg_inst] {
InstructionData::Unary { opcode: Opcode::Bint, arg } => arg,
_ => arg,
}
} else {
arg
}
}
/// If the given value was produced by the lowering of `Rvalue::Not` return the input and true, /// If the given value was produced by the lowering of `Rvalue::Not` return the input and true,
/// otherwise return the given value and false. /// otherwise return the given value and false.
pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) { pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) {
@ -48,13 +35,6 @@ pub(crate) fn maybe_known_branch_taken(
}; };
match bcx.func.dfg[arg_inst] { match bcx.func.dfg[arg_inst] {
InstructionData::UnaryBool { opcode: Opcode::Bconst, imm } => {
if test_zero {
Some(!imm)
} else {
Some(imm)
}
}
InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => { InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
if test_zero { if test_zero {
Some(imm.bits() == 0) Some(imm.bits() == 0)

View File

@ -392,7 +392,7 @@ impl<'tcx> CPlace<'tcx> {
local: Local, local: Local,
layout: TyAndLayout<'tcx>, layout: TyAndLayout<'tcx>,
) -> CPlace<'tcx> { ) -> CPlace<'tcx> {
let var = Variable::with_u32(fx.next_ssa_var); let var = Variable::from_u32(fx.next_ssa_var);
fx.next_ssa_var += 1; fx.next_ssa_var += 1;
fx.bcx.declare_var(var, fx.clif_type(layout.ty).unwrap()); fx.bcx.declare_var(var, fx.clif_type(layout.ty).unwrap());
CPlace { inner: CPlaceInner::Var(local, var), layout } CPlace { inner: CPlaceInner::Var(local, var), layout }
@ -403,9 +403,9 @@ impl<'tcx> CPlace<'tcx> {
local: Local, local: Local,
layout: TyAndLayout<'tcx>, layout: TyAndLayout<'tcx>,
) -> CPlace<'tcx> { ) -> CPlace<'tcx> {
let var1 = Variable::with_u32(fx.next_ssa_var); let var1 = Variable::from_u32(fx.next_ssa_var);
fx.next_ssa_var += 1; fx.next_ssa_var += 1;
let var2 = Variable::with_u32(fx.next_ssa_var); let var2 = Variable::from_u32(fx.next_ssa_var);
fx.next_ssa_var += 1; fx.next_ssa_var += 1;
let (ty1, ty2) = fx.clif_pair_type(layout.ty).unwrap(); let (ty1, ty2) = fx.clif_pair_type(layout.ty).unwrap();
@ -515,9 +515,7 @@ impl<'tcx> CPlace<'tcx> {
| (types::F32, types::I32) | (types::F32, types::I32)
| (types::I64, types::F64) | (types::I64, types::F64)
| (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data), | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data),
_ if src_ty.is_vector() && dst_ty.is_vector() => { _ if src_ty.is_vector() && dst_ty.is_vector() => fx.bcx.ins().bitcast(dst_ty, data),
fx.bcx.ins().raw_bitcast(dst_ty, data)
}
_ if src_ty.is_vector() || dst_ty.is_vector() => { _ if src_ty.is_vector() || dst_ty.is_vector() => {
// FIXME do something more efficient for transmutes between vectors and integers. // FIXME do something more efficient for transmutes between vectors and integers.
let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
@ -590,7 +588,10 @@ impl<'tcx> CPlace<'tcx> {
return; return;
} }
CPlaceInner::VarPair(_local, var1, var2) => { CPlaceInner::VarPair(_local, var1, var2) => {
let (data1, data2) = CValue(from.0, dst_layout).load_scalar_pair(fx); let (ptr, meta) = from.force_stack(fx);
assert!(meta.is_none());
let (data1, data2) =
CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx);
let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap(); let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap();
transmute_value(fx, var1, data1, dst_ty1); transmute_value(fx, var1, data1, dst_ty1);
transmute_value(fx, var2, data2, dst_ty2); transmute_value(fx, var2, data2, dst_ty2);

View File

@ -1,2 +1,2 @@
#!/usr/bin/env bash #!/usr/bin/env bash
exec ./y.rs test exec ./y.rs test "$@"

2
y.rs
View File

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