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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,16 +4,10 @@
"rust-analyzer.imports.granularity.enforce": true,
"rust-analyzer.imports.granularity.group": "module",
"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": [
"./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": [
{
"root_module": "./example/mini_core.rs",
@ -36,34 +30,11 @@
]
},
{
"roots": ["./example/std_example.rs"],
"sysroot_src": "./build_sysroot/sysroot_src/library",
"crates": [
{
"root_module": "./example/std_example.rs",
"edition": "2018",
"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",
"edition": "2015",
"deps": [],
"cfg": [],
},

View File

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

View File

@ -3,17 +3,24 @@ name = "rustc_codegen_cranelift"
version = "0.1.0"
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]
crate-type = ["dylib"]
[dependencies]
# These have to be in sync with each other
cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
cranelift-frontend = "0.88.1"
cranelift-module = "0.88.1"
cranelift-native = "0.88.1"
cranelift-jit = { version = "0.88.1", optional = true }
cranelift-object = "0.88.1"
cranelift-codegen = { version = "0.90.1", features = ["unwind", "all-arch"] }
cranelift-frontend = "0.90.1"
cranelift-module = "0.90.1"
cranelift-native = "0.90.1"
cranelift-jit = { version = "0.90.1", optional = true }
cranelift-object = "0.90.1"
target-lexicon = "0.12.0"
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
@ -39,6 +46,7 @@ smallvec = "1.8.1"
unstable-features = ["jit", "inline_asm"]
jit = ["cranelift-jit", "libloading"]
inline_asm = []
__check_build_system_using_ra = []
[package.metadata.rust-analyzer]
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:
```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.

View File

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

View File

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

View File

@ -1,16 +1,19 @@
use std::env;
use std::path::PathBuf;
use super::path::{Dirs, RelPath};
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(
dirs: &Dirs,
channel: &str,
host_triple: &str,
use_unstable_features: bool,
) -> PathBuf {
let source_dir = std::env::current_dir().unwrap();
let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
let mut cmd = CG_CLIF.build(&Compiler::host(), dirs);
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");
super::utils::spawn_and_wait(cmd);
source_dir
.join("target")
CG_CLIF
.target_dir(dirs)
.join(host_triple)
.join(channel)
.join(get_file_name("rustc_codegen_cranelift", "dylib"))

View File

@ -1,57 +1,60 @@
use std::fs;
use std::path::{Path, PathBuf};
use std::path::Path;
use std::process::{self, Command};
use super::path::{Dirs, RelPath};
use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler};
use super::SysrootKind;
static DIST_DIR: RelPath = RelPath::DIST;
static BIN_DIR: RelPath = RelPath::DIST.join("bin");
static LIB_DIR: RelPath = RelPath::DIST.join("lib");
static RUSTLIB_DIR: RelPath = LIB_DIR.join("rustlib");
pub(crate) fn build_sysroot(
dirs: &Dirs,
channel: &str,
sysroot_kind: SysrootKind,
target_dir: &Path,
cg_clif_dylib_src: &Path,
host_triple: &str,
target_triple: &str,
) {
eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
if target_dir.exists() {
fs::remove_dir_all(target_dir).unwrap();
}
fs::create_dir_all(target_dir.join("bin")).unwrap();
fs::create_dir_all(target_dir.join("lib")).unwrap();
DIST_DIR.ensure_fresh(dirs);
BIN_DIR.ensure_exists(dirs);
LIB_DIR.ensure_exists(dirs);
// Copy the backend
let cg_clif_dylib_path = target_dir
.join(if cfg!(windows) {
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
// binaries.
"bin"
} else {
"lib"
})
.join(get_file_name("rustc_codegen_cranelift", "dylib"));
let cg_clif_dylib_path = if cfg!(windows) {
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
// binaries.
BIN_DIR
} else {
LIB_DIR
}
.to_path(dirs)
.join(get_file_name("rustc_codegen_cranelift", "dylib"));
try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
// 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 mut build_cargo_wrapper_cmd = Command::new("rustc");
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(target_dir.join(wrapper_name))
.arg(DIST_DIR.to_path(dirs).join(wrapper_name))
.arg("-g");
spawn_and_wait(build_cargo_wrapper_cmd);
}
let default_sysroot = super::rustc_info::get_default_sysroot();
let rustlib = target_dir.join("lib").join("rustlib");
let host_rustlib_lib = rustlib.join(host_triple).join("lib");
let target_rustlib_lib = rustlib.join(target_triple).join("lib");
let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib");
let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(target_triple).join("lib");
fs::create_dir_all(&host_rustlib_lib).unwrap();
fs::create_dir_all(&target_rustlib_lib).unwrap();
@ -112,24 +115,18 @@ pub(crate) fn build_sysroot(
}
}
SysrootKind::Clif => {
build_clif_sysroot_for_triple(
channel,
target_dir,
host_triple,
&cg_clif_dylib_path,
None,
);
build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, None);
if host_triple != target_triple {
// When cross-compiling it is often necessary to manually pick the right linker
let linker = if target_triple == "aarch64-unknown-linux-gnu" {
Some("aarch64-linux-gnu-gcc")
} else {
None
let linker = match target_triple {
"aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"),
"s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"),
_ => None,
};
build_clif_sysroot_for_triple(
dirs,
channel,
target_dir,
target_triple,
&cg_clif_dylib_path,
linker,
@ -142,21 +139,26 @@ pub(crate) fn build_sysroot(
let file = file.unwrap().path();
let filename = file.file_name().unwrap().to_str().unwrap();
if filename.contains("std-") && !filename.contains(".rlib") {
try_hard_link(&file, 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(
dirs: &Dirs,
channel: &str,
target_dir: &Path,
triple: &str,
cg_clif_dylib_path: &Path,
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) => {
eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
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") {
// 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
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();
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" {
build_cmd.arg("--release");
rustflags.push_str(" -Zmir-opt-level=3");
}
if let Some(linker) = linker {
use std::fmt::Write;
write!(rustflags, " -Clinker={}", linker).unwrap();
}
build_cmd.env("RUSTFLAGS", rustflags);
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");
spawn_and_wait(build_cmd);
// Copy all relevant files to the sysroot
for entry in
fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps"))
.unwrap()
{
for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
let entry = entry.unwrap();
if let Some(ext) = entry.path().extension() {
if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
@ -216,7 +218,7 @@ fn build_clif_sysroot_for_triple(
};
try_hard_link(
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_sysroot;
mod config;
mod path;
mod prepare;
mod rustc_info;
mod tests;
mod utils;
const USAGE: &str = r#"The build system of cg_clif.
USAGE:
./y.rs prepare [--out-dir DIR]
./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
OPTIONS:
--sysroot none|clif|llvm
Which sysroot libraries to use:
`none` will not include any standard library in the sysroot.
`clif` will build the standard library using Cranelift.
`llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
--out-dir DIR
Specify the directory in which the download, build and dist directories are stored.
By default this is the working directory.
--no-unstable-features
fSome features are not yet ready for production usage. This option will disable these
features. This includes the JIT mode and inline assembly support.
"#;
fn usage() {
eprintln!("Usage:");
eprintln!(" ./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]"
);
eprintln!("{USAGE}");
}
macro_rules! arg_error {
@ -34,6 +51,7 @@ macro_rules! arg_error {
#[derive(PartialEq, Debug)]
enum Command {
Prepare,
Build,
Test,
}
@ -48,8 +66,6 @@ pub(crate) enum SysrootKind {
pub fn main() {
env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
// The target dir is expected in the default location. Guard against the user changing it.
env::set_var("CARGO_TARGET_DIR", "target");
if is_ci() {
// 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 command = match args.next().as_deref() {
Some("prepare") => {
if args.next().is_some() {
arg_error!("./y.rs prepare doesn't expect arguments");
}
prepare::prepare();
process::exit(0);
}
Some("prepare") => Command::Prepare,
Some("build") => Command::Build,
Some("test") => Command::Test,
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 sysroot_kind = SysrootKind::Clif;
let mut use_unstable_features = true;
while let Some(arg) = args.next().as_deref() {
match arg {
"--target-dir" => {
target_dir = PathBuf::from(args.next().unwrap_or_else(|| {
arg_error!("--target-dir requires argument");
"--out-dir" => {
out_dir = PathBuf::from(args.next().unwrap_or_else(|| {
arg_error!("--out-dir requires argument");
}))
}
"--debug" => channel = "debug",
@ -101,7 +111,6 @@ pub fn main() {
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") {
host_triple
@ -122,13 +131,43 @@ pub fn main() {
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 {
Command::Prepare => {
// Handled above
}
Command::Test => {
tests::run_tests(
&dirs,
channel,
sysroot_kind,
&target_dir,
&cg_clif_dylib,
&host_triple,
&target_triple,
@ -137,7 +176,7 @@ pub fn main() {
abi_cafe::run(
channel,
sysroot_kind,
&target_dir,
&dirs,
&cg_clif_dylib,
&host_triple,
&target_triple,
@ -145,9 +184,9 @@ pub fn main() {
}
Command::Build => {
build_sysroot::build_sysroot(
&dirs,
channel,
sysroot_kind,
&target_dir,
&cg_clif_dylib,
&host_triple,
&target_triple,

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::fs;
use std::path::{Path, PathBuf};
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::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 =
GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
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();
pub(crate) fn prepare(dirs: &Dirs) {
if RelPath::DOWNLOAD.to_path(dirs).exists() {
std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
}
std::fs::create_dir_all(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?
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();
RAND.fetch();
REGEX.fetch();
PORTABLE_SIMD.fetch();
SIMPLE_RAYTRACER.fetch();
super::abi_cafe::ABI_CAFE_REPO.fetch(dirs);
super::tests::RAND_REPO.fetch(dirs);
super::tests::REGEX_REPO.fetch(dirs);
super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs);
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);
fs::copy(
SIMPLE_RAYTRACER
.source_dir()
.join("target")
super::tests::SIMPLE_RAYTRACER
.target_dir(dirs)
.join(&host_compiler.triple)
.join("debug")
.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();
}
fn prepare_sysroot() {
fn prepare_sysroot(dirs: &Dirs) {
let rustc_path = get_rustc_path();
let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src");
let sysroot_src = SYSROOT_SRC;
assert!(sysroot_src_orig.exists());
if sysroot_src.exists() {
fs::remove_dir_all(&sysroot_src).unwrap();
}
fs::create_dir_all(sysroot_src.join("library")).unwrap();
sysroot_src.ensure_fresh(dirs);
fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap();
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();
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");
let mut git_init_cmd = Command::new("git");
git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src);
spawn_and_wait(git_init_cmd);
init_git_repo(&sysroot_src.to_path(dirs));
init_git_repo(&sysroot_src);
apply_patches("sysroot", &sysroot_src);
apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs));
}
pub(crate) struct GitRepo {
@ -100,7 +83,7 @@ enum GitRepoUrl {
}
impl GitRepo {
const fn github(
pub(crate) const fn github(
user: &'static str,
repo: &'static str,
rev: &'static str,
@ -109,21 +92,25 @@ impl GitRepo {
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 {
GitRepoUrl::Github { user: _, repo } => {
std::env::current_dir().unwrap().join("download").join(repo)
}
GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo),
}
}
fn fetch(&self) {
fn fetch(&self, dirs: &Dirs) {
match self.url {
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);
}
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) {
// 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);
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_file = downloads_dir.join(format!("{}.tar.gz", rev));
let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
let archive_file = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}.tar.gz", rev));
let archive_dir = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}-{}", repo, rev));
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
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);
// Rename unpacked dir to the expected name
@ -191,12 +176,21 @@ fn init_git_repo(repo_dir: &Path) {
spawn_and_wait(git_add_cmd);
let mut git_commit_cmd = Command::new("git");
git_commit_cmd.arg("commit").arg("-m").arg("Initial commit").arg("-q").current_dir(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);
}
fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> {
let mut patches: Vec<_> = fs::read_dir(RelPath::PATCHES.to_path(dirs))
.unwrap()
.map(|entry| entry.unwrap().path())
.filter(|path| path.extension() == Some(OsStr::new("patch")))
@ -215,19 +209,27 @@ fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
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>" {
return;
}
for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
for patch in get_patches(dirs, crate_name) {
eprintln!(
"[PATCH] {:?} <- {:?}",
target_dir.file_name().unwrap(),
patch.file_name().unwrap()
);
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);
}
}

View File

@ -23,6 +23,16 @@ pub(crate) fn get_host_triple() -> String {
.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 {
let rustc_path = Command::new("rustup")
.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()
}
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 {
let default_sysroot = Command::new("rustc")
.stderr(Stdio::inherit())

View File

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

View File

@ -2,7 +2,7 @@
set -e
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/
# 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.float-minmax-pass
aot.mod_bench
aot.issue-72793
testsuite.extended_sysroot
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:
```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.
@ -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.
```bash
$ $cg_clif_dir/build/rustc-clif my_crate.rs
$ $cg_clif_dir/dist/rustc-clif my_crate.rs
```
## 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.
```bash
$ $cg_clif_dir/build/cargo-clif jit
$ $cg_clif_dir/dist/cargo-clif jit
```
or
```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
first called.
```bash
$ $cg_clif_dir/build/cargo-clif lazy-jit
$ $cg_clif_dir/dist/cargo-clif lazy-jit
```
## Shell
@ -54,7 +54,7 @@ These are a few functions that allow you to easily run rust code from the shell
```bash
function jit_naked() {
echo "$@" | $cg_clif_dir/build/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() {

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"]
pub trait Destruct {}
#[lang = "tuple_trait"]
pub trait Tuple {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
@ -443,7 +446,7 @@ pub struct PhantomData<T: ?Sized>;
#[lang = "fn_once"]
#[rustc_paren_sugar]
pub trait FnOnce<Args> {
pub trait FnOnce<Args: Tuple> {
#[lang = "fn_once_output"]
type Output;
@ -452,7 +455,7 @@ pub trait FnOnce<Args> {
#[lang = "fn_mut"]
#[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;
}

View File

@ -171,8 +171,6 @@ fn main() {
assert_eq!(slice_ptr as usize % 4, 0);
//return;
unsafe {
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_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]>(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]);

View File

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

View File

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

View File

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

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]
rand = "0.7"
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
cat > config.toml <<EOF
@ -54,7 +36,7 @@ changelog-seen = 2
ninja = false
[build]
rustc = "$(pwd)/../build/rustc-clif"
rustc = "$(pwd)/../dist/rustc-clif"
cargo = "$(rustup which cargo)"
full-bootstrap = true
local-rebuild = true
@ -69,6 +51,8 @@ popd
# FIXME remove once inline asm is fully supported
export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd build_sysroot/sysroot_src; pwd)"
# Allow the testsuite to use llvm tools
host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
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
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
# ================
@ -30,6 +31,7 @@ rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abo
# requires compiling with -Cpanic=unwind
rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
rm -r src/test/run-make/test-benches
# vendor intrinsics
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 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 -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
# ==================
@ -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_raw_fat_ptr.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.
# 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/rustdoc-* # 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/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere
# 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-neg2.rs # same
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/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301)
# bugs in the test suite
# ======================
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
# 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 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

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>(
tcx: TyCtxt<'tcx>,
triple: &target_lexicon::Triple,
default_call_conv: CallConv,
inst: Instance<'tcx>,
) -> Signature {
assert!(!inst.substs.needs_infer());
clif_sig_from_fn_abi(
tcx,
CallConv::triple_default(triple),
default_call_conv,
&RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
)
}
@ -74,7 +74,7 @@ pub(crate) fn import_function<'tcx>(
inst: Instance<'tcx>,
) -> FuncId {
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) {
Ok(func_id) => func_id,
Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
@ -341,14 +341,13 @@ pub(crate) fn codegen_terminator_call<'tcx>(
destination: Place<'tcx>,
target: Option<BasicBlock>,
) {
let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
let fn_sig =
fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
let func = codegen_operand(fx, func);
let fn_sig = func.layout().ty.fn_sig(fx.tcx);
let ret_place = codegen_place(fx, destination);
// 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 =
ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
.polymorphize(fx.tcx);
@ -390,17 +389,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
None
};
let extra_args = &args[fn_sig.inputs().len()..];
let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
let extra_args = 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 {
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
} 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
} else {
instance
@ -417,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
}
// 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");
let self_arg = codegen_call_argument_operand(fx, &args[0]);
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");
}
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 = fx.bcx.import_signature(sig);
@ -516,11 +515,11 @@ pub(crate) fn codegen_terminator_call<'tcx>(
};
// FIXME find a cleaner way to support varargs
if fn_sig.c_variadic {
if !matches!(fn_sig.abi, Abi::C { .. }) {
if fn_sig.c_variadic() {
if !matches!(fn_sig.abi(), Abi::C { .. }) {
fx.tcx.sess.span_fatal(
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();

View File

@ -66,7 +66,7 @@ fn codegen_inner(
};
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(),
returns: output.into_iter().map(AbiParam::new).collect(),
};
@ -104,7 +104,7 @@ fn codegen_inner(
}
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)],
returns: vec![],
};

View File

@ -59,7 +59,7 @@ pub(crate) fn codegen_fn<'tcx>(
// Declare function
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();
// Make the FunctionBuilder
@ -390,11 +390,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
_ => unreachable!("{:?}", targets),
};
let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
let (discr, is_inverted) =
crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr);
let test_zero = if is_inverted { !test_zero } else { test_zero };
let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken(
&fx.bcx, discr, test_zero,
) {
@ -571,7 +569,7 @@ fn codegen_stmt<'tcx>(
UnOp::Not => match layout.ty.kind() {
ty::Bool => {
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(_) => {
CValue::by_val(fx.bcx.ins().bnot(val), layout)
@ -579,12 +577,6 @@ fn codegen_stmt<'tcx>(
_ => unreachable!("un op Not for {:?}", layout.ty),
},
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::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
_ => 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 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)
} else if from_ty.is_float() && to_ty.is_float() {
// float -> float

View File

@ -162,11 +162,20 @@ pub(crate) fn codegen_icmp_imm(
}
}
} 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)
}
}
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(
bcx: &mut FunctionBuilder<'_>,
ty: Type,

View File

@ -28,9 +28,7 @@ impl ConstantCx {
}
pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
//println!("todo {:?}", self.todo);
define_all_allocs(tcx, module, &mut self);
//println!("done {:?}", self.done);
self.done.clear();
}
}
@ -268,16 +266,7 @@ fn data_id_for_static(
def_id: DefId,
definition: bool,
) -> DataId {
let rlinkage = tcx.codegen_fn_attrs(def_id).linkage;
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 attrs = tcx.codegen_fn_attrs(def_id);
let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
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 attrs = tcx.codegen_fn_attrs(def_id);
if let Some(import_linkage) = attrs.import_linkage {
assert!(!definition);
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(),
};
let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
|| import_linkage == 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(),
};
if rlinkage.is_some() {
// 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
// is initialized with the address of `foo`. If `foo` is
@ -326,10 +323,34 @@ fn data_id_for_static(
Err(ModuleError::DuplicateDefinition(_)) => {}
res => res.unwrap(),
}
ref_data_id
} else {
data_id
return ref_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) {
@ -348,8 +369,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
(data_id, alloc, None)
}
TodoItem::Static(def_id) => {
//println!("static {:?}", def_id);
let section_name = tcx.codegen_fn_attrs(def_id).link_section;
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) {
continue;
}

View File

@ -39,7 +39,9 @@ impl UnwindContext {
}
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
} else {
return;

View File

@ -1,6 +1,7 @@
//! 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};
@ -47,13 +48,19 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
} => {
if variant_index != untagged_variant {
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 = ty::ScalarInt::try_from_uint(
u128::from(niche_value).wrapping_add(niche_start),
niche.layout().size,
)
.unwrap();
let niche_llval = CValue::const_val(fx, niche.layout(), niche_value);
let niche_value = (niche_value as u128).wrapping_add(niche_start);
let niche_value = match niche_type {
types::I128 => {
let lsb = fx.bcx.ins().iconst(types::I64, niche_value as u64 as i64);
let msb =
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);
}
}
@ -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();
// Read the tag/niche-encoded discriminant from memory.
@ -114,21 +122,128 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
dest.write_cvalue(fx, res);
}
TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
// Rebase from niche values to discriminants, and check
// whether the result is in range for the niche variants.
let tag_size = tag_scalar.size(fx);
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`),
// that is, if `n = niche_variants.end() - niche_variants.start()`,
// we remap `niche_start..=niche_start + n` (which may wrap around)
// to (non-wrap-around) `0..=n`, to be able to check whether the
// discriminant corresponds to a niche variant with one comparison.
// We also can't go directly to the (variant index) discriminant
// 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`).
let relative_discr = if niche_start == 0 {
tag
let sle = |lhs: u128, rhs: u128| -> bool {
// Signed and unsigned comparisons give the same results,
// except that in signed comparisons an integer with the
// sign bit set is less than one with the sign bit clear.
// Toggle the sign bit to do a signed comparison.
(lhs ^ min_signed) <= (rhs ^ min_signed)
};
// We have a subrange `niche_start..=niche_end` inside `range`.
// If the value of the tag is inside this subrange, it's a
// "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 {
(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) {
types::I128 => {
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),
};
fx.bcx.ins().isub(tag, niche_start)
};
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
let is_niche = {
codegen_icmp_imm(
let relative_discr = fx.bcx.ins().isub(tag, niche_start);
let cast_tag = clif_intcast(fx, relative_discr, cast_to, false);
let is_niche = crate::common::codegen_icmp_imm(
fx,
IntCC::UnsignedLessThanOrEqual,
relative_discr,
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
// type, in case the niche itself can't represent all variant
// indices (e.g. `u8` niche with more than `256` variants,
// but enough uninhabited variants so that the remaining variants
// fit in the niche).
// In other words, `niche_variants.end - niche_variants.start`
// is representable in the niche, but `niche_variants.end`
// might not be, in extreme cases.
let niche_discr = {
let relative_discr = if relative_max == 0 {
// 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)
let tagged_discr = if delta == 0 {
tagged_discr
} else {
let delta = match cast_to {
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_imm(relative_discr, i64::from(niche_variants.start().as_u32()))
fx.bcx.ins().iadd(tagged_discr, delta)
};
let untagged_variant =
fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()));
let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant);
let untagged_variant = if cast_to == types::I128 {
let zero = fx.bcx.ins().iconst(types::I64, 0);
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);
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();
jit_module.finalize_definitions();
jit_module.finalize_definitions().unwrap();
unsafe { cx.unwind_context.register_jit(&jit_module) };
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 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 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());
jit_module.finalize_definitions();
jit_module.finalize_definitions().unwrap();
unsafe { cx.unwind_context.register_jit(&jit_module) };
jit_module.get_finalized_function(func_id)
})
@ -344,7 +348,7 @@ fn codegen_shim<'tcx>(
let pointer_type = module.target_config().pointer_type();
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 instance_ptr = Box::into_raw(Box::new(inst));

View File

@ -24,7 +24,8 @@ fn predefine_mono_items<'tcx>(
MonoItem::Fn(instance) => {
let name = tcx.symbol_name(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(
mono_item,
linkage,

View File

@ -8,135 +8,37 @@ use rustc_middle::ty::subst::SubstsRef;
pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
intrinsic: &str,
_substs: SubstsRef<'tcx>,
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
}
if intrinsic.starts_with("llvm.aarch64") {
return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(
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`
"llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
match intrinsic {
_ if intrinsic.starts_with("llvm.ctlz.v") => {
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)
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
fx.bcx.ins().clz(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),
_ if intrinsic.starts_with("llvm.ctpop.v") => {
intrinsic_args!(fx, args => (a); intrinsic);
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
fx.bcx.ins().popcnt(lane)
});
}
"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
@ -150,47 +52,3 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
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

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

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 llvm;
mod llvm_aarch64;
mod llvm_x86;
mod simd;
pub(crate) use cpuid::codegen_cpuid_call;
@ -195,8 +197,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
ty => ty,
};
let val = fx.bcx.ins().bint(int_ty, val);
let mut res = fx.bcx.ins().ineg(val);
let mut res = fx.bcx.ins().bmask(int_ty, val);
if ty.is_float() {
res = fx.bcx.ins().bitcast(ty, res);
@ -632,85 +633,15 @@ fn codegen_regular_intrinsic_call<'tcx>(
ret.write_cvalue(fx, res);
}
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);
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);
}
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 is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old);
let ret_val =
CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout());
let ret_val = CValue::by_val_pair(old, is_eq, ret.layout());
ret.write_cvalue(fx, ret_val)
}
@ -1259,8 +1189,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
flags.set_notrap();
let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0);
let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0);
let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val);
fx.bcx.ins().bint(types::I8, eq)
fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val)
} else {
// Just call `memcmp` (like slices do in core) when the
// size is too large or it's not a power-of-two.
@ -1270,8 +1199,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
let returns = vec![AbiParam::new(types::I32)];
let args = &[lhs_ref, rhs_ref, bytes_val];
let cmp = fx.lib_call("memcmp", params, returns, args)[0];
let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0);
fx.bcx.ins().bint(types::I8, eq)
fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0)
};
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!(),
};
let ty = fx.clif_type(res_lane_ty).unwrap();
let res_lane = fx.bcx.ins().bint(ty, res_lane);
fx.bcx.ins().ineg(res_lane)
bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
});
}
@ -716,7 +713,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let res_type =
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 {
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*/)],
call_conv: crate::conv_to_call_conv(
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 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 mut ctx = Context::new();
@ -119,7 +119,7 @@ pub(crate) fn maybe_create_entry_wrapper(
.polymorphize(tcx);
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 =
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);

View File

@ -49,7 +49,6 @@ fn codegen_compare_bin_op<'tcx>(
) -> CValue<'tcx> {
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().bint(types::I8, val);
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),
};
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()));
CValue::by_val_pair(res, has_overflow, out_layout)
}
@ -368,7 +365,6 @@ pub(crate) fn codegen_float_binop<'tcx>(
_ => unreachable!(),
};
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));
}
_ => 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),
};
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_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,
/// otherwise return the given value and false.
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] {
InstructionData::UnaryBool { opcode: Opcode::Bconst, imm } => {
if test_zero {
Some(!imm)
} else {
Some(imm)
}
}
InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
if test_zero {
Some(imm.bits() == 0)

View File

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

View File

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

View File

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