diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index e8897e9ae81..5061010c86c 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -29,7 +29,11 @@ jobs: matrix: include: - os: ubuntu-latest + env: + TARGET_TRIPLE: x86_64-unknown-linux-gnu - os: macos-latest + env: + TARGET_TRIPLE: x86_64-apple-darwin # cross-compile from Linux to Windows using mingw - os: ubuntu-latest env: @@ -112,7 +116,7 @@ jobs: if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' uses: actions/upload-artifact@v2 with: - name: cg_clif-${{ runner.os }} + name: cg_clif-${{ matrix.env.TARGET_TRIPLE }} path: cg_clif.tar.xz - name: Upload prebuilt cg_clif (cross compile) @@ -122,56 +126,89 @@ jobs: name: cg_clif-${{ runner.os }}-cross-x86_64-mingw path: cg_clif.tar.xz - build_windows: - runs-on: windows-latest + windows: + runs-on: ${{ matrix.os }} timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + # Native Windows build with MSVC + - os: windows-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-msvc + # cross-compile from Windows to Windows MinGW + - os: windows-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-gnu + steps: - uses: actions/checkout@v3 - #- name: Cache cargo installed crates - # uses: actions/cache@v2 - # with: - # path: ~/.cargo/bin - # key: ${{ runner.os }}-cargo-installed-crates + - name: Cache cargo installed crates + uses: actions/cache@v2 + with: + path: ~/.cargo/bin + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates - #- name: Cache cargo registry and index - # uses: actions/cache@v2 - # with: - # path: | - # ~/.cargo/registry - # ~/.cargo/git - # key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} + - name: Cache cargo registry and index + uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} - #- name: Cache cargo target dir - # uses: actions/cache@v2 - # with: - # path: target - # key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + - name: Cache cargo target dir + uses: actions/cache@v2 + with: + path: target + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Set MinGW as the default toolchain + if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' + run: rustup set default-host x86_64-pc-windows-gnu - name: Prepare dependencies run: | git config --global user.email "user@example.com" git config --global user.name "User" git config --global core.autocrlf false - rustup set default-host x86_64-pc-windows-gnu rustc y.rs -o y.exe -g ./y.exe prepare + - name: Build without unstable features + env: + TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} + # This is the config rust-lang/rust uses for builds + run: ./y.rs build --no-unstable-features + - name: Build - #name: Test + run: ./y.rs build --sysroot none + + - name: Test run: | # Enable backtraces for easier debugging - #$Env:RUST_BACKTRACE=1 + $Env:RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow - #$Env:COMPILE_RUNS=2 - #$Env:RUN_RUNS=2 + $Env:COMPILE_RUNS=2 + $Env:RUN_RUNS=2 # Enable extra checks - #$Env:CG_CLIF_ENABLE_VERIFIER=1 + $Env:CG_CLIF_ENABLE_VERIFIER=1 + + # WIP Disable some tests + + # This fails due to some weird argument handling by hyperfine, not an actual regression + # more of a build system issue + (Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' | Out-File config.txt + + # This fails with a different output than expected + (Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' | Out-File config.txt - ./y.exe build + ./y.exe test - name: Package prebuilt cg_clif # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs @@ -180,5 +217,5 @@ jobs: - name: Upload prebuilt cg_clif uses: actions/upload-artifact@v2 with: - name: cg_clif-${{ runner.os }} + name: cg_clif-${{ matrix.env.TARGET_TRIPLE }} path: cg_clif.tar diff --git a/compiler/rustc_codegen_cranelift/.gitignore b/compiler/rustc_codegen_cranelift/.gitignore index 6fd3e4443de..fae09592c6a 100644 --- a/compiler/rustc_codegen_cranelift/.gitignore +++ b/compiler/rustc_codegen_cranelift/.gitignore @@ -15,8 +15,4 @@ perf.data.old /build_sysroot/compiler-builtins /build_sysroot/rustc_version /rust -/rand -/regex -/simple-raytracer -/portable-simd -/abi-checker +/download diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json index d88309e412e..13301bf20a5 100644 --- a/compiler/rustc_codegen_cranelift/.vscode/settings.json +++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json @@ -7,7 +7,7 @@ "rust-analyzer.cargo.features": ["unstable-features"], "rust-analyzer.linkedProjects": [ "./Cargo.toml", - //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml", + //"./build_sysroot/sysroot_src/library/std/Cargo.toml", { "roots": [ "./example/mini_core.rs", @@ -36,10 +36,10 @@ ] }, { - "roots": ["./scripts/filter_profile.rs"], + "roots": ["./example/std_example.rs"], "crates": [ { - "root_module": "./scripts/filter_profile.rs", + "root_module": "./example/std_example.rs", "edition": "2018", "deps": [{ "crate": 1, "name": "std" }], "cfg": [], diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index edae7e47157..3fa9d56cd01 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -24,6 +24,12 @@ name = "ar" version = "0.8.0" source = "git+https://github.com/bjorn3/rust-ar.git?branch=do_not_remove_cg_clif_ranlib#de9ab0e56bf3a208381d342aa5b60f9ff2891648" +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "autocfg" version = "1.1.0" @@ -36,6 +42,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + [[package]] name = "byteorder" version = "1.4.3" @@ -50,19 +62,21 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93945adbccc8d731503d3038814a51e8317497c9e205411820348132fa01a358" +checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b482acc9d0d0d1ad3288a90a8150ee648be3dce8dc8c8669ff026f72debdc31" +checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf" dependencies = [ + "arrayvec", + "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", @@ -77,30 +91,30 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9ec188d71e663192ef9048f204e410a7283b609942efc9fcc77da6d496edbb8" +checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad794b1b1c2c7bd9f7b76cfe0f084eaf7753e55d56191c3f7d89e8fa4978b99" +checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e" [[package]] name = "cranelift-entity" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342da0d5056f4119d3c311c4aab2460ceb6ee6e127bb395b76dd2279a09ea7a5" +checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103" [[package]] name = "cranelift-frontend" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfff792f775b07d4d9cfe9f1c767ce755c6cbadda1bbd6db18a1c75ff9f7376a" +checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc" dependencies = [ "cranelift-codegen", "log", @@ -110,15 +124,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d51089478849f2ac8ef60a8a2d5346c8d4abfec0e45ac5b24530ef9f9499e1e" +checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293" [[package]] name = "cranelift-jit" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "095936e41720f86004b4c57ce88e6a13af28646bb3a6fb4afbebd5ae90c50029" +checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015" dependencies = [ "anyhow", "cranelift-codegen", @@ -134,9 +148,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704a1aea4723d97eafe0fb7af110f6f6868b1ac95f5380bbc9adb2a3b8cf97e8" +checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49" dependencies = [ "anyhow", "cranelift-codegen", @@ -144,9 +158,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "885debe62f2078638d6585f54c9f05f5c2008f22ce5a2a9100ada785fc065dbd" +checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4" dependencies = [ "cranelift-codegen", "libc", @@ -155,9 +169,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.87.0" +version = "0.88.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac1310cf1081ae8eca916c92cd163b977c77cab6e831fa812273c26ff921816" +checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b" dependencies = [ "anyhow", "cranelift-codegen", @@ -232,9 +246,9 @@ checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" [[package]] name = "libloading" -version = "0.6.7" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" dependencies = [ "cfg-if", "winapi", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index e7c34274854..09cf5b4a1ed 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,19 +8,19 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -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" +cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] } +cranelift-frontend = "0.88.1" +cranelift-module = "0.88.1" +cranelift-native = "0.88.1" +cranelift-jit = { version = "0.88.1", optional = true } +cranelift-object = "0.88.1" target-lexicon = "0.12.0" gimli = { version = "0.26.0", default-features = false, features = ["write"]} object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } indexmap = "1.9.1" -libloading = { version = "0.6.0", optional = true } +libloading = { version = "0.7.3", optional = true } once_cell = "1.10.0" smallvec = "1.8.1" diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock index 6c5043bb6f8..f6a9cb67290 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock @@ -55,10 +55,20 @@ dependencies = [ ] [[package]] -name = "compiler_builtins" -version = "0.1.79" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "compiler_builtins" +version = "0.1.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603" dependencies = [ "rustc-std-workspace-core", ] @@ -123,9 +133,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897cd85af6387be149f55acf168e41be176a02de7872403aaab184afc2f327e6" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" dependencies = [ "compiler_builtins", "libc", @@ -135,9 +145,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.132" +version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" dependencies = [ "rustc-std-workspace-core", ] @@ -182,7 +192,7 @@ name = "panic_abort" version = "0.0.0" dependencies = [ "alloc", - "cfg-if", + "cfg-if 0.1.10", "compiler_builtins", "core", "libc", @@ -193,7 +203,7 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc", - "cfg-if", + "cfg-if 0.1.10", "compiler_builtins", "core", "libc", @@ -245,7 +255,7 @@ version = "0.0.0" dependencies = [ "addr2line", "alloc", - "cfg-if", + "cfg-if 1.0.0", "compiler_builtins", "core", "dlmalloc", @@ -267,7 +277,7 @@ dependencies = [ name = "std_detect" version = "0.1.5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "compiler_builtins", "libc", "rustc-std-workspace-alloc", @@ -289,7 +299,7 @@ dependencies = [ name = "test" version = "0.0.0" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "core", "getopts", "libc", @@ -301,9 +311,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", @@ -315,7 +325,7 @@ name = "unwind" version = "0.0.0" dependencies = [ "cc", - "cfg-if", + "cfg-if 0.1.10", "compiler_builtins", "core", "libc", diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs new file mode 100644 index 00000000000..fae5b271636 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs @@ -0,0 +1,52 @@ +use std::env; +use std::path::Path; + +use super::build_sysroot; +use super::config; +use super::prepare; +use super::utils::{cargo_command, spawn_and_wait}; +use super::SysrootKind; + +pub(crate) fn run( + channel: &str, + sysroot_kind: SysrootKind, + target_dir: &Path, + cg_clif_dylib: &Path, + host_triple: &str, + target_triple: &str, +) { + if !config::get_bool("testsuite.abi-cafe") { + eprintln!("[SKIP] abi-cafe"); + return; + } + + if host_triple != target_triple { + eprintln!("[SKIP] abi-cafe (cross-compilation not supported)"); + return; + } + + eprintln!("Building sysroot for abi-cafe"); + build_sysroot::build_sysroot( + channel, + sysroot_kind, + target_dir, + cg_clif_dylib, + host_triple, + target_triple, + ); + + eprintln!("Running abi-cafe"); + let abi_cafe_path = prepare::ABI_CAFE.source_dir(); + env::set_current_dir(abi_cafe_path.clone()).unwrap(); + + let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"]; + + let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path); + cmd.arg("--"); + cmd.arg("--pairs"); + cmd.args(pairs); + cmd.arg("--add-rustc-codegen-backend"); + cmd.arg(format!("cgclif:{}", cg_clif_dylib.display())); + + spawn_and_wait(cmd); +} diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs b/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs deleted file mode 100644 index 67dbd0a38a4..00000000000 --- a/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs +++ /dev/null @@ -1,60 +0,0 @@ -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); -} diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs index 9e59b8199b4..cda468bcfa2 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs @@ -1,16 +1,16 @@ use std::env; -use std::path::{Path, PathBuf}; -use std::process::Command; +use std::path::PathBuf; -use super::utils::is_ci; +use super::rustc_info::get_file_name; +use super::utils::{cargo_command, is_ci}; pub(crate) fn build_backend( channel: &str, host_triple: &str, use_unstable_features: bool, ) -> PathBuf { - let mut cmd = Command::new("cargo"); - cmd.arg("build").arg("--target").arg(host_triple); + let source_dir = std::env::current_dir().unwrap(); + let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir); cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode @@ -41,5 +41,9 @@ pub(crate) fn build_backend( eprintln!("[BUILD] rustc_codegen_cranelift"); super::utils::spawn_and_wait(cmd); - Path::new("target").join(host_triple).join(channel) + source_dir + .join("target") + .join(host_triple) + .join(channel) + .join(get_file_name("rustc_codegen_cranelift", "dylib")) } diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs index 7e205b0fd0b..856aecc49fd 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -3,14 +3,14 @@ use std::path::{Path, PathBuf}; use std::process::{self, Command}; 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::utils::{cargo_command, spawn_and_wait, try_hard_link}; use super::SysrootKind; pub(crate) fn build_sysroot( channel: &str, sysroot_kind: SysrootKind, target_dir: &Path, - cg_clif_build_dir: &Path, + cg_clif_dylib_src: &Path, host_triple: &str, target_triple: &str, ) { @@ -23,7 +23,6 @@ pub(crate) fn build_sysroot( fs::create_dir_all(target_dir.join("lib")).unwrap(); // Copy the backend - let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib"); let cg_clif_dylib_path = target_dir .join(if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the @@ -32,8 +31,8 @@ pub(crate) fn build_sysroot( } else { "lib" }) - .join(&cg_clif_dylib); - try_hard_link(cg_clif_build_dir.join(cg_clif_dylib), &cg_clif_dylib_path); + .join(get_file_name("rustc_codegen_cranelift", "dylib")); + try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path); // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { @@ -186,10 +185,10 @@ fn build_clif_sysroot_for_triple( } // Build sysroot - let mut build_cmd = Command::new("cargo"); - build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot"); + let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot")); let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string(); rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap())); + rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap())); if channel == "release" { build_cmd.arg("--release"); rustflags.push_str(" -Zmir-opt-level=3"); diff --git a/compiler/rustc_codegen_cranelift/build_system/config.rs b/compiler/rustc_codegen_cranelift/build_system/config.rs index ef540cf1f82..c31784e1097 100644 --- a/compiler/rustc_codegen_cranelift/build_system/config.rs +++ b/compiler/rustc_codegen_cranelift/build_system/config.rs @@ -1,4 +1,5 @@ -use std::{fs, process}; +use std::fs; +use std::process; fn load_config_file() -> Vec<(String, Option)> { fs::read_to_string("config.txt") diff --git a/compiler/rustc_codegen_cranelift/build_system/mod.rs b/compiler/rustc_codegen_cranelift/build_system/mod.rs index c3706dc6f82..b25270d832c 100644 --- a/compiler/rustc_codegen_cranelift/build_system/mod.rs +++ b/compiler/rustc_codegen_cranelift/build_system/mod.rs @@ -4,7 +4,7 @@ use std::process; use self::utils::is_ci; -mod abi_checker; +mod abi_cafe; mod build_backend; mod build_sysroot; mod config; @@ -122,32 +122,23 @@ pub fn main() { host_triple.clone() }; - if target_triple.ends_with("-msvc") { - eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); - eprintln!("Switch to the MinGW toolchain for Windows support."); - eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); - eprintln!("set the global default target to MinGW"); - process::exit(1); - } - - let cg_clif_build_dir = - build_backend::build_backend(channel, &host_triple, use_unstable_features); + let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features); match command { Command::Test => { tests::run_tests( channel, sysroot_kind, &target_dir, - &cg_clif_build_dir, + &cg_clif_dylib, &host_triple, &target_triple, ); - abi_checker::run( + abi_cafe::run( channel, sysroot_kind, &target_dir, - &cg_clif_build_dir, + &cg_clif_dylib, &host_triple, &target_triple, ); @@ -157,7 +148,7 @@ pub fn main() { channel, sysroot_kind, &target_dir, - &cg_clif_build_dir, + &cg_clif_dylib, &host_triple, &target_triple, ); diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index d23b7f00dcf..3111f62f6c2 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -1,64 +1,63 @@ use std::env; use std::ffi::OsStr; -use std::ffi::OsString; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::Command; use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; -use super::utils::{copy_dir_recursively, spawn_and_wait}; +use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait}; + +pub(crate) const ABI_CAFE: GitRepo = + GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe"); + +pub(crate) const RAND: GitRepo = + GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand"); + +pub(crate) const REGEX: GitRepo = + GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex"); + +pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github( + "rust-lang", + "portable-simd", + "d5cd4a8112d958bd3a252327e0d069a6363249bd", + "portable-simd", +); + +pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github( + "ebobby", + "simple-raytracer", + "804a7a21b9e673a482797aa289a18ed480e4d813", + "", +); pub(crate) fn prepare() { + if Path::new("download").exists() { + std::fs::remove_dir_all(Path::new("download")).unwrap(); + } + std::fs::create_dir_all(Path::new("download")).unwrap(); + prepare_sysroot(); + // FIXME maybe install this only locally? 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", - "rand", - "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", - ); - apply_patches("rand", Path::new("rand")); - - clone_repo_shallow_github( - "regex", - "rust-lang", - "regex", - "341f207c1071f7290e3f228c710817c280c8dca1", - ); - - clone_repo_shallow_github( - "portable-simd", - "rust-lang", - "portable-simd", - "b8d6b6844602f80af79cd96401339ec594d472d8", - ); - apply_patches("portable-simd", Path::new("portable-simd")); - - clone_repo_shallow_github( - "simple-raytracer", - "ebobby", - "simple-raytracer", - "804a7a21b9e673a482797aa289a18ed480e4d813", - ); + ABI_CAFE.fetch(); + RAND.fetch(); + REGEX.fetch(); + PORTABLE_SIMD.fetch(); + SIMPLE_RAYTRACER.fetch(); eprintln!("[LLVM BUILD] simple-raytracer"); - let mut build_cmd = Command::new("cargo"); - build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer"); + let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir()); spawn_and_wait(build_cmd); fs::copy( - Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), - Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")), + SIMPLE_RAYTRACER + .source_dir() + .join("target") + .join("debug") + .join(get_file_name("main", "bin")), + SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")), ) .unwrap(); } @@ -90,38 +89,78 @@ fn prepare_sysroot() { apply_patches("sysroot", &sysroot_src); } +pub(crate) struct GitRepo { + url: GitRepoUrl, + rev: &'static str, + patch_name: &'static str, +} + +enum GitRepoUrl { + Github { user: &'static str, repo: &'static str }, +} + +impl GitRepo { + const fn github( + user: &'static str, + repo: &'static str, + rev: &'static str, + patch_name: &'static str, + ) -> GitRepo { + GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name } + } + + pub(crate) fn source_dir(&self) -> PathBuf { + match self.url { + GitRepoUrl::Github { user: _, repo } => { + std::env::current_dir().unwrap().join("download").join(repo) + } + } + } + + fn fetch(&self) { + match self.url { + GitRepoUrl::Github { user, repo } => { + clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev); + } + } + apply_patches(self.patch_name, &self.source_dir()); + } +} + #[allow(dead_code)] -fn clone_repo(target_dir: &str, repo: &str, rev: &str) { +fn clone_repo(download_dir: &Path, repo: &str, rev: &str) { eprintln!("[CLONE] {}", repo); // Ignore exit code as the repo may already have been checked out - Command::new("git").arg("clone").arg(repo).arg(target_dir).spawn().unwrap().wait().unwrap(); + Command::new("git").arg("clone").arg(repo).arg(&download_dir).spawn().unwrap().wait().unwrap(); let mut clean_cmd = Command::new("git"); - clean_cmd.arg("checkout").arg("--").arg(".").current_dir(target_dir); + clean_cmd.arg("checkout").arg("--").arg(".").current_dir(&download_dir); spawn_and_wait(clean_cmd); let mut checkout_cmd = Command::new("git"); - checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(target_dir); + checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir); spawn_and_wait(checkout_cmd); } -fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev: &str) { +fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) { if cfg!(windows) { // Older windows doesn't have tar or curl by default. Fall back to using git. - clone_repo(target_dir, &format!("https://github.com/{}/{}.git", username, repo), rev); + clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev); return; } - let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", username, repo, rev); - let archive_file = format!("{}.tar.gz", rev); - let archive_dir = format!("{}-{}", repo, rev); + let downloads_dir = std::env::current_dir().unwrap().join("download"); - eprintln!("[DOWNLOAD] {}/{} from {}", username, repo, archive_url); + let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev); + let archive_file = downloads_dir.join(format!("{}.tar.gz", rev)); + let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev)); + + eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url); // Remove previous results if they exists let _ = std::fs::remove_file(&archive_file); let _ = std::fs::remove_dir_all(&archive_dir); - let _ = std::fs::remove_dir_all(target_dir); + let _ = std::fs::remove_dir_all(&download_dir); // Download zip archive let mut download_cmd = Command::new("curl"); @@ -130,13 +169,13 @@ fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev: // Unpack tar archive let mut unpack_cmd = Command::new("tar"); - unpack_cmd.arg("xf").arg(&archive_file); + unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir); spawn_and_wait(unpack_cmd); // Rename unpacked dir to the expected name - std::fs::rename(archive_dir, target_dir).unwrap(); + std::fs::rename(archive_dir, &download_dir).unwrap(); - init_git_repo(Path::new(target_dir)); + init_git_repo(&download_dir); // Cleanup std::fs::remove_file(archive_file).unwrap(); @@ -156,14 +195,20 @@ fn init_git_repo(repo_dir: &Path) { spawn_and_wait(git_commit_cmd); } -fn get_patches(crate_name: &str) -> Vec { - let mut patches: Vec<_> = fs::read_dir("patches") +fn get_patches(source_dir: &Path, crate_name: &str) -> Vec { + let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches")) .unwrap() .map(|entry| entry.unwrap().path()) .filter(|path| path.extension() == Some(OsStr::new("patch"))) - .map(|path| path.file_name().unwrap().to_owned()) - .filter(|file_name| { - file_name.to_str().unwrap().split_once("-").unwrap().1.starts_with(crate_name) + .filter(|path| { + path.file_name() + .unwrap() + .to_str() + .unwrap() + .split_once("-") + .unwrap() + .1 + .starts_with(crate_name) }) .collect(); patches.sort(); @@ -171,11 +216,18 @@ fn get_patches(crate_name: &str) -> Vec { } fn apply_patches(crate_name: &str, target_dir: &Path) { - for patch in get_patches(crate_name) { - eprintln!("[PATCH] {:?} <- {:?}", target_dir.file_name().unwrap(), patch); - let patch_arg = env::current_dir().unwrap().join("patches").join(patch); + if crate_name == "" { + return; + } + + for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) { + eprintln!( + "[PATCH] {:?} <- {:?}", + target_dir.file_name().unwrap(), + patch.file_name().unwrap() + ); let mut apply_patch_cmd = Command::new("git"); - apply_patch_cmd.arg("am").arg(patch_arg).arg("-q").current_dir(target_dir); + apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir); spawn_and_wait(apply_patch_cmd); } } diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index e21397cece8..a414b60f4e0 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -1,7 +1,8 @@ use super::build_sysroot; use super::config; +use super::prepare; use super::rustc_info::get_wrapper_file_name; -use super::utils::{spawn_and_wait, spawn_and_wait_with_input}; +use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input}; use build_system::SysrootKind; use std::env; use std::ffi::OsStr; @@ -217,103 +218,95 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ TestCase::new("test.rust-random/rand", &|runner| { - runner.in_dir(["rand"], |runner| { - runner.run_cargo(["clean"]); + runner.in_dir(prepare::RAND.source_dir(), |runner| { + runner.run_cargo("clean", []); if runner.host_triple == runner.target_triple { eprintln!("[TEST] rust-random/rand"); - runner.run_cargo(["test", "--workspace"]); + runner.run_cargo("test", ["--workspace"]); } else { eprintln!("[AOT] rust-random/rand"); - runner.run_cargo([ - "build", - "--workspace", - "--target", - &runner.target_triple, - "--tests", - ]); + runner.run_cargo("build", ["--workspace", "--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()); + runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| { + let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap(); if runner.host_triple == runner.target_triple { eprintln!("[BENCH COMPILE] ebobby/simple-raytracer"); - let 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"]))); + let prepare = runner.cargo_command("clean", []); - if cfg!(windows) { - bench_compile.arg("cmd /C \"set RUSTFLAGS= && cargo build\""); - } else { - bench_compile.arg("RUSTFLAGS='' cargo build"); - } + let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new(".")); + + let cargo_clif = runner + .root_dir + .clone() + .join("build") + .join(get_wrapper_file_name("cargo-clif", "bin")); + let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new(".")); + + let bench_compile = + hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd); - 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")); + let bench_run = hyperfine_command( + 0, + run_runs, + None, + Command::new("./raytracer_cg_llvm"), + Command::new("./raytracer_cg_clif"), + ); spawn_and_wait(bench_run); } else { - runner.run_cargo(["clean"]); + runner.run_cargo("clean", []); eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)"); eprintln!("[COMPILE] ebobby/simple-raytracer"); - runner.run_cargo(["build", "--target", &runner.target_triple]); + runner.run_cargo("build", []); 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"]); + runner.in_dir( + std::env::current_dir() + .unwrap() + .join("build_sysroot") + .join("sysroot_src") + .join("library") + .join("core") + .join("tests"), + |runner| { + runner.run_cargo("clean", []); - 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"]); - } - }); + if runner.host_triple == runner.target_triple { + runner.run_cargo("test", []); + } else { + eprintln!("Cross-Compiling: Not running tests"); + runner.run_cargo("build", ["--tests"]); + } + }, + ); }), TestCase::new("test.regex-shootout-regex-dna", &|runner| { - runner.in_dir(["regex"], |runner| { - runner.run_cargo(["clean"]); + runner.in_dir(prepare::REGEX.source_dir(), |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, - ]); + let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); if runner.host_triple == runner.target_triple { - let mut run_cmd = runner.cargo_command([ - "run", - "--example", - "shootout-regex-dna", - "--target", - &runner.target_triple, - ]); + let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]); run_cmd.env("RUSTFLAGS", lint_rust_flags); let input = @@ -353,41 +346,43 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ }); }), TestCase::new("test.regex", &|runner| { - runner.in_dir(["regex"], |runner| { - runner.run_cargo(["clean"]); + runner.in_dir(prepare::REGEX.source_dir(), |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([ + let mut run_cmd = runner.cargo_command( "test", - "--tests", - "--", - "--exclude-should-panic", - "--test-threads", - "1", - "-Zunstable-options", - "-q", - ]); + [ + "--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]); + 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]); + runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |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"]); + runner.run_cargo("test", ["-q"]); } }); }), @@ -397,7 +392,7 @@ pub(crate) fn run_tests( channel: &str, sysroot_kind: SysrootKind, target_dir: &Path, - cg_clif_build_dir: &Path, + cg_clif_dylib: &Path, host_triple: &str, target_triple: &str, ) { @@ -408,7 +403,7 @@ pub(crate) fn run_tests( channel, SysrootKind::None, &target_dir, - cg_clif_build_dir, + cg_clif_dylib, &host_triple, &target_triple, ); @@ -427,7 +422,7 @@ pub(crate) fn run_tests( channel, sysroot_kind, &target_dir, - cg_clif_build_dir, + cg_clif_dylib, &host_triple, &target_triple, ); @@ -521,16 +516,8 @@ impl TestRunner { } } - fn in_dir<'a, I, F>(&self, dir: I, callback: F) - where - I: IntoIterator, - F: FnOnce(&TestRunner), - { + fn in_dir(&self, new: impl AsRef, callback: impl 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); @@ -595,25 +582,29 @@ impl TestRunner { spawn_and_wait(cmd); } - fn cargo_command(&self, args: I) -> Command + fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command where - I: IntoIterator, - S: AsRef, + I: IntoIterator, { 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); + let mut cmd = cargo_command( + cargo_clif, + subcommand, + if subcommand == "clean" { None } else { Some(&self.target_triple) }, + Path::new("."), + ); cmd.args(args); cmd.env("RUSTFLAGS", &self.rust_flags); cmd } - fn run_cargo<'a, I>(&self, args: I) + fn run_cargo<'a, I>(&self, subcommand: &str, args: I) where I: IntoIterator, { - spawn_and_wait(self.cargo_command(args)); + spawn_and_wait(self.cargo_command(subcommand, args)); } } diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs index bdf8f8ecd99..48da64906e2 100644 --- a/compiler/rustc_codegen_cranelift/build_system/utils.rs +++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs @@ -4,6 +4,52 @@ use std::io::Write; use std::path::Path; use std::process::{self, Command, Stdio}; +pub(crate) fn cargo_command( + cargo: impl AsRef, + subcommand: &str, + triple: Option<&str>, + source_dir: &Path, +) -> Command { + let mut cmd = Command::new(cargo.as_ref()); + cmd.arg(subcommand) + .arg("--manifest-path") + .arg(source_dir.join("Cargo.toml")) + .arg("--target-dir") + .arg(source_dir.join("target")); + + if let Some(triple) = triple { + cmd.arg("--target").arg(triple); + } + + cmd +} + +pub(crate) fn hyperfine_command( + warmup: u64, + runs: u64, + prepare: Option, + a: Command, + b: Command, +) -> Command { + let mut bench = Command::new("hyperfine"); + + if warmup != 0 { + bench.arg("--warmup").arg(warmup.to_string()); + } + + if runs != 0 { + bench.arg("--runs").arg(runs.to_string()); + } + + if let Some(prepare) = prepare { + bench.arg("--prepare").arg(format!("{:?}", prepare)); + } + + bench.arg(format!("{:?}", a)).arg(format!("{:?}", b)); + + bench +} + #[track_caller] pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { let src = src.as_ref(); diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh index 62e52bd1958..fedab2433aa 100755 --- a/compiler/rustc_codegen_cranelift/clean_all.sh +++ b/compiler/rustc_codegen_cranelift/clean_all.sh @@ -3,4 +3,8 @@ 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/ abi-checker/ +rm -rf download/ + +# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh +# FIXME remove at some point in the future +rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ abi-cafe/ diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt index 2264d301d59..0d539191b12 100644 --- a/compiler/rustc_codegen_cranelift/config.txt +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -49,4 +49,4 @@ test.regex-shootout-regex-dna test.regex test.portable-simd -testsuite.abi-checker +testsuite.abi-cafe diff --git a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs index 2ecc8b8238b..03910069633 100644 --- a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs +++ b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs @@ -5,7 +5,6 @@ // Test that we can handle unsized types with an extern type tail part. // Regression test for issue #91827. -#![feature(const_ptr_offset_from)] #![feature(extern_types)] use std::ptr::addr_of; diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 42f8aa50ba1..7f85b52f083 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -559,16 +559,22 @@ pub union MaybeUninit { pub mod intrinsics { extern "rust-intrinsic" { + #[rustc_safe_intrinsic] pub fn abort() -> !; + #[rustc_safe_intrinsic] pub fn size_of() -> usize; pub fn size_of_val(val: *const T) -> usize; + #[rustc_safe_intrinsic] pub fn min_align_of() -> usize; pub fn min_align_of_val(val: *const T) -> usize; pub fn copy(src: *const T, dst: *mut T, count: usize); pub fn transmute(e: T) -> U; pub fn ctlz_nonzero(x: T) -> T; + #[rustc_safe_intrinsic] pub fn needs_drop() -> bool; + #[rustc_safe_intrinsic] pub fn bitreverse(x: T) -> T; + #[rustc_safe_intrinsic] pub fn bswap(x: T) -> T; pub fn write_bytes(dst: *mut T, val: u8, count: usize); } diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index e83be3a3df5..215d3556a17 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -93,6 +93,7 @@ fn start( main: fn() -> T, argc: isize, argv: *const *const u8, + _sigpipe: u8, ) -> isize { if argc == 3 { unsafe { puts(*argv as *const i8); } diff --git a/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch new file mode 100644 index 00000000000..0e5e7cdfcdf --- /dev/null +++ b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch @@ -0,0 +1,29 @@ +From 2b15fee2bb5fd14e34c7e17e44d99cb34f4c555d Mon Sep 17 00:00:00 2001 +From: Afonso Bordado +Date: Tue, 27 Sep 2022 07:55:17 +0100 +Subject: [PATCH] Disable some test on x86_64-pc-windows-gnu + +--- + src/report.rs | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/report.rs b/src/report.rs +index eeec614..f582867 100644 +--- a/src/report.rs ++++ b/src/report.rs +@@ -48,6 +48,12 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl + // + // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES + ++ // x86_64-pc-windows-gnu has some broken i128 tests that aren't disabled by default ++ if cfg!(all(target_os = "windows", target_env = "gnu")) && test.test_name == "ui128" { ++ result.run = Link; ++ result.check = Pass(Link); ++ } ++ + // END OF VENDOR RESERVED AREA + // + // +-- +2.30.1.windows.1 + 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 deleted file mode 100644 index 526366a7598..00000000000 --- a/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001 -From: Afonso Bordado -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 diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch index 54e13b090ab..89e2b61c1fc 100644 --- a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch @@ -1,80 +1,29 @@ -From 97c473937382a5b5858d9cce3c947855d23b2dc5 Mon Sep 17 00:00:00 2001 +From b742f03694b920cc14400727d54424e8e1b60928 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 18 Nov 2021 19:28:40 +0100 Subject: [PATCH] Disable unsupported tests --- - crates/core_simd/src/math.rs | 6 ++++++ - crates/core_simd/src/vector.rs | 2 ++ - crates/core_simd/tests/masks.rs | 2 ++ - crates/core_simd/tests/ops_macros.rs | 4 ++++ - 4 files changed, 14 insertions(+) + crates/core_simd/src/elements/int.rs | 8 ++++++++ + crates/core_simd/src/elements/uint.rs | 4 ++++ + crates/core_simd/src/masks/full_masks.rs | 6 ++++++ + crates/core_simd/src/vector.rs | 2 ++ + crates/core_simd/tests/masks.rs | 3 --- + 5 files changed, 20 insertions(+), 3 deletions(-) -diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs -index 2bae414..2f87499 100644 ---- a/crates/core_simd/src/math.rs -+++ b/crates/core_simd/src/math.rs -@@ -5,6 +5,7 @@ macro_rules! impl_uint_arith { - ($($ty:ty),+) => { - $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { - -+ /* - /// Lanewise saturating add. - /// - /// # Examples -@@ -43,6 +44,7 @@ macro_rules! impl_uint_arith { - pub fn saturating_sub(self, second: Self) -> Self { - unsafe { simd_saturating_sub(self, second) } - } -+ */ - })+ - } - } -@@ -51,6 +53,7 @@ macro_rules! impl_int_arith { - ($($ty:ty),+) => { - $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { - -+ /* - /// Lanewise saturating add. - /// - /// # Examples -@@ -89,6 +92,7 @@ macro_rules! impl_int_arith { - pub fn saturating_sub(self, second: Self) -> Self { - unsafe { simd_saturating_sub(self, second) } - } -+ */ - - /// Lanewise absolute value, implemented in Rust. - /// Every lane becomes its absolute value. -@@ -109,6 +113,7 @@ macro_rules! impl_int_arith { - (self^m) - m - } - -+ /* - /// Lanewise saturating absolute value, implemented in Rust. - /// As abs(), except the MIN value becomes MAX instead of itself. - /// -@@ -151,6 +156,7 @@ macro_rules! impl_int_arith { - pub fn saturating_neg(self) -> Self { - Self::splat(0).saturating_sub(self) - } -+ */ - })+ - } - } diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs -index 7c5ec2b..c8631e8 100644 +index e8e8f68..7173c24 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs -@@ -75,6 +75,7 @@ where - Self(array) +@@ -250,6 +250,7 @@ where + unsafe { intrinsics::simd_cast(self) } } + /* /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. /// If an index is out-of-bounds, the lane is instead selected from the `or` vector. /// -@@ -297,6 +298,7 @@ where +@@ -473,6 +474,7 @@ where // Cleared ☢️ *mut T Zone } } @@ -82,26 +31,5 @@ index 7c5ec2b..c8631e8 100644 } impl Copy for Simd -diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs -index 6a8ecd3..68fcb49 100644 ---- a/crates/core_simd/tests/masks.rs -+++ b/crates/core_simd/tests/masks.rs -@@ -68,6 +68,7 @@ macro_rules! test_mask_api { - assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask); - } - -+ /* - #[cfg(feature = "generic_const_exprs")] - #[test] - fn roundtrip_bitmask_conversion() { -@@ -80,6 +81,7 @@ macro_rules! test_mask_api { - assert_eq!(bitmask, [0b01001001, 0b10000011]); - assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask); - } -+ */ - } - } - } -- -2.26.2.7.g19db9cfb68 - +2.25.1 diff --git a/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch b/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch new file mode 100644 index 00000000000..d8775e2d022 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch @@ -0,0 +1,47 @@ +From eec874c889b8d24e5ad50faded24288150f057b1 Mon Sep 17 00:00:00 2001 +From: Afonso Bordado +Date: Tue, 27 Sep 2022 08:13:58 +0100 +Subject: [PATCH] Disable rand tests on mingw + +--- + rand_distr/src/pareto.rs | 2 ++ + rand_distr/tests/value_stability.rs | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/rand_distr/src/pareto.rs b/rand_distr/src/pareto.rs +index 217899e..9cedeb7 100644 +--- a/rand_distr/src/pareto.rs ++++ b/rand_distr/src/pareto.rs +@@ -107,6 +107,8 @@ mod tests { + } + + #[test] ++ // This is broken on x86_64-pc-windows-gnu presumably due to a broken powf implementation ++ #[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)] + fn value_stability() { + fn test_samples>( + distr: D, zero: F, expected: &[F], +diff --git a/rand_distr/tests/value_stability.rs b/rand_distr/tests/value_stability.rs +index 192ba74..0101ace 100644 +--- a/rand_distr/tests/value_stability.rs ++++ b/rand_distr/tests/value_stability.rs +@@ -72,6 +72,8 @@ fn unit_disc_stability() { + } + + #[test] ++// This is broken on x86_64-pc-windows-gnu ++#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)] + fn pareto_stability() { + test_samples(213, Pareto::new(1.0, 1.0).unwrap(), &[ + 1.0423688f32, 2.1235929, 4.132709, 1.4679428, +@@ -143,6 +145,8 @@ fn inverse_gaussian_stability() { + } + + #[test] ++// This is broken on x86_64-pc-windows-gnu ++#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)] + fn gamma_stability() { + // Gamma has 3 cases: shape == 1, shape < 1, shape > 1 + test_samples(223, Gamma::new(1.0, 5.0).unwrap(), &[ +-- +2.25.1 diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 14f2746ecb1..c0a2e7a7883 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-08-24" +channel = "nightly-2022-10-23" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index 091bfa1e992..d6a37789599 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -10,6 +10,8 @@ git fetch git checkout -- . git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')" +git am ../patches/*-sysroot-*.patch + git apply - <( let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); - (CallTarget::Indirect(sig, method), Some(ptr)) + (CallTarget::Indirect(sig, method), Some(ptr.get_addr(fx))) } // Normal call @@ -560,7 +560,19 @@ pub(crate) fn codegen_drop<'tcx>( // we don't actually need to drop anything } else { match ty.kind() { - ty::Dynamic(..) => { + ty::Dynamic(_, _, ty::Dyn) => { + // IN THIS ARM, WE HAVE: + // ty = *mut (dyn Trait) + // which is: exists ( *mut T, Vtable ) + // args[0] args[1] + // + // args = ( Data, Vtable ) + // | + // v + // /-------\ + // | ... | + // \-------/ + // let (ptr, vtable) = drop_place.to_ptr_maybe_unsized(); let ptr = ptr.get_addr(fx); let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap()); @@ -578,6 +590,43 @@ pub(crate) fn codegen_drop<'tcx>( let sig = fx.bcx.import_signature(sig); fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]); } + ty::Dynamic(_, _, ty::DynStar) => { + // IN THIS ARM, WE HAVE: + // ty = *mut (dyn* Trait) + // which is: *mut exists (T, Vtable) + // + // args = [ * ] + // | + // v + // ( Data, Vtable ) + // | + // v + // /-------\ + // | ... | + // \-------/ + // + // + // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING + // + // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer) + // vtable = (*args[0]).1 // loads the vtable out + // (data, vtable) // an equivalent Rust `*mut dyn Trait` + // + // SO THEN WE CAN USE THE ABOVE CODE. + let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx); + let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable); + + let virtual_drop = Instance { + def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), + substs: drop_instance.substs, + }; + let fn_abi = + RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty()); + + let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); + let sig = fx.bcx.import_signature(sig); + fx.bcx.ins().call_indirect(sig, drop_fn, &[data]); + } _ => { assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _))); diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 6d321c7b298..bad8a87b9be 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -78,7 +78,7 @@ fn codegen_inner( let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap(); let mut ctx = Context::new(); - ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig.clone()); + ctx.func.signature = sig.clone(); { let mut func_ctx = FunctionBuilderContext::new(); let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); @@ -116,7 +116,7 @@ fn codegen_inner( let callee_func_id = module.declare_function(callee_name, Linkage::Import, &sig).unwrap(); let mut ctx = Context::new(); - ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig); + ctx.func.signature = sig; { let mut func_ctx = FunctionBuilderContext::new(); let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index b4c79096170..31d3d0e0615 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -159,6 +159,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { let err = err.to_string(); if err == "Unknown file magic" { // Not an object file; skip it. + } else if object::read::archive::ArchiveFile::parse(&*data).is_ok() { + // Nested archive file; skip it. } else { sess.fatal(&format!( "error parsing `{}` during archive creation: {}", diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 4303d63fe21..a41b561598f 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -6,6 +6,8 @@ use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; +use cranelift_codegen::ir::UserFuncName; + use crate::constant::ConstantCx; use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; @@ -64,7 +66,7 @@ pub(crate) fn codegen_fn<'tcx>( let mut func_ctx = FunctionBuilderContext::new(); let mut func = cached_func; func.clear(); - func.name = ExternalName::user(0, func_id.as_u32()); + func.name = UserFuncName::user(0, func_id.as_u32()); func.signature = sig; func.collect_debug_info(); @@ -706,9 +708,9 @@ fn codegen_stmt<'tcx>( let operand = codegen_operand(fx, operand); operand.unsize_value(fx, lval); } - Rvalue::Cast(CastKind::DynStar, _, _) => { - // FIXME(dyn-star) - unimplemented!() + Rvalue::Cast(CastKind::DynStar, ref operand, _) => { + let operand = codegen_operand(fx, operand); + operand.coerce_dyn_star(fx, lval); } Rvalue::Discriminant(place) => { let place = codegen_place(fx, place); @@ -922,7 +924,7 @@ pub(crate) fn codegen_operand<'tcx>( let cplace = codegen_place(fx, *place); cplace.to_cvalue(fx) } - Operand::Constant(const_) => crate::constant::codegen_constant(fx, const_), + Operand::Constant(const_) => crate::constant::codegen_constant_operand(fx, const_), } } diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs index dfde9792046..f855e20e0a1 100644 --- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs +++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs @@ -10,6 +10,7 @@ pub(super) struct ConcurrencyLimiter { helper_thread: Option, state: Arc>, available_token_condvar: Arc, + finished: bool, } impl ConcurrencyLimiter { @@ -32,6 +33,7 @@ impl ConcurrencyLimiter { helper_thread: Some(helper_thread), state, available_token_condvar: Arc::new(Condvar::new()), + finished: false, } } @@ -56,16 +58,23 @@ impl ConcurrencyLimiter { let mut state = self.state.lock().unwrap(); state.job_already_done(); } -} -impl Drop for ConcurrencyLimiter { - fn drop(&mut self) { - // + pub(crate) fn finished(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(); + + self.finished = true; + } +} + +impl Drop for ConcurrencyLimiter { + fn drop(&mut self) { + if !self.finished && !std::thread::panicking() { + panic!("Forgot to call finished() on ConcurrencyLimiter"); + } } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index c5f44bb8479..d4bc3543b2d 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -7,7 +7,6 @@ use rustc_middle::mir::interpret::{ }; use rustc_span::DUMMY_SP; -use cranelift_codegen::ir::GlobalValueData; use cranelift_module::*; use crate::prelude::*; @@ -81,52 +80,45 @@ pub(crate) fn codegen_tls_ref<'tcx>( CValue::by_val(tls_ptr, layout) } -fn codegen_static_ref<'tcx>( +pub(crate) fn eval_mir_constant<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - def_id: DefId, - layout: TyAndLayout<'tcx>, -) -> CPlace<'tcx> { - let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false); - let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - if fx.clif_comments.enabled() { - fx.add_comment(local_data_id, format!("{:?}", def_id)); - } - let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id); - assert!(!layout.is_unsized(), "unsized statics aren't supported"); - assert!( - matches!( - fx.bcx.func.global_values[local_data_id], - GlobalValueData::Symbol { tls: false, .. } - ), - "tls static referenced without Rvalue::ThreadLocalRef" - ); - CPlace::for_ptr(crate::pointer::Pointer::new(global_ptr), layout) + constant: &Constant<'tcx>, +) -> (ConstValue<'tcx>, Ty<'tcx>) { + let constant_kind = fx.monomorphize(constant.literal); + let uv = match constant_kind { + ConstantKind::Ty(const_) => match const_.kind() { + ty::ConstKind::Unevaluated(uv) => uv.expand(), + ty::ConstKind::Value(val) => { + return (fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty()); + } + err => span_bug!( + constant.span, + "encountered bad ConstKind after monomorphizing: {:?}", + err + ), + }, + ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _) + if fx.tcx.is_static(def.did) => + { + span_bug!(constant.span, "MIR constant refers to static"); + } + ConstantKind::Unevaluated(uv, _) => uv, + ConstantKind::Val(val, _) => return (val, constant_kind.ty()), + }; + + ( + fx.tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).unwrap_or_else(|_err| { + span_bug!(constant.span, "erroneous constant not captured by required_consts"); + }), + constant_kind.ty(), + ) } -pub(crate) fn codegen_constant<'tcx>( +pub(crate) fn codegen_constant_operand<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, constant: &Constant<'tcx>, ) -> CValue<'tcx> { - let (const_val, ty) = match fx.monomorphize(constant.literal) { - ConstantKind::Ty(const_) => unreachable!("{:?}", const_), - ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs, promoted }, ty) - if fx.tcx.is_static(def.did) => - { - assert!(substs.is_empty()); - assert!(promoted.is_none()); - - return codegen_static_ref(fx, def.did, fx.layout_of(ty)).to_cvalue(fx); - } - ConstantKind::Unevaluated(unevaluated, ty) => { - match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { - Ok(const_val) => (const_val, ty), - Err(_) => { - span_bug!(constant.span, "erroneous constant not captured by required_consts"); - } - } - } - ConstantKind::Val(val, ty) => (val, ty), - }; + let (const_val, ty) = eval_mir_constant(fx, constant); codegen_const_value(fx, const_val, ty) } @@ -244,7 +236,7 @@ pub(crate) fn codegen_const_value<'tcx>( } } -pub(crate) fn pointer_for_allocation<'tcx>( +fn pointer_for_allocation<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, alloc: ConstAllocation<'tcx>, ) -> crate::pointer::Pointer { @@ -467,14 +459,13 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( operand: &Operand<'tcx>, ) -> Option> { match operand { - Operand::Constant(const_) => match const_.literal { - ConstantKind::Ty(const_) => fx - .monomorphize(const_) - .eval_for_mir(fx.tcx, ParamEnv::reveal_all()) - .try_to_value(fx.tcx), + Operand::Constant(const_) => match fx.monomorphize(const_.literal) { + ConstantKind::Ty(const_) => Some( + const_.eval_for_mir(fx.tcx, ParamEnv::reveal_all()).try_to_value(fx.tcx).unwrap(), + ), ConstantKind::Val(val, _) => Some(val), ConstantKind::Unevaluated(uv, _) => { - fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).ok() + Some(fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).unwrap()) } }, // FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 8eabe1cbcb1..f873561c171 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -106,7 +106,7 @@ impl OngoingCodegen { } } - drop(self.concurrency_limiter); + self.concurrency_limiter.finished(); ( CodegenResults { diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 0e77e4004c0..6a430b5215e 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -67,13 +67,12 @@ fn create_jit_module( hotswap: bool, ) -> (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); let isa = crate::build_isa(tcx.sess, backend_config); let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); jit_builder.hotswap(hotswap); crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); - jit_builder.symbols(imported_symbols); + jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info)); jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8); let mut jit_module = JITModule::new(jit_builder); @@ -286,10 +285,10 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> }) } -fn load_imported_symbols_for_jit( +fn dep_symbol_lookup_fn( sess: &Session, crate_info: CrateInfo, -) -> Vec<(String, *const u8)> { +) -> Box Option<*const u8>> { use rustc_middle::middle::dependency_format::Linkage; let mut dylib_paths = Vec::new(); @@ -316,39 +315,23 @@ fn load_imported_symbols_for_jit( } } - let mut imported_symbols = Vec::new(); - for path in dylib_paths { - use object::{Object, ObjectSymbol}; - let lib = libloading::Library::new(&path).unwrap(); - let obj = std::fs::read(path).unwrap(); - let obj = object::File::parse(&*obj).unwrap(); - imported_symbols.extend(obj.dynamic_symbols().filter_map(|symbol| { - let name = symbol.name().unwrap().to_string(); - if name.is_empty() || !symbol.is_global() || symbol.is_undefined() { - return None; - } - if name.starts_with("rust_metadata_") { - // The metadata is part of a section that is not loaded by the dynamic linker in - // case of cg_llvm. - return None; - } - let dlsym_name = if cfg!(target_os = "macos") { - // On macOS `dlsym` expects the name without leading `_`. - assert!(name.starts_with('_'), "{:?}", name); - &name[1..] - } else { - &name - }; - let symbol: libloading::Symbol<'_, *const u8> = - unsafe { lib.get(dlsym_name.as_bytes()) }.unwrap(); - Some((name, *symbol)) - })); - std::mem::forget(lib) - } + let imported_dylibs = Box::leak( + dylib_paths + .into_iter() + .map(|path| unsafe { libloading::Library::new(&path).unwrap() }) + .collect::>(), + ); sess.abort_if_errors(); - imported_symbols + Box::new(move |sym_name| { + for dylib in &*imported_dylibs { + if let Ok(sym) = unsafe { dylib.get::<*const u8>(sym_name.as_bytes()) } { + return Some(*sym); + } + } + None + }) } fn codegen_shim<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 8b3d475cb18..3fcc84d3929 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -27,7 +27,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( } // Used by stdarch - if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string()) + if template[0] == InlineAsmTemplatePiece::String("mov ".to_string()) && matches!( template[1], InlineAsmTemplatePiece::Placeholder { @@ -36,24 +36,26 @@ pub(crate) fn codegen_inline_asm<'tcx>( span: _ } ) - && template[2] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[3] == InlineAsmTemplatePiece::String("cpuid".to_string()) - && template[4] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[5] == InlineAsmTemplatePiece::String("xchgq %rbx, ".to_string()) + && template[2] == InlineAsmTemplatePiece::String(", rbx".to_string()) + && template[3] == InlineAsmTemplatePiece::String("\n".to_string()) + && template[4] == InlineAsmTemplatePiece::String("cpuid".to_string()) + && template[5] == InlineAsmTemplatePiece::String("\n".to_string()) + && template[6] == InlineAsmTemplatePiece::String("xchg ".to_string()) && matches!( - template[6], + template[7], InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: Some('r'), span: _ } ) + && template[8] == InlineAsmTemplatePiece::String(", rbx".to_string()) { assert_eq!(operands.len(), 4); let (leaf, eax_place) = match operands[1] { InlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), - late: true, + late: _, ref in_value, out_place: Some(out_place), } => ( @@ -68,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86( X86InlineAsmRegClass::reg, )), - late: true, + late: _, place: Some(place), } => crate::base::codegen_place(fx, place), _ => unreachable!(), @@ -76,7 +78,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( let (sub_leaf, ecx_place) = match operands[2] { InlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), - late: true, + late: _, ref in_value, out_place: Some(out_place), } => ( @@ -88,7 +90,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( let edx_place = match operands[3] { InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), - late: true, + late: _, place: Some(place), } => crate::base::codegen_place(fx, place), _ => unreachable!(), diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index a799dca938e..783d426c30b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -14,6 +14,10 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( target: Option, ) { match intrinsic { + "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => { + // Spin loop hint + } + // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8` "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => { intrinsic_args!(fx, args => (a); intrinsic); @@ -25,8 +29,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( let mut res = fx.bcx.ins().iconst(types::I32, 0); for lane in (0..lane_count).rev() { - let a_lane = - a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx); + let a_lane = a.value_lane(fx, lane).load_scalar(fx); // cast float to int let a_lane = match lane_ty { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 2e4ca594f91..0302b843aa2 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -84,6 +84,30 @@ fn simd_for_each_lane<'tcx>( } } +fn simd_pair_for_each_lane_typed<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + x: CValue<'tcx>, + y: CValue<'tcx>, + ret: CPlace<'tcx>, + f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, CValue<'tcx>, CValue<'tcx>) -> CValue<'tcx>, +) { + assert_eq!(x.layout(), y.layout()); + let layout = x.layout(); + + let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, _ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_count, ret_lane_count); + + for lane_idx in 0..lane_count { + let x_lane = x.value_lane(fx, lane_idx); + let y_lane = y.value_lane(fx, lane_idx); + + let res_lane = f(fx, x_lane, y_lane); + + ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane); + } +} + fn simd_pair_for_each_lane<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, x: CValue<'tcx>, @@ -504,37 +528,7 @@ fn codegen_regular_intrinsic_call<'tcx>( _ => unreachable!(), }; - let signed = type_sign(lhs.layout().ty); - - let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs); - - let (val, has_overflow) = checked_res.load_scalar_pair(fx); - let clif_ty = fx.clif_type(lhs.layout().ty).unwrap(); - - let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed); - - let val = match (intrinsic, signed) { - (sym::saturating_add, false) => fx.bcx.ins().select(has_overflow, max, val), - (sym::saturating_sub, false) => fx.bcx.ins().select(has_overflow, min, val), - (sym::saturating_add, true) => { - let rhs = rhs.load_scalar(fx); - let rhs_ge_zero = - fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); - let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min); - fx.bcx.ins().select(has_overflow, sat_val, val) - } - (sym::saturating_sub, true) => { - let rhs = rhs.load_scalar(fx); - let rhs_ge_zero = - fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); - let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max); - fx.bcx.ins().select(has_overflow, sat_val, val) - } - _ => unreachable!(), - }; - - let res = CValue::by_val(val, lhs.layout()); - + let res = crate::num::codegen_saturating_int_binop(fx, bin_op, lhs, rhs); ret.write_cvalue(fx, res); } sym::rotate_left => { @@ -819,8 +813,8 @@ fn codegen_regular_intrinsic_call<'tcx>( sym::ptr_guaranteed_cmp => { intrinsic_args!(fx, args => (a, b); intrinsic); - let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b); - ret.write_cvalue(fx, val); + let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b).load_scalar(fx); + ret.write_cvalue(fx, CValue::by_val(val, fx.layout_of(fx.tcx.types.u8))); } sym::caller_location => { @@ -1206,7 +1200,7 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME once unwinding is supported, change this to actually catch panics let f_sig = fx.bcx.func.import_signature(Signature { call_conv: fx.target_config.default_call_conv, - params: vec![AbiParam::new(fx.bcx.func.dfg.value_type(data))], + params: vec![AbiParam::new(pointer_ty(fx.tcx))], returns: vec![], }); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 1f358b1bbb9..51fce8c854b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -2,6 +2,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_span::Symbol; +use rustc_target::abi::Endian; use super::*; use crate::prelude::*; @@ -26,7 +27,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( span: Span, ) { match intrinsic { - sym::simd_cast => { + sym::simd_as | sym::simd_cast => { intrinsic_args!(fx, args => (a); intrinsic); if !a.layout().ty.is_simd() { @@ -162,6 +163,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } } } else { + // FIXME remove this case intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap() }; @@ -650,8 +652,128 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } } - // simd_saturating_* - // simd_bitmask + sym::simd_select_bitmask => { + intrinsic_args!(fx, args => (m, a, b); intrinsic); + + if !a.layout().ty.is_simd() { + report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); + return; + } + assert_eq!(a.layout(), b.layout()); + + let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + + let m = m.load_scalar(fx); + + for lane in 0..lane_count { + let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64); + let m_lane = fx.bcx.ins().band_imm(m_lane, 1); + let a_lane = a.value_lane(fx, lane).load_scalar(fx); + let b_lane = b.value_lane(fx, lane).load_scalar(fx); + + let m_lane = fx.bcx.ins().icmp_imm(IntCC::Equal, m_lane, 0); + let res_lane = + CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout); + + ret.place_lane(fx, lane).write_cvalue(fx, res_lane); + } + } + + sym::simd_bitmask => { + intrinsic_args!(fx, args => (a); intrinsic); + + let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); + let lane_clif_ty = fx.clif_type(lane_ty).unwrap(); + + // The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a + // vector mask and returns the most significant bit (MSB) of each lane in the form + // of either: + // * an unsigned integer + // * an array of `u8` + // If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits. + // + // The bit order of the result depends on the byte endianness, LSB-first for little + // endian and MSB-first for big endian. + let expected_int_bits = lane_count.max(8); + let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64); + + match lane_ty.kind() { + ty::Int(_) | ty::Uint(_) => {} + _ => { + fx.tcx.sess.span_fatal( + span, + &format!( + "invalid monomorphization of `simd_bitmask` intrinsic: \ + vector argument `{}`'s element type `{}`, expected integer element \ + type", + a.layout().ty, + lane_ty + ), + ); + } + } + + let res_type = + Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap(); + let mut res = fx.bcx.ins().iconst(res_type, 0); + + let lanes = match fx.tcx.sess.target.endian { + Endian::Big => Box::new(0..lane_count) as Box>, + Endian::Little => Box::new((0..lane_count).rev()) as Box>, + }; + for lane in lanes { + let a_lane = a.value_lane(fx, lane).load_scalar(fx); + + // extract sign bit of an int + let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_clif_ty.bits() - 1)); + + // shift sign bit into result + let a_lane_sign = clif_intcast(fx, a_lane_sign, res_type, false); + res = fx.bcx.ins().ishl_imm(res, 1); + res = fx.bcx.ins().bor(res, a_lane_sign); + } + + match ret.layout().ty.kind() { + ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {} + ty::Array(elem, len) + if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) + && len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()) + == Some(expected_bytes) => {} + _ => { + fx.tcx.sess.span_fatal( + span, + &format!( + "invalid monomorphization of `simd_bitmask` intrinsic: \ + cannot return `{}`, expected `u{}` or `[u8; {}]`", + ret.layout().ty, + expected_int_bits, + expected_bytes + ), + ); + } + } + + let res = CValue::by_val(res, ret.layout()); + ret.write_cvalue(fx, res); + } + + sym::simd_saturating_add | sym::simd_saturating_sub => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + let bin_op = match intrinsic { + sym::simd_saturating_add => BinOp::Add, + sym::simd_saturating_sub => BinOp::Sub, + _ => unreachable!(), + }; + + // FIXME use vector instructions when possible + simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| { + crate::num::codegen_saturating_int_binop(fx, bin_op, x_lane, y_lane) + }); + } + + // simd_arith_offset // simd_scatter // simd_gather _ => { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 913414e7618..629d79d5012 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -96,8 +96,8 @@ mod prelude { pub(crate) use cranelift_codegen::ir::function::Function; pub(crate) use cranelift_codegen::ir::types; pub(crate) use cranelift_codegen::ir::{ - AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, - StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value, + AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, + StackSlotData, StackSlotKind, TrapCode, Type, Value, }; pub(crate) use cranelift_codegen::isa::{self, CallConv}; pub(crate) use cranelift_codegen::Context; @@ -251,7 +251,6 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box Box( BinOp::BitXor => b.bxor(lhs, rhs), BinOp::BitAnd => b.band(lhs, rhs), BinOp::BitOr => b.bor(lhs, rhs), - BinOp::Shl => { - let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - fx.bcx.ins().ishl(lhs, actual_shift) - } + BinOp::Shl => b.ishl(lhs, rhs), BinOp::Shr => { - let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); if signed { - fx.bcx.ins().sshr(lhs, actual_shift) + b.sshr(lhs, rhs) } else { - fx.bcx.ins().ushr(lhs, actual_shift) + b.ushr(lhs, rhs) } } // Compare binops handles by `codegen_binop`. @@ -279,22 +273,15 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( } } BinOp::Shl => { - let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let val = fx.bcx.ins().ishl(lhs, masked_shift); + let val = fx.bcx.ins().ishl(lhs, rhs); let ty = fx.bcx.func.dfg.value_type(val); let max_shift = i64::from(ty.bits()) - 1; let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); (val, has_overflow) } BinOp::Shr => { - let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let val = if !signed { - fx.bcx.ins().ushr(lhs, masked_shift) - } else { - fx.bcx.ins().sshr(lhs, masked_shift) - }; + let val = + if !signed { fx.bcx.ins().ushr(lhs, rhs) } else { fx.bcx.ins().sshr(lhs, rhs) }; let ty = fx.bcx.func.dfg.value_type(val); let max_shift = i64::from(ty.bits()) - 1; let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); @@ -309,6 +296,42 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( CValue::by_val_pair(res, has_overflow, out_layout) } +pub(crate) fn codegen_saturating_int_binop<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + bin_op: BinOp, + lhs: CValue<'tcx>, + rhs: CValue<'tcx>, +) -> CValue<'tcx> { + assert_eq!(lhs.layout().ty, rhs.layout().ty); + + let signed = type_sign(lhs.layout().ty); + let clif_ty = fx.clif_type(lhs.layout().ty).unwrap(); + let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed); + + let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs); + let (val, has_overflow) = checked_res.load_scalar_pair(fx); + + let val = match (bin_op, signed) { + (BinOp::Add, false) => fx.bcx.ins().select(has_overflow, max, val), + (BinOp::Sub, false) => fx.bcx.ins().select(has_overflow, min, val), + (BinOp::Add, true) => { + let rhs = rhs.load_scalar(fx); + let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); + let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min); + fx.bcx.ins().select(has_overflow, sat_val, val) + } + (BinOp::Sub, true) => { + let rhs = rhs.load_scalar(fx); + let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); + let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max); + fx.bcx.ins().select(has_overflow, sat_val, val) + } + _ => unreachable!(), + }; + + CValue::by_val(val, lhs.layout()) +} + pub(crate) fn codegen_float_binop<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, bin_op: BinOp, diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index dd9d891ddbd..9c88f7dbcda 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -25,7 +25,12 @@ pub(crate) fn unsized_info<'tcx>( .bcx .ins() .iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64), - (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { + ( + &ty::Dynamic(ref data_a, _, src_dyn_kind), + &ty::Dynamic(ref data_b, _, target_dyn_kind), + ) => { + assert_eq!(src_dyn_kind, target_dyn_kind); + let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { @@ -101,6 +106,21 @@ fn unsize_ptr<'tcx>( } } +/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type. +pub(crate) fn cast_to_dyn_star<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + src: Value, + src_ty_and_layout: TyAndLayout<'tcx>, + dst_ty: Ty<'tcx>, + old_info: Option, +) -> (Value, Value) { + assert!( + matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)), + "destination type must be a dyn*" + ); + (src, unsized_info(fx, src_ty_and_layout.ty, dst_ty, old_info)) +} + /// Coerce `src`, which is a reference to a value of type `src_ty`, /// to a value of type `dst_ty` and store the result in `dst` pub(crate) fn coerce_unsized_into<'tcx>( @@ -147,6 +167,24 @@ pub(crate) fn coerce_unsized_into<'tcx>( } } +pub(crate) fn coerce_dyn_star<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + src: CValue<'tcx>, + dst: CPlace<'tcx>, +) { + let (data, extra) = if let ty::Dynamic(_, _, ty::DynStar) = src.layout().ty.kind() { + let (data, vtable) = src.load_scalar_pair(fx); + (data, Some(vtable)) + } else { + let data = src.load_scalar(fx); + (data, None) + }; + + let (data, vtable) = cast_to_dyn_star(fx, data, src.layout(), dst.layout().ty, extra); + + dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout())); +} + // Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs pub(crate) fn size_and_align_of_dst<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 3fa3e3657cb..c3dfbd37279 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -107,6 +107,50 @@ impl<'tcx> CValue<'tcx> { } } + // FIXME remove + // Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the + // vtable pointer. + pub(crate) fn dyn_star_force_data_on_stack( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + ) -> (Value, Value) { + assert!(self.1.ty.is_dyn_star()); + + match self.0 { + CValueInner::ByRef(ptr, None) => { + let (a_scalar, b_scalar) = match self.1.abi { + Abi::ScalarPair(a, b) => (a, b), + _ => unreachable!("dyn_star_force_data_on_stack({:?})", self), + }; + let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); + let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar); + let mut flags = MemFlags::new(); + flags.set_notrap(); + let vtable = ptr.offset(fx, b_offset).load(fx, clif_ty2, flags); + (ptr.get_addr(fx), vtable) + } + CValueInner::ByValPair(data, vtable) => { + 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. + size: (u32::try_from(fx.target_config.pointer_type().bytes()).unwrap() + 15) + / 16 + * 16, + }); + let data_ptr = Pointer::stack_slot(stack_slot); + let mut flags = MemFlags::new(); + flags.set_notrap(); + data_ptr.store(fx, data, flags); + + (data_ptr.get_addr(fx), vtable) + } + CValueInner::ByRef(_, Some(_)) | CValueInner::ByVal(_) => { + unreachable!("dyn_star_force_data_on_stack({:?})", self) + } + } + } + pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option)> { match self.0 { CValueInner::ByRef(ptr, meta) => Some((ptr, meta)), @@ -236,6 +280,10 @@ impl<'tcx> CValue<'tcx> { crate::unsize::coerce_unsized_into(fx, self, dest); } + pub(crate) fn coerce_dyn_star(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) { + crate::unsize::coerce_dyn_star(fx, self, dest); + } + /// If `ty` is signed, `const_val` must already be sign extended. pub(crate) fn const_val( fx: &mut FunctionCx<'_, '_, 'tcx>, diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index 36b3725ef42..f04fb82de8c 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -45,12 +45,26 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, arg: CValue<'tcx>, idx: usize, -) -> (Value, Value) { - let (ptr, vtable) = if let Abi::ScalarPair(_, _) = arg.layout().abi { - arg.load_scalar_pair(fx) - } else { - let (ptr, vtable) = arg.try_to_ptr().unwrap(); - (ptr.get_addr(fx), vtable.unwrap()) +) -> (Pointer, Value) { + let (ptr, vtable) = 'block: { + if let ty::Ref(_, ty, _) = arg.layout().ty.kind() { + if ty.is_dyn_star() { + let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty); + let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout); + let ptr = dyn_star.place_field(fx, mir::Field::new(0)).to_ptr(); + let vtable = + dyn_star.place_field(fx, mir::Field::new(1)).to_cvalue(fx).load_scalar(fx); + break 'block (ptr, vtable); + } + } + + if let Abi::ScalarPair(_, _) = arg.layout().abi { + let (ptr, vtable) = arg.load_scalar_pair(fx); + (Pointer::new(ptr), vtable) + } else { + let (ptr, vtable) = arg.try_to_ptr().unwrap(); + (ptr, vtable.unwrap()) + } }; let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes(); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b9e0d48c9bc..8a0239eceff 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -259,7 +259,9 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "ahash", "anyhow", "ar", + "arrayvec", "autocfg", + "bumpalo", "bitflags", "byteorder", "cfg-if",