]> git.lizzy.rs Git - rust.git/commitdiff
Merge commit 'e9d1a0a7b0b28dd422f1a790ccde532acafbf193' into sync_cg_clif-2022-08-24
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>
Wed, 24 Aug 2022 16:40:58 +0000 (18:40 +0200)
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>
Wed, 24 Aug 2022 16:40:58 +0000 (18:40 +0200)
46 files changed:
compiler/rustc_codegen_cranelift/.cirrus.yml
compiler/rustc_codegen_cranelift/.github/workflows/main.yml
compiler/rustc_codegen_cranelift/.gitignore
compiler/rustc_codegen_cranelift/Cargo.lock
compiler/rustc_codegen_cranelift/Cargo.toml
compiler/rustc_codegen_cranelift/Readme.md
compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
compiler/rustc_codegen_cranelift/build_system/abi_checker.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/build_backend.rs
compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
compiler/rustc_codegen_cranelift/build_system/mod.rs
compiler/rustc_codegen_cranelift/build_system/prepare.rs
compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
compiler/rustc_codegen_cranelift/build_system/tests.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/utils.rs
compiler/rustc_codegen_cranelift/clean_all.sh
compiler/rustc_codegen_cranelift/config.txt
compiler/rustc_codegen_cranelift/example/mini_core.rs
compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch [new file with mode: 0644]
compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch
compiler/rustc_codegen_cranelift/rust-toolchain
compiler/rustc_codegen_cranelift/scripts/tests.sh [deleted file]
compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_cranelift/src/common.rs
compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
compiler/rustc_codegen_cranelift/src/discriminant.rs
compiler/rustc_codegen_cranelift/src/driver/aot.rs
compiler/rustc_codegen_cranelift/src/driver/jit.rs
compiler/rustc_codegen_cranelift/src/global_asm.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/src/inline_asm.rs
compiler/rustc_codegen_cranelift/src/intrinsics/cpuid.rs
compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
compiler/rustc_codegen_cranelift/src/lib.rs
compiler/rustc_codegen_cranelift/src/optimize/mod.rs
compiler/rustc_codegen_cranelift/src/pretty_clif.rs
compiler/rustc_codegen_cranelift/src/toolchain.rs
compiler/rustc_codegen_cranelift/src/trap.rs
compiler/rustc_codegen_cranelift/src/value_and_place.rs
compiler/rustc_codegen_cranelift/test.sh

index 61da6a2491c52fcd3270195db5fb441e89c0a496..732edd66196d7de4c3d8d18e0c944e05d279906c 100644 (file)
@@ -22,4 +22,4 @@ task:
     - # Reduce amount of benchmark runs as they are slow
     - export COMPILE_RUNS=2
     - export RUN_RUNS=2
-    - ./test.sh
+    - ./y.rs test
index aa556a21bf8c30506b9f28471cf02b17af5cc5ea..e8897e9ae81454a01145a9b4343f66cafdb00565 100644 (file)
@@ -103,7 +103,7 @@ jobs:
         # Enable extra checks
         export CG_CLIF_ENABLE_VERIFIER=1
 
-        ./test.sh
+        ./y.rs test
 
     - name: Package prebuilt cg_clif
       run: tar cvfJ cg_clif.tar.xz build
@@ -162,14 +162,14 @@ jobs:
       #name: Test
       run: |
         # Enable backtraces for easier debugging
-        #export RUST_BACKTRACE=1
+        #$Env:RUST_BACKTRACE=1
 
         # Reduce amount of benchmark runs as they are slow
-        #export COMPILE_RUNS=2
-        #export RUN_RUNS=2
+        #$Env:COMPILE_RUNS=2
+        #$Env:RUN_RUNS=2
 
         # Enable extra checks
-        #export CG_CLIF_ENABLE_VERIFIER=1
+        #$Env:CG_CLIF_ENABLE_VERIFIER=1
 
         ./y.exe build
 
index 5aeaf3a1788043134ceb20fa64b11ec7e6f09cb7..6fd3e4443de5c29a78797daa438342723ce3468b 100644 (file)
@@ -8,6 +8,8 @@ perf.data.old
 *.string*
 /y.bin
 /y.bin.dSYM
+/y.exe
+/y.pdb
 /build
 /build_sysroot/sysroot_src
 /build_sysroot/compiler-builtins
@@ -17,3 +19,4 @@ perf.data.old
 /regex
 /simple-raytracer
 /portable-simd
+/abi-checker
index 402fbb16f97ee9f0acf661ef75b25739aa48d349..edae7e471578a88a9ec482c52397ab5330ac4cda 100644 (file)
@@ -50,18 +50,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "749d0d6022c9038dccf480bdde2a38d435937335bf2bb0f14e815d94517cdce8"
+checksum = "93945adbccc8d731503d3038814a51e8317497c9e205411820348132fa01a358"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e94370cc7b37bf652ccd8bb8f09bd900997f7ccf97520edfc75554bb5c4abbea"
+checksum = "2b482acc9d0d0d1ad3288a90a8150ee648be3dce8dc8c8669ff026f72debdc31"
 dependencies = [
  "cranelift-bforest",
  "cranelift-codegen-meta",
@@ -77,30 +77,30 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a3cea8fdab90e44018c5b9a1dfd460d8ee265ac354337150222a354628bdb6"
+checksum = "f9ec188d71e663192ef9048f204e410a7283b609942efc9fcc77da6d496edbb8"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ac72f76f2698598951ab26d8c96eaa854810e693e7dd52523958b5909fde6b2"
+checksum = "3ad794b1b1c2c7bd9f7b76cfe0f084eaf7753e55d56191c3f7d89e8fa4978b99"
 
 [[package]]
 name = "cranelift-entity"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09eaeacfcd2356fe0e66b295e8f9d59fdd1ac3ace53ba50de14d628ec902f72d"
+checksum = "342da0d5056f4119d3c311c4aab2460ceb6ee6e127bb395b76dd2279a09ea7a5"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dba69c9980d5ffd62c18a2bde927855fcd7c8dc92f29feaf8636052662cbd99c"
+checksum = "dfff792f775b07d4d9cfe9f1c767ce755c6cbadda1bbd6db18a1c75ff9f7376a"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -110,15 +110,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2920dc1e05cac40304456ed3301fde2c09bd6a9b0210bcfa2f101398d628d5b"
+checksum = "8d51089478849f2ac8ef60a8a2d5346c8d4abfec0e45ac5b24530ef9f9499e1e"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c3c5ed067f2c81577e431f3039148a9c187b33cc79e0d1731fede27d801ec56"
+checksum = "095936e41720f86004b4c57ce88e6a13af28646bb3a6fb4afbebd5ae90c50029"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -129,14 +129,14 @@ dependencies = [
  "log",
  "region",
  "target-lexicon",
- "winapi",
+ "windows-sys",
 ]
 
 [[package]]
 name = "cranelift-module"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eee6784303bf9af235237a4885f7417e09a35df896d38ea969a0081064b3ede4"
+checksum = "704a1aea4723d97eafe0fb7af110f6f6868b1ac95f5380bbc9adb2a3b8cf97e8"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -144,9 +144,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f04dfa45f9b2a6f587c564d6b63388e00cd6589d2df6ea2758cf79e1a13285e6"
+checksum = "885debe62f2078638d6585f54c9f05f5c2008f22ce5a2a9100ada785fc065dbd"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -155,9 +155,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.85.3"
+version = "0.87.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf38b2c505db749276793116c0cb30bd096206c7810e471677a453134881881"
+checksum = "aac1310cf1081ae8eca916c92cd163b977c77cab6e831fa812273c26ff921816"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -187,9 +187,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
 dependencies = [
  "cfg-if",
  "libc",
@@ -198,28 +198,22 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.26.1"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 dependencies = [
  "indexmap",
 ]
 
 [[package]]
 name = "hashbrown"
-version = "0.11.2"
+version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
 dependencies = [
  "ahash",
 ]
 
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
 [[package]]
 name = "indexmap"
 version = "1.9.1"
@@ -227,14 +221,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
 dependencies = [
  "autocfg",
- "hashbrown 0.12.3",
+ "hashbrown",
 ]
 
 [[package]]
 name = "libc"
-version = "0.2.126"
+version = "0.2.127"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
 
 [[package]]
 name = "libloading"
@@ -248,9 +242,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.14"
+version = "0.4.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
 dependencies = [
  "cfg-if",
 ]
@@ -266,33 +260,33 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.4.1"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
 name = "object"
-version = "0.28.4"
+version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
 dependencies = [
  "crc32fast",
- "hashbrown 0.11.2",
+ "hashbrown",
  "indexmap",
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.10.0"
+version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
+checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
 
 [[package]]
 name = "regalloc2"
-version = "0.2.3"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a8d23b35d7177df3b9d31ed8a9ab4bf625c668be77a319d4f5efd4a5257701c"
+checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779"
 dependencies = [
  "fxhash",
  "log",
@@ -340,15 +334,15 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec"
 
 [[package]]
 name = "smallvec"
-version = "1.8.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
+checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
 
 [[package]]
 name = "target-lexicon"
-version = "0.12.3"
+version = "0.12.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1"
+checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
 
 [[package]]
 name = "version_check"
@@ -358,9 +352,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
+version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "winapi"
@@ -383,3 +377,46 @@ name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+dependencies = [
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
index 61e977e3e69bfbd0ae0e23a4d82693a509e25d3e..e7c3427485480119829d0322b76cb0feb217e5f8 100644 (file)
@@ -8,15 +8,15 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.85.3", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.85.3"
-cranelift-module = "0.85.3"
-cranelift-native = "0.85.3"
-cranelift-jit = { version = "0.85.3", optional = true }
-cranelift-object = "0.85.3"
+cranelift-codegen = { version = "0.87.0", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.87.0"
+cranelift-module = "0.87.0"
+cranelift-native = "0.87.0"
+cranelift-jit = { version = "0.87.0", optional = true }
+cranelift-object = "0.87.0"
 target-lexicon = "0.12.0"
 gimli = { version = "0.26.0", default-features = false, features = ["write"]}
-object = { version = "0.28.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
+object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
 
 ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
 indexmap = "1.9.1"
index 8a2db5a43ecbf60488434ae6738677b8baad2d5b..1e84c7fa3657b37afeb26614a49896fab8846b40 100644 (file)
@@ -52,9 +52,7 @@ configuration options.
 ## Not yet supported
 
 * Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041))
-    * On Linux there is support for invoking an external assembler for `global_asm!` and `asm!`.
-      `llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You
-      have to specify specific registers instead.
+    * On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`.
 * SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work)
 
 ## License
index 7b2cdd273366f41ea8b21939395ba82e124b07ae..6c5043bb6f8e1e86cdde105d5607a4355581d5a4 100644 (file)
@@ -56,9 +56,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.75"
+version = "0.1.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6e3183e88f659a862835db8f4b67dbeed3d93e44dd4927eef78edb1c149d784"
+checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -69,9 +69,9 @@ version = "0.0.0"
 
 [[package]]
 name = "dlmalloc"
-version = "0.2.3"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e"
+checksum = "203540e710bfadb90e5e29930baf5d10270cec1f43ab34f46f78b147b2de715a"
 dependencies = [
  "compiler_builtins",
  "libc",
@@ -80,9 +80,9 @@ dependencies = [
 
 [[package]]
 name = "fortanix-sgx-abi"
-version = "0.3.3"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c56c422ef86062869b2d57ae87270608dc5929969dd130a6e248979cf4fb6ca6"
+checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -123,9 +123,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.2.4"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7668753748e445859e4e373c3d41117235d9feed578392f5a3a73efdc751ca4a"
+checksum = "897cd85af6387be149f55acf168e41be176a02de7872403aaab184afc2f327e6"
 dependencies = [
  "compiler_builtins",
  "libc",
@@ -135,9 +135,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.126"
+version = "0.2.132"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
 dependencies = [
  "rustc-std-workspace-core",
 ]
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs b/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs
new file mode 100644 (file)
index 0000000..67dbd0a
--- /dev/null
@@ -0,0 +1,60 @@
+use super::build_sysroot;
+use super::config;
+use super::utils::spawn_and_wait;
+use build_system::SysrootKind;
+use std::env;
+use std::path::Path;
+use std::process::Command;
+
+pub(crate) fn run(
+    channel: &str,
+    sysroot_kind: SysrootKind,
+    target_dir: &Path,
+    cg_clif_build_dir: &Path,
+    host_triple: &str,
+    target_triple: &str,
+) {
+    if !config::get_bool("testsuite.abi-checker") {
+        eprintln!("[SKIP] abi-checker");
+        return;
+    }
+
+    if host_triple != target_triple {
+        eprintln!("[SKIP] abi-checker (cross-compilation not supported)");
+        return;
+    }
+
+    eprintln!("Building sysroot for abi-checker");
+    build_sysroot::build_sysroot(
+        channel,
+        sysroot_kind,
+        target_dir,
+        cg_clif_build_dir,
+        host_triple,
+        target_triple,
+    );
+
+    eprintln!("Running abi-checker");
+    let mut abi_checker_path = env::current_dir().unwrap();
+    abi_checker_path.push("abi-checker");
+    env::set_current_dir(abi_checker_path.clone()).unwrap();
+
+    let build_dir = abi_checker_path.parent().unwrap().join("build");
+    let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join(
+        env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
+    );
+
+    let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
+
+    let mut cmd = Command::new("cargo");
+    cmd.arg("run");
+    cmd.arg("--target");
+    cmd.arg(target_triple);
+    cmd.arg("--");
+    cmd.arg("--pairs");
+    cmd.args(pairs);
+    cmd.arg("--add-rustc-codegen-backend");
+    cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display()));
+
+    spawn_and_wait(cmd);
+}
index 48faec8bc4b9434f5e9f278d88d3e8a2f5149455..9e59b8199b4123076a960771b4f2132a86d3cd54 100644 (file)
@@ -2,6 +2,8 @@
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use super::utils::is_ci;
+
 pub(crate) fn build_backend(
     channel: &str,
     host_triple: &str,
@@ -14,7 +16,7 @@ pub(crate) fn build_backend(
 
     let mut rustflags = env::var("RUSTFLAGS").unwrap_or_default();
 
-    if env::var("CI").as_ref().map(|val| &**val) == Ok("true") {
+    if is_ci() {
         // Deny warnings on CI
         rustflags += " -Dwarnings";
 
index 16cce83dd9c850f06222f5e0549fc30b538bb31f..7e205b0fd0b3b85dab07cb83a620a56fd256a233 100644 (file)
@@ -2,7 +2,7 @@
 use std::path::{Path, PathBuf};
 use std::process::{self, Command};
 
-use super::rustc_info::{get_file_name, get_rustc_version};
+use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
 use super::utils::{spawn_and_wait, try_hard_link};
 use super::SysrootKind;
 
@@ -10,10 +10,12 @@ pub(crate) fn build_sysroot(
     channel: &str,
     sysroot_kind: SysrootKind,
     target_dir: &Path,
-    cg_clif_build_dir: PathBuf,
+    cg_clif_build_dir: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
+    eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
+
     if target_dir.exists() {
         fs::remove_dir_all(target_dir).unwrap();
     }
@@ -35,11 +37,13 @@ pub(crate) fn build_sysroot(
 
     // Build and copy rustc and cargo wrappers
     for wrapper in ["rustc-clif", "cargo-clif"] {
+        let wrapper_name = get_wrapper_file_name(wrapper, "bin");
+
         let mut build_cargo_wrapper_cmd = Command::new("rustc");
         build_cargo_wrapper_cmd
             .arg(PathBuf::from("scripts").join(format!("{wrapper}.rs")))
             .arg("-o")
-            .arg(target_dir.join(wrapper))
+            .arg(target_dir.join(wrapper_name))
             .arg("-g");
         spawn_and_wait(build_cargo_wrapper_cmd);
     }
index b897b7fbacfcdf54426583790ed5116d2450ddd6..c3706dc6f82039cfee03fe18fdb7ef7c3f8c36d6 100644 (file)
@@ -2,11 +2,15 @@
 use std::path::PathBuf;
 use std::process;
 
+use self::utils::is_ci;
+
+mod abi_checker;
 mod build_backend;
 mod build_sysroot;
 mod config;
 mod prepare;
 mod rustc_info;
+mod tests;
 mod utils;
 
 fn usage() {
@@ -15,6 +19,9 @@ fn usage() {
     eprintln!(
         "  ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
     );
+    eprintln!(
+        "  ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
+    );
 }
 
 macro_rules! arg_error {
@@ -25,11 +32,13 @@ macro_rules! arg_error {
     }};
 }
 
+#[derive(PartialEq, Debug)]
 enum Command {
     Build,
+    Test,
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub(crate) enum SysrootKind {
     None,
     Clif,
@@ -42,16 +51,22 @@ pub fn main() {
     // The target dir is expected in the default location. Guard against the user changing it.
     env::set_var("CARGO_TARGET_DIR", "target");
 
+    if is_ci() {
+        // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
+        env::set_var("CARGO_BUILD_INCREMENTAL", "false");
+    }
+
     let mut args = env::args().skip(1);
     let command = match args.next().as_deref() {
         Some("prepare") => {
             if args.next().is_some() {
-                arg_error!("./x.rs prepare doesn't expect arguments");
+                arg_error!("./y.rs prepare doesn't expect arguments");
             }
             prepare::prepare();
             process::exit(0);
         }
         Some("build") => Command::Build,
+        Some("test") => Command::Test,
         Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
         Some(command) => arg_error!("Unknown command {}", command),
         None => {
@@ -117,12 +132,35 @@ pub fn main() {
 
     let cg_clif_build_dir =
         build_backend::build_backend(channel, &host_triple, use_unstable_features);
-    build_sysroot::build_sysroot(
-        channel,
-        sysroot_kind,
-        &target_dir,
-        cg_clif_build_dir,
-        &host_triple,
-        &target_triple,
-    );
+    match command {
+        Command::Test => {
+            tests::run_tests(
+                channel,
+                sysroot_kind,
+                &target_dir,
+                &cg_clif_build_dir,
+                &host_triple,
+                &target_triple,
+            );
+
+            abi_checker::run(
+                channel,
+                sysroot_kind,
+                &target_dir,
+                &cg_clif_build_dir,
+                &host_triple,
+                &target_triple,
+            );
+        }
+        Command::Build => {
+            build_sysroot::build_sysroot(
+                channel,
+                sysroot_kind,
+                &target_dir,
+                &cg_clif_build_dir,
+                &host_triple,
+                &target_triple,
+            );
+        }
+    }
 }
index 8bb00352d3fe3a83df4f9e4bd7936c7296199493..d23b7f00dcf16da744be926925043d5716cad145 100644 (file)
@@ -14,6 +14,14 @@ pub(crate) fn prepare() {
     eprintln!("[INSTALL] hyperfine");
     Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
 
+    clone_repo_shallow_github(
+        "abi-checker",
+        "Gankra",
+        "abi-checker",
+        "a2232d45f202846f5c02203c9f27355360f9a2ff",
+    );
+    apply_patches("abi-checker", Path::new("abi-checker"));
+
     clone_repo_shallow_github(
         "rand",
         "rust-random",
@@ -50,8 +58,7 @@ pub(crate) fn prepare() {
     spawn_and_wait(build_cmd);
     fs::copy(
         Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")),
-        // FIXME use get_file_name here too once testing is migrated to rust
-        "simple-raytracer/raytracer_cg_llvm",
+        Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")),
     )
     .unwrap();
 }
index 9206bb02bd3da56da6959cdbbf34cf2e55a93f1c..913b589afcc87f658510195969fd03aef5d683e2 100644 (file)
@@ -63,3 +63,12 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String {
     assert!(file_name.contains(crate_name));
     file_name
 }
+
+/// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to
+/// underscores (`_`). This is specially made for the the rustc and cargo wrappers
+/// which have a dash in the name, and that is not allowed in a crate name.
+pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str) -> String {
+    let crate_name = crate_name.replace('-', "_");
+    let wrapper_name = get_file_name(&crate_name, crate_type);
+    wrapper_name.replace('_', "-")
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
new file mode 100644 (file)
index 0000000..dc83b10
--- /dev/null
@@ -0,0 +1,618 @@
+use super::build_sysroot;
+use super::config;
+use super::rustc_info::get_wrapper_file_name;
+use super::utils::{spawn_and_wait, spawn_and_wait_with_input};
+use build_system::SysrootKind;
+use std::env;
+use std::ffi::OsStr;
+use std::fs;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+struct TestCase {
+    config: &'static str,
+    func: &'static dyn Fn(&TestRunner),
+}
+
+impl TestCase {
+    const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
+        Self { config, func }
+    }
+}
+
+const NO_SYSROOT_SUITE: &[TestCase] = &[
+    TestCase::new("build.mini_core", &|runner| {
+        runner.run_rustc([
+            "example/mini_core.rs",
+            "--crate-name",
+            "mini_core",
+            "--crate-type",
+            "lib,dylib",
+            "--target",
+            &runner.target_triple,
+        ]);
+    }),
+    TestCase::new("build.example", &|runner| {
+        runner.run_rustc([
+            "example/example.rs",
+            "--crate-type",
+            "lib",
+            "--target",
+            &runner.target_triple,
+        ]);
+    }),
+    TestCase::new("jit.mini_core_hello_world", &|runner| {
+        let mut jit_cmd = runner.rustc_command([
+            "-Zunstable-options",
+            "-Cllvm-args=mode=jit",
+            "-Cprefer-dynamic",
+            "example/mini_core_hello_world.rs",
+            "--cfg",
+            "jit",
+            "--target",
+            &runner.host_triple,
+        ]);
+        jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
+        spawn_and_wait(jit_cmd);
+
+        eprintln!("[JIT-lazy] mini_core_hello_world");
+        let mut jit_cmd = runner.rustc_command([
+            "-Zunstable-options",
+            "-Cllvm-args=mode=jit-lazy",
+            "-Cprefer-dynamic",
+            "example/mini_core_hello_world.rs",
+            "--cfg",
+            "jit",
+            "--target",
+            &runner.host_triple,
+        ]);
+        jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
+        spawn_and_wait(jit_cmd);
+    }),
+    TestCase::new("aot.mini_core_hello_world", &|runner| {
+        runner.run_rustc([
+            "example/mini_core_hello_world.rs",
+            "--crate-name",
+            "mini_core_hello_world",
+            "--crate-type",
+            "bin",
+            "-g",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
+    }),
+];
+
+const BASE_SYSROOT_SUITE: &[TestCase] = &[
+    TestCase::new("aot.arbitrary_self_types_pointers_and_wrappers", &|runner| {
+        runner.run_rustc([
+            "example/arbitrary_self_types_pointers_and_wrappers.rs",
+            "--crate-name",
+            "arbitrary_self_types_pointers_and_wrappers",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
+    }),
+    TestCase::new("aot.issue_91827_extern_types", &|runner| {
+        runner.run_rustc([
+            "example/issue-91827-extern-types.rs",
+            "--crate-name",
+            "issue_91827_extern_types",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("issue_91827_extern_types", []);
+    }),
+    TestCase::new("build.alloc_system", &|runner| {
+        runner.run_rustc([
+            "example/alloc_system.rs",
+            "--crate-type",
+            "lib",
+            "--target",
+            &runner.target_triple,
+        ]);
+    }),
+    TestCase::new("aot.alloc_example", &|runner| {
+        runner.run_rustc([
+            "example/alloc_example.rs",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("alloc_example", []);
+    }),
+    TestCase::new("jit.std_example", &|runner| {
+        runner.run_rustc([
+            "-Zunstable-options",
+            "-Cllvm-args=mode=jit",
+            "-Cprefer-dynamic",
+            "example/std_example.rs",
+            "--target",
+            &runner.host_triple,
+        ]);
+
+        eprintln!("[JIT-lazy] std_example");
+        runner.run_rustc([
+            "-Zunstable-options",
+            "-Cllvm-args=mode=jit-lazy",
+            "-Cprefer-dynamic",
+            "example/std_example.rs",
+            "--target",
+            &runner.host_triple,
+        ]);
+    }),
+    TestCase::new("aot.std_example", &|runner| {
+        runner.run_rustc([
+            "example/std_example.rs",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("std_example", ["arg"]);
+    }),
+    TestCase::new("aot.dst_field_align", &|runner| {
+        runner.run_rustc([
+            "example/dst-field-align.rs",
+            "--crate-name",
+            "dst_field_align",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("dst_field_align", []);
+    }),
+    TestCase::new("aot.subslice-patterns-const-eval", &|runner| {
+        runner.run_rustc([
+            "example/subslice-patterns-const-eval.rs",
+            "--crate-type",
+            "bin",
+            "-Cpanic=abort",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("subslice-patterns-const-eval", []);
+    }),
+    TestCase::new("aot.track-caller-attribute", &|runner| {
+        runner.run_rustc([
+            "example/track-caller-attribute.rs",
+            "--crate-type",
+            "bin",
+            "-Cpanic=abort",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("track-caller-attribute", []);
+    }),
+    TestCase::new("aot.float-minmax-pass", &|runner| {
+        runner.run_rustc([
+            "example/float-minmax-pass.rs",
+            "--crate-type",
+            "bin",
+            "-Cpanic=abort",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("float-minmax-pass", []);
+    }),
+    TestCase::new("aot.mod_bench", &|runner| {
+        runner.run_rustc([
+            "example/mod_bench.rs",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_triple,
+        ]);
+        runner.run_out_command("mod_bench", []);
+    }),
+];
+
+const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
+    TestCase::new("test.rust-random/rand", &|runner| {
+        runner.in_dir(["rand"], |runner| {
+            runner.run_cargo(["clean"]);
+
+            if runner.host_triple == runner.target_triple {
+                eprintln!("[TEST] rust-random/rand");
+                runner.run_cargo(["test", "--workspace"]);
+            } else {
+                eprintln!("[AOT] rust-random/rand");
+                runner.run_cargo([
+                    "build",
+                    "--workspace",
+                    "--target",
+                    &runner.target_triple,
+                    "--tests",
+                ]);
+            }
+        });
+    }),
+    TestCase::new("bench.simple-raytracer", &|runner| {
+        runner.in_dir(["simple-raytracer"], |runner| {
+            let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string());
+
+            if runner.host_triple == runner.target_triple {
+                eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
+                let mut bench_compile = Command::new("hyperfine");
+                bench_compile.arg("--runs");
+                bench_compile.arg(&run_runs);
+                bench_compile.arg("--warmup");
+                bench_compile.arg("1");
+                bench_compile.arg("--prepare");
+                bench_compile.arg(format!("{:?}", runner.cargo_command(["clean"])));
+
+                if cfg!(windows) {
+                    bench_compile.arg("cmd /C \"set RUSTFLAGS= && cargo build\"");
+                } else {
+                    bench_compile.arg("RUSTFLAGS='' cargo build");
+                }
+
+                bench_compile.arg(format!("{:?}", runner.cargo_command(["build"])));
+                spawn_and_wait(bench_compile);
+
+                eprintln!("[BENCH RUN] ebobby/simple-raytracer");
+                fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
+                    .unwrap();
+
+                let mut bench_run = Command::new("hyperfine");
+                bench_run.arg("--runs");
+                bench_run.arg(&run_runs);
+                bench_run.arg(PathBuf::from("./raytracer_cg_llvm"));
+                bench_run.arg(PathBuf::from("./raytracer_cg_clif"));
+                spawn_and_wait(bench_run);
+            } else {
+                runner.run_cargo(["clean"]);
+                eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
+                eprintln!("[COMPILE] ebobby/simple-raytracer");
+                runner.run_cargo(["build", "--target", &runner.target_triple]);
+                eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
+            }
+        });
+    }),
+    TestCase::new("test.libcore", &|runner| {
+        runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| {
+            runner.run_cargo(["clean"]);
+
+            if runner.host_triple == runner.target_triple {
+                runner.run_cargo(["test"]);
+            } else {
+                eprintln!("Cross-Compiling: Not running tests");
+                runner.run_cargo(["build", "--target", &runner.target_triple, "--tests"]);
+            }
+        });
+    }),
+    TestCase::new("test.regex-shootout-regex-dna", &|runner| {
+        runner.in_dir(["regex"], |runner| {
+            runner.run_cargo(["clean"]);
+
+            // newer aho_corasick versions throw a deprecation warning
+            let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
+
+            let mut build_cmd = runner.cargo_command([
+                "build",
+                "--example",
+                "shootout-regex-dna",
+                "--target",
+                &runner.target_triple,
+            ]);
+            build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+            spawn_and_wait(build_cmd);
+
+            if runner.host_triple == runner.target_triple {
+                let mut run_cmd = runner.cargo_command([
+                    "run",
+                    "--example",
+                    "shootout-regex-dna",
+                    "--target",
+                    &runner.target_triple,
+                ]);
+                run_cmd.env("RUSTFLAGS", lint_rust_flags);
+
+                let input =
+                    fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap();
+                let expected_path = PathBuf::from("examples/regexdna-output.txt");
+                let expected = fs::read_to_string(&expected_path).unwrap();
+
+                let output = spawn_and_wait_with_input(run_cmd, input);
+                // Make sure `[codegen mono items] start` doesn't poison the diff
+                let output = output
+                    .lines()
+                    .filter(|line| !line.contains("codegen mono items"))
+                    .chain(Some("")) // This just adds the trailing newline
+                    .collect::<Vec<&str>>()
+                    .join("\r\n");
+
+                let output_matches = expected.lines().eq(output.lines());
+                if !output_matches {
+                    let res_path = PathBuf::from("res.txt");
+                    fs::write(&res_path, &output).unwrap();
+
+                    if cfg!(windows) {
+                        println!("Output files don't match!");
+                        println!("Expected Output:\n{}", expected);
+                        println!("Actual Output:\n{}", output);
+                    } else {
+                        let mut diff = Command::new("diff");
+                        diff.arg("-u");
+                        diff.arg(res_path);
+                        diff.arg(expected_path);
+                        spawn_and_wait(diff);
+                    }
+
+                    std::process::exit(1);
+                }
+            }
+        });
+    }),
+    TestCase::new("test.regex", &|runner| {
+        runner.in_dir(["regex"], |runner| {
+            runner.run_cargo(["clean"]);
+
+            // newer aho_corasick versions throw a deprecation warning
+            let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
+
+            if runner.host_triple == runner.target_triple {
+                let mut run_cmd = runner.cargo_command([
+                    "test",
+                    "--tests",
+                    "--",
+                    "--exclude-should-panic",
+                    "--test-threads",
+                    "1",
+                    "-Zunstable-options",
+                    "-q",
+                ]);
+                run_cmd.env("RUSTFLAGS", lint_rust_flags);
+                spawn_and_wait(run_cmd);
+            } else {
+                eprintln!("Cross-Compiling: Not running tests");
+                let mut build_cmd =
+                    runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]);
+                build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+                spawn_and_wait(build_cmd);
+            }
+        });
+    }),
+    TestCase::new("test.portable-simd", &|runner| {
+        runner.in_dir(["portable-simd"], |runner| {
+            runner.run_cargo(["clean"]);
+            runner.run_cargo(["build", "--all-targets", "--target", &runner.target_triple]);
+
+            if runner.host_triple == runner.target_triple {
+                runner.run_cargo(["test", "-q"]);
+            }
+        });
+    }),
+];
+
+pub(crate) fn run_tests(
+    channel: &str,
+    sysroot_kind: SysrootKind,
+    target_dir: &Path,
+    cg_clif_build_dir: &Path,
+    host_triple: &str,
+    target_triple: &str,
+) {
+    let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string());
+
+    if config::get_bool("testsuite.no_sysroot") {
+        build_sysroot::build_sysroot(
+            channel,
+            SysrootKind::None,
+            &target_dir,
+            cg_clif_build_dir,
+            &host_triple,
+            &target_triple,
+        );
+
+        let _ = fs::remove_dir_all(Path::new("target").join("out"));
+        runner.run_testsuite(NO_SYSROOT_SUITE);
+    } else {
+        eprintln!("[SKIP] no_sysroot tests");
+    }
+
+    let run_base_sysroot = config::get_bool("testsuite.base_sysroot");
+    let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot");
+
+    if run_base_sysroot || run_extended_sysroot {
+        build_sysroot::build_sysroot(
+            channel,
+            sysroot_kind,
+            &target_dir,
+            cg_clif_build_dir,
+            &host_triple,
+            &target_triple,
+        );
+    }
+
+    if run_base_sysroot {
+        runner.run_testsuite(BASE_SYSROOT_SUITE);
+    } else {
+        eprintln!("[SKIP] base_sysroot tests");
+    }
+
+    if run_extended_sysroot {
+        runner.run_testsuite(EXTENDED_SYSROOT_SUITE);
+    } else {
+        eprintln!("[SKIP] extended_sysroot tests");
+    }
+}
+
+struct TestRunner {
+    root_dir: PathBuf,
+    out_dir: PathBuf,
+    jit_supported: bool,
+    rust_flags: String,
+    run_wrapper: Vec<String>,
+    host_triple: String,
+    target_triple: String,
+}
+
+impl TestRunner {
+    pub fn new(host_triple: String, target_triple: String) -> Self {
+        let root_dir = env::current_dir().unwrap();
+
+        let mut out_dir = root_dir.clone();
+        out_dir.push("target");
+        out_dir.push("out");
+
+        let is_native = host_triple == target_triple;
+        let jit_supported = target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
+
+        let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
+        let mut run_wrapper = Vec::new();
+
+        if !is_native {
+            match target_triple.as_str() {
+                "aarch64-unknown-linux-gnu" => {
+                    // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
+                    rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags);
+                    run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"];
+                }
+                "x86_64-pc-windows-gnu" => {
+                    // We are cross-compiling for Windows. Run tests in wine.
+                    run_wrapper = vec!["wine"];
+                }
+                _ => {
+                    println!("Unknown non-native platform");
+                }
+            }
+        }
+
+        // FIXME fix `#[linkage = "extern_weak"]` without this
+        if host_triple.contains("darwin") {
+            rust_flags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rust_flags);
+        }
+
+        Self {
+            root_dir,
+            out_dir,
+            jit_supported,
+            rust_flags,
+            run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(),
+            host_triple,
+            target_triple,
+        }
+    }
+
+    pub fn run_testsuite(&self, tests: &[TestCase]) {
+        for &TestCase { config, func } in tests {
+            let (tag, testname) = config.split_once('.').unwrap();
+            let tag = tag.to_uppercase();
+            let is_jit_test = tag == "JIT";
+
+            if !config::get_bool(config) || (is_jit_test && !self.jit_supported) {
+                eprintln!("[{tag}] {testname} (skipped)");
+                continue;
+            } else {
+                eprintln!("[{tag}] {testname}");
+            }
+
+            func(self);
+        }
+    }
+
+    fn in_dir<'a, I, F>(&self, dir: I, callback: F)
+    where
+        I: IntoIterator<Item = &'a str>,
+        F: FnOnce(&TestRunner),
+    {
+        let current = env::current_dir().unwrap();
+        let mut new = current.clone();
+        for d in dir {
+            new.push(d);
+        }
+
+        env::set_current_dir(new).unwrap();
+        callback(self);
+        env::set_current_dir(current).unwrap();
+    }
+
+    fn rustc_command<I, S>(&self, args: I) -> Command
+    where
+        I: IntoIterator<Item = S>,
+        S: AsRef<OsStr>,
+    {
+        let mut rustc_clif = self.root_dir.clone();
+        rustc_clif.push("build");
+        rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin"));
+
+        let mut cmd = Command::new(rustc_clif);
+        cmd.args(self.rust_flags.split_whitespace());
+        cmd.arg("-L");
+        cmd.arg(format!("crate={}", self.out_dir.display()));
+        cmd.arg("--out-dir");
+        cmd.arg(format!("{}", self.out_dir.display()));
+        cmd.arg("-Cdebuginfo=2");
+        cmd.args(args);
+        cmd
+    }
+
+    fn run_rustc<I, S>(&self, args: I)
+    where
+        I: IntoIterator<Item = S>,
+        S: AsRef<OsStr>,
+    {
+        spawn_and_wait(self.rustc_command(args));
+    }
+
+    fn run_out_command<'a, I>(&self, name: &str, args: I)
+    where
+        I: IntoIterator<Item = &'a str>,
+    {
+        let mut full_cmd = vec![];
+
+        // Prepend the RUN_WRAPPER's
+        if !self.run_wrapper.is_empty() {
+            full_cmd.extend(self.run_wrapper.iter().cloned());
+        }
+
+        full_cmd.push({
+            let mut out_path = self.out_dir.clone();
+            out_path.push(name);
+            out_path.to_str().unwrap().to_string()
+        });
+
+        for arg in args.into_iter() {
+            full_cmd.push(arg.to_string());
+        }
+
+        let mut cmd_iter = full_cmd.into_iter();
+        let first = cmd_iter.next().unwrap();
+
+        let mut cmd = Command::new(first);
+        cmd.args(cmd_iter);
+
+        spawn_and_wait(cmd);
+    }
+
+    fn cargo_command<I, S>(&self, args: I) -> Command
+    where
+        I: IntoIterator<Item = S>,
+        S: AsRef<OsStr>,
+    {
+        let mut cargo_clif = self.root_dir.clone();
+        cargo_clif.push("build");
+        cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
+
+        let mut cmd = Command::new(cargo_clif);
+        cmd.args(args);
+        cmd.env("RUSTFLAGS", &self.rust_flags);
+        cmd
+    }
+
+    fn run_cargo<'a, I>(&self, args: I)
+    where
+        I: IntoIterator<Item = &'a str>,
+    {
+        spawn_and_wait(self.cargo_command(args));
+    }
+}
index 12b5d70fad853133384fb064e19fd9a2cb9d189a..bdf8f8ecd9970cb4b71976de33a953101047c808 100644 (file)
@@ -1,6 +1,8 @@
+use std::env;
 use std::fs;
+use std::io::Write;
 use std::path::Path;
-use std::process::{self, Command};
+use std::process::{self, Command, Stdio};
 
 #[track_caller]
 pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
@@ -18,6 +20,27 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) {
     }
 }
 
+#[track_caller]
+pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> String {
+    let mut child = cmd
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .spawn()
+        .expect("Failed to spawn child process");
+
+    let mut stdin = child.stdin.take().expect("Failed to open stdin");
+    std::thread::spawn(move || {
+        stdin.write_all(input.as_bytes()).expect("Failed to write to stdin");
+    });
+
+    let output = child.wait_with_output().expect("Failed to read stdout");
+    if !output.status.success() {
+        process::exit(1);
+    }
+
+    String::from_utf8(output.stdout).unwrap()
+}
+
 pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
     for entry in fs::read_dir(from).unwrap() {
         let entry = entry.unwrap();
@@ -33,3 +56,7 @@ pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
         }
     }
 }
+
+pub(crate) fn is_ci() -> bool {
+    env::var("CI").as_ref().map(|val| &**val) == Ok("true")
+}
index ea1f8c1e8920a9a1b432430d97946e1114889803..62e52bd1958005655adbe4609fa3fbfe05c4b907 100755 (executable)
@@ -3,4 +3,4 @@ set -e
 
 rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
 rm -rf target/ build/ perf.data{,.old} y.bin
-rm -rf rand/ regex/ simple-raytracer/ portable-simd/
+rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/
index b14db27d6206fc79ffa1faf4805fea0ab126e92b..2264d301d592003b27f679becdeb32e90d583023 100644 (file)
 # This option can be changed while the build system is already running for as long as sysroot
 # building hasn't started yet.
 #keep_sysroot
+
+
+# Testsuite
+#
+# Each test suite item has a corresponding key here. The default is to run all tests.
+# Comment any of these lines to skip individual tests.
+
+testsuite.no_sysroot
+build.mini_core
+build.example
+jit.mini_core_hello_world
+aot.mini_core_hello_world
+
+testsuite.base_sysroot
+aot.arbitrary_self_types_pointers_and_wrappers
+aot.issue_91827_extern_types
+build.alloc_system
+aot.alloc_example
+jit.std_example
+aot.std_example
+aot.dst_field_align
+aot.subslice-patterns-const-eval
+aot.track-caller-attribute
+aot.float-minmax-pass
+aot.mod_bench
+
+testsuite.extended_sysroot
+test.rust-random/rand
+bench.simple-raytracer
+test.libcore
+test.regex-shootout-regex-dna
+test.regex
+test.portable-simd
+
+testsuite.abi-checker
index 8b6042a3d66380909f63bb727a4fcb08cce5fc5e..42f8aa50ba1a99d73f84d9de07eb550d1c778637 100644 (file)
@@ -535,7 +535,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
 }
 
 #[lang = "box_free"]
-unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, alloc: ()) {
+unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, _alloc: ()) {
     libc::free(ptr.pointer.0 as *mut u8);
 }
 
@@ -575,11 +575,19 @@ pub mod intrinsics {
 }
 
 pub mod libc {
+    // With the new Universal CRT, msvc has switched to all the printf functions being inline wrapper
+    // functions. legacy_stdio_definitions.lib which provides the printf wrapper functions as normal
+    // symbols to link against.
+    #[cfg_attr(unix, link(name = "c"))]
+    #[cfg_attr(target_env="msvc", link(name="legacy_stdio_definitions"))]
+    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" {
         pub fn puts(s: *const i8) -> i32;
-        pub fn printf(format: *const i8, ...) -> i32;
         pub fn malloc(size: usize) -> *mut u8;
         pub fn free(ptr: *mut u8);
         pub fn memcpy(dst: *mut u8, src: *const u8, size: usize);
index aa1f239bae23ec55bce6c5872f7eac3d37ae8355..e83be3a3df5c4f410f470099f1d623df22a2c76b 100644 (file)
@@ -139,7 +139,7 @@ pub struct bool_11 {
     field10: bool,
 }
 
-extern "C" fn bool_struct_in_11(arg0: bool_11) {}
+extern "C" fn bool_struct_in_11(_arg0: bool_11) {}
 
 #[allow(unreachable_code)] // FIXME false positive
 fn main() {
@@ -321,7 +321,7 @@ struct ExternTypeWrapper {
     #[cfg(not(any(jit, windows)))]
     test_tls();
 
-    #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
+    #[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))]
     unsafe {
         global_asm_test();
     }
@@ -343,7 +343,7 @@ fn main() {
 }
 }
 
-#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
+#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))]
 extern "C" {
     fn global_asm_test();
 }
@@ -358,6 +358,16 @@ fn main() {
     "
 }
 
+#[cfg(all(not(jit), target_arch = "x86_64", target_os = "darwin"))]
+global_asm! {
+    "
+    .global _global_asm_test
+    _global_asm_test:
+    // comment that would normally be removed by LLVM
+    ret
+    "
+}
+
 #[repr(C)]
 enum c_void {
     _1,
@@ -375,6 +385,7 @@ struct pthread_attr_t {
 }
 
 #[link(name = "pthread")]
+#[cfg(unix)]
 extern "C" {
     fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int;
 
@@ -391,6 +402,91 @@ fn pthread_join(
     ) -> c_int;
 }
 
+type DWORD = u32;
+type LPDWORD = *mut u32;
+
+type LPVOID = *mut c_void;
+type HANDLE = *mut c_void;
+
+#[link(name = "msvcrt")]
+#[cfg(windows)]
+extern "C" {
+    fn WaitForSingleObject(
+        hHandle: LPVOID,
+        dwMilliseconds: DWORD
+    ) -> DWORD;
+
+    fn CreateThread(
+        lpThreadAttributes: LPVOID, // Technically LPSECURITY_ATTRIBUTES, but we don't use it anyway
+        dwStackSize: usize,
+        lpStartAddress: extern "C" fn(_: *mut c_void) -> *mut c_void,
+        lpParameter: LPVOID,
+        dwCreationFlags: DWORD,
+        lpThreadId: LPDWORD
+    ) -> HANDLE;
+}
+
+struct Thread {
+    #[cfg(windows)]
+    handle: HANDLE,
+    #[cfg(unix)]
+    handle: pthread_t,
+}
+
+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;
+
+            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,
+            }
+        }
+
+        #[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);
+        }
+
+        #[cfg(windows)]
+        {
+            // The INFINITE macro is used to signal operations that do not timeout.
+            let infinite = 0xffffffff;
+            assert!(WaitForSingleObject(self.handle, infinite) == 0);
+        }
+    }
+}
+
+
+
+
 #[thread_local]
 #[cfg(not(jit))]
 static mut TLS: u8 = 42;
@@ -404,21 +500,10 @@ extern "C" fn mutate_tls(_: *mut c_void) -> *mut c_void {
 #[cfg(not(jit))]
 fn test_tls() {
     unsafe {
-        let mut attr: pthread_attr_t = zeroed();
-        let mut thread: pthread_t = 0;
-
         assert_eq!(TLS, 42);
 
-        if pthread_attr_init(&mut attr) != 0 {
-            assert!(false);
-        }
-
-        if pthread_create(&mut thread, &attr, mutate_tls, 0 as *mut c_void) != 0 {
-            assert!(false);
-        }
-
-        let mut res = 0 as *mut c_void;
-        pthread_join(thread, &mut res);
+        let thread = Thread::create(mutate_tls);
+        thread.join();
 
         // TLS of main thread must not have been changed by the other thread.
         assert_eq!(TLS, 42);
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch
new file mode 100644 (file)
index 0000000..526366a
--- /dev/null
@@ -0,0 +1,36 @@
+From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001
+From: Afonso Bordado <afonso360@users.noreply.github.com>
+Date: Fri, 12 Aug 2022 22:51:58 +0000
+Subject: [PATCH] Disable abi-checker tests
+
+---
+ src/report.rs | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/src/report.rs b/src/report.rs
+index 7346f5e..8347762 100644
+--- a/src/report.rs
++++ b/src/report.rs
+@@ -45,6 +45,20 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
+     //
+     // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
+
++    // Currently MSVC has some broken ABI issues. Furthermore, they cause
++    // a STATUS_ACCESS_VIOLATION, so we can't even run them. Ensure that they compile and link.
++    if cfg!(windows) && (test.test_name == "bool" || test.test_name == "ui128") {
++        result.run = Link;
++        result.check = Pass(Link);
++    }
++
++    // structs is broken in the current release of cranelift for aarch64.
++    // It has been fixed for cranelift 0.88: https://github.com/bytecodealliance/wasmtime/pull/4634
++    if cfg!(target_arch = "aarch64") && test.test_name == "structs" {
++        result.run = Link;
++        result.check = Pass(Link);
++    }
++
+     // END OF VENDOR RESERVED AREA
+     //
+     //
+--
+2.34.1
index 50ef0bd9418c74f8a760ca8b80629edc223be08c..f3cd7ee77e26e34586ac8cc146d0791f960c4520 100644 (file)
@@ -46,5 +46,17 @@ index 4bc44e9..8e3c7a4 100644
  
  #[test]
  fn cell_allows_array_cycle() {
+diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs
+index 13b12db..96fe4b9 100644
+--- a/library/core/tests/atomic.rs
++++ b/library/core/tests/atomic.rs
+@@ -185,6 +185,7 @@ fn ptr_bitops() {
+ }
+ #[test]
++#[cfg_attr(target_arch = "s390x", ignore)] // s390x backend doesn't support stack alignment >8 bytes
+ #[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins
+ fn ptr_bitops_tagging() {
+     #[repr(align(16))]
 -- 
 2.21.0 (Apple Git-122)
index 3ab395d89d50e884945dd045e080c922039c73aa..14f2746ecb19f0f342a286bf752732d678a94414 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-07-25"
+channel = "nightly-2022-08-24"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_cranelift/scripts/tests.sh b/compiler/rustc_codegen_cranelift/scripts/tests.sh
deleted file mode 100755 (executable)
index 9b5ffa4..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-export CG_CLIF_DISPLAY_CG_TIME=1
-export CG_CLIF_DISABLE_INCR_CACHE=1
-
-export HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
-export TARGET_TRIPLE=${TARGET_TRIPLE:-$HOST_TRIPLE}
-
-export RUN_WRAPPER=''
-
-case "$TARGET_TRIPLE" in
-   x86_64*)
-      export JIT_SUPPORTED=1
-      ;;
-   *)
-      export JIT_SUPPORTED=0
-      ;;
-esac
-
-if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
-   export JIT_SUPPORTED=0
-   if [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
-      # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
-      export RUSTFLAGS='-Clinker=aarch64-linux-gnu-gcc '$RUSTFLAGS
-      export RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu'
-   elif [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then
-      # We are cross-compiling for Windows. Run tests in wine.
-      export RUN_WRAPPER='wine'
-   else
-      echo "Unknown non-native platform"
-   fi
-fi
-
-# FIXME fix `#[linkage = "extern_weak"]` without this
-if [[ "$(uname)" == 'Darwin' ]]; then
-   export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
-fi
-
-MY_RUSTC="$(pwd)/build/rustc-clif $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2"
-
-function no_sysroot_tests() {
-    echo "[BUILD] mini_core"
-    $MY_RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target "$TARGET_TRIPLE"
-
-    echo "[BUILD] example"
-    $MY_RUSTC example/example.rs --crate-type lib --target "$TARGET_TRIPLE"
-
-    if [[ "$JIT_SUPPORTED" = "1" ]]; then
-        echo "[JIT] mini_core_hello_world"
-        CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE"
-
-        echo "[JIT-lazy] mini_core_hello_world"
-        CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE"
-    else
-        echo "[JIT] mini_core_hello_world (skipped)"
-    fi
-
-    echo "[AOT] mini_core_hello_world"
-    $MY_RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd
-    # (echo "break set -n main"; echo "run"; sleep 1; echo "si -c 10"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd
-}
-
-function base_sysroot_tests() {
-    echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
-    $MY_RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers
-
-    echo "[AOT] issue_91827_extern_types"
-    $MY_RUSTC example/issue-91827-extern-types.rs --crate-name issue_91827_extern_types --crate-type bin --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/issue_91827_extern_types
-
-    echo "[BUILD] alloc_system"
-    $MY_RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
-
-    echo "[AOT] alloc_example"
-    $MY_RUSTC example/alloc_example.rs --crate-type bin --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/alloc_example
-
-    if [[ "$JIT_SUPPORTED" = "1" ]]; then
-        echo "[JIT] std_example"
-        $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE"
-
-        echo "[JIT-lazy] std_example"
-        $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE"
-    else
-        echo "[JIT] std_example (skipped)"
-    fi
-
-    echo "[AOT] std_example"
-    $MY_RUSTC example/std_example.rs --crate-type bin --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/std_example arg
-
-    echo "[AOT] dst_field_align"
-    $MY_RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/dst_field_align
-
-    echo "[AOT] subslice-patterns-const-eval"
-    $MY_RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/subslice-patterns-const-eval
-
-    echo "[AOT] track-caller-attribute"
-    $MY_RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/track-caller-attribute
-
-    echo "[AOT] float-minmax-pass"
-    $MY_RUSTC example/float-minmax-pass.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/float-minmax-pass
-
-    echo "[AOT] mod_bench"
-    $MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE"
-    $RUN_WRAPPER ./target/out/mod_bench
-}
-
-function extended_sysroot_tests() {
-    pushd rand
-    ../build/cargo-clif clean
-    if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
-        echo "[TEST] rust-random/rand"
-        ../build/cargo-clif test --workspace
-    else
-        echo "[AOT] rust-random/rand"
-        ../build/cargo-clif build --workspace --target $TARGET_TRIPLE --tests
-    fi
-    popd
-
-    pushd simple-raytracer
-    if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
-        echo "[BENCH COMPILE] ebobby/simple-raytracer"
-        hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo-clif clean" \
-        "RUSTFLAGS='' cargo build" \
-        "../build/cargo-clif build"
-
-        echo "[BENCH RUN] ebobby/simple-raytracer"
-        cp ./target/debug/main ./raytracer_cg_clif
-        hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif
-    else
-        ../build/cargo-clif clean
-        echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
-        echo "[COMPILE] ebobby/simple-raytracer"
-        ../build/cargo-clif build --target $TARGET_TRIPLE
-        echo "[BENCH RUN] ebobby/simple-raytracer (skipped)"
-    fi
-    popd
-
-    pushd build_sysroot/sysroot_src/library/core/tests
-    echo "[TEST] libcore"
-    ../../../../../build/cargo-clif clean
-    if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
-        ../../../../../build/cargo-clif test
-    else
-        ../../../../../build/cargo-clif build --target $TARGET_TRIPLE --tests
-    fi
-    popd
-
-    pushd regex
-    echo "[TEST] rust-lang/regex example shootout-regex-dna"
-    ../build/cargo-clif clean
-    export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning
-    # Make sure `[codegen mono items] start` doesn't poison the diff
-    ../build/cargo-clif build --example shootout-regex-dna --target $TARGET_TRIPLE
-    if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
-        cat examples/regexdna-input.txt \
-            | ../build/cargo-clif run --example shootout-regex-dna --target $TARGET_TRIPLE \
-            | grep -v "Spawned thread" > res.txt
-        diff -u res.txt examples/regexdna-output.txt
-    fi
-
-    if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
-        echo "[TEST] rust-lang/regex tests"
-        ../build/cargo-clif test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q
-    else
-        echo "[AOT] rust-lang/regex tests"
-        ../build/cargo-clif build --tests --target $TARGET_TRIPLE
-    fi
-    popd
-
-    pushd portable-simd
-    echo "[TEST] rust-lang/portable-simd"
-    ../build/cargo-clif clean
-    ../build/cargo-clif build --all-targets --target $TARGET_TRIPLE
-    if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
-        ../build/cargo-clif test -q
-    fi
-    popd
-}
-
-case "$1" in
-    "no_sysroot")
-        no_sysroot_tests
-        ;;
-    "base_sysroot")
-        base_sysroot_tests
-        ;;
-    "extended_sysroot")
-        extended_sysroot_tests
-        ;;
-    *)
-        echo "unknown test suite"
-        ;;
-esac
index 6c10baa53d415da6e32e64adebecab4d57a059d4..f4ad76b3bab3c77edeb007f2c8b8c6dd9ef1e193 100644 (file)
@@ -23,7 +23,7 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
         (RegKind::Integer, 9..=16) => types::I128,
         (RegKind::Float, 4) => types::F32,
         (RegKind::Float, 8) => types::F64,
-        (RegKind::Vector, size) => types::I8.by(u16::try_from(size).unwrap()).unwrap(),
+        (RegKind::Vector, size) => types::I8.by(u32::try_from(size).unwrap()).unwrap(),
         _ => unreachable!("{:?}", reg),
     };
     AbiParam::new(clif_ty)
@@ -184,7 +184,7 @@ pub(super) fn from_casted_value<'tcx>(
     let abi_params = cast_target_to_abi_params(cast);
     let abi_param_size: u32 = abi_params.iter().map(|param| param.value_type.bytes()).sum();
     let layout_size = u32::try_from(layout.size.bytes()).unwrap();
-    let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
+    let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
         kind: StackSlotKind::ExplicitSlot,
         // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
         // specify stack slot alignment.
@@ -193,7 +193,7 @@ pub(super) fn from_casted_value<'tcx>(
         // larger alignment than the integer.
         size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16,
     });
-    let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0));
+    let ptr = Pointer::stack_slot(stack_slot);
     let mut offset = 0;
     let mut block_params_iter = block_params.iter().copied();
     for param in abi_params {
index 122e103ff62bc14262a1b91a7e38d4e293bba6e4..44c34d6c8cb79928ecf5aacac453df0f292bed82 100644 (file)
@@ -6,21 +6,43 @@
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 
-use indexmap::IndexSet;
-
 use crate::constant::ConstantCx;
+use crate::debuginfo::FunctionDebugContext;
 use crate::prelude::*;
 use crate::pretty_clif::CommentWriter;
 
-pub(crate) fn codegen_fn<'tcx>(
-    cx: &mut crate::CodegenCx<'tcx>,
+pub(crate) struct CodegenedFunction {
+    symbol_name: String,
+    func_id: FuncId,
+    func: Function,
+    clif_comments: CommentWriter,
+    func_debug_cx: Option<FunctionDebugContext>,
+}
+
+#[cfg_attr(not(feature = "jit"), allow(dead_code))]
+pub(crate) fn codegen_and_compile_fn<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    cx: &mut crate::CodegenCx,
+    cached_context: &mut Context,
     module: &mut dyn Module,
     instance: Instance<'tcx>,
 ) {
-    let tcx = cx.tcx;
-
     let _inst_guard =
         crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
+
+    let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
+    let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance);
+
+    compile_fn(cx, cached_context, module, codegened_func);
+}
+
+pub(crate) fn codegen_fn<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    cx: &mut crate::CodegenCx,
+    cached_func: Function,
+    module: &mut dyn Module,
+    instance: Instance<'tcx>,
+) -> CodegenedFunction {
     debug_assert!(!instance.substs.needs_infer());
 
     let mir = tcx.instance_mir(instance.def);
@@ -34,15 +56,14 @@ pub(crate) fn codegen_fn<'tcx>(
     });
 
     // Declare function
-    let symbol_name = tcx.symbol_name(instance);
+    let symbol_name = tcx.symbol_name(instance).name.to_string();
     let sig = get_function_sig(tcx, module.isa().triple(), instance);
-    let func_id = module.declare_function(symbol_name.name, Linkage::Local, &sig).unwrap();
-
-    cx.cached_context.clear();
+    let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
 
     // Make the FunctionBuilder
     let mut func_ctx = FunctionBuilderContext::new();
-    let mut func = std::mem::replace(&mut cx.cached_context.func, Function::new());
+    let mut func = cached_func;
+    func.clear();
     func.name = ExternalName::user(0, func_id.as_u32());
     func.signature = sig;
     func.collect_debug_info();
@@ -59,6 +80,12 @@ pub(crate) fn codegen_fn<'tcx>(
     let pointer_type = target_config.pointer_type();
     let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance);
 
+    let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context {
+        Some(debug_context.define_function(tcx, &symbol_name, mir.span))
+    } else {
+        None
+    };
+
     let mut fx = FunctionCx {
         cx,
         module,
@@ -66,6 +93,7 @@ pub(crate) fn codegen_fn<'tcx>(
         target_config,
         pointer_type,
         constants_cx: ConstantCx::new(),
+        func_debug_cx,
 
         instance,
         symbol_name,
@@ -78,81 +106,48 @@ pub(crate) fn codegen_fn<'tcx>(
         caller_location: None, // set by `codegen_fn_prelude`
 
         clif_comments,
-        source_info_set: indexmap::IndexSet::new(),
+        last_source_file: None,
         next_ssa_var: 0,
     };
 
-    let arg_uninhabited = fx
-        .mir
-        .args_iter()
-        .any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).abi.is_uninhabited());
-
-    if !crate::constant::check_constants(&mut fx) {
-        fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
-        fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
-        crate::trap::trap_unreachable(&mut fx, "compilation should have been aborted");
-    } else if arg_uninhabited {
-        fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
-        fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
-        fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
-    } else {
-        tcx.sess.time("codegen clif ir", || {
-            tcx.sess
-                .time("codegen prelude", || crate::abi::codegen_fn_prelude(&mut fx, start_block));
-            codegen_fn_content(&mut fx);
-        });
-    }
+    tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block));
 
     // Recover all necessary data from fx, before accessing func will prevent future access to it.
-    let instance = fx.instance;
+    let symbol_name = fx.symbol_name;
     let clif_comments = fx.clif_comments;
-    let source_info_set = fx.source_info_set;
-    let local_map = fx.local_map;
+    let func_debug_cx = fx.func_debug_cx;
 
     fx.constants_cx.finalize(fx.tcx, &mut *fx.module);
 
-    crate::pretty_clif::write_clif_file(
-        tcx,
-        "unopt",
-        module.isa(),
-        instance,
-        &func,
-        &clif_comments,
-    );
+    if cx.should_write_ir {
+        crate::pretty_clif::write_clif_file(
+            tcx.output_filenames(()),
+            &symbol_name,
+            "unopt",
+            module.isa(),
+            &func,
+            &clif_comments,
+        );
+    }
 
     // Verify function
     verify_func(tcx, &clif_comments, &func);
 
-    compile_fn(
-        cx,
-        module,
-        instance,
-        symbol_name.name,
-        func_id,
-        func,
-        clif_comments,
-        source_info_set,
-        local_map,
-    );
+    CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
 }
 
-fn compile_fn<'tcx>(
-    cx: &mut crate::CodegenCx<'tcx>,
+pub(crate) fn compile_fn(
+    cx: &mut crate::CodegenCx,
+    cached_context: &mut Context,
     module: &mut dyn Module,
-    instance: Instance<'tcx>,
-    symbol_name: &str,
-    func_id: FuncId,
-    func: Function,
-    mut clif_comments: CommentWriter,
-    source_info_set: IndexSet<SourceInfo>,
-    local_map: IndexVec<mir::Local, CPlace<'tcx>>,
+    codegened_func: CodegenedFunction,
 ) {
-    let tcx = cx.tcx;
+    let clif_comments = codegened_func.clif_comments;
 
     // Store function in context
-    let context = &mut cx.cached_context;
+    let context = cached_context;
     context.clear();
-    context.func = func;
+    context.func = codegened_func.func;
 
     // If the return block is not reachable, then the SSA builder may have inserted an `iconst.i128`
     // instruction, which doesn't have an encoding.
@@ -164,17 +159,6 @@ fn compile_fn<'tcx>(
     // invalidate it when it would change.
     context.domtree.clear();
 
-    // Perform rust specific optimizations
-    tcx.sess.time("optimize clif ir", || {
-        crate::optimize::optimize_function(
-            tcx,
-            module.isa(),
-            instance,
-            context,
-            &mut clif_comments,
-        );
-    });
-
     #[cfg(any())] // This is never true
     let _clif_guard = {
         use std::fmt::Write;
@@ -203,46 +187,44 @@ fn compile_fn<'tcx>(
     };
 
     // Define function
-    tcx.sess.time("define function", || {
-        context.want_disasm = crate::pretty_clif::should_write_ir(tcx);
-        module.define_function(func_id, context).unwrap();
+    cx.profiler.verbose_generic_activity("define function").run(|| {
+        context.want_disasm = cx.should_write_ir;
+        module.define_function(codegened_func.func_id, context).unwrap();
     });
 
-    // Write optimized function to file for debugging
-    crate::pretty_clif::write_clif_file(
-        tcx,
-        "opt",
-        module.isa(),
-        instance,
-        &context.func,
-        &clif_comments,
-    );
+    if cx.should_write_ir {
+        // Write optimized function to file for debugging
+        crate::pretty_clif::write_clif_file(
+            &cx.output_filenames,
+            &codegened_func.symbol_name,
+            "opt",
+            module.isa(),
+            &context.func,
+            &clif_comments,
+        );
 
-    if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm {
-        crate::pretty_clif::write_ir_file(
-            tcx,
-            || format!("{}.vcode", tcx.symbol_name(instance).name),
-            |file| file.write_all(disasm.as_bytes()),
-        )
+        if let Some(disasm) = &context.compiled_code().unwrap().disasm {
+            crate::pretty_clif::write_ir_file(
+                &cx.output_filenames,
+                &format!("{}.vcode", codegened_func.symbol_name),
+                |file| file.write_all(disasm.as_bytes()),
+            )
+        }
     }
 
     // Define debuginfo for function
     let isa = module.isa();
     let debug_context = &mut cx.debug_context;
     let unwind_context = &mut cx.unwind_context;
-    tcx.sess.time("generate debug info", || {
+    cx.profiler.verbose_generic_activity("generate debug info").run(|| {
         if let Some(debug_context) = debug_context {
-            debug_context.define_function(
-                instance,
-                func_id,
-                symbol_name,
-                isa,
+            codegened_func.func_debug_cx.unwrap().finalize(
+                debug_context,
+                codegened_func.func_id,
                 context,
-                &source_info_set,
-                local_map,
             );
         }
-        unwind_context.add_function(func_id, &context, isa);
+        unwind_context.add_function(codegened_func.func_id, &context, isa);
     });
 }
 
@@ -268,7 +250,27 @@ pub(crate) fn verify_func(
     });
 }
 
-fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
+fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
+    if !crate::constant::check_constants(fx) {
+        fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
+        fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
+        // compilation should have been aborted
+        fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
+        return;
+    }
+
+    let arg_uninhabited = fx
+        .mir
+        .args_iter()
+        .any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).abi.is_uninhabited());
+    if arg_uninhabited {
+        fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
+        fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
+        fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
+        return;
+    }
+    fx.tcx.sess.time("codegen prelude", || crate::abi::codegen_fn_prelude(fx, start_block));
+
     for (bb, bb_data) in fx.mir.basic_blocks().iter_enumerated() {
         let block = fx.get_block(bb);
         fx.bcx.switch_to_block(block);
@@ -457,17 +459,8 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
                     template,
                     operands,
                     *options,
+                    *destination,
                 );
-
-                match *destination {
-                    Some(destination) => {
-                        let destination_block = fx.get_block(destination);
-                        fx.bcx.ins().jump(destination_block, &[]);
-                    }
-                    None => {
-                        fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
-                    }
-                }
             }
             TerminatorKind::Resume | TerminatorKind::Abort => {
                 // FIXME implement unwinding
@@ -711,9 +704,7 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
                 Rvalue::Discriminant(place) => {
                     let place = codegen_place(fx, place);
                     let value = place.to_cvalue(fx);
-                    let discr =
-                        crate::discriminant::codegen_get_discriminant(fx, value, dest_layout);
-                    lval.write_cvalue(fx, discr);
+                    crate::discriminant::codegen_get_discriminant(fx, lval, value, dest_layout);
                 }
                 Rvalue::Repeat(ref operand, times) => {
                     let operand = codegen_operand(fx, operand);
index f9dc1b5169e1a624c35949691a5a8f0f6f0e6f8c..589594465783e1611c688cd17f5c82325ae9576f 100644 (file)
@@ -1,14 +1,18 @@
 use cranelift_codegen::isa::TargetFrontendConfig;
+use gimli::write::FileId;
+
+use rustc_data_structures::sync::Lrc;
 use rustc_index::vec::IndexVec;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
 };
-use rustc_middle::ty::SymbolName;
+use rustc_span::SourceFile;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Integer, Primitive};
 use rustc_target::spec::{HasTargetSpec, Target};
 
 use crate::constant::ConstantCx;
+use crate::debuginfo::FunctionDebugContext;
 use crate::prelude::*;
 
 pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type {
@@ -74,7 +78,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
                 _ => unreachable!(),
             };
 
-            match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) {
+            match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) {
                 // Cranelift currently only implements icmp for 128bit vectors.
                 Some(vector_ty) if vector_ty.bits() == 128 => vector_ty,
                 _ => return None,
@@ -232,15 +236,16 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool {
 }
 
 pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
-    pub(crate) cx: &'clif mut crate::CodegenCx<'tcx>,
+    pub(crate) cx: &'clif mut crate::CodegenCx,
     pub(crate) module: &'m mut dyn Module,
     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) instance: Instance<'tcx>,
-    pub(crate) symbol_name: SymbolName<'tcx>,
+    pub(crate) symbol_name: String,
     pub(crate) mir: &'tcx Body<'tcx>,
     pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>,
 
@@ -252,7 +257,11 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
     pub(crate) caller_location: Option<CValue<'tcx>>,
 
     pub(crate) clif_comments: crate::pretty_clif::CommentWriter,
-    pub(crate) source_info_set: indexmap::IndexSet<SourceInfo>,
+
+    /// Last accessed source file and it's debuginfo file id.
+    ///
+    /// For optimization purposes only
+    pub(crate) last_source_file: Option<(Lrc<SourceFile>, FileId)>,
 
     /// This should only be accessed by `CPlace::new_var`.
     pub(crate) next_ssa_var: u32,
@@ -336,8 +345,31 @@ pub(crate) fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> {
     }
 
     pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
-        let (index, _) = self.source_info_set.insert_full(source_info);
-        self.bcx.set_srcloc(SourceLoc::new(index as u32));
+        if let Some(debug_context) = &mut self.cx.debug_context {
+            let (file, line, column) =
+                DebugContext::get_span_loc(self.tcx, self.mir.span, source_info.span);
+
+            // add_source_file is very slow.
+            // Optimize for the common case of the current file not being changed.
+            let mut cached_file_id = None;
+            if let Some((ref last_source_file, last_file_id)) = self.last_source_file {
+                // If the allocations are not equal, the files may still be equal, but that
+                // doesn't matter, as this is just an optimization.
+                if rustc_data_structures::sync::Lrc::ptr_eq(last_source_file, &file) {
+                    cached_file_id = Some(last_file_id);
+                }
+            }
+
+            let file_id = if let Some(file_id) = cached_file_id {
+                file_id
+            } else {
+                debug_context.add_source_file(&file)
+            };
+
+            let source_loc =
+                self.func_debug_cx.as_mut().unwrap().add_dbg_loc(file_id, line, column);
+            self.bcx.set_srcloc(source_loc);
+        }
     }
 
     // Note: must be kept in sync with get_caller_location from cg_ssa
diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
new file mode 100644 (file)
index 0000000..dfde979
--- /dev/null
@@ -0,0 +1,168 @@
+use std::sync::{Arc, Condvar, Mutex};
+
+use rustc_session::Session;
+
+use jobserver::HelperThread;
+
+// FIXME don't panic when a worker thread panics
+
+pub(super) struct ConcurrencyLimiter {
+    helper_thread: Option<HelperThread>,
+    state: Arc<Mutex<state::ConcurrencyLimiterState>>,
+    available_token_condvar: Arc<Condvar>,
+}
+
+impl ConcurrencyLimiter {
+    pub(super) fn new(sess: &Session, pending_jobs: usize) -> Self {
+        let state = Arc::new(Mutex::new(state::ConcurrencyLimiterState::new(pending_jobs)));
+        let available_token_condvar = Arc::new(Condvar::new());
+
+        let state_helper = state.clone();
+        let available_token_condvar_helper = available_token_condvar.clone();
+        let helper_thread = sess
+            .jobserver
+            .clone()
+            .into_helper_thread(move |token| {
+                let mut state = state_helper.lock().unwrap();
+                state.add_new_token(token.unwrap());
+                available_token_condvar_helper.notify_one();
+            })
+            .unwrap();
+        ConcurrencyLimiter {
+            helper_thread: Some(helper_thread),
+            state,
+            available_token_condvar: Arc::new(Condvar::new()),
+        }
+    }
+
+    pub(super) fn acquire(&mut self) -> ConcurrencyLimiterToken {
+        let mut state = self.state.lock().unwrap();
+        loop {
+            state.assert_invariants();
+
+            if state.try_start_job() {
+                return ConcurrencyLimiterToken {
+                    state: self.state.clone(),
+                    available_token_condvar: self.available_token_condvar.clone(),
+                };
+            }
+
+            self.helper_thread.as_mut().unwrap().request_token();
+            state = self.available_token_condvar.wait(state).unwrap();
+        }
+    }
+
+    pub(super) fn job_already_done(&mut self) {
+        let mut state = self.state.lock().unwrap();
+        state.job_already_done();
+    }
+}
+
+impl Drop for ConcurrencyLimiter {
+    fn drop(&mut self) {
+        //
+        self.helper_thread.take();
+
+        // Assert that all jobs have finished
+        let state = Mutex::get_mut(Arc::get_mut(&mut self.state).unwrap()).unwrap();
+        state.assert_done();
+    }
+}
+
+#[derive(Debug)]
+pub(super) struct ConcurrencyLimiterToken {
+    state: Arc<Mutex<state::ConcurrencyLimiterState>>,
+    available_token_condvar: Arc<Condvar>,
+}
+
+impl Drop for ConcurrencyLimiterToken {
+    fn drop(&mut self) {
+        let mut state = self.state.lock().unwrap();
+        state.job_finished();
+        self.available_token_condvar.notify_one();
+    }
+}
+
+mod state {
+    use jobserver::Acquired;
+
+    #[derive(Debug)]
+    pub(super) struct ConcurrencyLimiterState {
+        pending_jobs: usize,
+        active_jobs: usize,
+
+        // None is used to represent the implicit token, Some to represent explicit tokens
+        tokens: Vec<Option<Acquired>>,
+    }
+
+    impl ConcurrencyLimiterState {
+        pub(super) fn new(pending_jobs: usize) -> Self {
+            ConcurrencyLimiterState { pending_jobs, active_jobs: 0, tokens: vec![None] }
+        }
+
+        pub(super) fn assert_invariants(&self) {
+            // There must be no excess active jobs
+            assert!(self.active_jobs <= self.pending_jobs);
+
+            // There may not be more active jobs than there are tokens
+            assert!(self.active_jobs <= self.tokens.len());
+        }
+
+        pub(super) fn assert_done(&self) {
+            assert_eq!(self.pending_jobs, 0);
+            assert_eq!(self.active_jobs, 0);
+        }
+
+        pub(super) fn add_new_token(&mut self, token: Acquired) {
+            self.tokens.push(Some(token));
+            self.drop_excess_capacity();
+        }
+
+        pub(super) fn try_start_job(&mut self) -> bool {
+            if self.active_jobs < self.tokens.len() {
+                // Using existing token
+                self.job_started();
+                return true;
+            }
+
+            false
+        }
+
+        pub(super) fn job_started(&mut self) {
+            self.assert_invariants();
+            self.active_jobs += 1;
+            self.drop_excess_capacity();
+            self.assert_invariants();
+        }
+
+        pub(super) fn job_finished(&mut self) {
+            self.assert_invariants();
+            self.pending_jobs -= 1;
+            self.active_jobs -= 1;
+            self.assert_invariants();
+            self.drop_excess_capacity();
+            self.assert_invariants();
+        }
+
+        pub(super) fn job_already_done(&mut self) {
+            self.assert_invariants();
+            self.pending_jobs -= 1;
+            self.assert_invariants();
+            self.drop_excess_capacity();
+            self.assert_invariants();
+        }
+
+        fn drop_excess_capacity(&mut self) {
+            self.assert_invariants();
+
+            // Drop all tokens that can never be used anymore
+            self.tokens.truncate(std::cmp::max(self.pending_jobs, 1));
+
+            // Keep some excess tokens to satisfy requests faster
+            const MAX_EXTRA_CAPACITY: usize = 2;
+            self.tokens.truncate(std::cmp::max(self.active_jobs + MAX_EXTRA_CAPACITY, 1));
+
+            self.assert_invariants();
+        }
+    }
+}
index 589910ede9688ce330e42bc2552ae3b9ea67cd54..9583cd2ec60f8a5bcf3bb3d4b0b74ea806f97614 100644 (file)
@@ -9,7 +9,7 @@
 use super::object::WriteDebugInfo;
 use super::DebugContext;
 
-impl DebugContext<'_> {
+impl DebugContext {
     pub(crate) fn emit(&mut self, product: &mut ObjectProduct) {
         let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
         let root = self.dwarf.unit.root();
index bbcb9591373dd7192f2e8b7f05a1063fbd0ed348..3ad0c420eaf0b010b313e4dae0a785778eb21f0f 100644 (file)
@@ -3,8 +3,10 @@
 use std::ffi::OsStr;
 use std::path::{Component, Path};
 
+use crate::debuginfo::FunctionDebugContext;
 use crate::prelude::*;
 
+use rustc_data_structures::sync::Lrc;
 use rustc_span::{
     FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
 };
@@ -14,7 +16,6 @@
 
 use gimli::write::{
     Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable,
-    UnitEntryId,
 };
 
 // OPTIMIZATION: It is cheaper to do this in one pass than using `.parent()` and `.file_name()`.
@@ -47,9 +48,9 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] {
     }
 }
 
-pub(crate) const MD5_LEN: usize = 16;
+const MD5_LEN: usize = 16;
 
-pub(crate) fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
+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());
@@ -59,160 +60,132 @@ pub(crate) fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
     }
 }
 
-fn line_program_add_file(
-    line_program: &mut LineProgram,
-    line_strings: &mut LineStringTable,
-    file: &SourceFile,
-) -> FileId {
-    match &file.name {
-        FileName::Real(path) => {
-            let (dir_path, file_name) = split_path_dir_and_file(path.remapped_path_if_available());
-            let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
-            let file_name = osstr_as_utf8_bytes(file_name);
-
-            let dir_id = if !dir_name.is_empty() {
-                let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings);
-                line_program.add_directory(dir_name)
-            } else {
-                line_program.default_directory()
-            };
-            let file_name = LineString::new(file_name, line_program.encoding(), line_strings);
+impl DebugContext {
+    pub(crate) fn get_span_loc(
+        tcx: TyCtxt<'_>,
+        function_span: Span,
+        span: Span,
+    ) -> (Lrc<SourceFile>, u64, u64) {
+        // Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
+        // In order to have a good line stepping behavior in debugger, we overwrite debug
+        // locations of macro expansions with that of the outermost expansion site
+        // (unless the crate is being compiled with `-Z debug-macros`).
+        let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros {
+            span
+        } else {
+            // Walk up the macro expansion chain until we reach a non-expanded span.
+            // We also stop at the function body level because no line stepping can occur
+            // at the level above that.
+            rustc_span::hygiene::walk_chain(span, function_span.ctxt())
+        };
 
-            let info = make_file_info(file.src_hash);
+        match tcx.sess.source_map().lookup_line(span.lo()) {
+            Ok(SourceFileAndLine { sf: file, line }) => {
+                let line_pos = file.line_begin_pos(span.lo());
 
-            line_program.file_has_md5 &= info.is_some();
-            line_program.add_file(file_name, dir_id, info)
+                (
+                    file,
+                    u64::try_from(line).unwrap() + 1,
+                    u64::from((span.lo() - line_pos).to_u32()) + 1,
+                )
+            }
+            Err(file) => (file, 0, 0),
         }
-        // FIXME give more appropriate file names
-        filename => {
-            let dir_id = line_program.default_directory();
-            let dummy_file_name = LineString::new(
-                filename.prefer_remapped().to_string().into_bytes(),
-                line_program.encoding(),
-                line_strings,
-            );
-            line_program.add_file(dummy_file_name, dir_id, None)
+    }
+
+    pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId {
+        let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
+        let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
+
+        match &source_file.name {
+            FileName::Real(path) => {
+                let (dir_path, file_name) =
+                    split_path_dir_and_file(path.remapped_path_if_available());
+                let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
+                let file_name = osstr_as_utf8_bytes(file_name);
+
+                let dir_id = if !dir_name.is_empty() {
+                    let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings);
+                    line_program.add_directory(dir_name)
+                } else {
+                    line_program.default_directory()
+                };
+                let file_name = LineString::new(file_name, line_program.encoding(), line_strings);
+
+                let info = make_file_info(source_file.src_hash);
+
+                line_program.file_has_md5 &= info.is_some();
+                line_program.add_file(file_name, dir_id, info)
+            }
+            // FIXME give more appropriate file names
+            filename => {
+                let dir_id = line_program.default_directory();
+                let dummy_file_name = LineString::new(
+                    filename.prefer_remapped().to_string().into_bytes(),
+                    line_program.encoding(),
+                    line_strings,
+                );
+                line_program.add_file(dummy_file_name, dir_id, None)
+            }
         }
     }
 }
 
-impl<'tcx> DebugContext<'tcx> {
-    pub(super) fn emit_location(&mut self, entry_id: UnitEntryId, span: Span) {
-        let loc = self.tcx.sess.source_map().lookup_char_pos(span.lo());
-
-        let file_id = line_program_add_file(
-            &mut self.dwarf.unit.line_program,
-            &mut self.dwarf.line_strings,
-            &loc.file,
-        );
-
-        let entry = self.dwarf.unit.get_mut(entry_id);
-
-        entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
-        entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(loc.line as u64));
-        entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(loc.col.to_usize() as u64));
+impl FunctionDebugContext {
+    pub(crate) fn add_dbg_loc(&mut self, file_id: FileId, line: u64, column: u64) -> SourceLoc {
+        let (index, _) = self.source_loc_set.insert_full((file_id, line, column));
+        SourceLoc::new(u32::try_from(index).unwrap())
     }
 
     pub(super) fn create_debug_lines(
         &mut self,
+        debug_context: &mut DebugContext,
         symbol: usize,
-        entry_id: UnitEntryId,
         context: &Context,
-        function_span: Span,
-        source_info_set: &indexmap::IndexSet<SourceInfo>,
     ) -> CodeOffset {
-        let tcx = self.tcx;
-        let line_program = &mut self.dwarf.unit.line_program;
-
-        let line_strings = &mut self.dwarf.line_strings;
-        let mut last_span = None;
-        let mut last_file = None;
-        let mut create_row_for_span = |line_program: &mut LineProgram, span: Span| {
-            if let Some(last_span) = last_span {
-                if span == last_span {
-                    line_program.generate_row();
-                    return;
-                }
-            }
-            last_span = Some(span);
-
-            // Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
-            // In order to have a good line stepping behavior in debugger, we overwrite debug
-            // locations of macro expansions with that of the outermost expansion site
-            // (unless the crate is being compiled with `-Z debug-macros`).
-            let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros {
-                span
-            } else {
-                // Walk up the macro expansion chain until we reach a non-expanded span.
-                // We also stop at the function body level because no line stepping can occur
-                // at the level above that.
-                rustc_span::hygiene::walk_chain(span, function_span.ctxt())
+        let create_row_for_span =
+            |debug_context: &mut DebugContext, source_loc: (FileId, u64, u64)| {
+                let (file_id, line, col) = source_loc;
+
+                debug_context.dwarf.unit.line_program.row().file = file_id;
+                debug_context.dwarf.unit.line_program.row().line = line;
+                debug_context.dwarf.unit.line_program.row().column = col;
+                debug_context.dwarf.unit.line_program.generate_row();
             };
 
-            let (file, line, col) = match tcx.sess.source_map().lookup_line(span.lo()) {
-                Ok(SourceFileAndLine { sf: file, line }) => {
-                    let line_pos = file.line_begin_pos(span.lo());
-
-                    (
-                        file,
-                        u64::try_from(line).unwrap() + 1,
-                        u64::from((span.lo() - line_pos).to_u32()) + 1,
-                    )
-                }
-                Err(file) => (file, 0, 0),
-            };
-
-            // line_program_add_file is very slow.
-            // Optimize for the common case of the current file not being changed.
-            let current_file_changed = if let Some(last_file) = &last_file {
-                // If the allocations are not equal, then the files may still be equal, but that
-                // is not a problem, as this is just an optimization.
-                !rustc_data_structures::sync::Lrc::ptr_eq(last_file, &file)
-            } else {
-                true
-            };
-            if current_file_changed {
-                let file_id = line_program_add_file(line_program, line_strings, &file);
-                line_program.row().file = file_id;
-                last_file = Some(file);
-            }
-
-            line_program.row().line = line;
-            line_program.row().column = col;
-            line_program.generate_row();
-        };
-
-        line_program.begin_sequence(Some(Address::Symbol { symbol, addend: 0 }));
+        debug_context
+            .dwarf
+            .unit
+            .line_program
+            .begin_sequence(Some(Address::Symbol { symbol, addend: 0 }));
 
         let mut func_end = 0;
 
-        let mcr = context.mach_compile_result.as_ref().unwrap();
+        let mcr = context.compiled_code().unwrap();
         for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() {
-            line_program.row().address_offset = u64::from(start);
+            debug_context.dwarf.unit.line_program.row().address_offset = u64::from(start);
             if !loc.is_default() {
-                let source_info = *source_info_set.get_index(loc.bits() as usize).unwrap();
-                create_row_for_span(line_program, source_info.span);
+                let source_loc = *self.source_loc_set.get_index(loc.bits() as usize).unwrap();
+                create_row_for_span(debug_context, source_loc);
             } else {
-                create_row_for_span(line_program, function_span);
+                create_row_for_span(debug_context, self.function_source_loc);
             }
             func_end = end;
         }
 
-        line_program.end_sequence(u64::from(func_end));
+        debug_context.dwarf.unit.line_program.end_sequence(u64::from(func_end));
 
         let func_end = mcr.buffer.total_size();
 
         assert_ne!(func_end, 0);
 
-        let entry = self.dwarf.unit.get_mut(entry_id);
+        let entry = debug_context.dwarf.unit.get_mut(self.entry_id);
         entry.set(
             gimli::DW_AT_low_pc,
             AttributeValue::Address(Address::Symbol { symbol, addend: 0 }),
         );
         entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(func_end)));
 
-        self.emit_location(entry_id, function_span);
-
         func_end
     }
 }
index 693092ba543ea947c5b448520fac7984935e697c..c55db2017ee68c31c53b0a59e12c82b6b72c6c7e 100644 (file)
@@ -7,35 +7,34 @@
 
 use crate::prelude::*;
 
-use rustc_index::vec::IndexVec;
-
-use cranelift_codegen::entity::EntityRef;
-use cranelift_codegen::ir::{Endianness, LabelValueLoc, ValueLabel};
+use cranelift_codegen::ir::Endianness;
 use cranelift_codegen::isa::TargetIsa;
-use cranelift_codegen::ValueLocRange;
 
 use gimli::write::{
-    Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, Location,
-    LocationList, Range, RangeList, UnitEntryId,
+    Address, AttributeValue, DwarfUnit, FileId, LineProgram, LineString, Range, RangeList,
+    UnitEntryId,
 };
-use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, X86_64};
+use gimli::{Encoding, Format, LineEncoding, RunTimeEndian};
+use indexmap::IndexSet;
 
 pub(crate) use emit::{DebugReloc, DebugRelocName};
 pub(crate) use unwind::UnwindContext;
 
-pub(crate) struct DebugContext<'tcx> {
-    tcx: TyCtxt<'tcx>,
-
+pub(crate) struct DebugContext {
     endian: RunTimeEndian,
 
     dwarf: DwarfUnit,
     unit_range_list: RangeList,
+}
 
-    types: FxHashMap<Ty<'tcx>, UnitEntryId>,
+pub(crate) struct FunctionDebugContext {
+    entry_id: UnitEntryId,
+    function_source_loc: (FileId, u64, u64),
+    source_loc_set: indexmap::IndexSet<(FileId, u64, u64)>,
 }
 
-impl<'tcx> DebugContext<'tcx> {
-    pub(crate) fn new(tcx: TyCtxt<'tcx>, isa: &dyn TargetIsa) -> Self {
+impl DebugContext {
+    pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa) -> Self {
         let encoding = Encoding {
             format: Format::Dwarf32,
             // FIXME this should be configurable
@@ -101,127 +100,18 @@ pub(crate) fn new(tcx: TyCtxt<'tcx>, isa: &dyn TargetIsa) -> Self {
             root.set(gimli::DW_AT_low_pc, AttributeValue::Address(Address::Constant(0)));
         }
 
-        DebugContext {
-            tcx,
-
-            endian,
-
-            dwarf,
-            unit_range_list: RangeList(Vec::new()),
-
-            types: FxHashMap::default(),
-        }
-    }
-
-    fn dwarf_ty(&mut self, ty: Ty<'tcx>) -> UnitEntryId {
-        if let Some(type_id) = self.types.get(&ty) {
-            return *type_id;
-        }
-
-        let new_entry = |dwarf: &mut DwarfUnit, tag| dwarf.unit.add(dwarf.unit.root(), tag);
-
-        let primitive = |dwarf: &mut DwarfUnit, ate| {
-            let type_id = new_entry(dwarf, gimli::DW_TAG_base_type);
-            let type_entry = dwarf.unit.get_mut(type_id);
-            type_entry.set(gimli::DW_AT_encoding, AttributeValue::Encoding(ate));
-            type_id
-        };
-
-        let name = format!("{}", ty);
-        let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
-
-        let type_id = match ty.kind() {
-            ty::Bool => primitive(&mut self.dwarf, gimli::DW_ATE_boolean),
-            ty::Char => primitive(&mut self.dwarf, gimli::DW_ATE_UTF),
-            ty::Uint(_) => primitive(&mut self.dwarf, gimli::DW_ATE_unsigned),
-            ty::Int(_) => primitive(&mut self.dwarf, gimli::DW_ATE_signed),
-            ty::Float(_) => primitive(&mut self.dwarf, gimli::DW_ATE_float),
-            ty::Ref(_, pointee_ty, _mutbl)
-            | ty::RawPtr(ty::TypeAndMut { ty: pointee_ty, mutbl: _mutbl }) => {
-                let type_id = new_entry(&mut self.dwarf, gimli::DW_TAG_pointer_type);
-
-                // Ensure that type is inserted before recursing to avoid duplicates
-                self.types.insert(ty, type_id);
-
-                let pointee = self.dwarf_ty(*pointee_ty);
-
-                let type_entry = self.dwarf.unit.get_mut(type_id);
-
-                //type_entry.set(gimli::DW_AT_mutable, AttributeValue::Flag(mutbl == rustc_hir::Mutability::Mut));
-                type_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(pointee));
-
-                type_id
-            }
-            ty::Adt(adt_def, _substs) if adt_def.is_struct() && !layout.is_unsized() => {
-                let type_id = new_entry(&mut self.dwarf, gimli::DW_TAG_structure_type);
-
-                // Ensure that type is inserted before recursing to avoid duplicates
-                self.types.insert(ty, type_id);
-
-                let variant = adt_def.non_enum_variant();
-
-                for (field_idx, field_def) in variant.fields.iter().enumerate() {
-                    let field_offset = layout.fields.offset(field_idx);
-                    let field_layout = layout.field(
-                        &layout::LayoutCx { tcx: self.tcx, param_env: ParamEnv::reveal_all() },
-                        field_idx,
-                    );
-
-                    let field_type = self.dwarf_ty(field_layout.ty);
-
-                    let field_id = self.dwarf.unit.add(type_id, gimli::DW_TAG_member);
-                    let field_entry = self.dwarf.unit.get_mut(field_id);
-
-                    field_entry.set(
-                        gimli::DW_AT_name,
-                        AttributeValue::String(field_def.name.as_str().to_string().into_bytes()),
-                    );
-                    field_entry.set(
-                        gimli::DW_AT_data_member_location,
-                        AttributeValue::Udata(field_offset.bytes()),
-                    );
-                    field_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(field_type));
-                }
-
-                type_id
-            }
-            _ => new_entry(&mut self.dwarf, gimli::DW_TAG_structure_type),
-        };
-
-        let type_entry = self.dwarf.unit.get_mut(type_id);
-
-        type_entry.set(gimli::DW_AT_name, AttributeValue::String(name.into_bytes()));
-        type_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes()));
-
-        self.types.insert(ty, type_id);
-
-        type_id
-    }
-
-    fn define_local(&mut self, scope: UnitEntryId, name: String, ty: Ty<'tcx>) -> UnitEntryId {
-        let dw_ty = self.dwarf_ty(ty);
-
-        let var_id = self.dwarf.unit.add(scope, gimli::DW_TAG_variable);
-        let var_entry = self.dwarf.unit.get_mut(var_id);
-
-        var_entry.set(gimli::DW_AT_name, AttributeValue::String(name.into_bytes()));
-        var_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(dw_ty));
-
-        var_id
+        DebugContext { endian, dwarf, unit_range_list: RangeList(Vec::new()) }
     }
 
     pub(crate) fn define_function(
         &mut self,
-        instance: Instance<'tcx>,
-        func_id: FuncId,
+        tcx: TyCtxt<'_>,
         name: &str,
-        isa: &dyn TargetIsa,
-        context: &Context,
-        source_info_set: &indexmap::IndexSet<SourceInfo>,
-        local_map: IndexVec<mir::Local, CPlace<'tcx>>,
-    ) {
-        let symbol = func_id.as_u32() as usize;
-        let mir = self.tcx.instance_mir(instance.def);
+        function_span: Span,
+    ) -> FunctionDebugContext {
+        let (file, line, column) = DebugContext::get_span_loc(tcx, function_span, function_span);
+
+        let file_id = self.add_source_file(&file);
 
         // FIXME: add to appropriate scope instead of root
         let scope = self.dwarf.unit.root();
@@ -233,14 +123,35 @@ pub(crate) fn define_function(
         entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));
         entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id));
 
-        let end = self.create_debug_lines(symbol, entry_id, context, mir.span, source_info_set);
+        entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
+        entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
+        entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(column));
 
-        self.unit_range_list.0.push(Range::StartLength {
+        FunctionDebugContext {
+            entry_id,
+            function_source_loc: (file_id, line, column),
+            source_loc_set: IndexSet::new(),
+        }
+    }
+}
+
+impl FunctionDebugContext {
+    pub(crate) fn finalize(
+        mut self,
+        debug_context: &mut DebugContext,
+        func_id: FuncId,
+        context: &Context,
+    ) {
+        let symbol = func_id.as_u32() as usize;
+
+        let end = self.create_debug_lines(debug_context, symbol, context);
+
+        debug_context.unit_range_list.0.push(Range::StartLength {
             begin: Address::Symbol { symbol, addend: 0 },
             length: u64::from(end),
         });
 
-        let func_entry = self.dwarf.unit.get_mut(entry_id);
+        let func_entry = debug_context.dwarf.unit.get_mut(self.entry_id);
         // Gdb requires both DW_AT_low_pc and DW_AT_high_pc. Otherwise the DW_TAG_subprogram is skipped.
         func_entry.set(
             gimli::DW_AT_low_pc,
@@ -248,110 +159,5 @@ pub(crate) fn define_function(
         );
         // Using Udata for DW_AT_high_pc requires at least DWARF4
         func_entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(end)));
-
-        // FIXME make it more reliable and implement scopes before re-enabling this.
-        if false {
-            let value_labels_ranges = std::collections::HashMap::new(); // FIXME
-
-            for (local, _local_decl) in mir.local_decls.iter_enumerated() {
-                let ty = self.tcx.subst_and_normalize_erasing_regions(
-                    instance.substs,
-                    ty::ParamEnv::reveal_all(),
-                    mir.local_decls[local].ty,
-                );
-                let var_id = self.define_local(entry_id, format!("{:?}", local), ty);
-
-                let location = place_location(
-                    self,
-                    isa,
-                    symbol,
-                    &local_map,
-                    &value_labels_ranges,
-                    Place { local, projection: ty::List::empty() },
-                );
-
-                let var_entry = self.dwarf.unit.get_mut(var_id);
-                var_entry.set(gimli::DW_AT_location, location);
-            }
-        }
-
-        // FIXME create locals for all entries in mir.var_debug_info
-    }
-}
-
-fn place_location<'tcx>(
-    debug_context: &mut DebugContext<'tcx>,
-    isa: &dyn TargetIsa,
-    symbol: usize,
-    local_map: &IndexVec<mir::Local, CPlace<'tcx>>,
-    #[allow(rustc::default_hash_types)] value_labels_ranges: &std::collections::HashMap<
-        ValueLabel,
-        Vec<ValueLocRange>,
-    >,
-    place: Place<'tcx>,
-) -> AttributeValue {
-    assert!(place.projection.is_empty()); // FIXME implement them
-
-    match local_map[place.local].inner() {
-        CPlaceInner::Var(_local, var) => {
-            let value_label = cranelift_codegen::ir::ValueLabel::new(var.index());
-            if let Some(value_loc_ranges) = value_labels_ranges.get(&value_label) {
-                let loc_list = LocationList(
-                    value_loc_ranges
-                        .iter()
-                        .map(|value_loc_range| Location::StartEnd {
-                            begin: Address::Symbol {
-                                symbol,
-                                addend: i64::from(value_loc_range.start),
-                            },
-                            end: Address::Symbol { symbol, addend: i64::from(value_loc_range.end) },
-                            data: translate_loc(isa, value_loc_range.loc).unwrap(),
-                        })
-                        .collect(),
-                );
-                let loc_list_id = debug_context.dwarf.unit.locations.add(loc_list);
-
-                AttributeValue::LocationListRef(loc_list_id)
-            } else {
-                // FIXME set value labels for unused locals
-
-                AttributeValue::Exprloc(Expression::new())
-            }
-        }
-        CPlaceInner::VarPair(_, _, _) => {
-            // FIXME implement this
-
-            AttributeValue::Exprloc(Expression::new())
-        }
-        CPlaceInner::VarLane(_, _, _) => {
-            // FIXME implement this
-
-            AttributeValue::Exprloc(Expression::new())
-        }
-        CPlaceInner::Addr(_, _) => {
-            // FIXME implement this (used by arguments and returns)
-
-            AttributeValue::Exprloc(Expression::new())
-
-            // For PointerBase::Stack:
-            //AttributeValue::Exprloc(translate_loc(ValueLoc::Stack(*stack_slot)).unwrap())
-        }
-    }
-}
-
-// Adapted from https://github.com/CraneStation/wasmtime/blob/5a1845b4caf7a5dba8eda1fef05213a532ed4259/crates/debug/src/transform/expression.rs#L59-L137
-fn translate_loc(isa: &dyn TargetIsa, loc: LabelValueLoc) -> Option<Expression> {
-    match loc {
-        LabelValueLoc::Reg(reg) => {
-            let machine_reg = isa.map_regalloc_reg_to_dwarf(reg).unwrap();
-            let mut expr = Expression::new();
-            expr.op_reg(gimli::Register(machine_reg));
-            Some(expr)
-        }
-        LabelValueLoc::SPOffset(offset) => {
-            let mut expr = Expression::new();
-            expr.op_breg(X86_64::RSP, offset);
-            Some(expr)
-        }
     }
 }
index f619bb5ed5e586ae33f5b7711095613bdad14472..e41ae1fbdbac54cd9a58bb80f4d8c9905e1738dc 100644 (file)
@@ -62,16 +62,14 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
 
 pub(crate) fn codegen_get_discriminant<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
+    dest: CPlace<'tcx>,
     value: CValue<'tcx>,
     dest_layout: TyAndLayout<'tcx>,
-) -> CValue<'tcx> {
+) {
     let layout = value.layout();
 
-    if layout.abi == Abi::Uninhabited {
-        let true_ = fx.bcx.ins().iconst(types::I32, 1);
-        fx.bcx.ins().trapnz(true_, TrapCode::UnreachableCodeReached);
-        // Return a dummy value
-        return CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout);
+    if layout.abi.is_uninhabited() {
+        return;
     }
 
     let (tag_scalar, tag_field, tag_encoding) = match &layout.variants {
@@ -89,7 +87,9 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
             } else {
                 ty::ScalarInt::try_from_uint(discr_val, dest_layout.size).unwrap()
             };
-            return CValue::const_val(fx, dest_layout, discr_val);
+            let res = CValue::const_val(fx, dest_layout, discr_val);
+            dest.write_cvalue(fx, res);
+            return;
         }
         Variants::Multiple { tag, tag_field, tag_encoding, variants: _ } => {
             (tag, *tag_field, tag_encoding)
@@ -110,7 +110,8 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
                 _ => false,
             };
             let val = clif_intcast(fx, tag, cast_to, signed);
-            CValue::by_val(val, dest_layout)
+            let res = CValue::by_val(val, dest_layout);
+            dest.write_cvalue(fx, res);
         }
         TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => {
             // Rebase from niche values to discriminants, and check
@@ -170,7 +171,8 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
 
             let dataful_variant = fx.bcx.ins().iconst(cast_to, i64::from(dataful_variant.as_u32()));
             let discr = fx.bcx.ins().select(is_niche, niche_discr, dataful_variant);
-            CValue::by_val(discr, dest_layout)
+            let res = CValue::by_val(discr, dest_layout);
+            dest.write_cvalue(fx, res);
         }
     }
 }
index 3cd1ef5639ef9f2e33f9c06e606ce4701fbf1ec2..8eabe1cbcb15030380e0ac333315d3326c765629 100644 (file)
 //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
 //! standalone executable.
 
+use std::fs::File;
 use std::path::PathBuf;
+use std::sync::Arc;
+use std::thread::JoinHandle;
 
-use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
+use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
 use rustc_session::cgu_reuse_tracker::CguReuse;
-use rustc_session::config::{DebugInfo, OutputType};
+use rustc_session::config::{DebugInfo, OutputFilenames, OutputType};
 use rustc_session::Session;
 
-use cranelift_codegen::isa::TargetIsa;
 use cranelift_object::{ObjectBuilder, ObjectModule};
 
+use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
+use crate::global_asm::GlobalAsmConfig;
 use crate::{prelude::*, BackendConfig};
 
-struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>);
+struct ModuleCodegenResult {
+    module_regular: CompiledModule,
+    module_global_asm: Option<CompiledModule>,
+    existing_work_product: Option<(WorkProductId, WorkProduct)>,
+}
+
+enum OngoingModuleCodegen {
+    Sync(Result<ModuleCodegenResult, String>),
+    Async(JoinHandle<Result<ModuleCodegenResult, String>>),
+}
 
-impl<HCX> HashStable<HCX> for ModuleCodegenResult {
+impl<HCX> HashStable<HCX> for OngoingModuleCodegen {
     fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
         // do nothing
     }
 }
 
-fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
+pub(crate) struct OngoingCodegen {
+    modules: Vec<OngoingModuleCodegen>,
+    allocator_module: Option<CompiledModule>,
+    metadata_module: Option<CompiledModule>,
+    metadata: EncodedMetadata,
+    crate_info: CrateInfo,
+    concurrency_limiter: ConcurrencyLimiter,
+}
+
+impl OngoingCodegen {
+    pub(crate) fn join(
+        self,
+        sess: &Session,
+        backend_config: &BackendConfig,
+    ) -> (CodegenResults, FxHashMap<WorkProductId, WorkProduct>) {
+        let mut work_products = FxHashMap::default();
+        let mut modules = vec![];
+
+        for module_codegen in self.modules {
+            let module_codegen_result = match module_codegen {
+                OngoingModuleCodegen::Sync(module_codegen_result) => module_codegen_result,
+                OngoingModuleCodegen::Async(join_handle) => match join_handle.join() {
+                    Ok(module_codegen_result) => module_codegen_result,
+                    Err(panic) => std::panic::resume_unwind(panic),
+                },
+            };
+
+            let module_codegen_result = match module_codegen_result {
+                Ok(module_codegen_result) => module_codegen_result,
+                Err(err) => sess.fatal(&err),
+            };
+            let ModuleCodegenResult { module_regular, module_global_asm, existing_work_product } =
+                module_codegen_result;
+
+            if let Some((work_product_id, work_product)) = existing_work_product {
+                work_products.insert(work_product_id, work_product);
+            } else {
+                let work_product = if backend_config.disable_incr_cache {
+                    None
+                } else if let Some(module_global_asm) = &module_global_asm {
+                    rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
+                        sess,
+                        &module_regular.name,
+                        &[
+                            ("o", &module_regular.object.as_ref().unwrap()),
+                            ("asm.o", &module_global_asm.object.as_ref().unwrap()),
+                        ],
+                    )
+                } else {
+                    rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
+                        sess,
+                        &module_regular.name,
+                        &[("o", &module_regular.object.as_ref().unwrap())],
+                    )
+                };
+                if let Some((work_product_id, work_product)) = work_product {
+                    work_products.insert(work_product_id, work_product);
+                }
+            }
+
+            modules.push(module_regular);
+            if let Some(module_global_asm) = module_global_asm {
+                modules.push(module_global_asm);
+            }
+        }
+
+        drop(self.concurrency_limiter);
+
+        (
+            CodegenResults {
+                modules,
+                allocator_module: self.allocator_module,
+                metadata_module: self.metadata_module,
+                metadata: self.metadata,
+                crate_info: self.crate_info,
+            },
+            work_products,
+        )
+    }
+}
+
+fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule {
+    let isa = crate::build_isa(sess, backend_config);
+
     let mut builder =
         ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
     // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size
@@ -37,15 +133,15 @@ fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectM
     ObjectModule::new(builder)
 }
 
-fn emit_module(
-    tcx: TyCtxt<'_>,
-    backend_config: &BackendConfig,
+fn emit_cgu(
+    output_filenames: &OutputFilenames,
+    prof: &SelfProfilerRef,
     name: String,
-    kind: ModuleKind,
     module: ObjectModule,
-    debug: Option<DebugContext<'_>>,
+    debug: Option<DebugContext>,
     unwind_context: UnwindContext,
-) -> ModuleCodegenResult {
+    global_asm_object_file: Option<PathBuf>,
+) -> Result<ModuleCodegenResult, String> {
     let mut product = module.finish();
 
     if let Some(mut debug) = debug {
@@ -54,134 +150,191 @@ fn emit_module(
 
     unwind_context.emit(&mut product);
 
-    let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name));
-    let obj = product.object.write().unwrap();
+    let module_regular =
+        emit_module(output_filenames, prof, product.object, ModuleKind::Regular, name.clone())?;
+
+    Ok(ModuleCodegenResult {
+        module_regular,
+        module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule {
+            name: format!("{name}.asm"),
+            kind: ModuleKind::Regular,
+            object: Some(global_asm_object_file),
+            dwarf_object: None,
+            bytecode: None,
+        }),
+        existing_work_product: None,
+    })
+}
 
-    tcx.sess.prof.artifact_size("object_file", name.clone(), obj.len().try_into().unwrap());
+fn emit_module(
+    output_filenames: &OutputFilenames,
+    prof: &SelfProfilerRef,
+    object: cranelift_object::object::write::Object<'_>,
+    kind: ModuleKind,
+    name: String,
+) -> Result<CompiledModule, String> {
+    let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name));
+    let mut file = match File::create(&tmp_file) {
+        Ok(file) => file,
+        Err(err) => return Err(format!("error creating object file: {}", err)),
+    };
 
-    if let Err(err) = std::fs::write(&tmp_file, obj) {
-        tcx.sess.fatal(&format!("error writing object file: {}", err));
+    if let Err(err) = object.write_stream(&mut file) {
+        return Err(format!("error writing object file: {}", err));
     }
 
-    let work_product = if backend_config.disable_incr_cache {
-        None
-    } else {
-        rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
-            tcx.sess,
-            &name,
-            &[("o", &tmp_file)],
-        )
-    };
+    prof.artifact_size("object_file", &*name, file.metadata().unwrap().len());
 
-    ModuleCodegenResult(
-        CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None },
-        work_product,
-    )
+    Ok(CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None })
 }
 
 fn reuse_workproduct_for_cgu(
     tcx: TyCtxt<'_>,
     cgu: &CodegenUnit<'_>,
-    work_products: &mut FxHashMap<WorkProductId, WorkProduct>,
-) -> CompiledModule {
+) -> Result<ModuleCodegenResult, String> {
     let work_product = cgu.previous_work_product(tcx);
-    let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str()));
-    let source_file = rustc_incremental::in_incr_comp_dir_sess(
+    let obj_out_regular =
+        tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str()));
+    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"),
     );
-    if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) {
-        tcx.sess.err(&format!(
+
+    if let Err(err) = rustc_fs_util::link_or_copy(&source_file_regular, &obj_out_regular) {
+        return Err(format!(
             "unable to copy {} to {}: {}",
-            source_file.display(),
-            obj_out.display(),
+            source_file_regular.display(),
+            obj_out_regular.display(),
             err
         ));
     }
+    let obj_out_global_asm =
+        crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm");
+    let has_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);
+        if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm)
+        {
+            return Err(format!(
+                "unable to copy {} to {}: {}",
+                source_file_regular.display(),
+                obj_out_regular.display(),
+                err
+            ));
+        }
+        true
+    } else {
+        false
+    };
 
-    work_products.insert(cgu.work_product_id(), work_product);
-
-    CompiledModule {
-        name: cgu.name().to_string(),
-        kind: ModuleKind::Regular,
-        object: Some(obj_out),
-        dwarf_object: None,
-        bytecode: None,
-    }
+    Ok(ModuleCodegenResult {
+        module_regular: CompiledModule {
+            name: cgu.name().to_string(),
+            kind: ModuleKind::Regular,
+            object: Some(obj_out_regular),
+            dwarf_object: None,
+            bytecode: None,
+        },
+        module_global_asm: if has_global_asm {
+            Some(CompiledModule {
+                name: cgu.name().to_string(),
+                kind: ModuleKind::Regular,
+                object: Some(obj_out_global_asm),
+                dwarf_object: None,
+                bytecode: None,
+            })
+        } else {
+            None
+        },
+        existing_work_product: Some((cgu.work_product_id(), work_product)),
+    })
 }
 
 fn module_codegen(
     tcx: TyCtxt<'_>,
-    (backend_config, cgu_name): (BackendConfig, rustc_span::Symbol),
-) -> ModuleCodegenResult {
-    let cgu = tcx.codegen_unit(cgu_name);
-    let mono_items = cgu.items_in_deterministic_order(tcx);
-
-    let isa = crate::build_isa(tcx.sess, &backend_config);
-    let mut module = make_module(tcx.sess, isa, cgu_name.as_str().to_string());
-
-    let mut cx = crate::CodegenCx::new(
-        tcx,
-        backend_config.clone(),
-        module.isa(),
-        tcx.sess.opts.debuginfo != DebugInfo::None,
-        cgu_name,
-    );
-    super::predefine_mono_items(tcx, &mut module, &mono_items);
-    for (mono_item, _) in mono_items {
-        match mono_item {
-            MonoItem::Fn(inst) => {
-                cx.tcx
-                    .sess
-                    .time("codegen fn", || crate::base::codegen_fn(&mut cx, &mut module, inst));
-            }
-            MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id),
-            MonoItem::GlobalAsm(item_id) => {
-                let item = cx.tcx.hir().item(item_id);
-                if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
-                    if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
-                        cx.global_asm.push_str("\n.intel_syntax noprefix\n");
-                    } else {
-                        cx.global_asm.push_str("\n.att_syntax\n");
-                    }
-                    for piece in asm.template {
-                        match *piece {
-                            InlineAsmTemplatePiece::String(ref s) => cx.global_asm.push_str(s),
-                            InlineAsmTemplatePiece::Placeholder { .. } => todo!(),
-                        }
-                    }
-                    cx.global_asm.push_str("\n.att_syntax\n\n");
-                } else {
-                    bug!("Expected GlobalAsm found {:?}", item);
+    (backend_config, global_asm_config, cgu_name, token): (
+        BackendConfig,
+        Arc<GlobalAsmConfig>,
+        rustc_span::Symbol,
+        ConcurrencyLimiterToken,
+    ),
+) -> OngoingModuleCodegen {
+    let (cgu_name, mut cx, mut module, codegened_functions) = tcx.sess.time("codegen cgu", || {
+        let cgu = tcx.codegen_unit(cgu_name);
+        let mono_items = cgu.items_in_deterministic_order(tcx);
+
+        let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string());
+
+        let mut cx = crate::CodegenCx::new(
+            tcx,
+            backend_config.clone(),
+            module.isa(),
+            tcx.sess.opts.debuginfo != DebugInfo::None,
+            cgu_name,
+        );
+        super::predefine_mono_items(tcx, &mut module, &mono_items);
+        let mut codegened_functions = vec![];
+        for (mono_item, _) in mono_items {
+            match mono_item {
+                MonoItem::Fn(inst) => {
+                    tcx.sess.time("codegen fn", || {
+                        let codegened_function = crate::base::codegen_fn(
+                            tcx,
+                            &mut cx,
+                            Function::new(),
+                            &mut module,
+                            inst,
+                        );
+                        codegened_functions.push(codegened_function);
+                    });
+                }
+                MonoItem::Static(def_id) => {
+                    crate::constant::codegen_static(tcx, &mut module, def_id)
+                }
+                MonoItem::GlobalAsm(item_id) => {
+                    crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id);
                 }
             }
         }
-    }
-    crate::main_shim::maybe_create_entry_wrapper(
-        tcx,
-        &mut module,
-        &mut cx.unwind_context,
-        false,
-        cgu.is_primary(),
-    );
-
-    let debug_context = cx.debug_context;
-    let unwind_context = cx.unwind_context;
-    let codegen_result = tcx.sess.time("write object file", || {
-        emit_module(
+        crate::main_shim::maybe_create_entry_wrapper(
             tcx,
-            &backend_config,
-            cgu.name().as_str().to_string(),
-            ModuleKind::Regular,
-            module,
-            debug_context,
-            unwind_context,
-        )
+            &mut module,
+            &mut cx.unwind_context,
+            false,
+            cgu.is_primary(),
+        );
+
+        let cgu_name = cgu.name().as_str().to_owned();
+
+        (cgu_name, cx, module, codegened_functions)
     });
 
-    codegen_global_asm(tcx, cgu.name().as_str(), &cx.global_asm);
+    OngoingModuleCodegen::Async(std::thread::spawn(move || {
+        cx.profiler.clone().verbose_generic_activity("compile functions").run(|| {
+            let mut cached_context = Context::new();
+            for codegened_func in codegened_functions {
+                crate::base::compile_fn(&mut cx, &mut cached_context, &mut module, codegened_func);
+            }
+        });
 
-    codegen_result
+        let global_asm_object_file =
+            cx.profiler.verbose_generic_activity("compile assembly").run(|| {
+                crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)
+            })?;
+
+        let codegen_result = cx.profiler.verbose_generic_activity("write object file").run(|| {
+            emit_cgu(
+                &global_asm_config.output_filenames,
+                &cx.profiler,
+                cgu_name,
+                module,
+                cx.debug_context,
+                cx.unwind_context,
+                global_asm_object_file,
+            )
+        });
+        std::mem::drop(token);
+        codegen_result
+    }))
 }
 
 pub(crate) fn run_aot(
@@ -189,9 +342,7 @@ pub(crate) fn run_aot(
     backend_config: BackendConfig,
     metadata: EncodedMetadata,
     need_metadata_module: bool,
-) -> Box<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)> {
-    let mut work_products = FxHashMap::default();
-
+) -> Box<OngoingCodegen> {
     let cgus = if tcx.sess.opts.output_types.should_codegen() {
         tcx.collect_and_partition_mono_items(()).1
     } else {
@@ -206,62 +357,69 @@ pub(crate) fn run_aot(
         }
     }
 
+    let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx));
+
+    let mut concurrency_limiter = ConcurrencyLimiter::new(tcx.sess, cgus.len());
+
     let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || {
         cgus.iter()
             .map(|cgu| {
-                let cgu_reuse = determine_cgu_reuse(tcx, cgu);
+                let cgu_reuse = if backend_config.disable_incr_cache {
+                    CguReuse::No
+                } else {
+                    determine_cgu_reuse(tcx, cgu)
+                };
                 tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse);
 
                 match cgu_reuse {
-                    _ if backend_config.disable_incr_cache => {}
-                    CguReuse::No => {}
-                    CguReuse::PreLto => {
-                        return reuse_workproduct_for_cgu(tcx, &*cgu, &mut work_products);
+                    CguReuse::No => {
+                        let dep_node = cgu.codegen_dep_node(tcx);
+                        tcx.dep_graph
+                            .with_task(
+                                dep_node,
+                                tcx,
+                                (
+                                    backend_config.clone(),
+                                    global_asm_config.clone(),
+                                    cgu.name(),
+                                    concurrency_limiter.acquire(),
+                                ),
+                                module_codegen,
+                                Some(rustc_middle::dep_graph::hash_result),
+                            )
+                            .0
+                    }
+                    CguReuse::PreLto => unreachable!(),
+                    CguReuse::PostLto => {
+                        concurrency_limiter.job_already_done();
+                        OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, &*cgu))
                     }
-                    CguReuse::PostLto => unreachable!(),
-                }
-
-                let dep_node = cgu.codegen_dep_node(tcx);
-                let (ModuleCodegenResult(module, work_product), _) = tcx.dep_graph.with_task(
-                    dep_node,
-                    tcx,
-                    (backend_config.clone(), cgu.name()),
-                    module_codegen,
-                    Some(rustc_middle::dep_graph::hash_result),
-                );
-
-                if let Some((id, product)) = work_product {
-                    work_products.insert(id, product);
                 }
-
-                module
             })
             .collect::<Vec<_>>()
     });
 
     tcx.sess.abort_if_errors();
 
-    let isa = crate::build_isa(tcx.sess, &backend_config);
-    let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string());
-    assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type());
+    let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string());
     let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true);
     let created_alloc_shim =
         crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context);
 
     let allocator_module = if created_alloc_shim {
-        let ModuleCodegenResult(module, work_product) = emit_module(
-            tcx,
-            &backend_config,
-            "allocator_shim".to_string(),
+        let mut product = allocator_module.finish();
+        allocator_unwind_context.emit(&mut product);
+
+        match emit_module(
+            tcx.output_filenames(()),
+            &tcx.sess.prof,
+            product.object,
             ModuleKind::Allocator,
-            allocator_module,
-            None,
-            allocator_unwind_context,
-        );
-        if let Some((id, product)) = work_product {
-            work_products.insert(id, product);
+            "allocator_shim".to_owned(),
+        ) {
+            Ok(allocator_module) => Some(allocator_module),
+            Err(err) => tcx.sess.fatal(err),
         }
-        Some(module)
     } else {
         None
     };
@@ -308,102 +466,14 @@ pub(crate) fn run_aot(
     }
     .to_owned();
 
-    Box::new((
-        CodegenResults {
-            modules,
-            allocator_module,
-            metadata_module,
-            metadata,
-            crate_info: CrateInfo::new(tcx, target_cpu),
-        },
-        work_products,
-    ))
-}
-
-fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) {
-    use std::io::Write;
-    use std::process::{Command, Stdio};
-
-    if global_asm.is_empty() {
-        return;
-    }
-
-    if cfg!(not(feature = "inline_asm"))
-        || tcx.sess.target.is_like_osx
-        || tcx.sess.target.is_like_windows
-    {
-        if global_asm.contains("__rust_probestack") {
-            return;
-        }
-
-        // FIXME fix linker error on macOS
-        if cfg!(not(feature = "inline_asm")) {
-            tcx.sess.fatal(
-                "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift",
-            );
-        } else {
-            tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows");
-        }
-    }
-
-    let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as");
-    let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld");
-
-    // Remove all LLVM style comments
-    let global_asm = global_asm
-        .lines()
-        .map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line })
-        .collect::<Vec<_>>()
-        .join("\n");
-
-    let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name));
-
-    // Assemble `global_asm`
-    let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm");
-    let mut child = Command::new(assembler)
-        .arg("-o")
-        .arg(&global_asm_object_file)
-        .stdin(Stdio::piped())
-        .spawn()
-        .expect("Failed to spawn `as`.");
-    child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
-    let status = child.wait().expect("Failed to wait for `as`.");
-    if !status.success() {
-        tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm));
-    }
-
-    // Link the global asm and main object file together
-    let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main");
-    std::fs::rename(&output_object_file, &main_object_file).unwrap();
-    let status = Command::new(linker)
-        .arg("-r") // Create a new object file
-        .arg("-o")
-        .arg(output_object_file)
-        .arg(&main_object_file)
-        .arg(&global_asm_object_file)
-        .status()
-        .unwrap();
-    if !status.success() {
-        tcx.sess.fatal(&format!(
-            "Failed to link `{}` and `{}` together",
-            main_object_file.display(),
-            global_asm_object_file.display(),
-        ));
-    }
-
-    std::fs::remove_file(global_asm_object_file).unwrap();
-    std::fs::remove_file(main_object_file).unwrap();
-}
-
-fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf {
-    let mut new_filename = path.file_stem().unwrap().to_owned();
-    new_filename.push(postfix);
-    if let Some(extension) = path.extension() {
-        new_filename.push(".");
-        new_filename.push(extension);
-    }
-    path.set_file_name(new_filename);
-    path
+    Box::new(OngoingCodegen {
+        modules,
+        allocator_module,
+        metadata_module,
+        metadata,
+        crate_info: CrateInfo::new(tcx, target_cpu),
+        concurrency_limiter,
+    })
 }
 
 // Adapted from https://github.com/rust-lang/rust/blob/303d8aff6092709edd4dbd35b1c88e9aa40bf6d8/src/librustc_codegen_ssa/base.rs#L922-L953
@@ -432,5 +502,5 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR
         cgu.name()
     );
 
-    if tcx.try_mark_green(&dep_node) { CguReuse::PreLto } else { CguReuse::No }
+    if tcx.try_mark_green(&dep_node) { CguReuse::PostLto } else { CguReuse::No }
 }
index a56a91000596c226441defac6acfdee86a814fe5..0e77e4004c0bb5d0ef4c814c9003fa114c1b51d1 100644 (file)
@@ -61,11 +61,11 @@ fn send(self) -> Result<(), mpsc::SendError<UnsafeMessage>> {
     }
 }
 
-fn create_jit_module<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn create_jit_module(
+    tcx: TyCtxt<'_>,
     backend_config: &BackendConfig,
     hotswap: bool,
-) -> (JITModule, CodegenCx<'tcx>) {
+) -> (JITModule, CodegenCx) {
     let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
     let imported_symbols = load_imported_symbols_for_jit(tcx.sess, crate_info);
 
@@ -111,6 +111,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
         &backend_config,
         matches!(backend_config.codegen_mode, CodegenMode::JitLazy),
     );
+    let mut cached_context = Context::new();
 
     let (_, cgus) = tcx.collect_and_partition_mono_items(());
     let mono_items = cgus
@@ -128,11 +129,19 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
                 MonoItem::Fn(inst) => match backend_config.codegen_mode {
                     CodegenMode::Aot => unreachable!(),
                     CodegenMode::Jit => {
-                        cx.tcx.sess.time("codegen fn", || {
-                            crate::base::codegen_fn(&mut cx, &mut jit_module, inst)
+                        tcx.sess.time("codegen fn", || {
+                            crate::base::codegen_and_compile_fn(
+                                tcx,
+                                &mut cx,
+                                &mut cached_context,
+                                &mut jit_module,
+                                inst,
+                            )
                         });
                     }
-                    CodegenMode::JitLazy => codegen_shim(&mut cx, &mut jit_module, inst),
+                    CodegenMode::JitLazy => {
+                        codegen_shim(tcx, &mut cx, &mut cached_context, &mut jit_module, inst)
+                    }
                 },
                 MonoItem::Static(def_id) => {
                     crate::constant::codegen_static(tcx, &mut jit_module, def_id);
@@ -259,7 +268,15 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
                 false,
                 Symbol::intern("dummy_cgu_name"),
             );
-            tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, jit_module, instance));
+            tcx.sess.time("codegen fn", || {
+                crate::base::codegen_and_compile_fn(
+                    tcx,
+                    &mut cx,
+                    &mut Context::new(),
+                    jit_module,
+                    instance,
+                )
+            });
 
             assert!(cx.global_asm.is_empty());
             jit_module.finalize_definitions();
@@ -334,9 +351,13 @@ fn load_imported_symbols_for_jit(
     imported_symbols
 }
 
-fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: Instance<'tcx>) {
-    let tcx = cx.tcx;
-
+fn codegen_shim<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    cx: &mut CodegenCx,
+    cached_context: &mut Context,
+    module: &mut JITModule,
+    inst: Instance<'tcx>,
+) {
     let pointer_type = module.target_config().pointer_type();
 
     let name = tcx.symbol_name(inst).name;
@@ -357,8 +378,9 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
         )
         .unwrap();
 
-    cx.cached_context.clear();
-    let trampoline = &mut cx.cached_context.func;
+    let context = cached_context;
+    context.clear();
+    let trampoline = &mut context.func;
     trampoline.signature = sig.clone();
 
     let mut builder_ctx = FunctionBuilderContext::new();
@@ -381,5 +403,6 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In
     let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
     trampoline_builder.ins().return_(&ret_vals);
 
-    module.define_function(func_id, &mut cx.cached_context).unwrap();
+    module.define_function(func_id, context).unwrap();
+    cx.unwind_context.add_function(func_id, context, module.isa());
 }
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
new file mode 100644 (file)
index 0000000..dcbcaba
--- /dev/null
@@ -0,0 +1,114 @@
+//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
+//! standalone executable.
+
+use std::io::Write;
+use std::path::PathBuf;
+use std::process::{Command, Stdio};
+use std::sync::Arc;
+
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_hir::ItemId;
+use rustc_session::config::{OutputFilenames, OutputType};
+
+use crate::prelude::*;
+
+pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
+    let item = tcx.hir().item(item_id);
+    if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
+        if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
+            global_asm.push_str("\n.intel_syntax noprefix\n");
+        } else {
+            global_asm.push_str("\n.att_syntax\n");
+        }
+        for piece in asm.template {
+            match *piece {
+                InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s),
+                InlineAsmTemplatePiece::Placeholder { .. } => todo!(),
+            }
+        }
+        global_asm.push_str("\n.att_syntax\n\n");
+    } else {
+        bug!("Expected GlobalAsm found {:?}", item);
+    }
+}
+
+#[derive(Debug)]
+pub(crate) struct GlobalAsmConfig {
+    asm_enabled: bool,
+    assembler: PathBuf,
+    pub(crate) output_filenames: Arc<OutputFilenames>,
+}
+
+impl GlobalAsmConfig {
+    pub(crate) fn new(tcx: TyCtxt<'_>) -> Self {
+        let asm_enabled = cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows;
+
+        GlobalAsmConfig {
+            asm_enabled,
+            assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"),
+            output_filenames: tcx.output_filenames(()).clone(),
+        }
+    }
+}
+
+pub(crate) fn compile_global_asm(
+    config: &GlobalAsmConfig,
+    cgu_name: &str,
+    global_asm: &str,
+) -> Result<Option<PathBuf>, String> {
+    if global_asm.is_empty() {
+        return Ok(None);
+    }
+
+    if !config.asm_enabled {
+        if global_asm.contains("__rust_probestack") {
+            return Ok(None);
+        }
+
+        // FIXME fix linker error on macOS
+        if cfg!(not(feature = "inline_asm")) {
+            return Err(
+                "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift"
+                    .to_owned(),
+            );
+        } else {
+            return Err("asm! and global_asm! are not yet supported on Windows".to_owned());
+        }
+    }
+
+    // Remove all LLVM style comments
+    let global_asm = global_asm
+        .lines()
+        .map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line })
+        .collect::<Vec<_>>()
+        .join("\n");
+
+    let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
+
+    // Assemble `global_asm`
+    let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm");
+    let mut child = Command::new(&config.assembler)
+        .arg("-o")
+        .arg(&global_asm_object_file)
+        .stdin(Stdio::piped())
+        .spawn()
+        .expect("Failed to spawn `as`.");
+    child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
+    let status = child.wait().expect("Failed to wait for `as`.");
+    if !status.success() {
+        return Err(format!("Failed to assemble `{}`", global_asm));
+    }
+
+    Ok(Some(global_asm_object_file))
+}
+
+pub(crate) fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf {
+    let mut new_filename = path.file_stem().unwrap().to_owned();
+    new_filename.push(postfix);
+    if let Some(extension) = path.extension() {
+        new_filename.push(".");
+        new_filename.push(extension);
+    }
+    path.set_file_name(new_filename);
+    path
+}
index 241de5e36530c8bbddb1bce99b2f4f2fe39fa23b..8b3d475cb1802dcc1662145ca0cc4a1c99a8119c 100644 (file)
@@ -15,15 +15,19 @@ pub(crate) fn codegen_inline_asm<'tcx>(
     template: &[InlineAsmTemplatePiece],
     operands: &[InlineAsmOperand<'tcx>],
     options: InlineAsmOptions,
+    destination: Option<mir::BasicBlock>,
 ) {
     // FIXME add .eh_frame unwind info directives
 
     if !template.is_empty() {
+        // Used by panic_abort
         if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) {
-            let true_ = fx.bcx.ins().iconst(types::I32, 1);
-            fx.bcx.ins().trapnz(true_, TrapCode::User(1));
+            fx.bcx.ins().trap(TrapCode::User(1));
             return;
-        } else if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string())
+        }
+
+        // Used by stdarch
+        if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string())
             && matches!(
                 template[1],
                 InlineAsmTemplatePiece::Placeholder {
@@ -47,51 +51,46 @@ pub(crate) fn codegen_inline_asm<'tcx>(
         {
             assert_eq!(operands.len(), 4);
             let (leaf, eax_place) = match operands[1] {
-                InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => {
-                    assert_eq!(
-                        reg,
-                        InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax))
-                    );
-                    (
-                        crate::base::codegen_operand(fx, in_value).load_scalar(fx),
-                        crate::base::codegen_place(fx, out_place.unwrap()),
-                    )
-                }
+                InlineAsmOperand::InOut {
+                    reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
+                    late: true,
+                    ref in_value,
+                    out_place: Some(out_place),
+                } => (
+                    crate::base::codegen_operand(fx, in_value).load_scalar(fx),
+                    crate::base::codegen_place(fx, out_place),
+                ),
                 _ => unreachable!(),
             };
             let ebx_place = match operands[0] {
-                InlineAsmOperand::Out { reg, late: true, place } => {
-                    assert_eq!(
-                        reg,
+                InlineAsmOperand::Out {
+                    reg:
                         InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86(
-                            X86InlineAsmRegClass::reg
-                        ))
-                    );
-                    crate::base::codegen_place(fx, place.unwrap())
-                }
+                            X86InlineAsmRegClass::reg,
+                        )),
+                    late: true,
+                    place: Some(place),
+                } => crate::base::codegen_place(fx, place),
                 _ => unreachable!(),
             };
             let (sub_leaf, ecx_place) = match operands[2] {
-                InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => {
-                    assert_eq!(
-                        reg,
-                        InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx))
-                    );
-                    (
-                        crate::base::codegen_operand(fx, in_value).load_scalar(fx),
-                        crate::base::codegen_place(fx, out_place.unwrap()),
-                    )
-                }
+                InlineAsmOperand::InOut {
+                    reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
+                    late: true,
+                    ref in_value,
+                    out_place: Some(out_place),
+                } => (
+                    crate::base::codegen_operand(fx, in_value).load_scalar(fx),
+                    crate::base::codegen_place(fx, out_place),
+                ),
                 _ => unreachable!(),
             };
             let edx_place = match operands[3] {
-                InlineAsmOperand::Out { reg, late: true, place } => {
-                    assert_eq!(
-                        reg,
-                        InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx))
-                    );
-                    crate::base::codegen_place(fx, place.unwrap())
-                }
+                InlineAsmOperand::Out {
+                    reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
+                    late: true,
+                    place: Some(place),
+                } => crate::base::codegen_place(fx, place),
                 _ => unreachable!(),
             };
 
@@ -101,12 +100,99 @@ pub(crate) fn codegen_inline_asm<'tcx>(
             ebx_place.write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.tcx.types.u32)));
             ecx_place.write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.tcx.types.u32)));
             edx_place.write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.tcx.types.u32)));
+            let destination_block = fx.get_block(destination.unwrap());
+            fx.bcx.ins().jump(destination_block, &[]);
             return;
-        } else if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") {
+        }
+
+        // Used by compiler-builtins
+        if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") {
             // ___chkstk, ___chkstk_ms and __alloca are only used on Windows
             crate::trap::trap_unimplemented(fx, "Stack probes are not supported");
+            return;
         } else if fx.tcx.symbol_name(fx.instance).name == "__alloca" {
             crate::trap::trap_unimplemented(fx, "Alloca is not supported");
+            return;
+        }
+
+        // Used by measureme
+        if template[0] == InlineAsmTemplatePiece::String("xor %eax, %eax".to_string())
+            && template[1] == InlineAsmTemplatePiece::String("\n".to_string())
+            && template[2] == InlineAsmTemplatePiece::String("mov %rbx, ".to_string())
+            && matches!(
+                template[3],
+                InlineAsmTemplatePiece::Placeholder {
+                    operand_idx: 0,
+                    modifier: Some('r'),
+                    span: _
+                }
+            )
+            && template[4] == InlineAsmTemplatePiece::String("\n".to_string())
+            && template[5] == InlineAsmTemplatePiece::String("cpuid".to_string())
+            && template[6] == InlineAsmTemplatePiece::String("\n".to_string())
+            && template[7] == InlineAsmTemplatePiece::String("mov ".to_string())
+            && matches!(
+                template[8],
+                InlineAsmTemplatePiece::Placeholder {
+                    operand_idx: 0,
+                    modifier: Some('r'),
+                    span: _
+                }
+            )
+            && template[9] == InlineAsmTemplatePiece::String(", %rbx".to_string())
+        {
+            let destination_block = fx.get_block(destination.unwrap());
+            fx.bcx.ins().jump(destination_block, &[]);
+            return;
+        } else if template[0] == InlineAsmTemplatePiece::String("rdpmc".to_string()) {
+            // Return zero dummy values for all performance counters
+            match operands[0] {
+                InlineAsmOperand::In {
+                    reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
+                    value: _,
+                } => {}
+                _ => unreachable!(),
+            };
+            let lo = match operands[1] {
+                InlineAsmOperand::Out {
+                    reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
+                    late: true,
+                    place: Some(place),
+                } => crate::base::codegen_place(fx, place),
+                _ => unreachable!(),
+            };
+            let hi = match operands[2] {
+                InlineAsmOperand::Out {
+                    reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
+                    late: true,
+                    place: Some(place),
+                } => crate::base::codegen_place(fx, place),
+                _ => unreachable!(),
+            };
+
+            let u32_layout = fx.layout_of(fx.tcx.types.u32);
+            let zero = fx.bcx.ins().iconst(types::I32, 0);
+            lo.write_cvalue(fx, CValue::by_val(zero, u32_layout));
+            hi.write_cvalue(fx, CValue::by_val(zero, u32_layout));
+
+            let destination_block = fx.get_block(destination.unwrap());
+            fx.bcx.ins().jump(destination_block, &[]);
+            return;
+        } else if template[0] == InlineAsmTemplatePiece::String("lock xadd ".to_string())
+            && matches!(
+                template[1],
+                InlineAsmTemplatePiece::Placeholder { operand_idx: 1, modifier: None, span: _ }
+            )
+            && template[2] == InlineAsmTemplatePiece::String(", (".to_string())
+            && matches!(
+                template[3],
+                InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ }
+            )
+            && template[4] == InlineAsmTemplatePiece::String(")".to_string())
+        {
+            let destination_block = fx.get_block(destination.unwrap());
+            fx.bcx.ins().jump(destination_block, &[]);
+            return;
         }
     }
 
@@ -175,6 +261,16 @@ pub(crate) fn codegen_inline_asm<'tcx>(
     }
 
     call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs);
+
+    match destination {
+        Some(destination) => {
+            let destination_block = fx.get_block(destination);
+            fx.bcx.ins().jump(destination_block, &[]);
+        }
+        None => {
+            fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
+        }
+    }
 }
 
 struct InlineAssemblyGenerator<'a, 'tcx> {
@@ -637,7 +733,7 @@ fn call_inline_asm<'tcx>(
     inputs: Vec<(Size, Value)>,
     outputs: Vec<(Size, CPlace<'tcx>)>,
 ) {
-    let stack_slot = fx.bcx.func.create_stack_slot(StackSlotData {
+    let stack_slot = fx.bcx.func.create_sized_stack_slot(StackSlotData {
         kind: StackSlotKind::ExplicitSlot,
         size: u32::try_from(slot_size.bytes()).unwrap(),
     });
index d02dfd93c3ee3c533aa2b27a601306a59a757c6d..5120b89c4e8b0b28dba764aac67ed47cbfac3f1a 100644 (file)
@@ -62,7 +62,7 @@ pub(crate) fn codegen_cpuid_call<'tcx>(
     fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]);
 
     fx.bcx.switch_to_block(unsupported_leaf);
-    crate::trap::trap_unreachable(
+    crate::trap::trap_unimplemented(
         fx,
         "__cpuid_count arch intrinsic doesn't yet support specified leaf",
     );
index 869670c8cfac7ec41e50df30dce1954f49ce915f..a799dca938e21bb4ef79027aaf408263aa961389 100644 (file)
@@ -139,6 +139,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
                 .sess
                 .warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
             crate::trap::trap_unimplemented(fx, intrinsic);
+            return;
         }
     }
 
index b2a83e1d4ebc96c57da441aff4e044123a5faeed..ef3d5ccea8a2406d42d1cae971cd9a1658a94473 100644 (file)
@@ -44,7 +44,7 @@ fn report_atomic_type_validation_error<'tcx>(
         ),
     );
     // Prevent verifier error
-    crate::trap::trap_unreachable(fx, "compilation should not have succeeded");
+    fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
 }
 
 pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option<Type> {
@@ -53,7 +53,7 @@ pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx
         _ => unreachable!(),
     };
 
-    match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) {
+    match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) {
         // Cranelift currently only implements icmp for 128bit vectors.
         Some(vector_ty) if vector_ty.bits() == 128 => Some(vector_ty),
         _ => None,
@@ -301,7 +301,44 @@ fn codegen_float_intrinsic_call<'tcx>(
         _ => unreachable!(),
     };
 
-    let res = fx.easy_call(name, &args, ty);
+    let layout = fx.layout_of(ty);
+    let res = match intrinsic {
+        sym::fmaf32 | sym::fmaf64 => {
+            let a = args[0].load_scalar(fx);
+            let b = args[1].load_scalar(fx);
+            let c = args[2].load_scalar(fx);
+            CValue::by_val(fx.bcx.ins().fma(a, b, c), layout)
+        }
+        sym::copysignf32 | sym::copysignf64 => {
+            let a = args[0].load_scalar(fx);
+            let b = args[1].load_scalar(fx);
+            CValue::by_val(fx.bcx.ins().fcopysign(a, b), layout)
+        }
+        sym::fabsf32
+        | sym::fabsf64
+        | sym::floorf32
+        | sym::floorf64
+        | sym::ceilf32
+        | sym::ceilf64
+        | sym::truncf32
+        | sym::truncf64 => {
+            let a = args[0].load_scalar(fx);
+
+            let val = match intrinsic {
+                sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(a),
+                sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(a),
+                sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(a),
+                sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(a),
+                _ => unreachable!(),
+            };
+
+            CValue::by_val(val, layout)
+        }
+        // These intrinsics aren't supported natively by Cranelift.
+        // Lower them to a libcall.
+        _ => fx.easy_call(name, &args, ty),
+    };
+
     ret.write_cvalue(fx, res);
 
     true
@@ -818,8 +855,6 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
                     if fx.tcx.is_compiler_builtins(LOCAL_CRATE) {
                         // special case for compiler-builtins to avoid having to patch it
                         crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported");
-                        let ret_block = fx.get_block(destination.unwrap());
-                        fx.bcx.ins().jump(ret_block, &[]);
                         return;
                     } else {
                         fx.tcx
@@ -851,8 +886,6 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
                     if fx.tcx.is_compiler_builtins(LOCAL_CRATE) {
                         // special case for compiler-builtins to avoid having to patch it
                         crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported");
-                        let ret_block = fx.get_block(destination.unwrap());
-                        fx.bcx.ins().jump(ret_block, &[]);
                         return;
                     } else {
                         fx.tcx
index 30e3d112594a6d60beb75bb8459ffeb485d1ec6d..a32b413d45f938d093f7f4efcae7e3a8fc2a240a 100644 (file)
@@ -14,7 +14,7 @@ fn report_simd_type_validation_error(
 ) {
     fx.tcx.sess.span_err(span, &format!("invalid monomorphization of `{}` intrinsic: expected SIMD input type, found non-SIMD `{}`", intrinsic, ty));
     // Prevent verifier error
-    crate::trap::trap_unreachable(fx, "compilation should not have succeeded");
+    fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
 }
 
 pub(super) fn codegen_simd_intrinsic_call<'tcx>(
@@ -157,7 +157,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                             ),
                         );
                         // Prevent verifier error
-                        crate::trap::trap_unreachable(fx, "compilation should not have succeeded");
+                        fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
                         return;
                     }
                 }
@@ -274,12 +274,17 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 idx_const
             } else {
                 fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant");
-                let res = crate::trap::trap_unimplemented_ret_value(
+                let trap_block = fx.bcx.create_block();
+                let dummy_block = fx.bcx.create_block();
+                let true_ = fx.bcx.ins().iconst(types::I8, 1);
+                fx.bcx.ins().brnz(true_, trap_block, &[]);
+                fx.bcx.ins().jump(dummy_block, &[]);
+                fx.bcx.switch_to_block(trap_block);
+                crate::trap::trap_unimplemented(
                     fx,
-                    ret.layout(),
                     "Index argument for `simd_extract` is not a constant",
                 );
-                ret.write_cvalue(fx, res);
+                fx.bcx.switch_to_block(dummy_block);
                 return;
             };
 
@@ -392,21 +397,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
 
             let layout = a.layout();
             let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
+            let res_lane_layout = fx.layout_of(lane_ty);
 
             for lane in 0..lane_count {
-                let a_lane = a.value_lane(fx, lane);
-                let b_lane = b.value_lane(fx, lane);
-                let c_lane = c.value_lane(fx, lane);
+                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+                let b_lane = b.value_lane(fx, lane).load_scalar(fx);
+                let c_lane = c.value_lane(fx, lane).load_scalar(fx);
 
-                let res_lane = match lane_ty.kind() {
-                    ty::Float(FloatTy::F32) => {
-                        fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty)
-                    }
-                    ty::Float(FloatTy::F64) => {
-                        fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty)
-                    }
-                    _ => unreachable!(),
-                };
+                let res_lane = fx.bcx.ins().fma(a_lane, b_lane, c_lane);
+                let res_lane = CValue::by_val(res_lane, res_lane_layout);
 
                 ret.place_lane(fx, lane).write_cvalue(fx, res_lane);
             }
index bb0793b1deb2e8e75262648ebc89ab6b1d1e76e5..913414e7618213d99adb63a711ef18412e747695 100644 (file)
@@ -4,6 +4,7 @@
 #![warn(unused_lifetimes)]
 #![warn(unreachable_pub)]
 
+extern crate jobserver;
 #[macro_use]
 extern crate rustc_middle;
 extern crate rustc_ast;
 extern crate rustc_driver;
 
 use std::any::Any;
-use std::cell::Cell;
+use std::cell::{Cell, RefCell};
+use std::sync::Arc;
 
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_codegen_ssa::CodegenResults;
+use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_errors::ErrorGuaranteed;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 mod codegen_i128;
 mod common;
 mod compiler_builtins;
+mod concurrency_limiter;
 mod config;
 mod constant;
 mod debuginfo;
 mod discriminant;
 mod driver;
+mod global_asm;
 mod inline_asm;
 mod intrinsics;
 mod linkage;
@@ -119,19 +124,20 @@ fn drop(&mut self) {
 
 /// 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<'tcx> {
-    tcx: TyCtxt<'tcx>,
+struct CodegenCx {
+    profiler: SelfProfilerRef,
+    output_filenames: Arc<OutputFilenames>,
+    should_write_ir: bool,
     global_asm: String,
     inline_asm_index: Cell<usize>,
-    cached_context: Context,
-    debug_context: Option<DebugContext<'tcx>>,
+    debug_context: Option<DebugContext>,
     unwind_context: UnwindContext,
     cgu_name: Symbol,
 }
 
-impl<'tcx> CodegenCx<'tcx> {
+impl CodegenCx {
     fn new(
-        tcx: TyCtxt<'tcx>,
+        tcx: TyCtxt<'_>,
         backend_config: BackendConfig,
         isa: &dyn TargetIsa,
         debug_info: bool,
@@ -147,10 +153,11 @@ fn new(
             None
         };
         CodegenCx {
-            tcx,
+            profiler: tcx.prof.clone(),
+            output_filenames: tcx.output_filenames(()).clone(),
+            should_write_ir: crate::pretty_clif::should_write_ir(tcx),
             global_asm: String::new(),
             inline_asm_index: Cell::new(0),
-            cached_context: Context::new(),
             debug_context,
             unwind_context,
             cgu_name,
@@ -159,7 +166,7 @@ fn new(
 }
 
 pub struct CraneliftCodegenBackend {
-    pub config: Option<BackendConfig>,
+    pub config: RefCell<Option<BackendConfig>>,
 }
 
 impl CodegenBackend for CraneliftCodegenBackend {
@@ -169,6 +176,13 @@ fn init(&self, sess: &Session) {
             Lto::No | Lto::ThinLocal => {}
             Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."),
         }
+
+        let mut config = self.config.borrow_mut();
+        if config.is_none() {
+            let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args)
+                .unwrap_or_else(|err| sess.fatal(&err));
+            *config = Some(new_config);
+        }
     }
 
     fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> {
@@ -186,15 +200,7 @@ fn codegen_crate(
         need_metadata_module: bool,
     ) -> Box<dyn Any> {
         tcx.sess.abort_if_errors();
-        let config = if let Some(config) = self.config.clone() {
-            config
-        } else {
-            if !tcx.sess.unstable_options() && !tcx.sess.opts.cg.llvm_args.is_empty() {
-                tcx.sess.fatal("`-Z unstable-options` must be passed to allow configuring cg_clif");
-            }
-            BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
-                .unwrap_or_else(|err| tcx.sess.fatal(&err))
-        };
+        let config = self.config.borrow().clone().unwrap();
         match config.codegen_mode {
             CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module),
             CodegenMode::Jit | CodegenMode::JitLazy => {
@@ -210,12 +216,13 @@ fn codegen_crate(
     fn join_codegen(
         &self,
         ongoing_codegen: Box<dyn Any>,
-        _sess: &Session,
+        sess: &Session,
         _outputs: &OutputFilenames,
     ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
-        Ok(*ongoing_codegen
-            .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
-            .unwrap())
+        Ok(ongoing_codegen
+            .downcast::<driver::aot::OngoingCodegen>()
+            .unwrap()
+            .join(sess, self.config.borrow().as_ref().unwrap()))
     }
 
     fn link(
@@ -312,5 +319,5 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
 #[no_mangle]
 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
-    Box::new(CraneliftCodegenBackend { config: None })
+    Box::new(CraneliftCodegenBackend { config: RefCell::new(None) })
 }
index d1f89adb3bb916789436685d774ff220b159ed9f..0df7e82294bd23521b72225d3746116488cac4d3 100644 (file)
@@ -1,20 +1,3 @@
 //! Various optimizations specific to cg_clif
 
-use cranelift_codegen::isa::TargetIsa;
-
-use crate::prelude::*;
-
 pub(crate) mod peephole;
-
-pub(crate) fn optimize_function<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    isa: &dyn TargetIsa,
-    instance: Instance<'tcx>,
-    ctx: &mut Context,
-    clif_comments: &mut crate::pretty_clif::CommentWriter,
-) {
-    // FIXME classify optimizations over opt levels once we have more
-
-    crate::pretty_clif::write_clif_file(tcx, "preopt", isa, instance, &ctx.func, &*clif_comments);
-    crate::base::verify_func(tcx, &*clif_comments, &ctx.func);
-}
index 1d1ec21680e30a7dc981c262b4fc7b172b12a013..a7af162687c34c5cd0fa4ffbea65459779231eb7 100644 (file)
@@ -62,7 +62,7 @@
 };
 
 use rustc_middle::ty::layout::FnAbiOf;
-use rustc_session::config::OutputType;
+use rustc_session::config::{OutputFilenames, OutputType};
 
 use crate::prelude::*;
 
@@ -205,15 +205,11 @@ pub(crate) fn should_write_ir(tcx: TyCtxt<'_>) -> bool {
 }
 
 pub(crate) fn write_ir_file(
-    tcx: TyCtxt<'_>,
-    name: impl FnOnce() -> String,
+    output_filenames: &OutputFilenames,
+    name: &str,
     write: impl FnOnce(&mut dyn Write) -> std::io::Result<()>,
 ) {
-    if !should_write_ir(tcx) {
-        return;
-    }
-
-    let clif_output_dir = tcx.output_filenames(()).with_extension("clif");
+    let clif_output_dir = output_filenames.with_extension("clif");
 
     match std::fs::create_dir(&clif_output_dir) {
         Ok(()) => {}
@@ -221,44 +217,43 @@ pub(crate) fn write_ir_file(
         res @ Err(_) => res.unwrap(),
     }
 
-    let clif_file_name = clif_output_dir.join(name());
+    let clif_file_name = clif_output_dir.join(name);
 
     let res = std::fs::File::create(clif_file_name).and_then(|mut file| write(&mut file));
     if let Err(err) = res {
-        tcx.sess.warn(&format!("error writing ir file: {}", err));
+        // Using early_warn as no Session is available here
+        rustc_session::early_warn(
+            rustc_session::config::ErrorOutputType::default(),
+            &format!("error writing ir file: {}", err),
+        );
     }
 }
 
-pub(crate) fn write_clif_file<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub(crate) fn write_clif_file(
+    output_filenames: &OutputFilenames,
+    symbol_name: &str,
     postfix: &str,
     isa: &dyn cranelift_codegen::isa::TargetIsa,
-    instance: Instance<'tcx>,
     func: &cranelift_codegen::ir::Function,
     mut clif_comments: &CommentWriter,
 ) {
     // FIXME work around filename too long errors
-    write_ir_file(
-        tcx,
-        || format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix),
-        |file| {
-            let mut clif = String::new();
-            cranelift_codegen::write::decorate_function(&mut clif_comments, &mut clif, func)
-                .unwrap();
+    write_ir_file(output_filenames, &format!("{}.{}.clif", symbol_name, postfix), |file| {
+        let mut clif = String::new();
+        cranelift_codegen::write::decorate_function(&mut clif_comments, &mut clif, func).unwrap();
 
-            for flag in isa.flags().iter() {
-                writeln!(file, "set {}", flag)?;
-            }
-            write!(file, "target {}", isa.triple().architecture.to_string())?;
-            for isa_flag in isa.isa_flags().iter() {
-                write!(file, " {}", isa_flag)?;
-            }
-            writeln!(file, "\n")?;
-            writeln!(file)?;
-            file.write_all(clif.as_bytes())?;
-            Ok(())
-        },
-    );
+        for flag in isa.flags().iter() {
+            writeln!(file, "set {}", flag)?;
+        }
+        write!(file, "target {}", isa.triple().architecture.to_string())?;
+        for isa_flag in isa.isa_flags().iter() {
+            write!(file, " {}", isa_flag)?;
+        }
+        writeln!(file, "\n")?;
+        writeln!(file)?;
+        file.write_all(clif.as_bytes())?;
+        Ok(())
+    });
 }
 
 impl fmt::Debug for FunctionCx<'_, '_, '_> {
index f86236ef3eafc6eee6c6a476bb19d2fed1f13ce4..b6b465e1f4e0a808a394c07b68ee0563d1538314 100644 (file)
@@ -8,10 +8,8 @@
 /// Tries to infer the path of a binary for the target toolchain from the linker name.
 pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf {
     let (mut linker, _linker_flavor) = linker_and_flavor(sess);
-    let linker_file_name = linker
-        .file_name()
-        .and_then(|name| name.to_str())
-        .unwrap_or_else(|| sess.fatal("couldn't extract file name from specified linker"));
+    let linker_file_name =
+        linker.file_name().unwrap().to_str().expect("linker filename should be valid UTF-8");
 
     if linker_file_name == "ld.lld" {
         if tool != "ld" {
index 923269c4de9ab8993fcf5e564f0a0a7f2f11dea4..82a2ec579549669afca23f19c1fac2e0eba12936 100644 (file)
@@ -25,33 +25,10 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) {
     fx.bcx.ins().call(puts, &[msg_ptr]);
 }
 
-/// Use this for example when a function call should never return. This will fill the current block,
-/// so you can **not** add instructions to it afterwards.
-///
-/// Trap code: user65535
-pub(crate) fn trap_unreachable(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef<str>) {
-    codegen_print(fx, msg.as_ref());
-    fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
-}
 /// Use this when something is unimplemented, but `libcore` or `libstd` requires it to codegen.
-/// Unlike `trap_unreachable` this will not fill the current block, so you **must** add instructions
-/// to it afterwards.
 ///
 /// Trap code: user65535
 pub(crate) fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef<str>) {
     codegen_print(fx, msg.as_ref());
-    let true_ = fx.bcx.ins().iconst(types::I32, 1);
-    fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
-}
-
-/// Like `trap_unimplemented` but returns a fake value of the specified type.
-///
-/// Trap code: user65535
-pub(crate) fn trap_unimplemented_ret_value<'tcx>(
-    fx: &mut FunctionCx<'_, '_, 'tcx>,
-    dest_layout: TyAndLayout<'tcx>,
-    msg: impl AsRef<str>,
-) -> CValue<'tcx> {
-    trap_unimplemented(fx, msg);
-    CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout)
+    fx.bcx.ins().trap(TrapCode::User(!0));
 }
index 45ae2bd8f07cb1c28003790b49344db68481307d..2ee98546c992a1ec8cce8ccd3c7e2a2fdb9d06a8 100644 (file)
@@ -122,7 +122,7 @@ pub(crate) fn load_scalar(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> Value {
                 let clif_ty = match layout.abi {
                     Abi::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar),
                     Abi::Vector { element, count } => scalar_to_clif_type(fx.tcx, element)
-                        .by(u16::try_from(count).unwrap())
+                        .by(u32::try_from(count).unwrap())
                         .unwrap(),
                     _ => unreachable!("{:?}", layout.ty),
                 };
@@ -330,7 +330,7 @@ pub(crate) fn new_stack_slot(
                 .fatal(&format!("values of type {} are too big to store on the stack", layout.ty));
         }
 
-        let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
+        let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
             kind: StackSlotKind::ExplicitSlot,
             // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
             // specify stack slot alignment.
@@ -472,7 +472,7 @@ fn transmute_value<'tcx>(
                 }
                 _ if src_ty.is_vector() || dst_ty.is_vector() => {
                     // FIXME do something more efficient for transmutes between vectors and integers.
-                    let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
+                    let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
                         kind: StackSlotKind::ExplicitSlot,
                         // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
                         // specify stack slot alignment.
@@ -519,7 +519,7 @@ fn transmute_value<'tcx>(
                 if let ty::Array(element, len) = dst_layout.ty.kind() {
                     // Can only happen for vector types
                     let len =
-                        u16::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap();
+                        u32::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap();
                     let vector_ty = fx.clif_type(*element).unwrap().by(len).unwrap();
 
                     let data = match from.0 {
@@ -614,7 +614,7 @@ fn transmute_value<'tcx>(
                     dst_align,
                     src_align,
                     true,
-                    MemFlags::trusted(),
+                    flags,
                 );
             }
             CValueInner::ByRef(_, Some(_)) => todo!(),
index a10924628bb0eba9350b56f5603ead5b068b75f4..3d929a1d50ce2435307a7834c1fe04c1c73b94bd 100755 (executable)
@@ -1,13 +1,2 @@
 #!/usr/bin/env bash
-set -e
-
-./y.rs build --sysroot none "$@"
-
-rm -r target/out || true
-
-scripts/tests.sh no_sysroot
-
-./y.rs build "$@"
-
-scripts/tests.sh base_sysroot
-scripts/tests.sh extended_sysroot
+exec ./y.rs test