Merge commit 'a0b865dc87' into sync_cg_clif-2025-11-08

This commit is contained in:
bjorn3 2025-11-08 14:18:53 +00:00
parent 2073d1209d
commit c90a9d836b
58 changed files with 1664 additions and 832 deletions

View file

@ -1,21 +1,23 @@
# FIXME re-enable once https://github.com/rust-lang/rust/issues/134863 is fixed.
# task:
# name: freebsd
# freebsd_instance:
# image: freebsd-13-2-release-amd64
# setup_rust_script:
# - pkg install -y git-tiny binutils
# - curl https://sh.rustup.rs -sSf --output rustup.sh
# - sh rustup.sh --default-toolchain none -y --profile=minimal
# target_cache:
# folder: build/cg_clif
# prepare_script:
# - . $HOME/.cargo/env
# - ./y.sh prepare
# test_script:
# - . $HOME/.cargo/env
# # Disabling incr comp reduces cache size and incr comp doesn't save as much
# # on CI anyway.
# - export CARGO_BUILD_INCREMENTAL=false
# # Skip rand as it fails on FreeBSD due to rust-random/rand#1355
# - ./y.sh test --skip-test test.rust-random/rand
task:
name: freebsd
freebsd_instance:
image_family: freebsd-14-2
setup_rust_script:
- pkg install -y git-tiny binutils
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh --default-toolchain none -y --profile=minimal
target_cache:
folder: build/cg_clif
prepare_script:
- . $HOME/.cargo/env
- ./y.sh prepare
test_script:
- . $HOME/.cargo/env
# Disabling incr comp reduces cache size and incr comp doesn't save as much
# on CI anyway.
- export CARGO_BUILD_INCREMENTAL=false
# FIXME(rust-lang/rust#134863) necessary to avoid error when dlopening proc
# macros during compilation of cg_clif.
- export LD_STATIC_TLS_EXTRA=4096
# Skip rand as it fails on FreeBSD due to rust-random/rand#1355
- ./y.sh test --skip-test test.rust-random/rand

View file

@ -28,7 +28,7 @@ jobs:
- os: ubuntu-24.04-arm
env:
TARGET_TRIPLE: aarch64-unknown-linux-gnu
- os: macos-13
- os: macos-15-intel
env:
TARGET_TRIPLE: x86_64-apple-darwin
- os: macos-latest

View file

@ -56,7 +56,7 @@ jobs:
- os: ubuntu-24.04-arm
env:
TARGET_TRIPLE: aarch64-unknown-linux-gnu
- os: macos-13
- os: macos-15-intel
env:
TARGET_TRIPLE: x86_64-apple-darwin
- os: macos-latest
@ -187,7 +187,7 @@ jobs:
- os: ubuntu-24.04-arm
env:
TARGET_TRIPLE: aarch64-unknown-linux-gnu
- os: macos-13
- os: macos-15-intel
env:
TARGET_TRIPLE: x86_64-apple-darwin
- os: macos-latest
@ -231,7 +231,7 @@ jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 10
if: ${{ github.ref == 'refs/heads/master' }}
if: ${{ github.ref == 'refs/heads/main' }}
needs: [rustfmt, test, bench, dist]
permissions:

View file

@ -20,13 +20,13 @@
"crates": [
{
"root_module": "./example/mini_core.rs",
"edition": "2015",
"edition": "2024",
"deps": [],
"cfg": [],
},
{
"root_module": "./example/mini_core_hello_world.rs",
"edition": "2015",
"edition": "2024",
"deps": [
{
"crate": 0,
@ -37,7 +37,7 @@
},
{
"root_module": "./example/std_example.rs",
"edition": "2015",
"edition": "2024",
"deps": [],
"cfg": [],
},

290
Cargo.lock generated
View file

@ -10,9 +10,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "anyhow"
version = "1.0.95"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "arbitrary"
@ -28,57 +28,57 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.16.0"
version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
dependencies = [
"allocator-api2",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "cranelift-assembler-x64"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f53499803b1607b6ee0ba0de4ba036e6da700c2e489fe8f9d0f683d0b84d31"
checksum = "f502c60b6af2025c312b37788c089943ef03156a2910da1aa046bb39eb8f61c7"
dependencies = [
"cranelift-assembler-x64-meta",
]
[[package]]
name = "cranelift-assembler-x64-meta"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aadaa5bc8430d0e7bb999459369bedd0e5816ad4a82a0e20748341c4e333eda"
checksum = "2b7e21a74bcf08443a4ef800a4a257063e5c51ee4d7a3bd58da5262d10340830"
dependencies = [
"cranelift-srcgen",
]
[[package]]
name = "cranelift-bforest"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2005fda2fc52a2dbce58229b4fb4483b70cbc806ba8ecc11b3f050c1a2d26cac"
checksum = "f337d268865c292ad5df0669a9bbf6223ca41460292a20ad5b0a57b8e9f27f93"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-bitset"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56935e02452ca1249d39ad5c45a96304d0b4300a158a391fd113451e0cd4483d"
checksum = "c0e60319a8242c8d1c7b5a2444d140c416f903f75e0d84da3256fceb822bab85"
[[package]]
name = "cranelift-codegen"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62612786bf00e10999f50217d6f455d02b31591155881a45a903d1a95d1a4043"
checksum = "78dee669e447a1c68760bf7acee33835e99d564f0137b067f74d4718dfc9970d"
dependencies = [
"bumpalo",
"cranelift-assembler-x64",
@ -97,49 +97,50 @@ dependencies = [
"serde",
"smallvec",
"target-lexicon",
"wasmtime-math",
"wasmtime-internal-math",
]
[[package]]
name = "cranelift-codegen-meta"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bae789df91ef236079733af9df11d852256c64af196f0bc6471ea0f5f301be"
checksum = "601f629d172b7230f41dd0e78ee797efaf7ec1a5e113c8f395f4027dff6a92ca"
dependencies = [
"cranelift-assembler-x64-meta",
"cranelift-codegen-shared",
"cranelift-srcgen",
"heck",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1be319616d36527782558a8312508757815f64deb19b094c7b8f4337229a9bc6"
checksum = "15755c2660902c7d59d96f6551a66ef629650dc3fd405f9dad841e8c58c1a4a2"
[[package]]
name = "cranelift-control"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8810ee1ab5e9bd5cff4c0c8d240e2009cb5c2b79888fde1d5256d605712314b7"
checksum = "727bfca18705101a294ab9077ad214a8b762ea2bc9844389d0db233d7c61ec3b"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "086452c97cfbe116bf17dbe622dc5fdf2ea97299c7d4ce42460f284387c9928a"
checksum = "15564c6f0c72750ca4374f40b044857cbc8087571e46d4c7ccdbdcc29b1dec8b"
dependencies = [
"cranelift-bitset",
]
[[package]]
name = "cranelift-frontend"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c27947010ab759330f252610c17a8cd64d123358be4f33164233d04fcd77b80"
checksum = "16c681f2731f1cf68eed9f3b6811571823a5ac498f59c52b73736b68599defb3"
dependencies = [
"cranelift-codegen",
"log",
@ -149,15 +150,15 @@ dependencies = [
[[package]]
name = "cranelift-isle"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec67bfb8bd55b1e9760eb9f5186dca8d81bd4d86110f8d5af01154a044c91802"
checksum = "40cedc02f08307da019a3e06d3f20f772f829ff813aec975accb012f8930b688"
[[package]]
name = "cranelift-jit"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d67cdfc447f2abdb46bb30a6582cce189539c3c051c1d5330692376e1400edff"
checksum = "c2864461448c72d15ae3311ea63df9c7e35f22f04683785f6715a0cf17e6577d"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -169,15 +170,15 @@ dependencies = [
"log",
"region",
"target-lexicon",
"wasmtime-jit-icache-coherence",
"windows-sys 0.59.0",
"wasmtime-internal-jit-icache-coherence",
"windows-sys 0.60.2",
]
[[package]]
name = "cranelift-module"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4597eaa52bca1ed111986c7a7f70cdbe192f83d271d627201365078e37b7e84"
checksum = "2b31d249bbbccc4c1ae54701087d4d49d05951897691eef44f4a60e70252743b"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -186,9 +187,9 @@ dependencies = [
[[package]]
name = "cranelift-native"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75a9b63edea46e013fce459c46e500462cb03a0490fdd9c18fe42b1dd7b93aa1"
checksum = "db03ab51c60710eb83d0217725b77db4062aca83b35359f5e6aa99ed1c275977"
dependencies = [
"cranelift-codegen",
"libc",
@ -197,9 +198,9 @@ dependencies = [
[[package]]
name = "cranelift-object"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce706f0166d5b7f31693dff521e87cb9858e12adf22ffcde93c4a2826f8f04a9"
checksum = "7131e0eb45ee10b0bd6082d0c0114c2e9a670b034d46774b39d0fc5c0ed7cedf"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -212,24 +213,24 @@ dependencies = [
[[package]]
name = "cranelift-srcgen"
version = "0.121.0"
version = "0.125.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5870e266df8237b56cc98b04f5739c228565c92dd629ec6c66efa87271a158"
checksum = "3d7a06c330b7994a891ad5b622ebc9aefcd17beae832dd25f577cf60c13426bf"
[[package]]
name = "crc32fast"
version = "1.4.2"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
"cfg-if",
]
[[package]]
name = "equivalent"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fallible-iterator"
@ -239,15 +240,15 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "foldhash"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "gimli"
version = "0.31.1"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
checksum = "93563d740bc9ef04104f9ed6f86f1e3275c2cdafb95664e26584b9ca807a8ffe"
dependencies = [
"fallible-iterator",
"indexmap",
@ -256,18 +257,24 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.15.2"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
dependencies = [
"foldhash",
]
[[package]]
name = "indexmap"
version = "2.7.0"
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "indexmap"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [
"equivalent",
"hashbrown",
@ -275,18 +282,18 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.169"
version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "libloading"
version = "0.8.6"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
"windows-targets",
"windows-targets 0.53.3",
]
[[package]]
@ -297,30 +304,30 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "log"
version = "0.4.22"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "mach2"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44"
dependencies = [
"libc",
]
[[package]]
name = "memchr"
version = "2.7.4"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "object"
version = "0.36.7"
version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
"crc32fast",
"hashbrown",
@ -330,27 +337,27 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.92"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.38"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regalloc2"
version = "0.12.2"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5216b1837de2149f8bc8e6d5f88a9326b63b8c836ed58ce4a0a29ec736a59734"
checksum = "efd8138ce7c3d7c13be4f61893154b5d711bd798d2d7be3ecb8dcc7e7a06ca98"
dependencies = [
"allocator-api2",
"bumpalo",
@ -374,9 +381,9 @@ dependencies = [
[[package]]
name = "rustc-hash"
version = "2.1.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustc_codegen_cranelift"
@ -398,18 +405,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.217"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
@ -418,9 +425,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.13.2"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "stable_deref_trait"
@ -430,9 +437,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "2.0.95"
version = "2.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
dependencies = [
"proc-macro2",
"quote",
@ -441,53 +448,59 @@ dependencies = [
[[package]]
name = "target-lexicon"
version = "0.13.1"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc12939a1c9b9d391e0b7135f72fd30508b73450753e28341fed159317582a77"
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
[[package]]
name = "unicode-ident"
version = "1.0.14"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "34.0.0"
name = "wasmtime-internal-jit-icache-coherence"
version = "38.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eedc0324e37cf39b049f4dca0c30997eaab49f09006d5f4c1994e64e7b7dba8"
checksum = "8d0a76f1a6e887cc1b551b02dfd6e2ce5f6738e8cacd9ad7284f6ac1aac4698f"
dependencies = [
"anyhow",
"cfg-if",
"libc",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
name = "wasmtime-math"
version = "34.0.0"
name = "wasmtime-internal-math"
version = "38.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd35fae4cf51d2b4a9bd2ef04b0eb309fa1849cab6a6ab5ac27cbd054ea284d"
checksum = "b900df4252ad86547e7f2b2c00201b006db4e864893bedfb3aca32b23d81868a"
dependencies = [
"libm",
]
[[package]]
name = "windows-link"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets",
"windows-targets 0.53.3",
]
[[package]]
@ -496,14 +509,31 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
@ -512,44 +542,92 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"

View file

@ -1,22 +1,22 @@
[package]
name = "rustc_codegen_cranelift"
version = "0.1.0"
edition = "2021"
edition = "2024"
[lib]
crate-type = ["dylib"]
[dependencies]
# These have to be in sync with each other
cranelift-codegen = { version = "0.121.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] }
cranelift-frontend = { version = "0.121.0" }
cranelift-module = { version = "0.121.0" }
cranelift-native = { version = "0.121.0" }
cranelift-jit = { version = "0.121.0", optional = true }
cranelift-object = { version = "0.121.0" }
cranelift-codegen = { version = "0.125.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] }
cranelift-frontend = { version = "0.125.0" }
cranelift-module = { version = "0.125.0" }
cranelift-native = { version = "0.125.0" }
cranelift-jit = { version = "0.125.0", optional = true }
cranelift-object = { version = "0.125.0" }
target-lexicon = "0.13"
gimli = { version = "0.31", default-features = false, features = ["write"] }
object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
gimli = { version = "0.32", default-features = false, features = ["write"] }
object = { version = "0.37.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
indexmap = "2.0.0"
libloading = { version = "0.8.0", optional = true }
@ -24,12 +24,12 @@ smallvec = "1.8.1"
[patch.crates-io]
# Uncomment to use an unreleased version of cranelift
#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
# Uncomment to use local checkout of cranelift
#cranelift-codegen = { path = "../wasmtime/cranelift/codegen" }
@ -46,6 +46,7 @@ smallvec = "1.8.1"
unstable-features = ["jit", "inline_asm_sym"]
jit = ["cranelift-jit", "libloading"]
inline_asm_sym = []
unwinding = [] # Not yet included in unstable-features for performance reasons
[package.metadata.rust-analyzer]
rustc_private = true

View file

@ -11,7 +11,7 @@ The Cranelift codegen backend is distributed in nightly builds on Linux, macOS a
install it using Rustup, you can do that by running:
```bash
$ rustup component add rustc-codegen-cranelift-preview --toolchain nightly
rustup component add rustc-codegen-cranelift-preview --toolchain nightly
```
Once it is installed, you can enable it with one of the following approaches:
@ -47,16 +47,16 @@ If you want to use `cargo clif build` instead of having to specify the full path
If you want to build the backend manually, you can download it from GitHub and build it yourself:
```bash
$ git clone https://github.com/rust-lang/rustc_codegen_cranelift
$ cd rustc_codegen_cranelift
$ ./y.sh build
git clone https://github.com/rust-lang/rustc_codegen_cranelift
cd rustc_codegen_cranelift
./y.sh build
```
To run the test suite replace the last command with:
```bash
$ ./y.sh prepare # only needs to be run the first time
$ ./test.sh
./y.sh prepare # only needs to be run the first time
./test.sh
```
For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.sh`.
@ -66,7 +66,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system
|OS \ architecture|x86\_64|AArch64|Riscv64|s390x (System-Z)|
|---|---|---|---|---|
|Linux|✅|✅|✅[^no-rustup]|✅[^no-rustup]|
|FreeBSD|✅[^no-rustup]|❓|❓|❓|
|FreeBSD|✅[^no-rustup][^tls]|❓|❓|❓|
|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
|Other unixes|❓|❓|❓|❓|
|macOS|✅|✅|N/A|N/A|
@ -80,6 +80,7 @@ Not all targets are available as rustup component for nightly. See notes in the
[^xcoff]: XCOFF object file format is not supported.
[^no-rustup]: Not available as [rustup component for nightly](https://rust-lang.github.io/rustup-components-history/). You can build it yourself.
[^tls]: FreeBSD requires setting `LD_STATIC_TLS_EXTRA=4096` to build cg_clif. In addition you need at least FreeBSD 14.
## Usage
@ -90,7 +91,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/dist/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.
@ -104,7 +105,7 @@ See [rustc_testing.md](docs/rustc_testing.md).
## Not yet supported
* SIMD ([tracked here](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported)
* Unwinding on panics ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1677), `-Cpanic=abort` is enabled by default)
* Unwinding on panics ([experimental and not supported on Windows and macOS](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1567), `-Cpanic=abort` is enabled by default)
## License

View file

@ -19,6 +19,7 @@ pub(crate) fn run(
cg_clif_dylib: &CodegenBackend,
rustup_toolchain_name: Option<&str>,
bootstrap_host_compiler: &Compiler,
panic_unwind_support: bool,
) {
std::fs::create_dir_all(&dirs.download_dir).unwrap();
ABI_CAFE_REPO.fetch(dirs);
@ -32,6 +33,7 @@ pub(crate) fn run(
bootstrap_host_compiler,
rustup_toolchain_name,
bootstrap_host_compiler.triple.clone(),
panic_unwind_support,
);
eprintln!("Running abi-cafe");

View file

@ -144,7 +144,7 @@ fn hyperfine_command(
}
for &(name, cmd) in cmds {
if name != "" {
if !name.is_empty() {
bench.arg("-n").arg(name);
}
bench.arg(cmd);

View file

@ -12,10 +12,11 @@ pub(crate) fn build_backend(
dirs: &Dirs,
bootstrap_host_compiler: &Compiler,
use_unstable_features: bool,
panic_unwind_support: bool,
) -> PathBuf {
let _group = LogGroup::guard("Build backend");
let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs);
let mut cmd = CG_CLIF.build(bootstrap_host_compiler, dirs);
let mut rustflags = rustflags_from_env("RUSTFLAGS");
rustflags.push("-Zallow-features=rustc_private,f16,f128".to_owned());
@ -31,6 +32,10 @@ pub(crate) fn build_backend(
cmd.arg("--features").arg("unstable-features");
}
if panic_unwind_support {
cmd.arg("--features").arg("unwinding");
}
cmd.arg("--release");
eprintln!("[BUILD] rustc_codegen_cranelift");

View file

@ -17,6 +17,7 @@ pub(crate) fn build_sysroot(
bootstrap_host_compiler: &Compiler,
rustup_toolchain_name: Option<&str>,
target_triple: String,
panic_unwind_support: bool,
) -> Compiler {
let _guard = LogGroup::guard("Build sysroot");
@ -48,10 +49,13 @@ pub(crate) fn build_sysroot(
let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc);
let wrapper_path = dist_dir.join(&wrapper_name);
build_cargo_wrapper_cmd
.arg(dirs.source_dir.join("scripts").join(&format!("{wrapper}.rs")))
.arg(dirs.source_dir.join("scripts").join(format!("{wrapper}.rs")))
.arg("-o")
.arg(&wrapper_path)
.arg("-Cstrip=debuginfo");
if panic_unwind_support {
build_cargo_wrapper_cmd.arg("--cfg").arg("support_panic_unwind");
}
if let Some(rustup_toolchain_name) = &rustup_toolchain_name {
build_cargo_wrapper_cmd
.env("TOOLCHAIN_NAME", rustup_toolchain_name)
@ -77,6 +81,7 @@ pub(crate) fn build_sysroot(
bootstrap_host_compiler.clone(),
&cg_clif_dylib_path,
sysroot_kind,
panic_unwind_support,
);
host.install_into_sysroot(dist_dir);
@ -91,6 +96,7 @@ pub(crate) fn build_sysroot(
},
&cg_clif_dylib_path,
sysroot_kind,
panic_unwind_support,
)
.install_into_sysroot(dist_dir);
}
@ -134,19 +140,20 @@ impl SysrootTarget {
static STDLIB_SRC: RelPath = RelPath::build("stdlib");
static STANDARD_LIBRARY: CargoProject =
CargoProject::new(&RelPath::build("stdlib/library/sysroot"), "stdlib_target");
static RTSTARTUP_SYSROOT: RelPath = RelPath::build("rtstartup");
fn build_sysroot_for_triple(
dirs: &Dirs,
compiler: Compiler,
cg_clif_dylib_path: &CodegenBackend,
sysroot_kind: SysrootKind,
panic_unwind_support: bool,
) -> SysrootTarget {
match sysroot_kind {
SysrootKind::None => build_rtstartup(dirs, &compiler)
.unwrap_or(SysrootTarget { triple: compiler.triple, libs: vec![] }),
SysrootKind::None => SysrootTarget { triple: compiler.triple, libs: vec![] },
SysrootKind::Llvm => build_llvm_sysroot_for_triple(compiler),
SysrootKind::Clif => build_clif_sysroot_for_triple(dirs, compiler, cg_clif_dylib_path),
SysrootKind::Clif => {
build_clif_sysroot_for_triple(dirs, compiler, cg_clif_dylib_path, panic_unwind_support)
}
}
}
@ -188,25 +195,28 @@ fn build_clif_sysroot_for_triple(
dirs: &Dirs,
mut compiler: Compiler,
cg_clif_dylib_path: &CodegenBackend,
panic_unwind_support: bool,
) -> SysrootTarget {
let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
if let Some(rtstartup_target_libs) = build_rtstartup(dirs, &compiler) {
rtstartup_target_libs.install_into_sysroot(&RTSTARTUP_SYSROOT.to_path(dirs));
target_libs.libs.extend(rtstartup_target_libs.libs);
}
let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(&compiler.triple).join("release");
if !config::get_bool("keep_sysroot") {
let sysroot_src_orig = get_default_sysroot(&compiler.rustc).join("lib/rustlib/src/rust");
assert!(sysroot_src_orig.exists());
apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs));
// Cleanup the deps dir, but keep build scripts and the incremental cache for faster
// recompilation as they are not affected by changes in cg_clif.
ensure_empty_dir(&build_dir.join("deps"));
}
// Build sysroot
let mut rustflags = vec!["-Zforce-unstable-if-unmarked".to_owned(), "-Cpanic=abort".to_owned()];
let mut rustflags = vec!["-Zforce-unstable-if-unmarked".to_owned()];
if !panic_unwind_support {
rustflags.push("-Cpanic=abort".to_owned());
}
match cg_clif_dylib_path {
CodegenBackend::Local(path) => {
rustflags.push(format!("-Zcodegen-backend={}", path.to_str().unwrap()));
@ -215,9 +225,7 @@ fn build_clif_sysroot_for_triple(
rustflags.push(format!("-Zcodegen-backend={name}"));
}
};
// Necessary for MinGW to find rsbegin.o and rsend.o
rustflags.push("--sysroot".to_owned());
rustflags.push(RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap().to_owned());
rustflags.push("--sysroot=/dev/null".to_owned());
// Incremental compilation by default disables mir inlining. This leads to both a decent
// compile perf and a significant runtime perf regression. As such forcefully enable mir
@ -258,38 +266,3 @@ fn build_clif_sysroot_for_triple(
target_libs
}
fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
if !config::get_bool("keep_sysroot") {
let sysroot_src_orig = get_default_sysroot(&compiler.rustc).join("lib/rustlib/src/rust");
assert!(sysroot_src_orig.exists());
apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs));
}
if !compiler.triple.ends_with("windows-gnu") {
return None;
}
let rtstartup_sysroot = RTSTARTUP_SYSROOT.to_path(dirs);
ensure_empty_dir(&rtstartup_sysroot);
let rtstartup_src = STDLIB_SRC.to_path(dirs).join("library").join("rtstartup");
let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
for file in ["rsbegin", "rsend"] {
let obj = rtstartup_sysroot.join(format!("{file}.o"));
let mut build_rtstartup_cmd = Command::new(&compiler.rustc);
build_rtstartup_cmd
.arg("--target")
.arg(&compiler.triple)
.arg("--emit=obj")
.arg("-o")
.arg(&obj)
.arg(rtstartup_src.join(format!("{file}.rs")));
spawn_and_wait(build_rtstartup_cmd);
target_libs.libs.push(obj.clone());
}
Some(target_libs)
}

View file

@ -83,6 +83,7 @@ fn main() {
let mut download_dir = None;
let mut sysroot_kind = SysrootKind::Clif;
let mut use_unstable_features = true;
let mut panic_unwind_support = false;
let mut frozen = false;
let mut skip_tests = vec![];
let mut use_backend = None;
@ -108,6 +109,7 @@ fn main() {
}
}
"--no-unstable-features" => use_unstable_features = false,
"--panic-unwind-support" => panic_unwind_support = true,
"--frozen" => frozen = true,
"--skip-test" => {
// FIXME check that all passed in tests actually exist
@ -201,6 +203,7 @@ fn main() {
&dirs,
&bootstrap_host_compiler,
use_unstable_features,
panic_unwind_support,
))
};
match command {
@ -212,6 +215,7 @@ fn main() {
&dirs,
sysroot_kind,
use_unstable_features,
panic_unwind_support,
&skip_tests.iter().map(|test| &**test).collect::<Vec<_>>(),
&cg_clif_dylib,
&bootstrap_host_compiler,
@ -230,6 +234,7 @@ fn main() {
&cg_clif_dylib,
rustup_toolchain_name.as_deref(),
&bootstrap_host_compiler,
panic_unwind_support,
);
}
Command::Build => {
@ -240,6 +245,7 @@ fn main() {
&bootstrap_host_compiler,
rustup_toolchain_name.as_deref(),
target_triple,
panic_unwind_support,
);
}
Command::Bench => {
@ -250,6 +256,7 @@ fn main() {
&bootstrap_host_compiler,
rustup_toolchain_name.as_deref(),
target_triple,
panic_unwind_support,
);
bench::benchmark(&dirs, &compiler);
}

View file

@ -2,25 +2,19 @@ use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
pub(crate) fn get_host_triple(rustc: &Path) -> String {
let version_info =
Command::new(rustc).stderr(Stdio::inherit()).args(&["-vV"]).output().unwrap().stdout;
String::from_utf8(version_info)
let version_info = Command::new(rustc)
.stderr(Stdio::inherit())
.args(["--print", "host-tuple"])
.output()
.unwrap()
.lines()
.to_owned()
.find(|line| line.starts_with("host"))
.unwrap()
.split(":")
.nth(1)
.unwrap()
.trim()
.to_owned()
.stdout;
String::from_utf8(version_info).unwrap().trim().to_owned()
}
pub(crate) fn get_toolchain_name() -> String {
let active_toolchain = Command::new("rustup")
.stderr(Stdio::inherit())
.args(&["show", "active-toolchain"])
.args(["show", "active-toolchain"])
.output()
.unwrap()
.stdout;
@ -33,7 +27,7 @@ pub(crate) fn get_cargo_path() -> PathBuf {
}
let cargo_path = Command::new("rustup")
.stderr(Stdio::inherit())
.args(&["which", "cargo"])
.args(["which", "cargo"])
.output()
.unwrap()
.stdout;
@ -46,7 +40,7 @@ pub(crate) fn get_rustc_path() -> PathBuf {
}
let rustc_path = Command::new("rustup")
.stderr(Stdio::inherit())
.args(&["which", "rustc"])
.args(["which", "rustc"])
.output()
.unwrap()
.stdout;
@ -59,7 +53,7 @@ pub(crate) fn get_rustdoc_path() -> PathBuf {
}
let rustc_path = Command::new("rustup")
.stderr(Stdio::inherit())
.args(&["which", "rustdoc"])
.args(["which", "rustdoc"])
.output()
.unwrap()
.stdout;
@ -69,7 +63,7 @@ pub(crate) fn get_rustdoc_path() -> PathBuf {
pub(crate) fn get_default_sysroot(rustc: &Path) -> PathBuf {
let default_sysroot = Command::new(rustc)
.stderr(Stdio::inherit())
.args(&["--print", "sysroot"])
.args(["--print", "sysroot"])
.output()
.unwrap()
.stdout;
@ -80,7 +74,7 @@ pub(crate) fn get_default_sysroot(rustc: &Path) -> PathBuf {
pub(crate) fn get_file_name(rustc: &Path, crate_name: &str, crate_type: &str) -> String {
let file_name = Command::new(rustc)
.stderr(Stdio::inherit())
.args(&[
.args([
"--crate-name",
crate_name,
"--crate-type",

View file

@ -89,15 +89,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]),
TestCase::build_bin("aot.issue-59326", "example/issue-59326.rs"),
TestCase::build_bin_and_run("aot.neon", "example/neon.rs", &[]),
TestCase::custom("aot.gen_block_iterate", &|runner| {
runner.run_rustc([
"example/gen_block_iterate.rs",
"--edition",
"2024",
"-Zunstable-options",
]);
runner.run_out_command("gen_block_iterate", &[]);
}),
TestCase::build_bin_and_run("aot.gen_block_iterate", "example/gen_block_iterate.rs", &[]),
TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]),
TestCase::custom("test.sysroot", &|runner| {
apply_patches(
@ -217,13 +209,15 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
PORTABLE_SIMD.clean(&runner.dirs);
let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
build_cmd.arg("--all-targets");
let build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
// FIXME uncomment once examples work: https://github.com/rust-lang/portable-simd/issues/470
//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");
// FIXME remove --tests once examples work: https://github.com/rust-lang/portable-simd/issues/470
test_cmd.arg("-q").arg("--tests");
spawn_and_wait(test_cmd);
}
}),
@ -233,6 +227,7 @@ pub(crate) fn run_tests(
dirs: &Dirs,
sysroot_kind: SysrootKind,
use_unstable_features: bool,
panic_unwind_support: bool,
skip_tests: &[&str],
cg_clif_dylib: &CodegenBackend,
bootstrap_host_compiler: &Compiler,
@ -251,12 +246,14 @@ pub(crate) fn run_tests(
bootstrap_host_compiler,
rustup_toolchain_name,
target_triple.clone(),
panic_unwind_support,
);
let runner = TestRunner::new(
dirs.clone(),
target_compiler,
use_unstable_features,
panic_unwind_support,
skip_tests,
bootstrap_host_compiler.triple == target_triple,
stdlib_source.clone(),
@ -283,12 +280,14 @@ pub(crate) fn run_tests(
bootstrap_host_compiler,
rustup_toolchain_name,
target_triple.clone(),
panic_unwind_support,
);
let mut runner = TestRunner::new(
dirs.clone(),
target_compiler,
use_unstable_features,
panic_unwind_support,
skip_tests,
bootstrap_host_compiler.triple == target_triple,
stdlib_source,
@ -314,6 +313,7 @@ pub(crate) fn run_tests(
struct TestRunner<'a> {
is_native: bool,
jit_supported: bool,
panic_unwind_support: bool,
skip_tests: &'a [&'a str],
dirs: Dirs,
target_compiler: Compiler,
@ -325,6 +325,7 @@ impl<'a> TestRunner<'a> {
dirs: Dirs,
mut target_compiler: Compiler,
use_unstable_features: bool,
panic_unwind_support: bool,
skip_tests: &'a [&'a str],
is_native: bool,
stdlib_source: PathBuf,
@ -335,7 +336,15 @@ impl<'a> TestRunner<'a> {
let jit_supported =
use_unstable_features && is_native && !target_compiler.triple.contains("windows");
Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source }
Self {
is_native,
jit_supported,
panic_unwind_support,
skip_tests,
dirs,
target_compiler,
stdlib_source,
}
}
fn run_testsuite(&self, tests: &[TestCase]) {
@ -346,7 +355,7 @@ impl<'a> TestRunner<'a> {
let _guard = if !config::get_bool(config)
|| (is_jit_test && !self.jit_supported)
|| self.skip_tests.contains(&config)
|| self.skip_tests.contains(config)
{
eprintln!("[{tag}] {testname} (skipped)");
continue;
@ -404,8 +413,11 @@ impl<'a> TestRunner<'a> {
cmd.arg("-Cdebuginfo=2");
cmd.arg("--target");
cmd.arg(&self.target_compiler.triple);
cmd.arg("-Cpanic=abort");
if !self.panic_unwind_support {
cmd.arg("-Cpanic=abort");
}
cmd.arg("--check-cfg=cfg(jit)");
cmd.arg("--edition=2024");
cmd.args(args);
cmd
}

View file

@ -25,6 +25,10 @@ OPTIONS:
Some features are not yet ready for production usage. This option will disable these
features. This includes the JIT mode and inline assembly support.
--panic-unwind-support
Enable support for unwinding when -Cpanic=unwind is used. This currently regresses build
performance.
--frozen
Require Cargo.lock and cache are up to date

View file

@ -162,7 +162,7 @@ impl CargoProject {
pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
let src = src.as_ref();
let dst = dst.as_ref();
if let Err(_) = fs::hard_link(src, dst) {
if fs::hard_link(src, dst).is_err() {
fs::copy(src, dst).unwrap(); // Fallback to copying if hardlinking failed
}
}
@ -179,7 +179,7 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) {
/// Create the specified directory if it doesn't exist yet and delete all contents.
pub(crate) fn ensure_empty_dir(path: &Path) {
fs::create_dir_all(path).unwrap();
let read_dir = match fs::read_dir(&path) {
let read_dir = match fs::read_dir(path) {
Ok(read_dir) => read_dir,
Err(err) if err.kind() == io::ErrorKind::NotFound => {
return;

View file

@ -20,7 +20,6 @@ aot.mini_core_hello_world
testsuite.base_sysroot
aot.arbitrary_self_types_pointers_and_wrappers
aot.issue_91827_extern_types
jit.std_example
aot.std_example
aot.dst_field_align

View file

@ -77,12 +77,16 @@ pub fn use_size_of() -> usize {
}
pub unsafe fn use_copy_intrinsic(src: *const u8, dst: *mut u8) {
intrinsics::copy::<u8>(src, dst, 1);
unsafe {
intrinsics::copy::<u8>(src, dst, 1);
}
}
pub unsafe fn use_copy_intrinsic_ref(src: *const u8, dst: *mut u8) {
let copy2 = &intrinsics::copy::<u8>;
copy2(src, dst, 1);
unsafe {
let copy2 = &intrinsics::copy::<u8>;
copy2(src, dst, 1);
}
}
pub const ABC: u8 = 6 * 7;
@ -126,11 +130,11 @@ pub fn eq_char(a: char, b: char) -> bool {
}
pub unsafe fn transmute(c: char) -> u32 {
intrinsics::transmute(c)
unsafe { intrinsics::transmute(c) }
}
pub unsafe fn deref_str_ptr(s: *const str) -> &'static str {
&*s
unsafe { &*s }
}
pub fn use_array(arr: [u8; 3]) -> u8 {
@ -146,7 +150,7 @@ pub fn array_as_slice(arr: &[u8; 3]) -> &[u8] {
}
pub unsafe fn use_ctlz_nonzero(a: u16) -> u32 {
intrinsics::ctlz_nonzero(a)
unsafe { intrinsics::ctlz_nonzero(a) }
}
pub fn ptr_as_usize(ptr: *const u8) -> usize {

View file

@ -546,7 +546,7 @@ fn panic_in_cleanup() -> ! {
#[cfg(all(unix, not(target_vendor = "apple")))]
#[link(name = "gcc_s")]
extern "C" {
unsafe extern "C" {
fn _Unwind_Resume(exc: *mut ()) -> !;
}
@ -555,7 +555,9 @@ extern "C" {
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
// Code here does not matter - this is replaced by the
// real drop glue by the compiler.
drop_in_place(to_drop);
unsafe {
drop_in_place(to_drop);
}
}
#[lang = "unpin"]
@ -622,7 +624,7 @@ impl<T: ?Sized> Deref for Box<T> {
#[lang = "exchange_malloc"]
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
libc::malloc(size)
unsafe { libc::malloc(size) }
}
#[lang = "drop"]
@ -649,11 +651,11 @@ pub mod intrinsics {
#[rustc_intrinsic]
pub const fn size_of<T>() -> usize;
#[rustc_intrinsic]
pub unsafe fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
pub unsafe fn size_of_val<T: ?crate::Sized>(val: *const T) -> usize;
#[rustc_intrinsic]
pub const fn align_of<T>() -> usize;
#[rustc_intrinsic]
pub unsafe fn align_of_val<T: ?::Sized>(val: *const T) -> usize;
pub unsafe fn align_of_val<T: ?crate::Sized>(val: *const T) -> usize;
#[rustc_intrinsic]
pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
#[rustc_intrinsic]
@ -661,7 +663,7 @@ pub mod intrinsics {
#[rustc_intrinsic]
pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
#[rustc_intrinsic]
pub const fn needs_drop<T: ?::Sized>() -> bool;
pub const fn needs_drop<T: ?crate::Sized>() -> bool;
#[rustc_intrinsic]
pub fn bitreverse<T>(x: T) -> T;
#[rustc_intrinsic]
@ -678,13 +680,13 @@ pub mod libc {
// symbols to link against.
#[cfg_attr(unix, link(name = "c"))]
#[cfg_attr(target_env = "msvc", link(name = "legacy_stdio_definitions"))]
extern "C" {
unsafe extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
#[cfg_attr(unix, link(name = "c"))]
#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))]
extern "C" {
unsafe extern "C" {
pub fn puts(s: *const i8) -> i32;
pub fn malloc(size: usize) -> *mut u8;
pub fn free(ptr: *mut u8);
@ -733,7 +735,7 @@ trait SizedTypeProperties: Sized {
}
impl<T> SizedTypeProperties for T {}
extern "C" {
unsafe extern "C" {
type VaListImpl;
}
@ -792,7 +794,7 @@ struct PanicLocation {
column: u32,
}
#[no_mangle]
#[unsafe(no_mangle)]
#[cfg(not(all(windows, target_env = "gnu")))]
pub fn get_tls() -> u8 {
#[thread_local]

View file

@ -124,9 +124,11 @@ static mut NUM: u8 = 6 * 7;
static NUM_REF: &'static u8 = unsafe { &*&raw const NUM };
unsafe fn zeroed<T>() -> T {
let mut uninit = MaybeUninit { uninit: () };
intrinsics::write_bytes(&mut uninit.value.value as *mut T, 0, 1);
uninit.value.value
unsafe {
let mut uninit = MaybeUninit { uninit: () };
intrinsics::write_bytes(&mut uninit.value.value as *mut T, 0, 1);
uninit.value.value
}
}
fn take_f32(_f: f32) {}
@ -237,7 +239,7 @@ fn main() {
}
unsafe fn uninitialized<T>() -> T {
MaybeUninit { uninit: () }.value.value
unsafe { MaybeUninit { uninit: () }.value.value }
}
zeroed::<(u8, u8)>();
@ -270,20 +272,20 @@ fn main() {
let x = &[0u32, 42u32] as &[u32];
match x {
[] => assert_eq!(0u32, 1),
[_, ref y @ ..] => assert_eq!(&x[1] as *const u32 as usize, &y[0] as *const u32 as usize),
[_, y @ ..] => assert_eq!(&x[1] as *const u32 as usize, &y[0] as *const u32 as usize),
}
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
#[cfg(not(any(jit, target_vendor = "apple", windows)))]
{
extern "C" {
unsafe extern "C" {
#[linkage = "extern_weak"]
static ABC: *const u8;
}
{
extern "C" {
unsafe extern "C" {
#[linkage = "extern_weak"]
static ABC: *const u8;
}
@ -310,7 +312,7 @@ fn main() {
check_niche_behavior();
extern "C" {
unsafe extern "C" {
type ExternType;
}
@ -364,7 +366,7 @@ fn stack_val_align() {
}
#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "macos")))]
extern "C" {
unsafe extern "C" {
fn global_asm_test();
}
@ -412,7 +414,7 @@ struct pthread_attr_t {
#[link(name = "pthread")]
#[cfg(unix)]
extern "C" {
unsafe extern "C" {
fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int;
fn pthread_create(
@ -433,7 +435,7 @@ type HANDLE = *mut c_void;
#[link(name = "msvcrt")]
#[cfg(windows)]
extern "C" {
unsafe extern "C" {
fn WaitForSingleObject(hHandle: LPVOID, dwMilliseconds: DWORD) -> DWORD;
fn CreateThread(
@ -455,46 +457,51 @@ struct Thread {
impl Thread {
unsafe fn create(f: extern "C" fn(_: *mut c_void) -> *mut c_void) -> Self {
#[cfg(unix)]
{
let mut attr: pthread_attr_t = zeroed();
let mut thread: pthread_t = 0;
unsafe {
#[cfg(unix)]
{
let mut attr: pthread_attr_t = zeroed();
let mut thread: pthread_t = 0;
if pthread_attr_init(&mut attr) != 0 {
assert!(false);
if pthread_attr_init(&mut attr) != 0 {
assert!(false);
}
if pthread_create(&mut thread, &attr, f, 0 as *mut c_void) != 0 {
assert!(false);
}
Thread { handle: thread }
}
if pthread_create(&mut thread, &attr, f, 0 as *mut c_void) != 0 {
assert!(false);
#[cfg(windows)]
{
let handle =
CreateThread(0 as *mut c_void, 0, f, 0 as *mut c_void, 0, 0 as *mut u32);
if (handle as u64) == 0 {
assert!(false);
}
Thread { handle }
}
Thread { handle: thread }
}
#[cfg(windows)]
{
let handle = CreateThread(0 as *mut c_void, 0, f, 0 as *mut c_void, 0, 0 as *mut u32);
if (handle as u64) == 0 {
assert!(false);
}
Thread { handle }
}
}
unsafe fn join(self) {
#[cfg(unix)]
{
let mut res = 0 as *mut c_void;
pthread_join(self.handle, &mut res);
}
unsafe {
#[cfg(unix)]
{
let mut res = 0 as *mut c_void;
pthread_join(self.handle, &mut res);
}
#[cfg(windows)]
{
// The INFINITE macro is used to signal operations that do not timeout.
let infinite = 0xffffffff;
assert!(WaitForSingleObject(self.handle, infinite) == 0);
#[cfg(windows)]
{
// The INFINITE macro is used to signal operations that do not timeout.
let infinite = 0xffffffff;
assert!(WaitForSingleObject(self.handle, infinite) == 0);
}
}
}
}

View file

@ -14,7 +14,7 @@ unsafe fn test_vpmin_s8() {
let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]);
let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]);
let e = i8x8::from([-2, -4, 5, 7, 0, 2, 4, 6]);
let r: i8x8 = transmute(vpmin_s8(transmute(a), transmute(b)));
let r: i8x8 = unsafe { transmute(vpmin_s8(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -23,7 +23,7 @@ unsafe fn test_vpmin_s16() {
let a = i16x4::from([1, 2, 3, -4]);
let b = i16x4::from([0, 3, 2, 5]);
let e = i16x4::from([1, -4, 0, 2]);
let r: i16x4 = transmute(vpmin_s16(transmute(a), transmute(b)));
let r: i16x4 = unsafe { transmute(vpmin_s16(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -32,7 +32,7 @@ unsafe fn test_vpmin_s32() {
let a = i32x2::from([1, -2]);
let b = i32x2::from([0, 3]);
let e = i32x2::from([-2, 0]);
let r: i32x2 = transmute(vpmin_s32(transmute(a), transmute(b)));
let r: i32x2 = unsafe { transmute(vpmin_s32(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -41,7 +41,7 @@ unsafe fn test_vpmin_u8() {
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]);
let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]);
let e = u8x8::from([1, 3, 5, 7, 0, 2, 4, 6]);
let r: u8x8 = transmute(vpmin_u8(transmute(a), transmute(b)));
let r: u8x8 = unsafe { transmute(vpmin_u8(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -50,7 +50,7 @@ unsafe fn test_vpmin_u16() {
let a = u16x4::from([1, 2, 3, 4]);
let b = u16x4::from([0, 3, 2, 5]);
let e = u16x4::from([1, 3, 0, 2]);
let r: u16x4 = transmute(vpmin_u16(transmute(a), transmute(b)));
let r: u16x4 = unsafe { transmute(vpmin_u16(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -59,7 +59,7 @@ unsafe fn test_vpmin_u32() {
let a = u32x2::from([1, 2]);
let b = u32x2::from([0, 3]);
let e = u32x2::from([1, 0]);
let r: u32x2 = transmute(vpmin_u32(transmute(a), transmute(b)));
let r: u32x2 = unsafe { transmute(vpmin_u32(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -68,7 +68,7 @@ unsafe fn test_vpmin_f32() {
let a = f32x2::from([1., -2.]);
let b = f32x2::from([0., 3.]);
let e = f32x2::from([-2., 0.]);
let r: f32x2 = transmute(vpmin_f32(transmute(a), transmute(b)));
let r: f32x2 = unsafe { transmute(vpmin_f32(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -77,7 +77,7 @@ unsafe fn test_vpmax_s8() {
let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]);
let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]);
let e = i8x8::from([1, 3, 6, 8, 3, 5, 7, 9]);
let r: i8x8 = transmute(vpmax_s8(transmute(a), transmute(b)));
let r: i8x8 = unsafe { transmute(vpmax_s8(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -86,7 +86,7 @@ unsafe fn test_vpmax_s16() {
let a = i16x4::from([1, 2, 3, -4]);
let b = i16x4::from([0, 3, 2, 5]);
let e = i16x4::from([2, 3, 3, 5]);
let r: i16x4 = transmute(vpmax_s16(transmute(a), transmute(b)));
let r: i16x4 = unsafe { transmute(vpmax_s16(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -95,7 +95,7 @@ unsafe fn test_vpmax_s32() {
let a = i32x2::from([1, -2]);
let b = i32x2::from([0, 3]);
let e = i32x2::from([1, 3]);
let r: i32x2 = transmute(vpmax_s32(transmute(a), transmute(b)));
let r: i32x2 = unsafe { transmute(vpmax_s32(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -104,7 +104,7 @@ unsafe fn test_vpmax_u8() {
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]);
let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]);
let e = u8x8::from([2, 4, 6, 8, 3, 5, 7, 9]);
let r: u8x8 = transmute(vpmax_u8(transmute(a), transmute(b)));
let r: u8x8 = unsafe { transmute(vpmax_u8(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -113,7 +113,7 @@ unsafe fn test_vpmax_u16() {
let a = u16x4::from([1, 2, 3, 4]);
let b = u16x4::from([0, 3, 2, 5]);
let e = u16x4::from([2, 4, 3, 5]);
let r: u16x4 = transmute(vpmax_u16(transmute(a), transmute(b)));
let r: u16x4 = unsafe { transmute(vpmax_u16(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -122,7 +122,7 @@ unsafe fn test_vpmax_u32() {
let a = u32x2::from([1, 2]);
let b = u32x2::from([0, 3]);
let e = u32x2::from([2, 3]);
let r: u32x2 = transmute(vpmax_u32(transmute(a), transmute(b)));
let r: u32x2 = unsafe { transmute(vpmax_u32(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -131,7 +131,7 @@ unsafe fn test_vpmax_f32() {
let a = f32x2::from([1., -2.]);
let b = f32x2::from([0., 3.]);
let e = f32x2::from([1., 3.]);
let r: f32x2 = transmute(vpmax_f32(transmute(a), transmute(b)));
let r: f32x2 = unsafe { transmute(vpmax_f32(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -139,7 +139,7 @@ unsafe fn test_vpmax_f32() {
unsafe fn test_vpadd_s16() {
let a = i16x4::from([1, 2, 3, 4]);
let b = i16x4::from([0, -1, -2, -3]);
let r: i16x4 = transmute(vpadd_s16(transmute(a), transmute(b)));
let r: i16x4 = unsafe { transmute(vpadd_s16(transmute(a), transmute(b))) };
let e = i16x4::from([3, 7, -1, -5]);
assert_eq!(r, e);
}
@ -147,7 +147,7 @@ unsafe fn test_vpadd_s16() {
unsafe fn test_vpadd_s32() {
let a = i32x2::from([1, 2]);
let b = i32x2::from([0, -1]);
let r: i32x2 = transmute(vpadd_s32(transmute(a), transmute(b)));
let r: i32x2 = unsafe { transmute(vpadd_s32(transmute(a), transmute(b))) };
let e = i32x2::from([3, -1]);
assert_eq!(r, e);
}
@ -155,7 +155,7 @@ unsafe fn test_vpadd_s32() {
unsafe fn test_vpadd_s8() {
let a = i8x8::from([1, 2, 3, 4, 5, 6, 7, 8]);
let b = i8x8::from([0, -1, -2, -3, -4, -5, -6, -7]);
let r: i8x8 = transmute(vpadd_s8(transmute(a), transmute(b)));
let r: i8x8 = unsafe { transmute(vpadd_s8(transmute(a), transmute(b))) };
let e = i8x8::from([3, 7, 11, 15, -1, -5, -9, -13]);
assert_eq!(r, e);
}
@ -163,7 +163,7 @@ unsafe fn test_vpadd_s8() {
unsafe fn test_vpadd_u16() {
let a = u16x4::from([1, 2, 3, 4]);
let b = u16x4::from([30, 31, 32, 33]);
let r: u16x4 = transmute(vpadd_u16(transmute(a), transmute(b)));
let r: u16x4 = unsafe { transmute(vpadd_u16(transmute(a), transmute(b))) };
let e = u16x4::from([3, 7, 61, 65]);
assert_eq!(r, e);
}
@ -171,7 +171,7 @@ unsafe fn test_vpadd_u16() {
unsafe fn test_vpadd_u32() {
let a = u32x2::from([1, 2]);
let b = u32x2::from([30, 31]);
let r: u32x2 = transmute(vpadd_u32(transmute(a), transmute(b)));
let r: u32x2 = unsafe { transmute(vpadd_u32(transmute(a), transmute(b))) };
let e = u32x2::from([3, 61]);
assert_eq!(r, e);
}
@ -179,7 +179,7 @@ unsafe fn test_vpadd_u32() {
unsafe fn test_vpadd_u8() {
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]);
let b = u8x8::from([30, 31, 32, 33, 34, 35, 36, 37]);
let r: u8x8 = transmute(vpadd_u8(transmute(a), transmute(b)));
let r: u8x8 = unsafe { transmute(vpadd_u8(transmute(a), transmute(b))) };
let e = u8x8::from([3, 7, 11, 15, 61, 65, 69, 73]);
assert_eq!(r, e);
}
@ -188,7 +188,7 @@ unsafe fn test_vpadd_u8() {
unsafe fn test_vqsub_u8() {
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]);
let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]);
let r: u8x8 = transmute(vqsub_u8(transmute(a), transmute(b)));
let r: u8x8 = unsafe { transmute(vqsub_u8(transmute(a), transmute(b))) };
let e = u8x8::from([0, 1, 2, 3, 0, 0, 0, 218]);
assert_eq!(r, e);
}
@ -197,7 +197,7 @@ unsafe fn test_vqsub_u8() {
unsafe fn test_vqadd_u8() {
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]);
let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]);
let r: u8x8 = transmute(vqadd_u8(transmute(a), transmute(b)));
let r: u8x8 = unsafe { transmute(vqadd_u8(transmute(a), transmute(b))) };
let e = u8x8::from([31, 3, 4, 5, 39, 0xff, 43, 0xff]);
assert_eq!(r, e);
}
@ -208,7 +208,7 @@ unsafe fn test_vmaxq_f32() {
let a = f32x4::from([0., -1., 2., -3.]);
let b = f32x4::from([-4., 5., -6., 7.]);
let e = f32x4::from([0., 5., 2., 7.]);
let r: f32x4 = transmute(vmaxq_f32(transmute(a), transmute(b)));
let r: f32x4 = unsafe { transmute(vmaxq_f32(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -218,7 +218,7 @@ unsafe fn test_vminq_f32() {
let a = f32x4::from([0., -1., 2., -3.]);
let b = f32x4::from([-4., 5., -6., 7.]);
let e = f32x4::from([-4., -1., -6., -3.]);
let r: f32x4 = transmute(vminq_f32(transmute(a), transmute(b)));
let r: f32x4 = unsafe { transmute(vminq_f32(transmute(a), transmute(b))) };
assert_eq!(r, e);
}
@ -227,7 +227,7 @@ unsafe fn test_vaddvq_f32() {
// AArch64 llvm intrinsic: llvm.aarch64.neon.faddv.f32.v4f32
let a = f32x4::from([0., 1., 2., 3.]);
let e = 6f32;
let r = vaddvq_f32(transmute(a));
let r = unsafe { vaddvq_f32(transmute(a)) };
assert_eq!(r, e);
}
@ -236,7 +236,7 @@ unsafe fn test_vrndnq_f32() {
// llvm intrinsic: llvm.roundeven.v4f32
let a = f32x4::from([0.1, -1.9, 4.5, 5.5]);
let e = f32x4::from([0., -2., 4., 6.]);
let r: f32x4 = transmute(vrndnq_f32(transmute(a)));
let r: f32x4 = unsafe { transmute(vrndnq_f32(transmute(a))) };
assert_eq!(r, e);
}

View file

@ -5,7 +5,7 @@ fn main() {
#[cfg(windows)]
{
#[link(name = "kernel32", kind = "raw-dylib")]
extern "C" {
unsafe extern "C" {
fn GetModuleFileNameA(
module: *mut std::ffi::c_void,
filename: *mut u8,

View file

@ -230,51 +230,53 @@ unsafe fn test_crc32() {
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "sse2")]
unsafe fn test_simd() {
assert!(is_x86_feature_detected!("sse2"));
unsafe {
assert!(is_x86_feature_detected!("sse2"));
let x = _mm_setzero_si128();
let y = _mm_set1_epi16(7);
let or = _mm_or_si128(x, y);
let cmp_eq = _mm_cmpeq_epi8(y, y);
let cmp_lt = _mm_cmplt_epi8(y, y);
let x = _mm_setzero_si128();
let y = _mm_set1_epi16(7);
let or = _mm_or_si128(x, y);
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]);
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]);
test_mm_slli_si128();
test_mm_movemask_epi8();
test_mm256_movemask_epi8();
test_mm_add_epi8();
test_mm_add_pd();
test_mm_cvtepi8_epi16();
#[cfg(not(jit))]
test_mm_cvtps_epi32();
test_mm_cvttps_epi32();
test_mm_cvtsi128_si64();
test_mm_slli_si128();
test_mm_movemask_epi8();
test_mm256_movemask_epi8();
test_mm_add_epi8();
test_mm_add_pd();
test_mm_cvtepi8_epi16();
#[cfg(not(jit))]
test_mm_cvtps_epi32();
test_mm_cvttps_epi32();
test_mm_cvtsi128_si64();
test_mm_extract_epi8();
test_mm_insert_epi16();
test_mm_shuffle_epi8();
test_mm_extract_epi8();
test_mm_insert_epi16();
test_mm_shuffle_epi8();
#[cfg(not(jit))]
test_mm_cmpestri();
#[cfg(not(jit))]
test_mm_cmpestri();
test_mm256_shuffle_epi8();
test_mm256_permute2x128_si256();
test_mm256_permutevar8x32_epi32();
test_mm256_shuffle_epi8();
test_mm256_permute2x128_si256();
test_mm256_permutevar8x32_epi32();
#[rustfmt::skip]
#[rustfmt::skip]
let mask1 = _mm_movemask_epi8(dbg!(_mm_setr_epi8(255u8 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)));
assert_eq!(mask1, 1);
assert_eq!(mask1, 1);
#[cfg(not(jit))]
test_crc32();
#[cfg(not(jit))]
test_crc32();
}
}
#[cfg(target_arch = "x86_64")]
@ -361,7 +363,7 @@ fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i)
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "sse2")]
pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
pub fn assert_eq_m128d(a: __m128d, b: __m128d) {
if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 {
panic!("{:?} != {:?}", a, b);
}
@ -369,15 +371,19 @@ pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx")]
pub unsafe fn assert_eq_m256i(a: __m256i, b: __m256i) {
assert_eq!(std::mem::transmute::<_, [u64; 4]>(a), std::mem::transmute::<_, [u64; 4]>(b))
pub fn assert_eq_m256i(a: __m256i, b: __m256i) {
unsafe {
assert_eq!(std::mem::transmute::<_, [u64; 4]>(a), std::mem::transmute::<_, [u64; 4]>(b))
}
}
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "sse2")]
unsafe fn test_mm_cvtsi128_si64() {
let r = _mm_cvtsi128_si64(std::mem::transmute::<[i64; 2], _>([5, 0]));
assert_eq!(r, 5);
unsafe {
let r = _mm_cvtsi128_si64(std::mem::transmute::<[i64; 2], _>([5, 0]));
assert_eq!(r, 5);
}
}
#[cfg(target_arch = "x86_64")]
@ -445,20 +451,24 @@ unsafe fn test_mm_shuffle_epi8() {
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "sse4.2")]
unsafe fn str_to_m128i(s: &[u8]) -> __m128i {
assert!(s.len() <= 16);
let slice = &mut [0u8; 16];
std::ptr::copy_nonoverlapping(s.as_ptr(), slice.as_mut_ptr(), s.len());
_mm_loadu_si128(slice.as_ptr() as *const _)
unsafe {
assert!(s.len() <= 16);
let slice = &mut [0u8; 16];
std::ptr::copy_nonoverlapping(s.as_ptr(), slice.as_mut_ptr(), s.len());
_mm_loadu_si128(slice.as_ptr() as *const _)
}
}
#[cfg(not(jit))]
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "sse4.2")]
unsafe fn test_mm_cmpestri() {
let a = str_to_m128i(b"bar - garbage");
let b = str_to_m128i(b"foobar");
let i = _mm_cmpestri::<_SIDD_CMP_EQUAL_ORDERED>(a, 3, b, 6);
assert_eq!(3, i);
unsafe {
let a = str_to_m128i(b"bar - garbage");
let b = str_to_m128i(b"foobar");
let i = _mm_cmpestri::<_SIDD_CMP_EQUAL_ORDERED>(a, 3, b, 6);
assert_eq!(3, i);
}
}
#[cfg(target_arch = "x86_64")]
@ -513,35 +523,39 @@ unsafe fn test_mm256_permutevar8x32_epi32() {
#[target_feature(enable = "avx2")]
#[cfg(not(jit))]
unsafe fn test_mm_cvtps_epi32() {
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
unsafe {
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
let float_vec = _mm_loadu_ps(floats.as_ptr());
let int_vec = _mm_cvtps_epi32(float_vec);
let float_vec = _mm_loadu_ps(floats.as_ptr());
let int_vec = _mm_cvtps_epi32(float_vec);
let mut ints: [i32; 4] = [0; 4];
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
let mut ints: [i32; 4] = [0; 4];
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
// this is very different from `floats.map(|f| f as i32)`!
let expected_ints: [i32; 4] = [2, -2, i32::MIN, i32::MIN];
// this is very different from `floats.map(|f| f as i32)`!
let expected_ints: [i32; 4] = [2, -2, i32::MIN, i32::MIN];
assert_eq!(ints, expected_ints);
assert_eq!(ints, expected_ints);
}
}
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx2")]
unsafe fn test_mm_cvttps_epi32() {
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
unsafe {
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
let float_vec = _mm_loadu_ps(floats.as_ptr());
let int_vec = _mm_cvttps_epi32(float_vec);
let float_vec = _mm_loadu_ps(floats.as_ptr());
let int_vec = _mm_cvttps_epi32(float_vec);
let mut ints: [i32; 4] = [0; 4];
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
let mut ints: [i32; 4] = [0; 4];
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
// this is very different from `floats.map(|f| f as i32)`!
let expected_ints: [i32; 4] = [1, -2, i32::MIN, i32::MIN];
// this is very different from `floats.map(|f| f as i32)`!
let expected_ints: [i32; 4] = [1, -2, i32::MIN, i32::MIN];
assert_eq!(ints, expected_ints);
assert_eq!(ints, expected_ints);
}
}
fn test_checked_mul() {

View file

@ -11,38 +11,41 @@ diff --git a/coretests/tests/slice.rs b/coretests/tests/slice.rs
index 8402833..84592e0 100644
--- a/coretests/tests/slice.rs
+++ b/coretests/tests/slice.rs
@@ -1809,6 +1809,7 @@ fn sort_unstable() {
}
}
@@ -1619,7 +1619,7 @@ fn brute_force_rotate_test_1() {
+/*
#[test]
#[cfg(not(target_arch = "wasm32"))]
#[cfg_attr(miri, ignore)] // Miri is too slow
@@ -1914,6 +1915,7 @@ fn select_nth_unstable() {
v.select_nth_unstable(0);
assert!(v == [0xDEADBEEF]);
}
+*/
-#[cfg_attr(miri, ignore)] // Miri is too slow
+#[ignore] // Miri is too slow
fn select_nth_unstable() {
use core::cmp::Ordering::{Equal, Greater, Less};
#[test]
#[should_panic(expected = "index 0 greater than length of slice")]
@@ -2462,6 +2462,7 @@ take_tests! {
#[cfg(not(miri))] // unused in Miri
@@ -2303,14 +2303,14 @@ split_off_tests! {
const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
+/*
// can't be a constant due to const mutability rules
#[cfg(not(miri))] // unused in Miri
-#[cfg(not(miri))] // unused in Miri
+#[cfg(any())] // unused in Miri
macro_rules! empty_max_mut {
@@ -2485,6 +2486,7 @@ take_tests! {
(split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
(split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
() => {
&mut [(); usize::MAX] as _
};
}
+*/
#[test]
fn test_slice_from_ptr_range() {
-#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
+#[cfg(any())] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
split_off_tests! {
slice: &[(); usize::MAX], method: split_off,
(split_off_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]),
@@ -2318,7 +2318,7 @@ split_off_tests! {
(split_off_in_bounds_max_range_from, (usize::MAX..), Some(&[] as _), EMPTY_MAX),
}
-#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
+#[cfg(any())] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
split_off_tests! {
slice: &mut [(); usize::MAX], method: split_off_mut,
(split_off_mut_in_bounds_max_range_to, (..usize::MAX), Some(empty_max_mut!()), &mut [(); 0]),
diff --git a/alloctests/tests/sort/tests.rs b/alloctests/tests/sort/tests.rs
index d321f8d..8b2040a 100644
--- a/alloctests/tests/sort/tests.rs

View file

@ -1,4 +1,4 @@
[toolchain]
channel = "nightly-2025-06-24"
channel = "nightly-2025-11-08"
components = ["rust-src", "rustc-dev", "llvm-tools"]
profile = "minimal"

View file

@ -12,7 +12,11 @@ fn main() {
sysroot = sysroot.parent().unwrap();
}
let mut rustflags = vec!["-Cpanic=abort".to_owned(), "-Zpanic-abort-tests".to_owned()];
let mut rustflags = vec![];
if !cfg!(support_panic_unwind) {
rustflags.push("-Cpanic=abort".to_owned());
rustflags.push("-Zpanic-abort-tests".to_owned());
}
if let Some(name) = option_env!("BUILTIN_BACKEND") {
rustflags.push(format!("-Zcodegen-backend={name}"));
} else {

View file

@ -17,8 +17,10 @@ fn main() {
let passed_args = std::env::args_os().skip(1).collect::<Vec<_>>();
let mut args = vec![];
args.push(OsString::from("-Cpanic=abort"));
args.push(OsString::from("-Zpanic-abort-tests"));
if !cfg!(support_panic_unwind) {
args.push(OsString::from("-Cpanic=abort"));
args.push(OsString::from("-Zpanic-abort-tests"));
}
if let Some(name) = option_env!("BUILTIN_BACKEND") {
args.push(OsString::from(format!("-Zcodegen-backend={name}")))
} else {

View file

@ -17,8 +17,10 @@ fn main() {
let passed_args = std::env::args_os().skip(1).collect::<Vec<_>>();
let mut args = vec![];
args.push(OsString::from("-Cpanic=abort"));
args.push(OsString::from("-Zpanic-abort-tests"));
if !cfg!(support_panic_unwind) {
args.push(OsString::from("-Cpanic=abort"));
args.push(OsString::from("-Zpanic-abort-tests"));
}
if let Some(name) = option_env!("BUILTIN_BACKEND") {
args.push(OsString::from(format!("-Zcodegen-backend={name}")))
} else {

View file

@ -46,7 +46,7 @@ case $1 in
git pull origin master
branch=sync_cg_clif-$(date +%Y-%m-%d)
git checkout -b "$branch"
"$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/rust-lang/rustc_codegen_cranelift.git master
"$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/rust-lang/rustc_codegen_cranelift.git main
git push -u my "$branch"
# immediately merge the merge commit into cg_clif to prevent merge conflicts when syncing

View file

@ -50,23 +50,24 @@ EOF
cat <<EOF | git apply -
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index cf4ef4ee310..fe78560fcaf 100644
index a656927b1f6..44fc5546fac 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -3138,13 +3138,6 @@ fn parse_download_ci_llvm(
);
}
- if b && self.is_running_on_ci {
- // On CI, we must always rebuild LLVM if there were any modifications to it
- panic!(
- "\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead."
- );
- }
-
// If download-ci-llvm=true we also want to check that CI llvm is available
b && llvm::is_ci_llvm_available_for_target(self, asserts)
@@ -2249,14 +2249,6 @@ pub fn parse_download_ci_llvm<'a>(
);
}
- #[cfg(not(test))]
- if b && dwn_ctx.is_running_on_ci && CiEnv::is_rust_lang_managed_ci_job() {
- // On rust-lang CI, we must always rebuild LLVM if there were any modifications to it
- panic!(
- "\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead."
- );
- }
-
// If download-ci-llvm=true we also want to check that CI llvm is available
b && llvm::is_ci_llvm_available_for_target(&dwn_ctx.host_target, asserts)
}
EOF
popd

View file

@ -10,7 +10,7 @@ pushd rust
command -v rg >/dev/null 2>&1 || cargo install ripgrep
rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true
rm -r tests/ui/{lto/,linkage*} || true
for test in $(rg --files-with-matches "lto" tests/{codegen-units,ui,incremental}); do
rm $test
done
@ -34,6 +34,7 @@ git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs
# vendor intrinsics
rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic
rm tests/ui/simd/dont-invalid-bitcast-x86_64.rs # unimplemented llvm.x86.sse41.round.ps
rm tests/ui/simd/intrinsic/generic-arithmetic-pass.rs # unimplemented simd_funnel_{shl,shr}
# exotic linkages
rm tests/incremental/hashes/function_interfaces.rs
@ -42,8 +43,14 @@ rm -r tests/run-make/naked-symbol-visibility
# variadic arguments
rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs
rm tests/ui/c-variadic/naked.rs # same
rm tests/ui/abi/variadic-ffi.rs # requires callee side vararg support
rm -r tests/run-make/c-link-to-rust-va-list-fn # requires callee side vararg support
rm tests/ui/c-variadic/valid.rs # same
rm tests/ui/c-variadic/trait-method.rs # same
rm tests/ui/c-variadic/inherent-method.rs # same
rm tests/ui/sanitizer/kcfi-c-variadic.rs # same
rm tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs # variadics for calling conventions other than C unsupported
rm tests/ui/delegation/fn-header.rs
# misc unimplemented things
@ -56,8 +63,13 @@ rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't
rm tests/ui/asm/global-asm-mono-sym-fn.rs # same
rm tests/ui/asm/naked-asm-mono-sym-fn.rs # same
rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported
rm tests/ui/asm/label-operand.rs # same
rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes
rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo
rm -r tests/run-make/used-proc-macro # used(linker) isn't supported yet
rm tests/ui/linking/no-gc-encapsulation-symbols.rs # same
rm tests/ui/attributes/fn-align-dyn.rs # per-function alignment not supported
rm -r tests/ui/explicit-tail-calls # tail calls
rm -r tests/run-make/pointer-auth-link-with-c # pointer auth
# requires LTO
rm -r tests/run-make/cdylib
@ -69,15 +81,13 @@ rm -r tests/run-make/reachable-extern-fn-available-lto
# coverage instrumentation
rm tests/ui/consts/precise-drop-with-coverage.rs
rm tests/ui/issues/issue-85461.rs
rm -r tests/ui/instrument-coverage/
# optimization tests
# ==================
rm tests/ui/codegen/issue-28950.rs # depends on stack size optimizations
rm tests/ui/codegen/init-large-type.rs # same
rm -r tests/run-make/fmt-write-bloat/ # tests an optimization
rm tests/ui/statics/const_generics.rs # same
rm tests/ui/statics/const_generics.rs # tests an optimization
rm tests/ui/linking/executable-no-mangle-strip.rs # requires --gc-sections to work for statics
# backend specific tests
@ -92,7 +102,7 @@ rm -r tests/run-make/llvm-location-discriminator-limit-dummy-span # same
rm tests/ui/abi/stack-protector.rs # requires stack protector support
rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes
rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
rm -r tests/ui/optimization-remark.rs # same
rm -r tests/ui/codegen/remark-flag-functionality.rs # same
rm -r tests/run-make/print-to-output # requires --print relocation-models
# requires asm, llvm-ir and/or llvm-bc emit support
@ -123,6 +133,8 @@ rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
rm -r tests/run-make/strip # same
rm -r tests/run-make-cargo/compiler-builtins # Expects lib/rustlib/src/rust to contains the standard library source
rm -r tests/run-make/translation # same
rm -r tests/run-make-cargo/panic-immediate-abort-works # same
rm -r tests/run-make-cargo/panic-immediate-abort-codegen # same
rm -r tests/run-make/missing-unstable-trait-bound # This disables support for unstable features, but running cg_clif needs some unstable features
rm -r tests/run-make/const-trait-stable-toolchain # same
rm -r tests/run-make/print-request-help-stable-unstable # same
@ -130,6 +142,7 @@ rm -r tests/run-make/incr-add-rust-src-component
rm tests/ui/errors/remap-path-prefix-sysroot.rs # different sysroot source path
rm -r tests/run-make/export/extern-opt # something about rustc version mismatches
rm -r tests/run-make/export # same
rm -r tests/ui/compiletest-self-test/compile-flags-incremental.rs # needs compiletest compiled with panic=unwind
# genuine bugs
# ============
@ -143,9 +156,9 @@ rm tests/ui/backtrace/synchronized-panic-handler.rs # missing needs-unwind annot
rm tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs # same
rm tests/ui/async-await/async-drop/async-drop-initial.rs # same (rust-lang/rust#140493)
rm -r tests/ui/codegen/equal-pointers-unequal # make incorrect assumptions about the location of stack variables
rm -r tests/run-make-cargo/rustdoc-scrape-examples-paths # FIXME(rust-lang/rust#145580) incr comp bug
rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same
rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # really slow with unoptimized libstd
rm tests/ui/process/process-panic-after-fork.rs # same
cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist

View file

@ -7,7 +7,9 @@ mod returning;
use std::borrow::Cow;
use std::mem;
use cranelift_codegen::ir::{ArgumentPurpose, SigRef};
use cranelift_codegen::ir::{
ArgumentPurpose, BlockArg, ExceptionTableData, ExceptionTableItem, ExceptionTag, SigRef,
};
use cranelift_codegen::isa::CallConv;
use cranelift_module::ModuleError;
use rustc_abi::{CanonAbi, ExternAbi, X86Call};
@ -21,10 +23,12 @@ use rustc_session::Session;
use rustc_span::source_map::Spanned;
use rustc_target::callconv::{FnAbi, PassMode};
use rustc_target::spec::Arch;
use smallvec::SmallVec;
use smallvec::{SmallVec, smallvec};
use self::pass_mode::*;
pub(crate) use self::returning::codegen_return;
use crate::base::codegen_unwind_terminate;
use crate::debuginfo::EXCEPTION_HANDLER_CLEANUP;
use crate::prelude::*;
fn clif_sig_from_fn_abi<'tcx>(
@ -82,7 +86,7 @@ pub(crate) fn get_function_sig<'tcx>(
clif_sig_from_fn_abi(
tcx,
default_call_conv,
&FullyMonomorphizedLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
FullyMonomorphizedLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
)
}
@ -111,7 +115,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
/// Instance must be monomorphized
pub(crate) fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
let func_id = import_function(self.tcx, self.module, inst);
let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
let func_ref = self.module.declare_func_in_func(func_id, self.bcx.func);
if self.clif_comments.enabled() {
self.add_comment(func_ref, format!("{:?}", inst));
@ -182,7 +186,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
) -> &[Value] {
let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv };
let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap();
let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
let func_ref = self.module.declare_func_in_func(func_id, self.bcx.func);
let call_inst = self.bcx.ins().call(func_ref, args);
if self.clif_comments.enabled() {
self.add_comment(func_ref, format!("{:?}", name));
@ -267,7 +271,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
// individual function arguments.
let tupled_arg_tys = match arg_ty.kind() {
ty::Tuple(ref tys) => tys,
ty::Tuple(tys) => tys,
_ => bug!("spread argument isn't a tuple?! but {:?}", arg_ty),
};
@ -297,7 +301,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
Some(cvalue_for_param(fx, None, None, arg_abi, &mut block_params_iter).unwrap());
}
assert!(arg_abis_iter.next().is_none(), "ArgAbi left behind");
assert_eq!(arg_abis_iter.next(), None, "ArgAbi left behind for {:?}", fx.fn_abi);
assert!(block_params_iter.next().is_none(), "arg_value left behind");
self::comments::add_locals_header_comment(fx);
@ -381,7 +385,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
args: &[Spanned<Operand<'tcx>>],
destination: Place<'tcx>,
target: Option<BasicBlock>,
_unwind: UnwindAction,
unwind: UnwindAction,
) {
let func = codegen_operand(fx, func);
let fn_sig = func.layout().ty.fn_sig(fx.tcx);
@ -416,7 +420,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
if fx.tcx.symbol_name(instance).name.starts_with("llvm.") {
crate::intrinsics::codegen_llvm_intrinsic_call(
fx,
&fx.tcx.symbol_name(instance).name,
fx.tcx.symbol_name(instance).name,
args,
ret_place,
target,
@ -490,7 +494,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
};
let tupled_arguments = match pack_arg.value.layout().ty.kind() {
ty::Tuple(ref tupled_arguments) => tupled_arguments,
ty::Tuple(tupled_arguments) => tupled_arguments,
_ => bug!("argument to function with \"rust-call\" ABI is not a tuple"),
};
@ -516,12 +520,6 @@ pub(crate) fn codegen_terminator_call<'tcx>(
let args = args;
assert_eq!(fn_abi.args.len(), args.len());
#[derive(Copy, Clone)]
enum CallTarget {
Direct(FuncRef),
Indirect(SigRef, Value),
}
let (func_ref, first_arg_override) = match instance {
// Trait object call
Some(Instance { def: InstanceKind::Virtual(_, idx), .. }) => {
@ -537,7 +535,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
}
let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0].value, idx);
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, fn_abi);
let sig = fx.bcx.import_signature(sig);
(CallTarget::Indirect(sig, method), Some(ptr.get_addr(fx)))
@ -557,7 +555,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
}
let func = func.load_scalar(fx);
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, fn_abi);
let sig = fx.bcx.import_signature(sig);
(CallTarget::Indirect(sig, func), None)
@ -567,7 +565,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| {
let mut call_args = return_ptr
.into_iter()
.chain(first_arg_override.into_iter())
.chain(first_arg_override)
.chain(
args.into_iter()
.enumerate()
@ -580,21 +578,15 @@ pub(crate) fn codegen_terminator_call<'tcx>(
// FIXME: Find a cleaner way to support varargs.
if fn_abi.c_variadic {
adjust_call_for_c_variadic(fx, &fn_abi, source_info, func_ref, &mut call_args);
adjust_call_for_c_variadic(fx, fn_abi, source_info, func_ref, &mut call_args);
}
let call_inst = match func_ref {
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args),
CallTarget::Indirect(sig, func_ptr) => {
fx.bcx.ins().call_indirect(sig, func_ptr, &call_args)
}
};
if fx.clif_comments.enabled() {
with_no_trimmed_paths!(fx.add_comment(call_inst, format!("abi: {:?}", fn_abi)));
let nop_inst = fx.bcx.ins().nop();
with_no_trimmed_paths!(fx.add_post_comment(nop_inst, format!("abi: {:?}", fn_abi)));
}
fx.bcx.func.dfg.inst_results(call_inst).iter().copied().collect::<SmallVec<[Value; 2]>>()
codegen_call_with_unwind_action(fx, source_info.span, func_ref, unwind, &call_args, None)
});
if let Some(dest) = target {
@ -704,7 +696,7 @@ pub(crate) fn codegen_drop<'tcx>(
source_info: mir::SourceInfo,
drop_place: CPlace<'tcx>,
target: BasicBlock,
_unwind: UnwindAction,
unwind: UnwindAction,
) {
let ty = drop_place.layout().ty;
let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty);
@ -748,11 +740,16 @@ pub(crate) fn codegen_drop<'tcx>(
let fn_abi = FullyMonomorphizedLayoutCx(fx.tcx)
.fn_abi_of_instance(virtual_drop, ty::List::empty());
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, fn_abi);
let sig = fx.bcx.import_signature(sig);
// FIXME implement cleanup on exceptions
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
fx.bcx.ins().jump(ret_block, &[]);
codegen_call_with_unwind_action(
fx,
source_info.span,
CallTarget::Indirect(sig, drop_fn),
unwind,
&[ptr],
Some(ret_block),
);
}
_ => {
assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _)));
@ -771,15 +768,146 @@ pub(crate) fn codegen_drop<'tcx>(
if drop_instance.def.requires_caller_location(fx.tcx) {
// Pass the caller location for `#[track_caller]`.
let caller_location = fx.get_caller_location(source_info);
call_args.extend(
adjust_arg_for_abi(fx, caller_location, &fn_abi.args[1], false).into_iter(),
);
call_args.extend(adjust_arg_for_abi(
fx,
caller_location,
&fn_abi.args[1],
false,
));
}
let func_ref = fx.get_function_ref(drop_instance);
fx.bcx.ins().call(func_ref, &call_args);
// FIXME implement cleanup on exceptions
fx.bcx.ins().jump(ret_block, &[]);
codegen_call_with_unwind_action(
fx,
source_info.span,
CallTarget::Direct(func_ref),
unwind,
&call_args,
Some(ret_block),
);
}
}
}
}
#[derive(Copy, Clone)]
pub(crate) enum CallTarget {
Direct(FuncRef),
Indirect(SigRef, Value),
}
pub(crate) fn codegen_call_with_unwind_action(
fx: &mut FunctionCx<'_, '_, '_>,
span: Span,
func_ref: CallTarget,
mut unwind: UnwindAction,
call_args: &[Value],
target_block: Option<Block>,
) -> SmallVec<[Value; 2]> {
let sig_ref = match func_ref {
CallTarget::Direct(func_ref) => fx.bcx.func.dfg.ext_funcs[func_ref].signature,
CallTarget::Indirect(sig_ref, _func_ptr) => sig_ref,
};
if target_block.is_some() {
assert!(fx.bcx.func.dfg.signatures[sig_ref].returns.is_empty());
}
if cfg!(not(feature = "unwinding")) {
unwind = UnwindAction::Unreachable;
}
match unwind {
UnwindAction::Continue | UnwindAction::Unreachable => {
let call_inst = match func_ref {
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, call_args),
CallTarget::Indirect(sig, func_ptr) => {
fx.bcx.ins().call_indirect(sig, func_ptr, call_args)
}
};
if let Some(target_block) = target_block {
fx.bcx.ins().jump(target_block, &[]);
smallvec![]
} else {
fx.bcx
.func
.dfg
.inst_results(call_inst)
.iter()
.copied()
.collect::<SmallVec<[Value; 2]>>()
}
}
UnwindAction::Cleanup(_) | UnwindAction::Terminate(_) => {
let returns_types = fx.bcx.func.dfg.signatures[sig_ref]
.returns
.iter()
.map(|return_param| return_param.value_type)
.collect::<Vec<_>>();
let fallthrough_block = fx.bcx.create_block();
let fallthrough_block_call_args = returns_types
.iter()
.enumerate()
.map(|(i, _)| BlockArg::TryCallRet(i.try_into().unwrap()))
.collect::<Vec<_>>();
let fallthrough_block_call = fx.bcx.func.dfg.block_call(
target_block.unwrap_or(fallthrough_block),
&fallthrough_block_call_args,
);
let pre_cleanup_block = fx.bcx.create_block();
let pre_cleanup_block_call =
fx.bcx.func.dfg.block_call(pre_cleanup_block, &[BlockArg::TryCallExn(0)]);
let exception_table = fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
sig_ref,
fallthrough_block_call,
[ExceptionTableItem::Tag(
ExceptionTag::with_number(EXCEPTION_HANDLER_CLEANUP).unwrap(),
pre_cleanup_block_call,
)],
));
match func_ref {
CallTarget::Direct(func_ref) => {
fx.bcx.ins().try_call(func_ref, call_args, exception_table);
}
CallTarget::Indirect(_sig, func_ptr) => {
fx.bcx.ins().try_call_indirect(func_ptr, call_args, exception_table);
}
}
fx.bcx.seal_block(pre_cleanup_block);
fx.bcx.switch_to_block(pre_cleanup_block);
fx.bcx.set_cold_block(pre_cleanup_block);
match unwind {
UnwindAction::Continue | UnwindAction::Unreachable => unreachable!(),
UnwindAction::Cleanup(cleanup) => {
let exception_ptr =
fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
fx.bcx.def_var(fx.exception_slot, exception_ptr);
let cleanup_block = fx.get_block(cleanup);
fx.bcx.ins().jump(cleanup_block, &[]);
}
UnwindAction::Terminate(reason) => {
// FIXME dedup terminate blocks
fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
codegen_unwind_terminate(fx, span, reason);
}
}
if target_block.is_none() {
fx.bcx.seal_block(fallthrough_block);
fx.bcx.switch_to_block(fallthrough_block);
let returns = returns_types
.into_iter()
.map(|ty| fx.bcx.append_block_param(fallthrough_block, ty))
.collect();
fx.bcx.ins().nop();
returns
} else {
smallvec![]
}
}
}

View file

@ -209,12 +209,7 @@ pub(super) fn to_casted_value<'tcx>(
cast_target_to_abi_params(cast)
.into_iter()
.map(|(offset, param)| {
let val = ptr.offset_i64(fx, offset.bytes() as i64).load(
fx,
param.value_type,
MemFlags::new(),
);
val
ptr.offset_i64(fx, offset.bytes() as i64).load(fx, param.value_type, MemFlags::new())
})
.collect()
}

View file

@ -12,6 +12,8 @@ use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::config::OutputFilenames;
use rustc_span::Symbol;
use crate::constant::ConstantCx;
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
@ -25,11 +27,13 @@ pub(crate) struct CodegenedFunction {
func: Function,
clif_comments: CommentWriter,
func_debug_cx: Option<FunctionDebugContext>,
inline_asm: String,
}
pub(crate) fn codegen_fn<'tcx>(
tcx: TyCtxt<'tcx>,
cx: &mut crate::CodegenCx,
cgu_name: Symbol,
mut debug_context: Option<&mut DebugContext>,
type_dbg: &mut TypeDebugContext<'tcx>,
cached_func: Function,
module: &mut dyn Module,
@ -60,7 +64,9 @@ pub(crate) fn codegen_fn<'tcx>(
func.clear();
func.name = UserFuncName::user(0, func_id.as_u32());
func.signature = sig;
func.collect_debug_info();
if debug_context.is_some() {
func.collect_debug_info();
}
let mut bcx = FunctionBuilder::new(&mut func, &mut func_ctx);
@ -74,23 +80,27 @@ pub(crate) fn codegen_fn<'tcx>(
// Make FunctionCx
let target_config = module.target_config();
let pointer_type = target_config.pointer_type();
assert_eq!(pointer_ty(tcx), pointer_type);
let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance, fn_abi);
let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context {
let func_debug_cx = if let Some(debug_context) = debug_context.as_deref_mut() {
Some(debug_context.define_function(tcx, type_dbg, instance, fn_abi, &symbol_name, mir.span))
} else {
None
};
let exception_slot = bcx.declare_var(pointer_type);
let mut fx = FunctionCx {
cx,
module,
debug_context,
tcx,
target_config,
pointer_type,
constants_cx: ConstantCx::new(),
func_debug_cx,
cgu_name,
instance,
symbol_name,
mir,
@ -100,9 +110,11 @@ pub(crate) fn codegen_fn<'tcx>(
block_map,
local_map: IndexVec::with_capacity(mir.local_decls.len()),
caller_location: None, // set by `codegen_fn_prelude`
exception_slot,
clif_comments,
next_ssa_var: 0,
inline_asm: String::new(),
inline_asm_index: 0,
};
tcx.prof.generic_activity("codegen clif ir").run(|| codegen_fn_body(&mut fx, start_block));
@ -113,10 +125,11 @@ pub(crate) fn codegen_fn<'tcx>(
let symbol_name = fx.symbol_name;
let clif_comments = fx.clif_comments;
let func_debug_cx = fx.func_debug_cx;
let inline_asm = fx.inline_asm;
fx.constants_cx.finalize(fx.tcx, &mut *fx.module);
if cx.should_write_ir {
if crate::pretty_clif::should_write_ir(tcx.sess) {
crate::pretty_clif::write_clif_file(
tcx.output_filenames(()),
&symbol_name,
@ -130,20 +143,24 @@ pub(crate) fn codegen_fn<'tcx>(
// Verify function
verify_func(tcx, &clif_comments, &func);
CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx, inline_asm }
}
pub(crate) fn compile_fn(
cx: &mut crate::CodegenCx,
profiler: &SelfProfilerRef,
output_filenames: &OutputFilenames,
should_write_ir: bool,
cached_context: &mut Context,
module: &mut dyn Module,
debug_context: Option<&mut DebugContext>,
global_asm: &mut String,
codegened_func: CodegenedFunction,
) {
let _timer =
profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name);
let clif_comments = codegened_func.clif_comments;
global_asm.push_str(&codegened_func.inline_asm);
// Store function in context
let context = cached_context;
@ -180,7 +197,7 @@ pub(crate) fn compile_fn(
// Define function
profiler.generic_activity("define function").run(|| {
context.want_disasm = cx.should_write_ir;
context.want_disasm = should_write_ir;
match module.define_function(codegened_func.func_id, context) {
Ok(()) => {}
Err(ModuleError::Compilation(CodegenError::ImplLimitExceeded)) => {
@ -210,10 +227,10 @@ pub(crate) fn compile_fn(
}
});
if cx.should_write_ir {
if should_write_ir {
// Write optimized function to file for debugging
crate::pretty_clif::write_clif_file(
&cx.output_filenames,
output_filenames,
&codegened_func.symbol_name,
"opt",
module.isa(),
@ -223,7 +240,7 @@ pub(crate) fn compile_fn(
if let Some(disasm) = &context.compiled_code().unwrap().vcode {
crate::pretty_clif::write_ir_file(
&cx.output_filenames,
output_filenames,
&format!("{}.vcode", codegened_func.symbol_name),
|file| file.write_all(disasm.as_bytes()),
)
@ -231,7 +248,6 @@ pub(crate) fn compile_fn(
}
// Define debuginfo for function
let debug_context = &mut cx.debug_context;
profiler.generic_activity("generate debug info").run(|| {
if let Some(debug_context) = debug_context {
codegened_func.func_debug_cx.unwrap().finalize(
@ -250,12 +266,12 @@ fn verify_func(tcx: TyCtxt<'_>, writer: &crate::pretty_clif::CommentWriter, func
tcx.prof.generic_activity("verify clif ir").run(|| {
let flags = cranelift_codegen::settings::Flags::new(cranelift_codegen::settings::builder());
match cranelift_codegen::verify_function(&func, &flags) {
match cranelift_codegen::verify_function(func, &flags) {
Ok(_) => {}
Err(err) => {
tcx.dcx().err(format!("{:?}", err));
let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error(
&func,
func,
Some(Box::new(writer)),
err,
);
@ -295,11 +311,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
}
if bb_data.is_cleanup {
// Unwinding after panicking is not supported
continue;
if cfg!(not(feature = "unwinding")) {
continue;
}
// FIXME Once unwinding is supported and Cranelift supports marking blocks as cold, do
// so for cleanup blocks.
fx.bcx.set_cold_block(block);
}
fx.bcx.ins().nop();
@ -369,7 +385,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
fx.bcx.ins().nop();
match &**msg {
AssertKind::BoundsCheck { ref len, ref index } => {
AssertKind::BoundsCheck { len, index } => {
let len = codegen_operand(fx, len).load_scalar(fx);
let index = codegen_operand(fx, index).load_scalar(fx);
let location = fx.get_caller_location(source_info).load_scalar(fx);
@ -382,7 +398,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
source_info.span,
);
}
AssertKind::MisalignedPointerDereference { ref required, ref found } => {
AssertKind::MisalignedPointerDereference { required, found } => {
let required = codegen_operand(fx, required).load_scalar(fx);
let found = codegen_operand(fx, found).load_scalar(fx);
let location = fx.get_caller_location(source_info).load_scalar(fx);
@ -538,14 +554,22 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
template,
operands,
*options,
targets.get(0).copied(),
targets.first().copied(),
);
}
TerminatorKind::UnwindTerminate(reason) => {
codegen_unwind_terminate(fx, source_info.span, *reason);
}
TerminatorKind::UnwindResume => {
// FIXME implement unwinding
if cfg!(feature = "unwinding") {
let exception_ptr = fx.bcx.use_var(fx.exception_slot);
fx.lib_call(
"_Unwind_Resume",
vec![AbiParam::new(fx.pointer_type)],
vec![],
&[exception_ptr],
);
}
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
}
TerminatorKind::Unreachable => {
@ -929,7 +953,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
| StatementKind::AscribeUserType(..) => {}
StatementKind::Coverage { .. } => unreachable!(),
StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic {
StatementKind::Intrinsic(intrinsic) => match &**intrinsic {
// We ignore `assume` intrinsics, they are only useful for optimizations
NonDivergingIntrinsic::Assume(_) => {}
NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
@ -1060,7 +1084,7 @@ pub(crate) fn codegen_panic_nounwind<'tcx>(
msg_str: &str,
span: Span,
) {
let msg_ptr = fx.anonymous_str(msg_str);
let msg_ptr = crate::constant::pointer_for_anonymous_str(fx, msg_str);
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
let args = [msg_ptr, msg_len];
@ -1085,7 +1109,7 @@ fn codegen_panic_inner<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
lang_item: rustc_hir::LangItem,
args: &[Value],
_unwind: UnwindAction,
unwind: UnwindAction,
span: Span,
) {
fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
@ -1101,14 +1125,23 @@ fn codegen_panic_inner<'tcx>(
let symbol_name = fx.tcx.symbol_name(instance).name;
// FIXME implement cleanup on exceptions
let sig = Signature {
params: args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(),
returns: vec![],
call_conv: fx.target_config.default_call_conv,
};
let func_id = fx.module.declare_function(symbol_name, Linkage::Import, &sig).unwrap();
let func_ref = fx.module.declare_func_in_func(func_id, fx.bcx.func);
if fx.clif_comments.enabled() {
fx.add_comment(func_ref, format!("{:?}", symbol_name));
}
fx.lib_call(
symbol_name,
args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(),
vec![],
args,
);
let nop_inst = fx.bcx.ins().nop();
if fx.clif_comments.enabled() {
fx.add_comment(nop_inst, format!("panic {}", symbol_name));
}
codegen_call_with_unwind_action(fx, span, CallTarget::Direct(func_ref), unwind, args, None);
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
}

View file

@ -1,5 +1,6 @@
use rustc_target::spec::Arch;
use crate::compiler_builtins::CMP_RESULT_TY;
use crate::prelude::*;
pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
@ -74,15 +75,11 @@ pub(crate) fn fcmp(fx: &mut FunctionCx<'_, '_, '_>, cc: FloatCC, lhs: Value, rhs
let res = fx.lib_call(
name,
vec![AbiParam::new(types::F128), AbiParam::new(types::F128)],
// FIXME(rust-lang/compiler-builtins#919): This should be `I64` on non-AArch64
// architectures, but switching it before compiler-builtins is fixed causes test
// failures.
vec![AbiParam::new(types::I32)],
vec![AbiParam::new(CMP_RESULT_TY)],
&[lhs, rhs],
)[0];
let zero = fx.bcx.ins().iconst(types::I32, 0);
let res = fx.bcx.ins().icmp(int_cc, res, zero);
res
let zero = fx.bcx.ins().iconst(CMP_RESULT_TY, 0);
fx.bcx.ins().icmp(int_cc, res, zero)
}
_ => unreachable!("{ty:?}"),
}

View file

@ -1,11 +1,12 @@
use cranelift_codegen::isa::TargetFrontendConfig;
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
use rustc_abi::{Float, Integer, Primitive};
use rustc_index::IndexVec;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::layout::{
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
};
use rustc_span::Symbol;
use rustc_span::source_map::Spanned;
use rustc_target::callconv::FnAbi;
use rustc_target::spec::{Arch, HasTargetSpec, Target};
@ -256,7 +257,7 @@ pub(crate) fn create_wrapper_function(
.map(|param| func.dfg.append_block_param(block, param.value_type))
.collect::<Vec<Value>>();
let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
let callee_func_ref = module.declare_func_in_func(callee_func_id, bcx.func);
let call_inst = bcx.ins().call(callee_func_ref, &args);
let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error
@ -268,14 +269,15 @@ pub(crate) fn create_wrapper_function(
}
pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
pub(crate) cx: &'clif mut crate::CodegenCx,
pub(crate) module: &'m mut dyn Module,
pub(crate) debug_context: Option<&'clif mut DebugContext>,
pub(crate) tcx: TyCtxt<'tcx>,
pub(crate) target_config: TargetFrontendConfig, // Cached from module
pub(crate) pointer_type: Type, // Cached from module
pub(crate) constants_cx: ConstantCx,
pub(crate) func_debug_cx: Option<FunctionDebugContext>,
pub(crate) cgu_name: Symbol,
pub(crate) instance: Instance<'tcx>,
pub(crate) symbol_name: String,
pub(crate) mir: &'tcx Body<'tcx>,
@ -288,10 +290,13 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
/// When `#[track_caller]` is used, the implicit caller location is stored in this variable.
pub(crate) caller_location: Option<CValue<'tcx>>,
/// During cleanup the exception pointer will be stored in this variable.
pub(crate) exception_slot: Variable,
pub(crate) clif_comments: crate::pretty_clif::CommentWriter,
/// This should only be accessed by `CPlace::new_var`.
pub(crate) next_ssa_var: u32,
pub(crate) inline_asm: String,
pub(crate) inline_asm_index: u32,
}
impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
@ -369,7 +374,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer {
assert!(
size % align == 0,
size.is_multiple_of(align),
"size must be a multiple of alignment (size={size}, align={align})"
);
@ -379,7 +384,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
kind: StackSlotKind::ExplicitSlot,
// FIXME Don't force the size to a multiple of <abi_align> bytes once Cranelift gets
// a way to specify stack slot alignment.
size: (size + abi_align - 1) / abi_align * abi_align,
size: size.div_ceil(abi_align) * abi_align,
align_shift: 4,
});
Pointer::stack_slot(stack_slot)
@ -401,7 +406,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
}
pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
if let Some(debug_context) = &mut self.cx.debug_context {
if let Some(debug_context) = &mut self.debug_context {
let (file_id, line, column) =
debug_context.get_span_loc(self.tcx, self.mir.span, source_info.span);
@ -417,21 +422,6 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty())
})
}
pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
let mut data = DataDescription::new();
data.define(msg.as_bytes().to_vec().into_boxed_slice());
let msg_id = self.module.declare_anonymous_data(false, false).unwrap();
// Ignore DuplicateDefinition error, as the data will be the same
let _ = self.module.define_data(msg_id, &data);
let local_msg_id = self.module.declare_data_in_func(msg_id, self.bcx.func);
if self.clif_comments.enabled() {
self.add_comment(local_msg_id, msg);
}
self.bcx.ins().global_value(self.pointer_type, local_msg_id)
}
}
pub(crate) struct FullyMonomorphizedLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);

View file

@ -3,11 +3,34 @@ use std::ffi::c_int;
#[cfg(feature = "jit")]
use std::ffi::c_void;
use cranelift_codegen::ir::{Type, types};
// FIXME replace with core::ffi::c_size_t once stabilized
#[allow(non_camel_case_types)]
#[cfg(feature = "jit")]
type size_t = usize;
// Needs to stay in sync with compiler-builtins
// Aarch64 uses `int` rather than a pointer-sized value.
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
#[cfg(feature = "jit")]
type CmpResult = i32;
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
pub(crate) const CMP_RESULT_TY: Type = types::I32;
// In compiler-rt, LLP64 ABIs use `long long` and everything else uses `long`. In effect,
// this means the return value is always pointer-sized.
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm64ec")))]
#[cfg(feature = "jit")]
type CmpResult = isize;
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm64ec")))]
#[cfg(target_pointer_width = "32")]
pub(crate) const CMP_RESULT_TY: Type = types::I32;
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm64ec")))]
#[cfg(target_pointer_width = "64")]
pub(crate) const CMP_RESULT_TY: Type = types::I64;
macro_rules! builtin_functions {
(
$register:ident;
@ -18,7 +41,7 @@ macro_rules! builtin_functions {
) => {
#[cfg(feature = "jit")]
#[allow(improper_ctypes)]
extern "C" {
unsafe extern "C" {
$(
$(#[$attr])?
fn $name($($arg_name: $arg_ty),*) -> $ret_ty;
@ -85,15 +108,18 @@ builtin_functions! {
fn __divtf3(a: f128, b: f128) -> f128;
fn fmodf(a: f32, b: f32) -> f32;
fn fmod(a: f64, b: f64) -> f64;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn fmodf128(a: f128, b: f128) -> f128;
// float comparison
fn __eqtf2(a: f128, b: f128) -> i32;
fn __netf2(a: f128, b: f128) -> i32;
fn __lttf2(a: f128, b: f128) -> i32;
fn __letf2(a: f128, b: f128) -> i32;
fn __gttf2(a: f128, b: f128) -> i32;
fn __getf2(a: f128, b: f128) -> i32;
fn __eqtf2(a: f128, b: f128) -> CmpResult;
fn __netf2(a: f128, b: f128) -> CmpResult;
fn __lttf2(a: f128, b: f128) -> CmpResult;
fn __letf2(a: f128, b: f128) -> CmpResult;
fn __gttf2(a: f128, b: f128) -> CmpResult;
fn __getf2(a: f128, b: f128) -> CmpResult;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn fminimumf128(a: f128, b: f128) -> f128;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn fmaximumf128(a: f128, b: f128) -> f128;
// Cranelift float libcalls
fn fmaf(a: f32, b: f32, c: f32) -> f32;
@ -127,16 +153,27 @@ builtin_functions! {
fn sin(f: f64) -> f64;
fn cosf(f: f32) -> f32;
fn cos(f: f64) -> f64;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn fmaf128(a: f128, b: f128, c: f128) -> f128;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn floorf16(f: f16) -> f16;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn floorf128(f: f128) -> f128;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn ceilf16(f: f16) -> f16;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn ceilf128(f: f128) -> f128;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn truncf16(f: f16) -> f16;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn truncf128(f: f128) -> f128;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn rintf16(f: f16) -> f16;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn rintf128(f: f128) -> f128;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn sqrtf16(f: f16) -> f16;
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
fn sqrtf128(f: f128) -> f128;
// FIXME(f16_f128): Add other float intrinsics as compiler-builtins gains support (meaning they
// are available on all targets).

View file

@ -1,5 +1,5 @@
/// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct BackendConfig {
/// Should the crate be AOT compiled or JIT executed.
///

View file

@ -3,6 +3,7 @@
use std::cmp::Ordering;
use cranelift_module::*;
use rustc_const_eval::interpret::CTFE_ALLOC_SALT;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{
@ -64,7 +65,7 @@ pub(crate) fn codegen_tls_ref<'tcx>(
// For a declaration the stated mutability doesn't matter.
false,
);
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("tls {:?}", def_id));
}
@ -110,7 +111,7 @@ pub(crate) fn codegen_const_value<'tcx>(
ConstValue::Scalar(x) => match x {
Scalar::Int(int) => {
if fx.clif_type(layout.ty).is_some() {
return CValue::const_val(fx, layout, int);
CValue::const_val(fx, layout, int)
} else {
let raw_val = int.size().truncate(int.to_bits(int.size()));
let val = match int.size().bytes() {
@ -140,11 +141,7 @@ pub(crate) fn codegen_const_value<'tcx>(
let base_addr = match fx.tcx.global_alloc(alloc_id) {
GlobalAlloc::Memory(alloc) => {
if alloc.inner().len() == 0 {
let val = alloc.inner().align.bytes().wrapping_add(offset.bytes());
fx.bcx.ins().iconst(
fx.pointer_type,
fx.tcx.truncate_to_target_usize(val) as i64,
)
fx.bcx.ins().iconst(fx.pointer_type, alloc.inner().align.bytes() as i64)
} else {
let data_id = data_id_for_alloc_id(
&mut fx.constants_cx,
@ -153,17 +150,16 @@ pub(crate) fn codegen_const_value<'tcx>(
alloc.inner().mutability,
);
let local_data_id =
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
fx.module.declare_data_in_func(data_id, fx.bcx.func);
if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("{:?}", alloc_id));
}
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
}
}
GlobalAlloc::Function { instance, .. } => {
let func_id = crate::abi::import_function(fx.tcx, fx.module, instance);
let local_func_id =
fx.module.declare_func_in_func(func_id, &mut fx.bcx.func);
let local_func_id = fx.module.declare_func_in_func(func_id, fx.bcx.func);
fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
}
GlobalAlloc::VTable(ty, dyn_ty) => {
@ -176,9 +172,8 @@ pub(crate) fn codegen_const_value<'tcx>(
fx.tcx.instantiate_bound_regions_with_erased(principal)
}),
);
let local_data_id =
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
}
GlobalAlloc::TypeId { .. } => {
return CValue::const_val(
@ -194,16 +189,26 @@ pub(crate) fn codegen_const_value<'tcx>(
// For a declaration the stated mutability doesn't matter.
false,
);
let local_data_id =
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("{:?}", def_id));
}
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
if fx
.tcx
.codegen_fn_attrs(def_id)
.flags
.contains(CodegenFnAttrFlags::THREAD_LOCAL)
{
fx.bcx.ins().tls_value(fx.pointer_type, local_data_id)
} else {
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
}
}
};
let val = if offset.bytes() != 0 {
fx.bcx.ins().iadd_imm(base_addr, i64::try_from(offset.bytes()).unwrap())
fx.bcx
.ins()
.iadd_imm(base_addr, fx.tcx.truncate_to_target_usize(offset.bytes()) as i64)
} else {
base_addr
};
@ -211,32 +216,28 @@ pub(crate) fn codegen_const_value<'tcx>(
}
},
ConstValue::Indirect { alloc_id, offset } => CValue::by_ref(
pointer_for_allocation(fx, alloc_id)
Pointer::new(pointer_for_allocation(fx, alloc_id))
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
layout,
),
ConstValue::Slice { alloc_id, meta } => {
let ptr = pointer_for_allocation(fx, alloc_id).get_addr(fx);
let ptr = pointer_for_allocation(fx, alloc_id);
let len = fx.bcx.ins().iconst(fx.pointer_type, meta as i64);
CValue::by_val_pair(ptr, len, layout)
}
}
}
fn pointer_for_allocation<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
alloc_id: AllocId,
) -> crate::pointer::Pointer {
fn pointer_for_allocation<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, alloc_id: AllocId) -> Value {
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
let data_id =
data_id_for_alloc_id(&mut fx.constants_cx, fx.module, alloc_id, alloc.inner().mutability);
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("{:?}", alloc_id));
}
let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
crate::pointer::Pointer::new(global_ptr)
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
}
fn data_id_for_alloc_id(
@ -262,6 +263,11 @@ pub(crate) fn data_id_for_vtable<'tcx>(
data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
}
pub(crate) fn pointer_for_anonymous_str(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) -> Value {
let alloc_id = fx.tcx.allocate_bytes_dedup(msg.as_bytes(), CTFE_ALLOC_SALT);
pointer_for_allocation(fx, alloc_id)
}
fn data_id_for_static(
tcx: TyCtxt<'_>,
module: &mut dyn Module,
@ -345,7 +351,7 @@ fn data_id_for_static(
Linkage::Import
};
let data_id = match module.declare_data(
match module.declare_data(
symbol_name,
linkage,
definition_writable,
@ -356,9 +362,7 @@ fn data_id_for_static(
"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) {
@ -368,6 +372,8 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
continue;
}
let mut data = DataDescription::new();
let (data_id, alloc, section_name) = match todo_item {
TodoItem::Alloc(alloc_id) => {
let alloc = match tcx.global_alloc(alloc_id) {
@ -386,7 +392,10 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
(data_id, alloc, None)
}
TodoItem::Static(def_id) => {
let section_name = tcx.codegen_fn_attrs(def_id).link_section;
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
let section_name = codegen_fn_attrs.link_section;
data.set_used(codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
let alloc = tcx.eval_static_initializer(def_id).unwrap();
@ -401,7 +410,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
}
};
let mut data = DataDescription::new();
let alloc = alloc.inner();
data.set_align(alloc.align.bytes());
@ -594,7 +602,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
{
return None;
}
StatementKind::Intrinsic(ref intrinsic) => match **intrinsic {
StatementKind::Intrinsic(intrinsic) => match **intrinsic {
NonDivergingIntrinsic::CopyNonOverlapping(..) => return None,
NonDivergingIntrinsic::Assume(..) => {}
},

View file

@ -96,7 +96,7 @@ impl WriterRelocate {
if jit_module.declarations().get_function_decl(func_id).name.as_deref()
== Some("rust_eh_personality")
{
extern "C" {
unsafe extern "C" {
fn rust_eh_personality() -> !;
}
rust_eh_personality as *const u8
@ -222,12 +222,12 @@ impl Writer for WriterRelocate {
gimli::DW_EH_PE_absptr => {
self.relocs.push(DebugReloc {
offset: self.len() as u32,
size: size.into(),
size,
name: DebugRelocName::Symbol(symbol),
addend,
kind: object::RelocationKind::Absolute,
});
self.write_udata(0, size.into())
self.write_udata(0, size)
}
_ => Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)),
},

View file

@ -0,0 +1,271 @@
use gimli::write::{Address, Writer};
use gimli::{DW_EH_PE_omit, DW_EH_PE_uleb128, Encoding, LittleEndian};
pub(super) struct GccExceptTable {
pub call_sites: CallSiteTable,
pub actions: ActionTable,
pub type_info: TypeInfoTable,
}
impl GccExceptTable {
pub(super) fn write<W: Writer>(
&self,
w: &mut W,
encoding: Encoding,
) -> gimli::write::Result<()> {
// lpStartEncoding
w.write_u8(DW_EH_PE_omit.0)?;
// lpStart (omitted)
let type_info_padding = if self.type_info.type_info.is_empty() {
// ttypeEncoding
w.write_u8(DW_EH_PE_omit.0)?;
None
} else {
// ttypeEncoding
w.write_u8(self.type_info.ttype_encoding.0)?;
// classInfoOffset
let class_info_offset_field_offset = w.len() as u64;
// Note: The offset in classInfoOffset is relative to position right after classInfoOffset
// itself.
let class_info_offset_no_padding = self.call_sites.encoded_size()
+ self.actions.encoded_size()
+ self.type_info.encoded_size(encoding);
let type_info_is_aligned = |type_info_padding: u64| {
(class_info_offset_field_offset
+ gimli::leb128::write::uleb128_size(
class_info_offset_no_padding + type_info_padding,
) as u64
+ self.call_sites.encoded_size()
+ self.actions.encoded_size()
+ type_info_padding)
.is_multiple_of(4)
};
let mut type_info_padding = 0;
while !type_info_is_aligned(type_info_padding) {
type_info_padding += 1;
}
w.write_uleb128(class_info_offset_no_padding + type_info_padding)?;
Some(type_info_padding)
};
// call site table
self.call_sites.write(w)?;
// action table
self.actions.write(w)?;
// align to 4 bytes
if let Some(type_info_padding) = type_info_padding {
for _ in 0..type_info_padding {
w.write_u8(0)?;
}
// In this case we calculated the expected padding amount and used it to write the
// classInfoOffset field. Assert that the expected value matched the actual value to catch
// any inconsistency.
assert!(w.len().is_multiple_of(4), "type_info must be aligned to 4 bytes");
} else {
while !w.len().is_multiple_of(4) {
w.write_u8(0)?;
}
}
// type_info
self.type_info.write(w, encoding)?;
// exception specs (unused for rust)
// align to 4 bytes
while !w.len().is_multiple_of(4) {
w.write_u8(0)?;
}
Ok(())
}
}
pub(super) struct CallSiteTable(pub Vec<CallSite>);
impl CallSiteTable {
fn encoded_size(&self) -> u64 {
let mut len = LenWriter(0);
self.write(&mut len).unwrap();
len.0 as u64
}
fn write<W: Writer>(&self, w: &mut W) -> gimli::write::Result<()> {
let callsite_table_length = self.0.iter().map(|call_site| call_site.encoded_size()).sum();
// callsiteEncoding
w.write_u8(DW_EH_PE_uleb128.0)?;
// callsiteTableLength
w.write_uleb128(callsite_table_length)?;
for call_site in &self.0 {
call_site.write(w)?;
}
Ok(())
}
}
pub(super) struct CallSite {
pub start: u64,
pub length: u64,
pub landing_pad: u64,
pub action_entry: Option<ActionOffset>,
}
impl CallSite {
fn encoded_size(&self) -> u64 {
let mut len = LenWriter(0);
self.write(&mut len).unwrap();
len.0 as u64
}
fn write<W: Writer>(&self, w: &mut W) -> gimli::write::Result<()> {
w.write_uleb128(self.start)?;
w.write_uleb128(self.length)?;
w.write_uleb128(self.landing_pad)?;
w.write_uleb128(match self.action_entry {
Some(action_offset) => action_offset.0 + 1,
None => 0,
})?;
Ok(())
}
}
pub(super) struct ActionTable {
actions: Vec<Action>,
encoded_length: u64,
}
impl ActionTable {
pub(super) fn new() -> ActionTable {
ActionTable { actions: vec![], encoded_length: 0 }
}
pub(super) fn add(&mut self, action: Action) -> ActionOffset {
let id = ActionOffset(self.encoded_length);
self.encoded_length += action.encoded_size(self.encoded_length);
self.actions.push(action);
id
}
fn encoded_size(&self) -> u64 {
let mut len = LenWriter(0);
self.write(&mut len).unwrap();
len.0 as u64
}
fn write<W: Writer>(&self, w: &mut W) -> gimli::write::Result<()> {
let action_table_start = w.len() as u64;
for action in &self.actions {
action.write(w, w.len() as u64 - action_table_start)?;
}
Ok(())
}
}
#[derive(Copy, Clone)]
pub(super) struct ActionOffset(u64);
pub(super) struct Action {
pub(super) kind: ActionKind,
pub(super) next_action: Option<ActionOffset>,
}
impl Action {
fn encoded_size(&self, action_table_offset: u64) -> u64 {
let mut len = LenWriter(0);
self.write(&mut len, action_table_offset).unwrap();
len.0 as u64
}
fn write<W: Writer>(&self, w: &mut W, action_table_offset: u64) -> gimli::write::Result<()> {
// ttypeIndex
let ttype_index = match self.kind {
ActionKind::Catch(type_info_id) => type_info_id.0 as i64 + 1,
};
w.write_sleb128(ttype_index)?;
// actionOffset
let action_offset_field_offset =
action_table_offset + gimli::leb128::write::sleb128_size(ttype_index) as u64;
w.write_sleb128(match self.next_action {
Some(next_action_offset) => {
next_action_offset.0 as i64 - action_offset_field_offset as i64
}
None => 0,
})?;
Ok(())
}
}
#[derive(Copy, Clone)]
pub(super) enum ActionKind {
Catch(TypeInfoId),
}
pub(super) struct TypeInfoTable {
ttype_encoding: gimli::DwEhPe,
type_info: Vec<Address>,
}
impl TypeInfoTable {
pub(super) fn new(ttype_encoding: gimli::DwEhPe) -> TypeInfoTable {
TypeInfoTable { ttype_encoding, type_info: vec![] }
}
pub(super) fn add(&mut self, type_info: Address) -> TypeInfoId {
let id = TypeInfoId(self.type_info.len() as u64);
self.type_info.push(type_info);
id
}
fn encoded_size(&self, encoding: Encoding) -> u64 {
let mut len = LenWriter(0);
self.write(&mut len, encoding).unwrap();
len.0 as u64
}
fn write<W: Writer>(&self, w: &mut W, encoding: Encoding) -> gimli::write::Result<()> {
for &type_info in self.type_info.iter().rev() {
w.write_eh_pointer(type_info, self.ttype_encoding, encoding.address_size)?;
}
Ok(())
}
}
#[derive(Copy, Clone)]
pub(super) struct TypeInfoId(u64);
struct LenWriter(usize);
impl Writer for LenWriter {
type Endian = LittleEndian;
fn endian(&self) -> LittleEndian {
LittleEndian
}
fn len(&self) -> usize {
self.0
}
fn write(&mut self, bytes: &[u8]) -> gimli::write::Result<()> {
self.0 += bytes.len();
Ok(())
}
fn write_at(&mut self, offset: usize, bytes: &[u8]) -> gimli::write::Result<()> {
assert!(offset + bytes.len() < self.0);
Ok(())
}
}

View file

@ -6,9 +6,7 @@ use std::path::{Component, Path};
use cranelift_codegen::MachSrcLoc;
use cranelift_codegen::binemit::CodeOffset;
use gimli::write::{AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable};
use rustc_span::{
FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm, hygiene,
};
use rustc_span::{FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHashAlgorithm, hygiene};
use crate::debuginfo::FunctionDebugContext;
use crate::debuginfo::emit::address_for_func;
@ -44,21 +42,27 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] {
}
}
const MD5_LEN: usize = 16;
fn make_file_info(source_file: &SourceFile, embed_source: bool) -> Option<FileInfo> {
let has_md5 = source_file.src_hash.kind == SourceFileHashAlgorithm::Md5;
let has_source = embed_source && source_file.src.is_some();
fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
if hash.kind == SourceFileHashAlgorithm::Md5 {
let mut buf = [0u8; MD5_LEN];
buf.copy_from_slice(hash.hash_bytes());
Some(FileInfo {
timestamp: 0,
size: 0,
md5: buf,
source: None, // FIXME implement -Zembed-source
})
} else {
None
if !has_md5 && !has_source {
return None;
}
let mut info = FileInfo::default();
if has_md5 {
info.md5.copy_from_slice(source_file.src_hash.hash_bytes());
}
if embed_source {
if let Some(src) = &source_file.src {
info.source = Some(LineString::String(src.as_bytes().to_vec()));
}
}
Some(info)
}
impl DebugContext {
@ -105,15 +109,19 @@ impl DebugContext {
let file_name =
LineString::new(file_name, line_program.encoding(), line_strings);
let info = make_file_info(source_file.src_hash);
let info = make_file_info(source_file, self.embed_source);
line_program.file_has_md5 &= info.is_some();
let has_md5 = source_file.src_hash.kind == SourceFileHashAlgorithm::Md5;
line_program.file_has_md5 &= has_md5;
line_program.add_file(file_name, dir_id, info)
}
filename => {
let dir_id = line_program.default_directory();
// For anonymous sources, create an empty directory instead of using the default
let empty_dir = LineString::new(b"", line_program.encoding(), line_strings);
let dir_id = line_program.add_directory(empty_dir);
let dummy_file_name = LineString::new(
filename.display(self.filename_display_preference).to_string().into_bytes(),
filename.prefer_remapped_unconditionally().to_string().into_bytes(),
line_program.encoding(),
line_strings,
);

View file

@ -1,6 +1,7 @@
//! Handling of everything related to debuginfo.
mod emit;
mod gcc_except_table;
mod line_info;
mod object;
mod types;
@ -19,12 +20,13 @@ use rustc_codegen_ssa::debuginfo::type_names;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefIdMap;
use rustc_session::Session;
use rustc_session::config::DebugInfo;
use rustc_span::{FileNameDisplayPreference, SourceFileHash, StableSourceFileId};
use rustc_target::callconv::FnAbi;
pub(crate) use self::emit::{DebugReloc, DebugRelocName};
pub(crate) use self::types::TypeDebugContext;
pub(crate) use self::unwind::UnwindContext;
pub(crate) use self::unwind::{EXCEPTION_HANDLER_CATCH, EXCEPTION_HANDLER_CLEANUP, UnwindContext};
use crate::debuginfo::emit::{address_for_data, address_for_func};
use crate::prelude::*;
@ -43,6 +45,7 @@ pub(crate) struct DebugContext {
array_size_type: UnitEntryId,
filename_display_preference: FileNameDisplayPreference,
embed_source: bool,
}
pub(crate) struct FunctionDebugContext {
@ -52,22 +55,37 @@ pub(crate) struct FunctionDebugContext {
}
impl DebugContext {
pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, cgu_name: &str) -> Self {
pub(crate) fn new(
tcx: TyCtxt<'_>,
isa: &dyn TargetIsa,
force_disable_debuginfo: bool,
cgu_name: &str,
) -> Option<Self> {
if tcx.sess.opts.debuginfo == DebugInfo::None
|| force_disable_debuginfo
|| tcx.sess.target.options.is_like_windows
{
return None;
}
let mut requested_dwarf_version = tcx.sess.dwarf_version();
if tcx.sess.target.is_like_darwin && requested_dwarf_version > 4 {
// Apples shipped debuggers still expect DWARF <= 4 by default.
// Stay on v4 unless the user explicitly opts into a feature that
// only works with v5 (e.g. -Zembed-source).
if !tcx.sess.opts.unstable_opts.embed_source {
requested_dwarf_version = 4;
}
}
let encoding = Encoding {
format: Format::Dwarf32,
// FIXME this should be configurable
// macOS doesn't seem to support DWARF > 3
// 5 version is required for md5 file hash
version: if tcx.sess.target.is_like_darwin {
3
} else {
// FIXME change to version 5 once the gdb and lldb shipping with the latest debian
// support it.
4
},
version: requested_dwarf_version as u16,
address_size: isa.frontend_config().pointer_bytes(),
};
let embed_source = tcx.sess.opts.unstable_opts.embed_source && encoding.version >= 5;
let endian = match isa.endianness() {
Endianness::Little => RunTimeEndian::Little,
Endianness::Big => RunTimeEndian::Big,
@ -106,10 +124,14 @@ impl DebugContext {
encoding,
LineEncoding::default(),
LineString::new(comp_dir.as_bytes(), encoding, &mut dwarf.line_strings),
None,
LineString::new(name.as_bytes(), encoding, &mut dwarf.line_strings),
file_info,
);
line_program.file_has_md5 = file_has_md5;
if embed_source {
line_program.file_has_source = true;
}
dwarf.unit.line_program = line_program;
@ -145,7 +167,7 @@ impl DebugContext {
AttributeValue::Udata(isa.frontend_config().pointer_bytes().into()),
);
DebugContext {
Some(DebugContext {
endian,
dwarf,
unit_range_list: RangeList(Vec::new()),
@ -154,7 +176,8 @@ impl DebugContext {
namespace_map: DefIdMap::default(),
array_size_type,
filename_display_preference,
}
embed_source,
})
}
fn item_namespace(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> UnitEntryId {

View file

@ -56,7 +56,7 @@ impl DebugContext {
// ty::FnDef(..) | ty::FnPtr(..)
// ty::Closure(..)
// ty::Adt(def, ..)
ty::Tuple(components) => self.tuple_type(tcx, type_dbg, ty, *components),
ty::Tuple(components) => self.tuple_type(tcx, type_dbg, ty, components),
// ty::Param(_)
// FIXME implement remaining types and add unreachable!() to the fallback branch
_ => self.placeholder_for_type(tcx, type_dbg, ty),
@ -152,7 +152,7 @@ impl DebugContext {
components: &'tcx [Ty<'tcx>],
) -> UnitEntryId {
let components = components
.into_iter()
.iter()
.map(|&ty| (ty, self.debug_type(tcx, type_dbg, ty)))
.collect::<Vec<_>>();

View file

@ -1,15 +1,23 @@
//! Unwind info generation (`.eh_frame`)
use cranelift_codegen::FinalizedMachExceptionHandler;
use cranelift_codegen::ir::Endianness;
use cranelift_codegen::isa::unwind::UnwindInfo;
use cranelift_module::DataId;
use cranelift_object::ObjectProduct;
use gimli::RunTimeEndian;
use gimli::write::{CieId, EhFrame, FrameTable, Section};
use gimli::write::{Address, CieId, EhFrame, FrameTable, Section};
use gimli::{Encoding, Format, RunTimeEndian};
use super::emit::address_for_func;
use super::emit::{DebugRelocName, address_for_data, address_for_func};
use super::gcc_except_table::{
Action, ActionKind, ActionTable, CallSite, CallSiteTable, GccExceptTable, TypeInfoTable,
};
use super::object::WriteDebugInfo;
use crate::prelude::*;
pub(crate) const EXCEPTION_HANDLER_CLEANUP: u32 = 0;
pub(crate) const EXCEPTION_HANDLER_CATCH: u32 = 1;
pub(crate) struct UnwindContext {
endian: RunTimeEndian,
frame_table: FrameTable,
@ -25,10 +33,79 @@ impl UnwindContext {
let mut frame_table = FrameTable::default();
let cie_id = if let Some(mut cie) = module.isa().create_systemv_cie() {
if pic_eh_frame {
cie.fde_address_encoding =
gimli::DwEhPe(gimli::DW_EH_PE_pcrel.0 | gimli::DW_EH_PE_sdata4.0);
let ptr_encoding = if pic_eh_frame {
gimli::DwEhPe(gimli::DW_EH_PE_pcrel.0 | gimli::DW_EH_PE_sdata4.0)
} else {
gimli::DW_EH_PE_absptr
};
cie.fde_address_encoding = ptr_encoding;
// FIXME only add personality function and lsda when necessary: https://github.com/rust-lang/rust/blob/1f76d219c906f0112bb1872f33aa977164c53fa6/compiler/rustc_codegen_ssa/src/mir/mod.rs#L200-L204
if cfg!(feature = "unwinding") {
let code_ptr_encoding = if pic_eh_frame {
if module.isa().triple().architecture == target_lexicon::Architecture::X86_64 {
gimli::DwEhPe(
gimli::DW_EH_PE_indirect.0
| gimli::DW_EH_PE_pcrel.0
| gimli::DW_EH_PE_sdata4.0,
)
} else if let target_lexicon::Architecture::Aarch64(_) =
module.isa().triple().architecture
{
gimli::DwEhPe(
gimli::DW_EH_PE_indirect.0
| gimli::DW_EH_PE_pcrel.0
| gimli::DW_EH_PE_sdata8.0,
)
} else {
todo!()
}
} else {
gimli::DwEhPe(gimli::DW_EH_PE_indirect.0 | gimli::DW_EH_PE_absptr.0)
};
cie.lsda_encoding = Some(ptr_encoding);
// FIXME use eh_personality lang item instead
let personality = module
.declare_function(
"rust_eh_personality",
Linkage::Import,
&Signature {
params: vec![
AbiParam::new(types::I32),
AbiParam::new(types::I32),
AbiParam::new(types::I64),
AbiParam::new(module.target_config().pointer_type()),
AbiParam::new(module.target_config().pointer_type()),
],
returns: vec![AbiParam::new(types::I32)],
call_conv: module.target_config().default_call_conv,
},
)
.unwrap();
// Use indirection here to support PIC the case where rust_eh_personality is defined in
// another DSO.
let personality_ref = module
.declare_data("DW.ref.rust_eh_personality", Linkage::Local, false, false)
.unwrap();
let mut personality_ref_data = DataDescription::new();
// Note: Must not use define_zeroinit. The unwinder can't handle this being in the .bss
// section.
let pointer_bytes = usize::from(module.target_config().pointer_bytes());
personality_ref_data.define(vec![0; pointer_bytes].into_boxed_slice());
let personality_func_ref =
module.declare_func_in_data(personality, &mut personality_ref_data);
personality_ref_data.write_function_addr(0, personality_func_ref);
module.define_data(personality_ref, &personality_ref_data).unwrap();
cie.personality = Some((code_ptr_encoding, address_for_data(personality_ref)));
}
Some(frame_table.add_cie(cie))
} else {
None
@ -63,8 +140,100 @@ impl UnwindContext {
match unwind_info {
UnwindInfo::SystemV(unwind_info) => {
self.frame_table
.add_fde(self.cie_id.unwrap(), unwind_info.to_fde(address_for_func(func_id)));
let mut fde = unwind_info.to_fde(address_for_func(func_id));
// FIXME only add personality function and lsda when necessary: https://github.com/rust-lang/rust/blob/1f76d219c906f0112bb1872f33aa977164c53fa6/compiler/rustc_codegen_ssa/src/mir/mod.rs#L200-L204
if cfg!(feature = "unwinding") {
// FIXME use unique symbol name derived from function name
let lsda = module.declare_anonymous_data(false, false).unwrap();
let encoding = Encoding {
format: Format::Dwarf32,
version: 1,
address_size: module.isa().frontend_config().pointer_bytes(),
};
let mut gcc_except_table_data = GccExceptTable {
call_sites: CallSiteTable(vec![]),
actions: ActionTable::new(),
type_info: TypeInfoTable::new(gimli::DW_EH_PE_udata4),
};
let catch_type = gcc_except_table_data.type_info.add(Address::Constant(0));
let catch_action = gcc_except_table_data
.actions
.add(Action { kind: ActionKind::Catch(catch_type), next_action: None });
for call_site in context.compiled_code().unwrap().buffer.call_sites() {
if call_site.exception_handlers.is_empty() {
gcc_except_table_data.call_sites.0.push(CallSite {
start: u64::from(call_site.ret_addr - 1),
length: 1,
landing_pad: 0,
action_entry: None,
});
}
for &handler in call_site.exception_handlers {
match handler {
FinalizedMachExceptionHandler::Tag(tag, landingpad) => {
match tag.as_u32() {
EXCEPTION_HANDLER_CLEANUP => {
gcc_except_table_data.call_sites.0.push(CallSite {
start: u64::from(call_site.ret_addr - 1),
length: 1,
landing_pad: u64::from(landingpad),
action_entry: None,
})
}
EXCEPTION_HANDLER_CATCH => {
gcc_except_table_data.call_sites.0.push(CallSite {
start: u64::from(call_site.ret_addr - 1),
length: 1,
landing_pad: u64::from(landingpad),
action_entry: Some(catch_action),
})
}
_ => unreachable!(),
}
}
_ => unreachable!(),
}
}
}
let mut gcc_except_table = super::emit::WriterRelocate::new(self.endian);
gcc_except_table_data.write(&mut gcc_except_table, encoding).unwrap();
let mut data = DataDescription::new();
data.define(gcc_except_table.writer.into_vec().into_boxed_slice());
data.set_segment_section("", ".gcc_except_table");
for reloc in &gcc_except_table.relocs {
match reloc.name {
DebugRelocName::Section(_id) => unreachable!(),
DebugRelocName::Symbol(id) => {
let id = id.try_into().unwrap();
if id & 1 << 31 == 0 {
let func_ref = module
.declare_func_in_data(FuncId::from_u32(id), &mut data);
data.write_function_addr(reloc.offset, func_ref);
} else {
let gv = module.declare_data_in_data(
DataId::from_u32(id & !(1 << 31)),
&mut data,
);
data.write_data_addr(reloc.offset, gv, 0);
}
}
};
}
module.define_data(lsda, &data).unwrap();
fde.lsda = Some(address_for_data(lsda));
}
self.frame_table.add_fde(self.cie_id.unwrap(), fde);
}
UnwindInfo::WindowsX64(_) | UnwindInfo::WindowsArm64(_) => {
// Windows does not have debug info for its unwind info.
@ -116,7 +285,7 @@ impl UnwindContext {
// Everything after this line up to the end of the file is loosely based on
// https://github.com/bytecodealliance/wasmtime/blob/4471a82b0c540ff48960eca6757ccce5b1b5c3e4/crates/jit/src/unwind/systemv.rs
#[cfg(target_os = "macos")]
{
unsafe {
// On macOS, `__register_frame` takes a pointer to a single FDE
let start = eh_frame.as_ptr();
let end = start.add(eh_frame.len());
@ -138,12 +307,12 @@ impl UnwindContext {
#[cfg(not(target_os = "macos"))]
{
// On other platforms, `__register_frame` will walk the FDEs until an entry of length 0
__register_frame(eh_frame.as_ptr());
unsafe { __register_frame(eh_frame.as_ptr()) };
}
}
}
extern "C" {
unsafe extern "C" {
// libunwind import
fn __register_frame(fde: *const u8);
}

View file

@ -24,9 +24,8 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility};
use rustc_session::Session;
use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
use rustc_session::config::{OutFileName, OutputFilenames, OutputType};
use crate::CodegenCx;
use crate::base::CodegenedFunction;
use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
use crate::debuginfo::TypeDebugContext;
@ -98,8 +97,8 @@ impl OngoingCodegen {
sess,
&module_regular.name,
&[
("o", &module_regular.object.as_ref().unwrap()),
("asm.o", &module_global_asm.object.as_ref().unwrap()),
("o", module_regular.object.as_ref().unwrap()),
("asm.o", module_global_asm.object.as_ref().unwrap()),
],
&[],
)
@ -107,7 +106,7 @@ impl OngoingCodegen {
rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
sess,
&module_regular.name,
&[("o", &module_regular.object.as_ref().unwrap())],
&[("o", module_regular.object.as_ref().unwrap())],
&[],
)
};
@ -309,7 +308,7 @@ fn produce_final_output_artifacts(
module.for_each_output(|path, ty| {
if sess.opts.output_types.contains_key(&ty) {
let descr = ty.shorthand();
sess.dcx().emit_artifact_notification(&path, descr);
sess.dcx().emit_artifact_notification(path, descr);
}
});
}
@ -451,8 +450,8 @@ fn reuse_workproduct_for_cgu(
tcx.sess.invocation_temp.as_deref(),
);
let source_file_regular = rustc_incremental::in_incr_comp_dir_sess(
&tcx.sess,
&work_product.saved_files.get("o").expect("no saved object file in work product"),
tcx.sess,
work_product.saved_files.get("o").expect("no saved object file in work product"),
);
if let Err(err) = rustc_fs_util::link_or_copy(&source_file_regular, &obj_out_regular) {
@ -467,7 +466,7 @@ fn reuse_workproduct_for_cgu(
let obj_out_global_asm =
crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm");
let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") {
let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o);
let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(tcx.sess, asm_o);
if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm)
{
return Err(format!(
@ -511,18 +510,14 @@ fn codegen_cgu_content(
tcx: TyCtxt<'_>,
module: &mut dyn Module,
cgu_name: rustc_span::Symbol,
) -> (CodegenCx, Vec<CodegenedFunction>) {
) -> (Option<DebugContext>, Vec<CodegenedFunction>, String) {
let _timer = tcx.prof.generic_activity_with_arg("codegen cgu", cgu_name.as_str());
let cgu = tcx.codegen_unit(cgu_name);
let mono_items = cgu.items_in_deterministic_order(tcx);
let mut cx = crate::CodegenCx::new(
tcx,
module.isa(),
tcx.sess.opts.debuginfo != DebugInfo::None,
cgu_name,
);
let mut debug_context = DebugContext::new(tcx, module.isa(), false, cgu_name.as_str());
let mut global_asm = String::new();
let mut type_dbg = TypeDebugContext::default();
super::predefine_mono_items(tcx, module, &mono_items);
let mut codegened_functions = vec![];
@ -532,7 +527,7 @@ fn codegen_cgu_content(
let flags = tcx.codegen_instance_attrs(instance.def).flags;
if flags.contains(CodegenFnAttrFlags::NAKED) {
rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm(
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
&mut GlobalAsmContext { tcx, global_asm: &mut global_asm },
instance,
MonoItemData {
linkage: RLinkage::External,
@ -548,7 +543,8 @@ fn codegen_cgu_content(
}
let codegened_function = crate::base::codegen_fn(
tcx,
&mut cx,
cgu_name,
debug_context.as_mut(),
&mut type_dbg,
Function::new(),
module,
@ -558,13 +554,13 @@ fn codegen_cgu_content(
}
MonoItem::Static(def_id) => {
let data_id = crate::constant::codegen_static(tcx, module, def_id);
if let Some(debug_context) = &mut cx.debug_context {
if let Some(debug_context) = debug_context.as_mut() {
debug_context.define_static(tcx, &mut type_dbg, def_id, data_id);
}
}
MonoItem::GlobalAsm(item_id) => {
rustc_codegen_ssa::base::codegen_global_asm(
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
&mut GlobalAsmContext { tcx, global_asm: &mut global_asm },
item_id,
);
}
@ -572,7 +568,7 @@ fn codegen_cgu_content(
}
crate::main_shim::maybe_create_entry_wrapper(tcx, module, false, cgu.is_primary());
(cx, codegened_functions)
(debug_context, codegened_functions, global_asm)
}
fn module_codegen(
@ -585,13 +581,17 @@ fn module_codegen(
) -> OngoingModuleCodegen {
let mut module = make_module(tcx.sess, cgu_name.as_str().to_string());
let (mut cx, codegened_functions) = codegen_cgu_content(tcx, &mut module, cgu_name);
let (mut debug_context, codegened_functions, mut global_asm) =
codegen_cgu_content(tcx, &mut module, cgu_name);
let cgu_name = cgu_name.as_str().to_owned();
let producer = crate::debuginfo::producer(tcx.sess);
let profiler = tcx.prof.clone();
let invocation_temp = tcx.sess.invocation_temp.clone();
let output_filenames = tcx.output_filenames(()).clone();
let should_write_ir = crate::pretty_clif::should_write_ir(tcx.sess);
OngoingModuleCodegen::Async(std::thread::spawn(move || {
profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| {
@ -602,10 +602,13 @@ fn module_codegen(
let mut cached_context = Context::new();
for codegened_func in codegened_functions {
crate::base::compile_fn(
&mut cx,
&profiler,
&output_filenames,
should_write_ir,
&mut cached_context,
&mut module,
debug_context.as_mut(),
&mut global_asm,
codegened_func,
);
}
@ -616,8 +619,8 @@ fn module_codegen(
crate::global_asm::compile_global_asm(
&global_asm_config,
&cgu_name,
&cx.global_asm,
cx.invocation_temp.as_deref(),
global_asm,
invocation_temp.as_deref(),
)
})?;
@ -625,11 +628,11 @@ fn module_codegen(
profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| {
emit_cgu(
&global_asm_config.output_filenames,
cx.invocation_temp.as_deref(),
invocation_temp.as_deref(),
&profiler,
cgu_name,
module,
cx.debug_context,
debug_context,
global_asm_object_file,
&producer,
)
@ -681,7 +684,7 @@ pub(crate) fn run_aot(tcx: TyCtxt<'_>) -> Box<OngoingCodegen> {
// Calculate the CGU reuse
let cgu_reuse = tcx.sess.time("find_cgu_reuse", || {
cgus.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect::<Vec<_>>()
cgus.iter().map(|cgu| determine_cgu_reuse(tcx, cgu)).collect::<Vec<_>>()
});
rustc_codegen_ssa::assert_module_sources::assert_module_sources(tcx, &|cgu_reuse_tracker| {
@ -695,7 +698,7 @@ pub(crate) fn run_aot(tcx: TyCtxt<'_>) -> Box<OngoingCodegen> {
let disable_incr_cache = disable_incr_cache();
let (todo_cgus, done_cgus) =
cgus.into_iter().enumerate().partition::<Vec<_>, _>(|&(i, _)| match cgu_reuse[i] {
cgus.iter().enumerate().partition::<Vec<_>, _>(|&(i, _)| match cgu_reuse[i] {
_ if disable_incr_cache => true,
CguReuse::No => true,
CguReuse::PreLto | CguReuse::PostLto => false,

View file

@ -9,14 +9,14 @@ use rustc_codegen_ssa::CrateInfo;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::mono::MonoItem;
use rustc_session::Session;
use rustc_session::config::OutputFilenames;
use rustc_span::sym;
use crate::CodegenCx;
use crate::debuginfo::TypeDebugContext;
use crate::prelude::*;
use crate::unwind_module::UnwindModule;
fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, Option<DebugContext>) {
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
let isa = crate::build_isa(tcx.sess, true);
@ -25,7 +25,7 @@ fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
let cx = DebugContext::new(tcx, jit_module.isa(), false, "dummy_cgu_name");
crate::allocator::codegen(tcx, &mut jit_module);
@ -33,13 +33,13 @@ fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
}
pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
// FIXME error on check mode or crate types other than bin in CodegenBackend::init()
if !tcx.crate_types().contains(&rustc_session::config::CrateType::Executable) {
tcx.dcx().fatal("can't jit non-executable crate");
}
let (mut jit_module, mut cx) = create_jit_module(tcx);
let output_filenames = tcx.output_filenames(());
let should_write_ir = crate::pretty_clif::should_write_ir(tcx.sess);
let (mut jit_module, mut debug_context) = create_jit_module(tcx);
let mut cached_context = Context::new();
let cgus = tcx.collect_and_partition_mono_items(()).codegen_units;
@ -58,7 +58,9 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
MonoItem::Fn(inst) => {
codegen_and_compile_fn(
tcx,
&mut cx,
&output_filenames,
should_write_ir,
debug_context.as_mut(),
&mut cached_context,
&mut jit_module,
inst,
@ -75,10 +77,6 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
}
});
if !cx.global_asm.is_empty() {
tcx.dcx().fatal("Inline asm is not supported in JIT mode");
}
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, true, true);
tcx.dcx().abort_if_errors();
@ -120,7 +118,9 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
fn codegen_and_compile_fn<'tcx>(
tcx: TyCtxt<'tcx>,
cx: &mut crate::CodegenCx,
output_filenames: &OutputFilenames,
should_write_ir: bool,
mut debug_context: Option<&mut DebugContext>,
cached_context: &mut Context,
module: &mut dyn Module,
instance: Instance<'tcx>,
@ -141,13 +141,28 @@ fn codegen_and_compile_fn<'tcx>(
let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
let codegened_func = crate::base::codegen_fn(
tcx,
cx,
sym::dummy_cgu_name,
debug_context.as_deref_mut(),
&mut TypeDebugContext::default(),
cached_func,
module,
instance,
);
crate::base::compile_fn(cx, &tcx.prof, cached_context, module, codegened_func);
let mut global_asm = String::new();
crate::base::compile_fn(
&tcx.prof,
output_filenames,
should_write_ir,
cached_context,
module,
debug_context.as_deref_mut(),
&mut global_asm,
codegened_func,
);
if !global_asm.is_empty() {
tcx.dcx().fatal("Inline asm is not supported in JIT mode");
}
});
}

View file

@ -38,16 +38,12 @@ fn predefine_mono_items<'tcx>(
.codegen_instance_attrs(instance.def)
.flags
.contains(CodegenFnAttrFlags::NAKED);
module
.declare_function(
name,
// Naked functions are defined in a separate object
// file from the codegen unit rustc expects them to
// be defined in.
if is_naked { Linkage::Import } else { linkage },
&sig,
)
.unwrap();
if is_naked {
// Naked functions are defined in a separate object
// file, so they can be declared on the fly.
continue;
}
module.declare_function(name, linkage, &sig).unwrap();
}
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {}
}

View file

@ -171,7 +171,7 @@ impl GlobalAsmConfig {
pub(crate) fn compile_global_asm(
config: &GlobalAsmConfig,
cgu_name: &str,
global_asm: &str,
global_asm: String,
invocation_temp: Option<&str>,
) -> Result<Option<PathBuf>, String> {
if global_asm.is_empty() {
@ -205,6 +205,9 @@ pub(crate) fn compile_global_asm(
return Err(format!("Failed to assemble `{}`", global_asm));
}
} else {
// Escape { and }
let global_asm = global_asm.replace('{', "{{").replace('}', "}}");
let mut child = Command::new(std::env::current_exe().unwrap())
// Avoid a warning about the jobserver fd not being passed
.env_remove("CARGO_MAKEFLAGS")

View file

@ -7,6 +7,7 @@ use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::LangItem;
use rustc_span::sym;
use rustc_target::asm::*;
use rustc_target::spec::Arch;
use target_lexicon::BinaryFormat;
use crate::prelude::*;
@ -51,6 +52,26 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
return;
}
if fx.tcx.sess.target.arch == Arch::S390x
&& template.len() == 3
&& template[0] == InlineAsmTemplatePiece::String("stfle 0(".into())
&& let InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ } =
template[1]
&& template[2] == InlineAsmTemplatePiece::String(")".into())
{
// FIXME no inline asm support for s390x yet, but stdarch needs it for feature detection
match destination {
Some(destination) => {
let destination_block = fx.get_block(destination);
fx.bcx.ins().jump(destination_block, &[]);
}
None => {
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
}
}
return;
}
let operands = operands
.iter()
.map(|operand| match *operand {
@ -103,11 +124,12 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
// be exported from the main codegen unit and may thus be unreachable from the
// object file created by an external assembler.
let wrapper_name = format!(
"__inline_asm_{}_wrapper_n{}",
fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
fx.cx.inline_asm_index
"{}__inline_asm_{}_wrapper_n{}",
fx.symbol_name,
fx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
fx.inline_asm_index,
);
fx.cx.inline_asm_index += 1;
fx.inline_asm_index += 1;
let sig =
get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name);
@ -166,14 +188,15 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>(
asm_gen.allocate_stack_slots();
let asm_name = format!(
"__inline_asm_{}_n{}",
fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
fx.cx.inline_asm_index
"{}__inline_asm_{}_n{}",
fx.symbol_name,
fx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
fx.inline_asm_index,
);
fx.cx.inline_asm_index += 1;
fx.inline_asm_index += 1;
let generated_asm = asm_gen.generate_asm_wrapper(&asm_name);
fx.cx.global_asm.push_str(&generated_asm);
fx.inline_asm.push_str(&generated_asm);
let mut inputs = Vec::new();
let mut outputs = Vec::new();
@ -546,20 +569,6 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
.emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier)
.unwrap(),
},
InlineAsmArch::AArch64 => match reg {
InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
// rustc emits v0 rather than q0
reg.emit(
&mut generated_asm,
InlineAsmArch::AArch64,
Some(modifier.unwrap_or('q')),
)
.unwrap()
}
_ => reg
.emit(&mut generated_asm, InlineAsmArch::AArch64, *modifier)
.unwrap(),
},
_ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(),
}
}
@ -827,6 +836,7 @@ fn call_inline_asm<'tcx>(
}
let stack_slot_addr = stack_slot.get_addr(fx);
// FIXME use try_call once unwinding inline assembly is supported
fx.bcx.ins().call(inline_asm_func, &[stack_slot_addr]);
for (offset, place) in outputs {

View file

@ -3,7 +3,7 @@
macro_rules! intrinsic_args {
($fx:expr, $args:expr => ($($arg:tt),*); $intrinsic:expr) => {
#[allow(unused_parens)]
#[allow(unused_parens, clippy::unused_unit)]
let ($($arg),*) = if let [$($arg),*] = $args {
($(codegen_operand($fx, &($arg).node)),*)
} else {
@ -17,17 +17,21 @@ mod llvm_aarch64;
mod llvm_x86;
mod simd;
use cranelift_codegen::ir::AtomicRmwOp;
use cranelift_codegen::ir::{
AtomicRmwOp, BlockArg, ExceptionTableData, ExceptionTableItem, ExceptionTag,
};
use rustc_middle::ty;
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_span::source_map::Spanned;
use rustc_span::{Symbol, sym};
use rustc_target::spec::PanicStrategy;
pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
use crate::cast::clif_intcast;
use crate::codegen_f16_f128;
use crate::debuginfo::EXCEPTION_HANDLER_CATCH;
use crate::prelude::*;
fn bug_on_incorrect_arg_count(intrinsic: impl std::fmt::Display) -> ! {
@ -479,7 +483,7 @@ fn codegen_float_intrinsic_call<'tcx>(
};
let input_tys: Vec<_> =
vec![AbiParam::new(clif_ty), lib_call_arg_param(fx.tcx, types::I32, true)];
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0];
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0];
let ret_val = if intrinsic == sym::powif16 {
codegen_f16_f128::f32_to_f16(fx, ret_val)
} else {
@ -501,7 +505,7 @@ fn codegen_float_intrinsic_call<'tcx>(
}
_ => {
let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect();
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0];
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0];
CValue::by_val(ret_val, fx.layout_of(ty))
}
};
@ -1337,23 +1341,75 @@ fn codegen_regular_intrinsic_call<'tcx>(
}
sym::catch_unwind => {
let ret_block = fx.get_block(destination.unwrap());
intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic);
let f = f.load_scalar(fx);
let data = data.load_scalar(fx);
let _catch_fn = catch_fn.load_scalar(fx);
let catch_fn = catch_fn.load_scalar(fx);
// FIXME once unwinding is supported, change this to actually catch panics
let f_sig = fx.bcx.func.import_signature(Signature {
call_conv: fx.target_config.default_call_conv,
params: vec![AbiParam::new(pointer_ty(fx.tcx))],
returns: vec![],
});
fx.bcx.ins().call_indirect(f_sig, f, &[data]);
if cfg!(not(feature = "unwinding"))
|| fx.tcx.sess.panic_strategy() == PanicStrategy::Abort
{
fx.bcx.ins().call_indirect(f_sig, f, &[data]);
let layout = fx.layout_of(fx.tcx.types.i32);
let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 0), layout);
ret.write_cvalue(fx, ret_val);
let layout = fx.layout_of(fx.tcx.types.i32);
let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 0), layout);
ret.write_cvalue(fx, ret_val);
fx.bcx.ins().jump(ret_block, &[]);
} else {
let catch_fn_sig = fx.bcx.func.import_signature(Signature {
call_conv: fx.target_config.default_call_conv,
params: vec![
AbiParam::new(pointer_ty(fx.tcx)),
AbiParam::new(pointer_ty(fx.tcx)),
],
returns: vec![],
});
let fallthrough_block = fx.bcx.create_block();
let fallthrough_block_call = fx.bcx.func.dfg.block_call(fallthrough_block, &[]);
let catch_block = fx.bcx.create_block();
let catch_block_call =
fx.bcx.func.dfg.block_call(catch_block, &[BlockArg::TryCallExn(0)]);
let exception_table =
fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
f_sig,
fallthrough_block_call,
[ExceptionTableItem::Tag(
ExceptionTag::with_number(EXCEPTION_HANDLER_CATCH).unwrap(),
catch_block_call,
)],
));
fx.bcx.ins().try_call_indirect(f, &[data], exception_table);
fx.bcx.seal_block(fallthrough_block);
fx.bcx.switch_to_block(fallthrough_block);
let layout = fx.layout_of(fx.tcx.types.i32);
let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 0), layout);
ret.write_cvalue(fx, ret_val);
fx.bcx.ins().jump(ret_block, &[]);
fx.bcx.seal_block(catch_block);
fx.bcx.switch_to_block(catch_block);
fx.bcx.set_cold_block(catch_block);
let exception = fx.bcx.append_block_param(catch_block, pointer_ty(fx.tcx));
fx.bcx.ins().call_indirect(catch_fn_sig, catch_fn, &[data, exception]);
let layout = fx.layout_of(fx.tcx.types.i32);
let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 1), layout);
ret.write_cvalue(fx, ret_val);
fx.bcx.ins().jump(ret_block, &[]);
}
return Ok(());
}
sym::fadd_fast

View file

@ -813,7 +813,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
Endian::Big => lane_count - 1 - lane,
Endian::Little => lane,
};
let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(mask_lane) as i64);
let m_lane = fx.bcx.ins().ushr_imm(m, mask_lane.cast_signed());
let m_lane = fx.bcx.ins().band_imm(m_lane, 1);
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
let b_lane = b.value_lane(fx, lane).load_scalar(fx);
@ -1059,6 +1059,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let ret_lane_layout = fx.layout_of(ret_lane_ty);
let ptr_val = ptr.load_scalar(fx);
let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.unwrap_leaf()
.to_simd_alignment();
let memflags = match alignment {
SimdAlign::Unaligned => MemFlags::new().with_notrap(),
_ => MemFlags::trusted(),
};
for lane_idx in 0..ret_lane_count {
let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
@ -1074,12 +1083,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
fx.bcx.switch_to_block(if_enabled);
let offset = lane_idx as i32 * lane_clif_ty.bytes() as i32;
let res = fx.bcx.ins().load(
lane_clif_ty,
MemFlags::trusted(),
ptr_val,
Offset32::new(offset),
);
let res = fx.bcx.ins().load(lane_clif_ty, memflags, ptr_val, Offset32::new(offset));
fx.bcx.ins().jump(next, &[res.into()]);
fx.bcx.switch_to_block(if_disabled);

View file

@ -17,6 +17,7 @@ extern crate rustc_middle;
extern crate rustc_abi;
extern crate rustc_ast;
extern crate rustc_codegen_ssa;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fs_util;
@ -35,6 +36,7 @@ extern crate rustc_target;
extern crate rustc_driver;
use std::any::Any;
use std::cell::OnceCell;
use std::env;
use std::sync::Arc;
@ -120,41 +122,8 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
}
}
/// The codegen context holds any information shared between the codegen of individual functions
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
struct CodegenCx {
output_filenames: Arc<OutputFilenames>,
invocation_temp: Option<String>,
should_write_ir: bool,
global_asm: String,
inline_asm_index: usize,
debug_context: Option<DebugContext>,
cgu_name: Symbol,
}
impl CodegenCx {
fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, debug_info: bool, cgu_name: Symbol) -> Self {
assert_eq!(pointer_ty(tcx), isa.pointer_type());
let debug_context = if debug_info && !tcx.sess.target.options.is_like_windows {
Some(DebugContext::new(tcx, isa, cgu_name.as_str()))
} else {
None
};
CodegenCx {
output_filenames: tcx.output_filenames(()).clone(),
invocation_temp: tcx.sess.invocation_temp.clone(),
should_write_ir: crate::pretty_clif::should_write_ir(tcx),
global_asm: String::new(),
inline_asm_index: 0,
debug_context,
cgu_name,
}
}
}
pub struct CraneliftCodegenBackend {
pub config: Option<BackendConfig>,
pub config: OnceCell<BackendConfig>,
}
impl CodegenBackend for CraneliftCodegenBackend {
@ -180,6 +149,15 @@ impl CodegenBackend for CraneliftCodegenBackend {
sess.dcx()
.fatal("`-Cinstrument-coverage` is LLVM specific and not supported by Cranelift");
}
let config = self.config.get_or_init(|| {
BackendConfig::from_opts(&sess.opts.cg.llvm_args)
.unwrap_or_else(|err| sess.dcx().fatal(err))
});
if config.jit_mode && !sess.opts.output_types.should_codegen() {
sess.dcx().fatal("JIT mode doesn't work with `cargo check`");
}
}
fn target_config(&self, sess: &Session) -> TargetConfig {
@ -202,36 +180,23 @@ impl CodegenBackend for CraneliftCodegenBackend {
// FIXME do `unstable_target_features` properly
let unstable_target_features = target_features.clone();
// FIXME(f16_f128): LLVM 20 (currently used by `rustc`) passes `f128` in XMM registers on
// Windows, whereas LLVM 21+ and Cranelift pass it indirectly. This means that `f128` won't
// work when linking against a LLVM-built sysroot.
let has_reliable_f128 = !sess.target.is_like_windows;
let has_reliable_f16 = match sess.target.arch {
// FIXME(f16_f128): LLVM 20 does not support `f16` on s390x, meaning the required
// builtins are not available in `compiler-builtins`.
Arch::S390x => false,
// FIXME(f16_f128): `rustc_codegen_llvm` currently disables support on Windows GNU
// targets due to GCC using a different ABI than LLVM. Therefore `f16` won't be
// available when using a LLVM-built sysroot.
Arch::X86_64
if sess.target.os == "windows"
&& sess.target.env == "gnu"
&& sess.target.abi != "llvm" =>
{
false
}
_ => true,
};
// FIXME(f16_f128): `rustc_codegen_llvm` currently disables support on Windows GNU
// targets due to GCC using a different ABI than LLVM. Therefore `f16` and `f128`
// won't be available when using a LLVM-built sysroot.
let has_reliable_f16_f128 = !(sess.target.arch == Arch::X86_64
&& sess.target.os == "windows"
&& sess.target.env == "gnu"
&& sess.target.abi != "llvm");
TargetConfig {
target_features,
unstable_target_features,
// `rustc_codegen_cranelift` polyfills functionality not yet
// available in Cranelift.
has_reliable_f16,
has_reliable_f16_math: has_reliable_f16,
has_reliable_f128,
has_reliable_f128_math: has_reliable_f128,
has_reliable_f16: has_reliable_f16_f128,
has_reliable_f16_math: has_reliable_f16_f128,
has_reliable_f128: has_reliable_f16_f128,
has_reliable_f128_math: has_reliable_f16_f128,
}
}
@ -241,13 +206,10 @@ impl CodegenBackend for CraneliftCodegenBackend {
fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
info!("codegen crate {}", tcx.crate_name(LOCAL_CRATE));
let config = self.config.clone().unwrap_or_else(|| {
BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
.unwrap_or_else(|err| tcx.sess.dcx().fatal(err))
});
let config = self.config.get().unwrap();
if config.jit_mode {
#[cfg(feature = "jit")]
driver::jit::run_jit(tcx, config.jit_args);
driver::jit::run_jit(tcx, config.jit_args.clone());
#[cfg(not(feature = "jit"))]
tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
@ -294,8 +256,8 @@ fn build_isa(sess: &Session, jit: bool) -> Arc<dyn TargetIsa + 'static> {
flags_builder.set("enable_verifier", enable_verifier).unwrap();
flags_builder.set("regalloc_checker", enable_verifier).unwrap();
let mut frame_ptr = sess.target.options.frame_pointer.clone();
frame_ptr.ratchet(sess.opts.cg.force_frame_pointers);
let frame_ptr =
{ sess.target.options.frame_pointer }.ratchet(sess.opts.cg.force_frame_pointers);
let preserve_frame_pointer = frame_ptr != rustc_target::spec::FramePointer::MayOmit;
flags_builder
.set("preserve_frame_pointers", if preserve_frame_pointer { "true" } else { "false" })
@ -391,7 +353,7 @@ fn build_isa(sess: &Session, jit: bool) -> Arc<dyn TargetIsa + 'static> {
}
/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
#[unsafe(no_mangle)]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
Box::new(CraneliftCodegenBackend { config: None })
Box::new(CraneliftCodegenBackend { config: OnceCell::new() })
}

View file

@ -93,7 +93,7 @@ pub(crate) fn maybe_create_entry_wrapper(
let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());
let arg_sigpipe = bcx.ins().iconst(types::I8, sigpipe as i64);
let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);
let main_func_ref = m.declare_func_in_func(main_func_id, bcx.func);
let result = if ignore_lang_start_wrapper {
// ignoring #[lang = "start"] as we are running in the jit
@ -123,7 +123,7 @@ pub(crate) fn maybe_create_entry_wrapper(
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);
let report_func_ref = m.declare_func_in_func(report_func_id, bcx.func);
// FIXME do proper abi handling instead of expecting the pass mode to be identical
// for returns and arguments.
@ -148,7 +148,7 @@ pub(crate) fn maybe_create_entry_wrapper(
let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);
let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
let func_ref = m.declare_func_in_func(start_func_id, bcx.func);
let call_inst =
bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv, arg_sigpipe]);
bcx.inst_results(call_inst)[0]

View file

@ -64,6 +64,7 @@ use cranelift_codegen::ir::Fact;
use cranelift_codegen::ir::entities::AnyEntity;
use cranelift_codegen::write::{FuncWriter, PlainWriter};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::Session;
use rustc_session::config::{OutputFilenames, OutputType};
use rustc_target::callconv::FnAbi;
@ -83,7 +84,7 @@ impl CommentWriter {
instance: Instance<'tcx>,
fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
) -> Self {
let enabled = should_write_ir(tcx);
let enabled = should_write_ir(tcx.sess);
let global_comments = if enabled {
with_no_trimmed_paths!({
vec![
@ -247,8 +248,8 @@ impl FunctionCx<'_, '_, '_> {
}
}
pub(crate) fn should_write_ir(tcx: TyCtxt<'_>) -> bool {
tcx.sess.opts.output_types.contains_key(&OutputType::LlvmAssembly)
pub(crate) fn should_write_ir(sess: &Session) -> bool {
sess.opts.output_types.contains_key(&OutputType::LlvmAssembly)
}
pub(crate) fn write_ir_file(
@ -311,7 +312,7 @@ impl fmt::Debug for FunctionCx<'_, '_, '_> {
::cranelift_codegen::write::decorate_function(
&mut &self.clif_comments,
&mut clif,
&self.bcx.func,
self.bcx.func,
)
.unwrap();
writeln!(f, "\n{}", clif)

View file

@ -134,7 +134,7 @@ pub(crate) fn coerce_unsized_into<'tcx>(
(ty::Pat(a, _), ty::Pat(b, _)) => {
let src = src.cast_pat_ty_to_base(fx.layout_of(*a));
let dst = dst.place_transmute_type(fx, *b);
return coerce_unsized_into(fx, src, dst);
coerce_unsized_into(fx, src, dst)
}
(&ty::Ref(..), &ty::Ref(..))
| (&ty::Ref(..), &ty::RawPtr(..))

View file

@ -310,13 +310,13 @@ impl<'tcx> CValue<'tcx> {
fx.bcx.ins().iconst(clif_ty, raw_val as i64)
}
ty::Float(FloatTy::F16) => {
fx.bcx.ins().f16const(Ieee16::with_bits(u16::try_from(const_val).unwrap()))
fx.bcx.ins().f16const(Ieee16::with_bits(u16::from(const_val)))
}
ty::Float(FloatTy::F32) => {
fx.bcx.ins().f32const(Ieee32::with_bits(u32::try_from(const_val).unwrap()))
fx.bcx.ins().f32const(Ieee32::with_bits(u32::from(const_val)))
}
ty::Float(FloatTy::F64) => {
fx.bcx.ins().f64const(Ieee64::with_bits(u64::try_from(const_val).unwrap()))
fx.bcx.ins().f64const(Ieee64::with_bits(u64::from(const_val)))
}
ty::Float(FloatTy::F128) => {
let value = fx
@ -324,7 +324,7 @@ impl<'tcx> CValue<'tcx> {
.func
.dfg
.constants
.insert(Ieee128::with_bits(u128::try_from(const_val).unwrap()).into());
.insert(Ieee128::with_bits(u128::from(const_val)).into());
fx.bcx.ins().f128const(value)
}
_ => panic!(
@ -401,9 +401,7 @@ impl<'tcx> CPlace<'tcx> {
local: Local,
layout: TyAndLayout<'tcx>,
) -> CPlace<'tcx> {
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());
let var = fx.bcx.declare_var(fx.clif_type(layout.ty).unwrap());
CPlace { inner: CPlaceInner::Var(local, var), layout }
}
@ -412,14 +410,9 @@ impl<'tcx> CPlace<'tcx> {
local: Local,
layout: TyAndLayout<'tcx>,
) -> CPlace<'tcx> {
let var1 = Variable::from_u32(fx.next_ssa_var);
fx.next_ssa_var += 1;
let var2 = Variable::from_u32(fx.next_ssa_var);
fx.next_ssa_var += 1;
let (ty1, ty2) = fx.clif_pair_type(layout.ty).unwrap();
fx.bcx.declare_var(var1, ty1);
fx.bcx.declare_var(var2, ty2);
let var1 = fx.bcx.declare_var(ty1);
let var2 = fx.bcx.declare_var(ty2);
CPlace { inner: CPlaceInner::VarPair(local, var1, var2), layout }
}

View file

@ -84,5 +84,5 @@ pub(crate) fn get_vtable<'tcx>(
if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, "vtable");
}
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
}