diff --git a/compiler/rustc_codegen_cranelift/.cirrus.yml b/compiler/rustc_codegen_cranelift/.cirrus.yml index d627c2ee09c..7886cae42a1 100644 --- a/compiler/rustc_codegen_cranelift/.cirrus.yml +++ b/compiler/rustc_codegen_cranelift/.cirrus.yml @@ -1,13 +1,11 @@ task: name: freebsd freebsd_instance: - image: freebsd-12-1-release-amd64 + image: freebsd-13-1-release-amd64 setup_rust_script: - pkg install -y curl git bash - curl https://sh.rustup.rs -sSf --output rustup.sh - sh rustup.sh --default-toolchain none -y --profile=minimal - cargo_bin_cache: - folder: ~/.cargo/bin target_cache: folder: target prepare_script: @@ -15,9 +13,4 @@ task: - ./y.rs prepare test_script: - . $HOME/.cargo/env - - # Enable backtraces for easier debugging - - export RUST_BACKTRACE=1 - - # Reduce amount of benchmark runs as they are slow - - export COMPILE_RUNS=2 - - export RUN_RUNS=2 - ./y.rs test diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index a6bb12a66a2..c0daf69e98e 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -25,6 +25,10 @@ jobs: runs-on: ${{ matrix.os }} timeout-minutes: 60 + defaults: + run: + shell: bash + strategy: fail-fast: false matrix: @@ -46,36 +50,31 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: s390x-unknown-linux-gnu + - os: windows-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-msvc + - os: windows-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - uses: actions/checkout@v3 - - name: Cache cargo installed crates - uses: actions/cache@v3 - with: - path: ~/.cargo/bin - key: ${{ runner.os }}-cargo-installed-crates - - - name: Cache cargo registry and index - uses: actions/cache@v3 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} - - name: Cache cargo target dir uses: actions/cache@v3 with: path: build/cg_clif - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Set MinGW as the default toolchain + if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' + run: rustup set default-host x86_64-pc-windows-gnu - name: Install MinGW toolchain and wine if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: | sudo apt-get update sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable - rustup target add x86_64-pc-windows-gnu - name: Install AArch64 toolchain and qemu if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu' @@ -89,6 +88,13 @@ jobs: sudo apt-get update sudo apt-get install -y gcc-s390x-linux-gnu qemu-user + - name: Use sparse cargo registry + run: | + cat >> ~/.cargo/config.toml <> ~/.cargo/config.toml <> ~/.cargo/config.toml <> ~/.cargo/config.toml <", +); + +// Use a separate target dir for the initial LLVM build to reduce unnecessary recompiles +pub(crate) static SIMPLE_RAYTRACER_LLVM: CargoProject = + CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer_llvm"); + +pub(crate) static SIMPLE_RAYTRACER: CargoProject = + CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer"); + +pub(crate) fn benchmark(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { + benchmark_simple_raytracer(dirs, bootstrap_host_compiler); +} + +fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { + if std::process::Command::new("hyperfine").output().is_err() { + eprintln!("Hyperfine not installed"); + eprintln!("Hint: Try `cargo install hyperfine` to install hyperfine"); + std::process::exit(1); + } + + eprintln!("[LLVM BUILD] simple-raytracer"); + let build_cmd = SIMPLE_RAYTRACER_LLVM.build(bootstrap_host_compiler, dirs); + spawn_and_wait(build_cmd); + fs::copy( + SIMPLE_RAYTRACER_LLVM + .target_dir(dirs) + .join(&bootstrap_host_compiler.triple) + .join("debug") + .join(get_file_name("main", "bin")), + RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")), + ) + .unwrap(); + + let run_runs = env::var("RUN_RUNS") + .unwrap_or(if is_ci() { "2" } else { "10" }.to_string()) + .parse() + .unwrap(); + + eprintln!("[BENCH COMPILE] ebobby/simple-raytracer"); + let cargo_clif = + RelPath::DIST.to_path(dirs).join(get_file_name("cargo_clif", "bin").replace('_', "-")); + let manifest_path = SIMPLE_RAYTRACER.manifest_path(dirs); + let target_dir = SIMPLE_RAYTRACER.target_dir(dirs); + + let clean_cmd = format!( + "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}", + manifest_path = manifest_path.display(), + target_dir = target_dir.display(), + ); + let llvm_build_cmd = format!( + "cargo build --manifest-path {manifest_path} --target-dir {target_dir}", + manifest_path = manifest_path.display(), + target_dir = target_dir.display(), + ); + let clif_build_cmd = format!( + "{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}", + cargo_clif = cargo_clif.display(), + manifest_path = manifest_path.display(), + target_dir = target_dir.display(), + ); + + let bench_compile = + hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd); + + spawn_and_wait(bench_compile); + + eprintln!("[BENCH RUN] ebobby/simple-raytracer"); + fs::copy( + target_dir.join("debug").join(get_file_name("main", "bin")), + RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_clif", "bin")), + ) + .unwrap(); + + let mut bench_run = hyperfine_command( + 0, + run_runs, + None, + Path::new(".").join(get_file_name("raytracer_cg_llvm", "bin")).to_str().unwrap(), + Path::new(".").join(get_file_name("raytracer_cg_clif", "bin")).to_str().unwrap(), + ); + bench_run.current_dir(RelPath::BUILD.to_path(dirs)); + spawn_and_wait(bench_run); +} diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs index fde8ef424cc..514404305a3 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs @@ -5,15 +5,15 @@ use super::path::{Dirs, RelPath}; use super::rustc_info::get_file_name; use super::utils::{is_ci, CargoProject, Compiler}; -static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif"); +pub(crate) static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif"); pub(crate) fn build_backend( dirs: &Dirs, channel: &str, - host_triple: &str, + bootstrap_host_compiler: &Compiler, use_unstable_features: bool, ) -> PathBuf { - let mut cmd = CG_CLIF.build(&Compiler::host(), dirs); + let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs); cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode @@ -25,6 +25,8 @@ pub(crate) fn build_backend( // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway cmd.env("CARGO_BUILD_INCREMENTAL", "false"); + + cmd.env("CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS", "true"); } if use_unstable_features { @@ -46,7 +48,7 @@ pub(crate) fn build_backend( CG_CLIF .target_dir(dirs) - .join(host_triple) + .join(&bootstrap_host_compiler.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 cbbf09b9b97..bd04fdbe304 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -1,31 +1,32 @@ use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{self, Command}; use super::path::{Dirs, RelPath}; -use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name}; -use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler}; +use super::rustc_info::{get_file_name, get_rustc_version, get_toolchain_name}; +use super::utils::{remove_dir_if_exists, spawn_and_wait, try_hard_link, CargoProject, Compiler}; use super::SysrootKind; static DIST_DIR: RelPath = RelPath::DIST; static BIN_DIR: RelPath = RelPath::DIST.join("bin"); static LIB_DIR: RelPath = RelPath::DIST.join("lib"); -static RUSTLIB_DIR: RelPath = LIB_DIR.join("rustlib"); pub(crate) fn build_sysroot( dirs: &Dirs, channel: &str, sysroot_kind: SysrootKind, cg_clif_dylib_src: &Path, - host_triple: &str, - target_triple: &str, -) { + bootstrap_host_compiler: &Compiler, + target_triple: String, +) -> Compiler { eprintln!("[BUILD] sysroot {:?}", sysroot_kind); DIST_DIR.ensure_fresh(dirs); BIN_DIR.ensure_exists(dirs); LIB_DIR.ensure_exists(dirs); + let is_native = bootstrap_host_compiler.triple == target_triple; + // Copy the backend let cg_clif_dylib_path = if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the @@ -35,129 +36,169 @@ pub(crate) fn build_sysroot( LIB_DIR } .to_path(dirs) - .join(get_file_name("rustc_codegen_cranelift", "dylib")); + .join(cg_clif_dylib_src.file_name().unwrap()); try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path); // Build and copy rustc and cargo wrappers + let wrapper_base_name = get_file_name("____", "bin"); + let toolchain_name = get_toolchain_name(); for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] { - let wrapper_name = get_wrapper_file_name(wrapper, "bin"); + let wrapper_name = wrapper_base_name.replace("____", wrapper); - let mut build_cargo_wrapper_cmd = Command::new("rustc"); + let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc); build_cargo_wrapper_cmd + .env("TOOLCHAIN_NAME", toolchain_name.clone()) .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs"))) .arg("-o") .arg(DIST_DIR.to_path(dirs).join(wrapper_name)) - .arg("-g"); + .arg("-Cstrip=debuginfo"); spawn_and_wait(build_cargo_wrapper_cmd); } - let default_sysroot = super::rustc_info::get_default_sysroot(); + let host = build_sysroot_for_triple( + dirs, + channel, + bootstrap_host_compiler.clone(), + &cg_clif_dylib_path, + sysroot_kind, + ); + host.install_into_sysroot(&DIST_DIR.to_path(dirs)); - let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib"); - let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(target_triple).join("lib"); - fs::create_dir_all(&host_rustlib_lib).unwrap(); - fs::create_dir_all(&target_rustlib_lib).unwrap(); - - if target_triple == "x86_64-pc-windows-gnu" { - if !default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib").exists() { - eprintln!( - "The x86_64-pc-windows-gnu target needs to be installed first before it is possible \ - to compile a sysroot for it.", - ); - process::exit(1); - } - for file in fs::read_dir( - default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"), + if !is_native { + build_sysroot_for_triple( + dirs, + channel, + { + let mut bootstrap_target_compiler = bootstrap_host_compiler.clone(); + bootstrap_target_compiler.triple = target_triple.clone(); + bootstrap_target_compiler.set_cross_linker_and_runner(); + bootstrap_target_compiler + }, + &cg_clif_dylib_path, + sysroot_kind, ) - .unwrap() - { - let file = file.unwrap().path(); - if file.extension().map_or(true, |ext| ext.to_str().unwrap() != "o") { - continue; // only copy object files - } - try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap())); + .install_into_sysroot(&DIST_DIR.to_path(dirs)); + } + + // Copy std for the host to the lib dir. This is necessary for the jit mode to find + // libstd. + for lib in host.libs { + let filename = lib.file_name().unwrap().to_str().unwrap(); + if filename.contains("std-") && !filename.contains(".rlib") { + try_hard_link(&lib, LIB_DIR.to_path(dirs).join(lib.file_name().unwrap())); } } - match sysroot_kind { - SysrootKind::None => {} // Nothing to do - SysrootKind::Llvm => { - for file in fs::read_dir( - default_sysroot.join("lib").join("rustlib").join(host_triple).join("lib"), - ) - .unwrap() - { - let file = file.unwrap().path(); - let file_name_str = file.file_name().unwrap().to_str().unwrap(); - if (file_name_str.contains("rustc_") - && !file_name_str.contains("rustc_std_workspace_") - && !file_name_str.contains("rustc_demangle")) - || file_name_str.contains("chalk") - || file_name_str.contains("tracing") - || file_name_str.contains("regex") - { - // These are large crates that are part of the rustc-dev component and are not - // necessary to run regular programs. - continue; - } - try_hard_link(&file, host_rustlib_lib.join(file.file_name().unwrap())); - } + let mut target_compiler = { + let dirs: &Dirs = &dirs; + let rustc_clif = + RelPath::DIST.to_path(&dirs).join(wrapper_base_name.replace("____", "rustc-clif")); + let rustdoc_clif = + RelPath::DIST.to_path(&dirs).join(wrapper_base_name.replace("____", "rustdoc-clif")); - if target_triple != host_triple { - for file in fs::read_dir( - default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"), - ) - .unwrap() - { - let file = file.unwrap().path(); - try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap())); - } - } + Compiler { + cargo: bootstrap_host_compiler.cargo.clone(), + rustc: rustc_clif.clone(), + rustdoc: rustdoc_clif.clone(), + rustflags: String::new(), + rustdocflags: String::new(), + triple: target_triple, + runner: vec![], } - SysrootKind::Clif => { - build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, None); + }; + if !is_native { + target_compiler.set_cross_linker_and_runner(); + } + target_compiler +} - if host_triple != target_triple { - // When cross-compiling it is often necessary to manually pick the right linker - let linker = match target_triple { - "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"), - "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"), - _ => None, - }; - build_clif_sysroot_for_triple( - dirs, - channel, - target_triple, - &cg_clif_dylib_path, - linker, - ); - } +struct SysrootTarget { + triple: String, + libs: Vec, +} - // Copy std for the host to the lib dir. This is necessary for the jit mode to find - // libstd. - for file in fs::read_dir(host_rustlib_lib).unwrap() { - let file = file.unwrap().path(); - let filename = file.file_name().unwrap().to_str().unwrap(); - if filename.contains("std-") && !filename.contains(".rlib") { - try_hard_link(&file, LIB_DIR.to_path(dirs).join(file.file_name().unwrap())); - } - } +impl SysrootTarget { + fn install_into_sysroot(&self, sysroot: &Path) { + if self.libs.is_empty() { + return; + } + + let target_rustlib_lib = sysroot.join("lib").join("rustlib").join(&self.triple).join("lib"); + fs::create_dir_all(&target_rustlib_lib).unwrap(); + + for lib in &self.libs { + try_hard_link(lib, target_rustlib_lib.join(lib.file_name().unwrap())); } } } -// FIXME move to download/ or dist/ -pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = RelPath::BUILD_SYSROOT.join("rustc_version"); -pub(crate) static SYSROOT_SRC: RelPath = RelPath::BUILD_SYSROOT.join("sysroot_src"); -static STANDARD_LIBRARY: CargoProject = CargoProject::new(&RelPath::BUILD_SYSROOT, "build_sysroot"); +pub(crate) static ORIG_BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot"); +pub(crate) static BUILD_SYSROOT: RelPath = RelPath::DOWNLOAD.join("sysroot"); +pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = BUILD_SYSROOT.join("rustc_version"); +pub(crate) static SYSROOT_SRC: RelPath = BUILD_SYSROOT.join("sysroot_src"); +pub(crate) static STANDARD_LIBRARY: CargoProject = + CargoProject::new(&BUILD_SYSROOT, "build_sysroot"); +pub(crate) static RTSTARTUP_SYSROOT: RelPath = RelPath::BUILD.join("rtstartup"); +#[must_use] +fn build_sysroot_for_triple( + dirs: &Dirs, + channel: &str, + compiler: Compiler, + cg_clif_dylib_path: &Path, + sysroot_kind: SysrootKind, +) -> SysrootTarget { + match sysroot_kind { + SysrootKind::None => build_rtstartup(dirs, &compiler) + .unwrap_or(SysrootTarget { triple: compiler.triple, libs: vec![] }), + SysrootKind::Llvm => build_llvm_sysroot_for_triple(compiler), + SysrootKind::Clif => { + build_clif_sysroot_for_triple(dirs, channel, compiler, &cg_clif_dylib_path) + } + } +} + +#[must_use] +fn build_llvm_sysroot_for_triple(compiler: Compiler) -> SysrootTarget { + let default_sysroot = super::rustc_info::get_default_sysroot(&compiler.rustc); + + let mut target_libs = SysrootTarget { triple: compiler.triple, libs: vec![] }; + + for entry in fs::read_dir( + default_sysroot.join("lib").join("rustlib").join(&target_libs.triple).join("lib"), + ) + .unwrap() + { + let entry = entry.unwrap(); + if entry.file_type().unwrap().is_dir() { + continue; + } + let file = entry.path(); + let file_name_str = file.file_name().unwrap().to_str().unwrap(); + if (file_name_str.contains("rustc_") + && !file_name_str.contains("rustc_std_workspace_") + && !file_name_str.contains("rustc_demangle")) + || file_name_str.contains("chalk") + || file_name_str.contains("tracing") + || file_name_str.contains("regex") + { + // These are large crates that are part of the rustc-dev component and are not + // necessary to run regular programs. + continue; + } + target_libs.libs.push(file); + } + + target_libs +} + +#[must_use] fn build_clif_sysroot_for_triple( dirs: &Dirs, channel: &str, - triple: &str, + mut compiler: Compiler, cg_clif_dylib_path: &Path, - linker: Option<&str>, -) { +) -> SysrootTarget { match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) { Err(e) => { eprintln!("Failed to get rustc version for patched sysroot source: {}", e); @@ -165,7 +206,7 @@ fn build_clif_sysroot_for_triple( process::exit(1); } Ok(source_version) => { - let rustc_version = get_rustc_version(); + let rustc_version = get_rustc_version(&compiler.rustc); if source_version != rustc_version { eprintln!("The patched sysroot source is outdated"); eprintln!("Source version: {}", source_version.trim()); @@ -176,29 +217,32 @@ fn build_clif_sysroot_for_triple( } } - let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(triple).join(channel); + let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] }; + + if let Some(rtstartup_target_libs) = build_rtstartup(dirs, &compiler) { + rtstartup_target_libs.install_into_sysroot(&RTSTARTUP_SYSROOT.to_path(dirs)); + + target_libs.libs.extend(rtstartup_target_libs.libs); + } + + let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(&compiler.triple).join(channel); if !super::config::get_bool("keep_sysroot") { // Cleanup the deps dir, but keep build scripts and the incremental cache for faster // recompilation as they are not affected by changes in cg_clif. - if build_dir.join("deps").exists() { - fs::remove_dir_all(build_dir.join("deps")).unwrap(); - } + remove_dir_if_exists(&build_dir.join("deps")); } // Build sysroot - let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string(); + let mut rustflags = " -Zforce-unstable-if-unmarked -Cpanic=abort".to_string(); rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap())); - rustflags.push_str(&format!(" --sysroot={}", DIST_DIR.to_path(dirs).to_str().unwrap())); + // Necessary for MinGW to find rsbegin.o and rsend.o + rustflags + .push_str(&format!(" --sysroot={}", RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap())); if channel == "release" { rustflags.push_str(" -Zmir-opt-level=3"); } - if let Some(linker) = linker { - use std::fmt::Write; - write!(rustflags, " -Clinker={}", linker).unwrap(); - } - let mut compiler = Compiler::with_triple(triple.to_owned()); - compiler.rustflags = rustflags; + compiler.rustflags += &rustflags; let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs); if channel == "release" { build_cmd.arg("--release"); @@ -206,7 +250,6 @@ fn build_clif_sysroot_for_triple( build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); spawn_and_wait(build_cmd); - // Copy all relevant files to the sysroot for entry in fs::read_dir(build_dir.join("deps")).unwrap() { let entry = entry.unwrap(); if let Some(ext) = entry.path().extension() { @@ -216,9 +259,35 @@ fn build_clif_sysroot_for_triple( } else { continue; }; - try_hard_link( - entry.path(), - RUSTLIB_DIR.to_path(dirs).join(triple).join("lib").join(entry.file_name()), - ); + target_libs.libs.push(entry.path()); } + + target_libs +} + +fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option { + if !compiler.triple.ends_with("windows-gnu") { + return None; + } + + RTSTARTUP_SYSROOT.ensure_fresh(dirs); + + let rtstartup_src = SYSROOT_SRC.to_path(dirs).join("library").join("rtstartup"); + let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] }; + + for file in ["rsbegin", "rsend"] { + let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o")); + let mut build_rtstartup_cmd = Command::new(&compiler.rustc); + build_rtstartup_cmd + .arg("--target") + .arg(&compiler.triple) + .arg("--emit=obj") + .arg("-o") + .arg(&obj) + .arg(rtstartup_src.join(format!("{file}.rs"))); + spawn_and_wait(build_rtstartup_cmd); + target_libs.libs.push(obj.clone()); + } + + Some(target_libs) } diff --git a/compiler/rustc_codegen_cranelift/build_system/mod.rs b/compiler/rustc_codegen_cranelift/build_system/mod.rs index 1afc9a55c73..8dcbe8de189 100644 --- a/compiler/rustc_codegen_cranelift/build_system/mod.rs +++ b/compiler/rustc_codegen_cranelift/build_system/mod.rs @@ -2,9 +2,10 @@ use std::env; use std::path::PathBuf; use std::process; -use self::utils::is_ci; +use self::utils::{is_ci, Compiler}; mod abi_cafe; +mod bench; mod build_backend; mod build_sysroot; mod config; @@ -14,31 +15,8 @@ mod rustc_info; mod tests; mod utils; -const USAGE: &str = r#"The build system of cg_clif. - -USAGE: - ./y.rs prepare [--out-dir DIR] - ./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features] - ./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features] - -OPTIONS: - --sysroot none|clif|llvm - Which sysroot libraries to use: - `none` will not include any standard library in the sysroot. - `clif` will build the standard library using Cranelift. - `llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM. - - --out-dir DIR - Specify the directory in which the download, build and dist directories are stored. - By default this is the working directory. - - --no-unstable-features - fSome features are not yet ready for production usage. This option will disable these - features. This includes the JIT mode and inline assembly support. -"#; - fn usage() { - eprintln!("{USAGE}"); + eprintln!("{}", include_str!("usage.txt")); } macro_rules! arg_error { @@ -54,6 +32,8 @@ enum Command { Prepare, Build, Test, + AbiCafe, + Bench, } #[derive(Copy, Clone, Debug)] @@ -64,12 +44,17 @@ pub(crate) enum SysrootKind { } pub fn main() { - env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1"); + if env::var("RUST_BACKTRACE").is_err() { + env::set_var("RUST_BACKTRACE", "1"); + } env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1"); 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"); + + // Enable the Cranelift verifier + env::set_var("CG_CLIF_ENABLE_VERIFIER", "1"); } let mut args = env::args().skip(1); @@ -77,6 +62,8 @@ pub fn main() { Some("prepare") => Command::Prepare, Some("build") => Command::Build, Some("test") => Command::Test, + Some("abi-cafe") => Command::AbiCafe, + Some("bench") => Command::Bench, Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { @@ -112,24 +99,16 @@ pub fn main() { } } - let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { - host_triple - } else if let Some(host_triple) = config::get_value("host") { - host_triple - } else { - rustc_info::get_host_triple() - }; - let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { - if target_triple != "" { - target_triple - } else { - host_triple.clone() // Empty target triple can happen on GHA - } - } else if let Some(target_triple) = config::get_value("target") { - target_triple - } else { - host_triple.clone() - }; + let bootstrap_host_compiler = Compiler::bootstrap_with_triple( + std::env::var("HOST_TRIPLE") + .ok() + .or_else(|| config::get_value("host")) + .unwrap_or_else(|| rustc_info::get_host_triple()), + ); + let target_triple = std::env::var("TARGET_TRIPLE") + .ok() + .or_else(|| config::get_value("target")) + .unwrap_or_else(|| bootstrap_host_compiler.triple.clone()); // FIXME allow changing the location of these dirs using cli arguments let current_dir = std::env::current_dir().unwrap(); @@ -157,8 +136,15 @@ pub fn main() { process::exit(0); } - let cg_clif_dylib = - build_backend::build_backend(&dirs, channel, &host_triple, use_unstable_features); + env::set_var("RUSTC", "rustc_should_be_set_explicitly"); + env::set_var("RUSTDOC", "rustdoc_should_be_set_explicitly"); + + let cg_clif_dylib = build_backend::build_backend( + &dirs, + channel, + &bootstrap_host_compiler, + use_unstable_features, + ); match command { Command::Prepare => { // Handled above @@ -169,28 +155,37 @@ pub fn main() { channel, sysroot_kind, &cg_clif_dylib, - &host_triple, - &target_triple, - ); - - abi_cafe::run( - channel, - sysroot_kind, - &dirs, - &cg_clif_dylib, - &host_triple, - &target_triple, + &bootstrap_host_compiler, + target_triple.clone(), ); } + Command::AbiCafe => { + if bootstrap_host_compiler.triple != target_triple { + eprintln!("Abi-cafe doesn't support cross-compilation"); + process::exit(1); + } + abi_cafe::run(channel, sysroot_kind, &dirs, &cg_clif_dylib, &bootstrap_host_compiler); + } Command::Build => { build_sysroot::build_sysroot( &dirs, channel, sysroot_kind, &cg_clif_dylib, - &host_triple, - &target_triple, + &bootstrap_host_compiler, + target_triple, ); } + Command::Bench => { + build_sysroot::build_sysroot( + &dirs, + channel, + sysroot_kind, + &cg_clif_dylib, + &bootstrap_host_compiler, + target_triple, + ); + bench::benchmark(&dirs, &bootstrap_host_compiler); + } } } diff --git a/compiler/rustc_codegen_cranelift/build_system/path.rs b/compiler/rustc_codegen_cranelift/build_system/path.rs index e93981f1d64..3290723005d 100644 --- a/compiler/rustc_codegen_cranelift/build_system/path.rs +++ b/compiler/rustc_codegen_cranelift/build_system/path.rs @@ -1,6 +1,8 @@ use std::fs; use std::path::PathBuf; +use super::utils::remove_dir_if_exists; + #[derive(Debug, Clone)] pub(crate) struct Dirs { pub(crate) source_dir: PathBuf, @@ -42,7 +44,6 @@ impl RelPath { pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist); pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts"); - pub(crate) const BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot"); pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches"); pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath { @@ -62,9 +63,7 @@ impl RelPath { pub(crate) fn ensure_fresh(&self, dirs: &Dirs) { let path = self.to_path(dirs); - if path.exists() { - fs::remove_dir_all(&path).unwrap(); - } + remove_dir_if_exists(&path); fs::create_dir_all(path).unwrap(); } } diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index 8ac67e8f942..f25a81dc234 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -3,73 +3,55 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -use super::build_sysroot::{SYSROOT_RUSTC_VERSION, SYSROOT_SRC}; +use super::build_sysroot::{BUILD_SYSROOT, ORIG_BUILD_SYSROOT, SYSROOT_RUSTC_VERSION, SYSROOT_SRC}; use super::path::{Dirs, RelPath}; -use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; -use super::utils::{copy_dir_recursively, spawn_and_wait, Compiler}; +use super::rustc_info::{get_default_sysroot, get_rustc_version}; +use super::utils::{copy_dir_recursively, git_command, retry_spawn_and_wait, spawn_and_wait}; pub(crate) fn prepare(dirs: &Dirs) { - if RelPath::DOWNLOAD.to_path(dirs).exists() { - std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap(); - } - std::fs::create_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap(); + RelPath::DOWNLOAD.ensure_fresh(dirs); + + spawn_and_wait(super::build_backend::CG_CLIF.fetch("cargo", dirs)); prepare_sysroot(dirs); - - // FIXME maybe install this only locally? - eprintln!("[INSTALL] hyperfine"); - Command::new("cargo") - .arg("install") - .arg("hyperfine") - .env_remove("CARGO_TARGET_DIR") - .spawn() - .unwrap() - .wait() - .unwrap(); + spawn_and_wait(super::build_sysroot::STANDARD_LIBRARY.fetch("cargo", dirs)); + spawn_and_wait(super::tests::LIBCORE_TESTS.fetch("cargo", dirs)); super::abi_cafe::ABI_CAFE_REPO.fetch(dirs); + spawn_and_wait(super::abi_cafe::ABI_CAFE.fetch("cargo", dirs)); super::tests::RAND_REPO.fetch(dirs); + spawn_and_wait(super::tests::RAND.fetch("cargo", dirs)); super::tests::REGEX_REPO.fetch(dirs); + spawn_and_wait(super::tests::REGEX.fetch("cargo", dirs)); super::tests::PORTABLE_SIMD_REPO.fetch(dirs); - super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs); - - eprintln!("[LLVM BUILD] simple-raytracer"); - let host_compiler = Compiler::host(); - let build_cmd = super::tests::SIMPLE_RAYTRACER.build(&host_compiler, dirs); - spawn_and_wait(build_cmd); - fs::copy( - super::tests::SIMPLE_RAYTRACER - .target_dir(dirs) - .join(&host_compiler.triple) - .join("debug") - .join(get_file_name("main", "bin")), - RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")), - ) - .unwrap(); + spawn_and_wait(super::tests::PORTABLE_SIMD.fetch("cargo", dirs)); + super::bench::SIMPLE_RAYTRACER_REPO.fetch(dirs); + spawn_and_wait(super::bench::SIMPLE_RAYTRACER.fetch("cargo", dirs)); } fn prepare_sysroot(dirs: &Dirs) { - let rustc_path = get_rustc_path(); - let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust"); - let sysroot_src = SYSROOT_SRC; - + let sysroot_src_orig = get_default_sysroot(Path::new("rustc")).join("lib/rustlib/src/rust"); assert!(sysroot_src_orig.exists()); - sysroot_src.ensure_fresh(dirs); - fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap(); eprintln!("[COPY] sysroot src"); + + // FIXME ensure builds error out or update the copy if any of the files copied here change + BUILD_SYSROOT.ensure_fresh(dirs); + copy_dir_recursively(&ORIG_BUILD_SYSROOT.to_path(dirs), &BUILD_SYSROOT.to_path(dirs)); + + fs::create_dir_all(SYSROOT_SRC.to_path(dirs).join("library")).unwrap(); copy_dir_recursively( &sysroot_src_orig.join("library"), - &sysroot_src.to_path(dirs).join("library"), + &SYSROOT_SRC.to_path(dirs).join("library"), ); - let rustc_version = get_rustc_version(); + let rustc_version = get_rustc_version(Path::new("rustc")); fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &rustc_version).unwrap(); eprintln!("[GIT] init"); - init_git_repo(&sysroot_src.to_path(dirs)); + init_git_repo(&SYSROOT_SRC.to_path(dirs)); - apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs)); + apply_patches(dirs, "sysroot", &SYSROOT_SRC.to_path(dirs)); } pub(crate) struct GitRepo { @@ -118,14 +100,14 @@ impl GitRepo { 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(&download_dir).spawn().unwrap().wait().unwrap(); + git_command(None, "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(&download_dir); + let mut clean_cmd = git_command(download_dir, "checkout"); + clean_cmd.arg("--").arg("."); spawn_and_wait(clean_cmd); - let mut checkout_cmd = Command::new("git"); - checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir); + let mut checkout_cmd = git_command(download_dir, "checkout"); + checkout_cmd.arg("-q").arg(rev); spawn_and_wait(checkout_cmd); } @@ -149,8 +131,22 @@ fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo: // Download zip archive let mut download_cmd = Command::new("curl"); - download_cmd.arg("--location").arg("--output").arg(&archive_file).arg(archive_url); - spawn_and_wait(download_cmd); + download_cmd + .arg("--max-time") + .arg("600") + .arg("-y") + .arg("30") + .arg("-Y") + .arg("10") + .arg("--connect-timeout") + .arg("30") + .arg("--continue-at") + .arg("-") + .arg("--location") + .arg("--output") + .arg(&archive_file) + .arg(archive_url); + retry_spawn_and_wait(5, download_cmd); // Unpack tar archive let mut unpack_cmd = Command::new("tar"); @@ -167,25 +163,16 @@ fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo: } fn init_git_repo(repo_dir: &Path) { - let mut git_init_cmd = Command::new("git"); - git_init_cmd.arg("init").arg("-q").current_dir(repo_dir); + let mut git_init_cmd = git_command(repo_dir, "init"); + git_init_cmd.arg("-q"); spawn_and_wait(git_init_cmd); - let mut git_add_cmd = Command::new("git"); - git_add_cmd.arg("add").arg(".").current_dir(repo_dir); + let mut git_add_cmd = git_command(repo_dir, "add"); + git_add_cmd.arg("."); spawn_and_wait(git_add_cmd); - let mut git_commit_cmd = Command::new("git"); - git_commit_cmd - .arg("-c") - .arg("user.name=Dummy") - .arg("-c") - .arg("user.email=dummy@example.com") - .arg("commit") - .arg("-m") - .arg("Initial commit") - .arg("-q") - .current_dir(repo_dir); + let mut git_commit_cmd = git_command(repo_dir, "commit"); + git_commit_cmd.arg("-m").arg("Initial commit").arg("-q"); spawn_and_wait(git_commit_cmd); } @@ -220,16 +207,8 @@ fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) { target_dir.file_name().unwrap(), patch.file_name().unwrap() ); - let mut apply_patch_cmd = Command::new("git"); - apply_patch_cmd - .arg("-c") - .arg("user.name=Dummy") - .arg("-c") - .arg("user.email=dummy@example.com") - .arg("am") - .arg(patch) - .arg("-q") - .current_dir(target_dir); + let mut apply_patch_cmd = git_command(target_dir, "am"); + apply_patch_cmd.arg(patch).arg("-q"); spawn_and_wait(apply_patch_cmd); } } diff --git a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs index 8e5ab688e13..a70453b4422 100644 --- a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs +++ b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs @@ -1,9 +1,9 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -pub(crate) fn get_rustc_version() -> String { +pub(crate) fn get_rustc_version(rustc: &Path) -> String { let version_info = - Command::new("rustc").stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout; + Command::new(rustc).stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout; String::from_utf8(version_info).unwrap() } @@ -23,6 +23,16 @@ pub(crate) fn get_host_triple() -> String { .to_owned() } +pub(crate) fn get_toolchain_name() -> String { + let active_toolchain = Command::new("rustup") + .stderr(Stdio::inherit()) + .args(&["show", "active-toolchain"]) + .output() + .unwrap() + .stdout; + String::from_utf8(active_toolchain).unwrap().trim().split_once(' ').unwrap().0.to_owned() +} + pub(crate) fn get_cargo_path() -> PathBuf { let cargo_path = Command::new("rustup") .stderr(Stdio::inherit()) @@ -53,8 +63,8 @@ pub(crate) fn get_rustdoc_path() -> PathBuf { Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned() } -pub(crate) fn get_default_sysroot() -> PathBuf { - let default_sysroot = Command::new("rustc") +pub(crate) fn get_default_sysroot(rustc: &Path) -> PathBuf { + let default_sysroot = Command::new(rustc) .stderr(Stdio::inherit()) .args(&["--print", "sysroot"]) .output() @@ -83,12 +93,3 @@ 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 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 index 1c372736ed6..dcfadd73756 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -1,11 +1,10 @@ -use super::build_sysroot; +use super::bench::SIMPLE_RAYTRACER; +use super::build_sysroot::{self, SYSROOT_SRC}; use super::config; use super::path::{Dirs, RelPath}; use super::prepare::GitRepo; -use super::rustc_info::{get_cargo_path, get_wrapper_file_name}; -use super::utils::{ - hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler, -}; +use super::rustc_info::get_host_triple; +use super::utils::{spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler}; use super::SysrootKind; use std::env; use std::ffi::OsStr; @@ -17,256 +16,111 @@ static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example"); struct TestCase { config: &'static str, - func: &'static dyn Fn(&TestRunner), + cmd: TestCaseCmd, +} + +enum TestCaseCmd { + Custom { func: &'static dyn Fn(&TestRunner) }, + BuildLib { source: &'static str, crate_types: &'static str }, + BuildBinAndRun { source: &'static str, args: &'static [&'static str] }, + JitBin { source: &'static str, args: &'static str }, } impl TestCase { - const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self { - Self { config, func } + // FIXME reduce usage of custom test case commands + const fn custom(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self { + Self { config, cmd: TestCaseCmd::Custom { func } } + } + + const fn build_lib( + config: &'static str, + source: &'static str, + crate_types: &'static str, + ) -> Self { + Self { config, cmd: TestCaseCmd::BuildLib { source, crate_types } } + } + + const fn build_bin_and_run( + config: &'static str, + source: &'static str, + args: &'static [&'static str], + ) -> Self { + Self { config, cmd: TestCaseCmd::BuildBinAndRun { source, args } } + } + + const fn jit_bin(config: &'static str, source: &'static str, args: &'static str) -> Self { + Self { config, cmd: TestCaseCmd::JitBin { source, args } } } } 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_compiler.triple, - ]); - }), - TestCase::new("build.example", &|runner| { - runner.run_rustc([ - "example/example.rs", - "--crate-type", - "lib", - "--target", - &runner.target_compiler.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.target_compiler.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.target_compiler.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_compiler.triple, - ]); - runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]); - }), + TestCase::build_lib("build.mini_core", "example/mini_core.rs", "lib,dylib"), + TestCase::build_lib("build.example", "example/example.rs", "lib"), + TestCase::jit_bin("jit.mini_core_hello_world", "example/mini_core_hello_world.rs", "abc bcd"), + TestCase::build_bin_and_run( + "aot.mini_core_hello_world", + "example/mini_core_hello_world.rs", + &["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_compiler.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_compiler.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_compiler.triple, - ]); - }), - TestCase::new("aot.alloc_example", &|runner| { - runner.run_rustc([ - "example/alloc_example.rs", - "--crate-type", - "bin", - "--target", - &runner.target_compiler.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.target_compiler.triple, - ]); - - eprintln!("[JIT-lazy] std_example"); - runner.run_rustc([ - "-Zunstable-options", - "-Cllvm-args=mode=jit-lazy", - "-Cprefer-dynamic", - "example/std_example.rs", - "--target", - &runner.target_compiler.triple, - ]); - }), - TestCase::new("aot.std_example", &|runner| { - runner.run_rustc([ - "example/std_example.rs", - "--crate-type", - "bin", - "--target", - &runner.target_compiler.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_compiler.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_compiler.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_compiler.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_compiler.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_compiler.triple, - ]); - runner.run_out_command("mod_bench", []); - }), - TestCase::new("aot.issue-72793", &|runner| { - runner.run_rustc([ - "example/issue-72793.rs", - "--crate-type", - "bin", - "--target", - &runner.target_compiler.triple, - ]); - runner.run_out_command("issue-72793", []); - }), + TestCase::build_bin_and_run( + "aot.arbitrary_self_types_pointers_and_wrappers", + "example/arbitrary_self_types_pointers_and_wrappers.rs", + &[], + ), + TestCase::build_bin_and_run( + "aot.issue_91827_extern_types", + "example/issue-91827-extern-types.rs", + &[], + ), + TestCase::build_lib("build.alloc_system", "example/alloc_system.rs", "lib"), + TestCase::build_bin_and_run("aot.alloc_example", "example/alloc_example.rs", &[]), + TestCase::jit_bin("jit.std_example", "example/std_example.rs", ""), + TestCase::build_bin_and_run("aot.std_example", "example/std_example.rs", &["arg"]), + TestCase::build_bin_and_run("aot.dst_field_align", "example/dst-field-align.rs", &[]), + TestCase::build_bin_and_run( + "aot.subslice-patterns-const-eval", + "example/subslice-patterns-const-eval.rs", + &[], + ), + TestCase::build_bin_and_run( + "aot.track-caller-attribute", + "example/track-caller-attribute.rs", + &[], + ), + TestCase::build_bin_and_run("aot.float-minmax-pass", "example/float-minmax-pass.rs", &[]), + TestCase::build_bin_and_run("aot.mod_bench", "example/mod_bench.rs", &[]), + TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]), ]; pub(crate) static RAND_REPO: GitRepo = GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand"); -static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand"); +pub(crate) static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand"); pub(crate) static REGEX_REPO: GitRepo = GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex"); -static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex"); +pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex"); pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github( "rust-lang", "portable-simd", - "d5cd4a8112d958bd3a252327e0d069a6363249bd", + "582239ac3b32007613df04d7ffa78dc30f4c5645", "portable-simd", ); -static PORTABLE_SIMD: CargoProject = +pub(crate) static PORTABLE_SIMD: CargoProject = CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd"); -pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github( - "ebobby", - "simple-raytracer", - "804a7a21b9e673a482797aa289a18ed480e4d813", - "", -); - -pub(crate) static SIMPLE_RAYTRACER: CargoProject = - CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer"); - -static LIBCORE_TESTS: CargoProject = - CargoProject::new(&RelPath::BUILD_SYSROOT.join("sysroot_src/library/core/tests"), "core_tests"); +pub(crate) static LIBCORE_TESTS: CargoProject = + CargoProject::new(&SYSROOT_SRC.join("library/core/tests"), "core_tests"); const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ - TestCase::new("test.rust-random/rand", &|runner| { - spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs)); + TestCase::custom("test.rust-random/rand", &|runner| { + RAND.clean(&runner.dirs); if runner.is_native { eprintln!("[TEST] rust-random/rand"); @@ -280,60 +134,12 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::new("bench.simple-raytracer", &|runner| { - let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap(); - - if runner.is_native { - eprintln!("[BENCH COMPILE] ebobby/simple-raytracer"); - let cargo_clif = RelPath::DIST - .to_path(&runner.dirs) - .join(get_wrapper_file_name("cargo-clif", "bin")); - let manifest_path = SIMPLE_RAYTRACER.manifest_path(&runner.dirs); - let target_dir = SIMPLE_RAYTRACER.target_dir(&runner.dirs); - - let clean_cmd = format!( - "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}", - manifest_path = manifest_path.display(), - target_dir = target_dir.display(), - ); - let llvm_build_cmd = format!( - "cargo build --manifest-path {manifest_path} --target-dir {target_dir}", - manifest_path = manifest_path.display(), - target_dir = target_dir.display(), - ); - let clif_build_cmd = format!( - "{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}", - cargo_clif = cargo_clif.display(), - manifest_path = manifest_path.display(), - target_dir = target_dir.display(), - ); - - let bench_compile = - hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd); - - spawn_and_wait(bench_compile); - - eprintln!("[BENCH RUN] ebobby/simple-raytracer"); - fs::copy( - target_dir.join("debug").join("main"), - RelPath::BUILD.to_path(&runner.dirs).join("raytracer_cg_clif"), - ) - .unwrap(); - - let mut bench_run = - hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif"); - bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs)); - spawn_and_wait(bench_run); - } else { - spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs)); - eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)"); - eprintln!("[COMPILE] ebobby/simple-raytracer"); - spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs)); - eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)"); - } + TestCase::custom("test.simple-raytracer", &|runner| { + SIMPLE_RAYTRACER.clean(&runner.dirs); + spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs)); }), - TestCase::new("test.libcore", &|runner| { - spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs)); + TestCase::custom("test.libcore", &|runner| { + LIBCORE_TESTS.clean(&runner.dirs); if runner.is_native { spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs)); @@ -344,8 +150,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::new("test.regex-shootout-regex-dna", &|runner| { - spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs)); + TestCase::custom("test.regex-shootout-regex-dna", &|runner| { + REGEX.clean(&runner.dirs); // newer aho_corasick versions throw a deprecation warning let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags); @@ -364,9 +170,10 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"), ) .unwrap(); - let expected_path = - REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt"); - let expected = fs::read_to_string(&expected_path).unwrap(); + let expected = fs::read_to_string( + REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt"), + ) + .unwrap(); let output = spawn_and_wait_with_input(run_cmd, input); // Make sure `[codegen mono items] start` doesn't poison the diff @@ -379,27 +186,16 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ let output_matches = expected.lines().eq(output.lines()); if !output_matches { - let res_path = REGEX.source_dir(&runner.dirs).join("res.txt"); - fs::write(&res_path, &output).unwrap(); - - if cfg!(windows) { - println!("Output files don't match!"); - println!("Expected Output:\n{}", expected); - println!("Actual Output:\n{}", output); - } else { - let mut diff = Command::new("diff"); - diff.arg("-u"); - diff.arg(res_path); - diff.arg(expected_path); - spawn_and_wait(diff); - } + println!("Output files don't match!"); + println!("Expected Output:\n{}", expected); + println!("Actual Output:\n{}", output); std::process::exit(1); } } }), - TestCase::new("test.regex", &|runner| { - spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs)); + TestCase::custom("test.regex", &|runner| { + REGEX.clean(&runner.dirs); // newer aho_corasick versions throw a deprecation warning let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags); @@ -425,8 +221,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::new("test.portable-simd", &|runner| { - spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs)); + TestCase::custom("test.portable-simd", &|runner| { + PORTABLE_SIMD.clean(&runner.dirs); let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs); build_cmd.arg("--all-targets"); @@ -445,21 +241,22 @@ pub(crate) fn run_tests( channel: &str, sysroot_kind: SysrootKind, cg_clif_dylib: &Path, - host_triple: &str, - target_triple: &str, + bootstrap_host_compiler: &Compiler, + target_triple: String, ) { - let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string()); - if config::get_bool("testsuite.no_sysroot") { - build_sysroot::build_sysroot( + let target_compiler = build_sysroot::build_sysroot( dirs, channel, SysrootKind::None, cg_clif_dylib, - &host_triple, - &target_triple, + bootstrap_host_compiler, + target_triple.clone(), ); + let runner = + TestRunner::new(dirs.clone(), target_compiler, get_host_triple() == target_triple); + BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs); runner.run_testsuite(NO_SYSROOT_SUITE); } else { @@ -470,26 +267,29 @@ pub(crate) fn run_tests( let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot"); if run_base_sysroot || run_extended_sysroot { - build_sysroot::build_sysroot( + let target_compiler = build_sysroot::build_sysroot( dirs, channel, sysroot_kind, cg_clif_dylib, - &host_triple, - &target_triple, + bootstrap_host_compiler, + target_triple.clone(), ); - } - if run_base_sysroot { - runner.run_testsuite(BASE_SYSROOT_SUITE); - } else { - eprintln!("[SKIP] base_sysroot tests"); - } + let runner = + TestRunner::new(dirs.clone(), target_compiler, get_host_triple() == target_triple); - if run_extended_sysroot { - runner.run_testsuite(EXTENDED_SYSROOT_SUITE); - } else { - eprintln!("[SKIP] extended_sysroot tests"); + 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"); + } } } @@ -497,84 +297,34 @@ struct TestRunner { is_native: bool, jit_supported: bool, dirs: Dirs, - host_compiler: Compiler, target_compiler: Compiler, } impl TestRunner { - pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self { - let is_native = host_triple == target_triple; - let jit_supported = - target_triple.contains("x86_64") && is_native && !host_triple.contains("windows"); - - let rustc_clif = - RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustc-clif", "bin")); - let rustdoc_clif = - RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustdoc-clif", "bin")); - - let mut rustflags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); - let mut runner = vec![]; - - if !is_native { - match target_triple.as_str() { - "aarch64-unknown-linux-gnu" => { - // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags); - runner = vec![ - "qemu-aarch64".to_owned(), - "-L".to_owned(), - "/usr/aarch64-linux-gnu".to_owned(), - ]; - } - "s390x-unknown-linux-gnu" => { - // We are cross-compiling for s390x. Use the correct linker and run tests in qemu. - rustflags = format!("-Clinker=s390x-linux-gnu-gcc{}", rustflags); - runner = vec![ - "qemu-s390x".to_owned(), - "-L".to_owned(), - "/usr/s390x-linux-gnu".to_owned(), - ]; - } - "x86_64-pc-windows-gnu" => { - // We are cross-compiling for Windows. Run tests in wine. - runner = vec!["wine".to_owned()]; - } - _ => { - println!("Unknown non-native platform"); - } - } + pub fn new(dirs: Dirs, mut target_compiler: Compiler, is_native: bool) -> Self { + if let Ok(rustflags) = env::var("RUSTFLAGS") { + target_compiler.rustflags.push(' '); + target_compiler.rustflags.push_str(&rustflags); + } + if let Ok(rustdocflags) = env::var("RUSTDOCFLAGS") { + target_compiler.rustdocflags.push(' '); + target_compiler.rustdocflags.push_str(&rustdocflags); } // FIXME fix `#[linkage = "extern_weak"]` without this - if target_triple.contains("darwin") { - rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags); + if target_compiler.triple.contains("darwin") { + target_compiler.rustflags.push_str(" -Clink-arg=-undefined -Clink-arg=dynamic_lookup"); } - let host_compiler = Compiler { - cargo: get_cargo_path(), - rustc: rustc_clif.clone(), - rustdoc: rustdoc_clif.clone(), - rustflags: String::new(), - rustdocflags: String::new(), - triple: host_triple, - runner: vec![], - }; + let jit_supported = is_native + && target_compiler.triple.contains("x86_64") + && !target_compiler.triple.contains("windows"); - let target_compiler = Compiler { - cargo: get_cargo_path(), - rustc: rustc_clif, - rustdoc: rustdoc_clif, - rustflags: rustflags.clone(), - rustdocflags: rustflags, - triple: target_triple, - runner, - }; - - Self { is_native, jit_supported, dirs, host_compiler, target_compiler } + Self { is_native, jit_supported, dirs, target_compiler } } pub fn run_testsuite(&self, tests: &[TestCase]) { - for &TestCase { config, func } in tests { + for TestCase { config, cmd } in tests { let (tag, testname) = config.split_once('.').unwrap(); let tag = tag.to_uppercase(); let is_jit_test = tag == "JIT"; @@ -586,7 +336,47 @@ impl TestRunner { eprintln!("[{tag}] {testname}"); } - func(self); + match *cmd { + TestCaseCmd::Custom { func } => func(self), + TestCaseCmd::BuildLib { source, crate_types } => { + self.run_rustc([source, "--crate-type", crate_types]); + } + TestCaseCmd::BuildBinAndRun { source, args } => { + self.run_rustc([source]); + self.run_out_command( + source.split('/').last().unwrap().split('.').next().unwrap(), + args, + ); + } + TestCaseCmd::JitBin { source, args } => { + let mut jit_cmd = self.rustc_command([ + "-Zunstable-options", + "-Cllvm-args=mode=jit", + "-Cprefer-dynamic", + source, + "--cfg", + "jit", + ]); + if !args.is_empty() { + jit_cmd.env("CG_CLIF_JIT_ARGS", args); + } + spawn_and_wait(jit_cmd); + + eprintln!("[JIT-lazy] {testname}"); + let mut jit_cmd = self.rustc_command([ + "-Zunstable-options", + "-Cllvm-args=mode=jit-lazy", + "-Cprefer-dynamic", + source, + "--cfg", + "jit", + ]); + if !args.is_empty() { + jit_cmd.env("CG_CLIF_JIT_ARGS", args); + } + spawn_and_wait(jit_cmd); + } + } } } @@ -603,6 +393,9 @@ impl TestRunner { cmd.arg("--out-dir"); cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display())); cmd.arg("-Cdebuginfo=2"); + cmd.arg("--target"); + cmd.arg(&self.target_compiler.triple); + cmd.arg("-Cpanic=abort"); cmd.args(args); cmd } @@ -615,10 +408,7 @@ impl TestRunner { spawn_and_wait(self.rustc_command(args)); } - fn run_out_command<'a, I>(&self, name: &str, args: I) - where - I: IntoIterator, - { + fn run_out_command<'a>(&self, name: &str, args: &[&str]) { let mut full_cmd = vec![]; // Prepend the RUN_WRAPPER's @@ -630,7 +420,7 @@ impl TestRunner { BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(), ); - for arg in args.into_iter() { + for arg in args { full_cmd.push(arg.to_string()); } diff --git a/compiler/rustc_codegen_cranelift/build_system/usage.txt b/compiler/rustc_codegen_cranelift/build_system/usage.txt new file mode 100644 index 00000000000..ab98ccc35a5 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/usage.txt @@ -0,0 +1,35 @@ +The build system of cg_clif. + +USAGE: + ./y.rs prepare [--out-dir DIR] + ./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features] + ./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features] + ./y.rs abi-cafe [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features] + ./y.rs bench [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features] + +OPTIONS: + --debug + Build cg_clif and the standard library in debug mode rather than release mode. + Warning: An unoptimized cg_clif is very slow. + + --sysroot none|clif|llvm + Which sysroot libraries to use: + `none` will not include any standard library in the sysroot. + `clif` will build the standard library using Cranelift. + `llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM. + + --out-dir DIR + Specify the directory in which the download, build and dist directories are stored. + By default this is the working directory. + + --no-unstable-features + Some features are not yet ready for production usage. This option will disable these + features. This includes the JIT mode and inline assembly support. + +REQUIREMENTS: + * Rustup: The build system has a hard coded dependency on rustup to install the right nightly + version and make sure it is used where necessary. + * Git: `./y.rs prepare` uses git for applying patches and on Windows for downloading test repos. + * Curl and tar (non-Windows only): Used by `./y.rs prepare` to download a single commit for + repos. Git will be used to clone the whole repo when using Windows. + * [Hyperfine](https://github.com/sharkdp/hyperfine/): Used for benchmarking with `./y.rs bench`. diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs index 2be70e8e421..da2a94a0a4f 100644 --- a/compiler/rustc_codegen_cranelift/build_system/utils.rs +++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs @@ -1,12 +1,13 @@ use std::env; use std::fs; -use std::io::Write; +use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; use super::path::{Dirs, RelPath}; -use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path}; +use super::rustc_info::{get_cargo_path, get_rustc_path, get_rustdoc_path}; +#[derive(Clone, Debug)] pub(crate) struct Compiler { pub(crate) cargo: PathBuf, pub(crate) rustc: PathBuf, @@ -18,19 +19,7 @@ pub(crate) struct Compiler { } impl Compiler { - pub(crate) fn host() -> Compiler { - Compiler { - cargo: get_cargo_path(), - rustc: get_rustc_path(), - rustdoc: get_rustdoc_path(), - rustflags: String::new(), - rustdocflags: String::new(), - triple: get_host_triple(), - runner: vec![], - } - } - - pub(crate) fn with_triple(triple: String) -> Compiler { + pub(crate) fn bootstrap_with_triple(triple: String) -> Compiler { Compiler { cargo: get_cargo_path(), rustc: get_rustc_path(), @@ -41,6 +30,38 @@ impl Compiler { runner: vec![], } } + + pub(crate) fn set_cross_linker_and_runner(&mut self) { + match self.triple.as_str() { + "aarch64-unknown-linux-gnu" => { + // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. + self.rustflags += " -Clinker=aarch64-linux-gnu-gcc"; + self.rustdocflags += " -Clinker=aarch64-linux-gnu-gcc"; + self.runner = vec![ + "qemu-aarch64".to_owned(), + "-L".to_owned(), + "/usr/aarch64-linux-gnu".to_owned(), + ]; + } + "s390x-unknown-linux-gnu" => { + // We are cross-compiling for s390x. Use the correct linker and run tests in qemu. + self.rustflags += " -Clinker=s390x-linux-gnu-gcc"; + self.rustdocflags += " -Clinker=s390x-linux-gnu-gcc"; + self.runner = vec![ + "qemu-s390x".to_owned(), + "-L".to_owned(), + "/usr/s390x-linux-gnu".to_owned(), + ]; + } + "x86_64-pc-windows-gnu" => { + // We are cross-compiling for Windows. Run tests in wine. + self.runner = vec!["wine".to_owned()]; + } + _ => { + println!("Unknown non-native platform"); + } + } + } } pub(crate) struct CargoProject { @@ -65,6 +86,7 @@ impl CargoProject { RelPath::BUILD.join(self.target).to_path(dirs) } + #[must_use] fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command { let mut cmd = Command::new(cargo); @@ -72,11 +94,13 @@ impl CargoProject { .arg("--manifest-path") .arg(self.manifest_path(dirs)) .arg("--target-dir") - .arg(self.target_dir(dirs)); + .arg(self.target_dir(dirs)) + .arg("--frozen"); cmd } + #[must_use] fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command { let mut cmd = self.base_cmd(command, &compiler.cargo, dirs); @@ -105,9 +129,8 @@ impl CargoProject { cmd } - #[must_use] - pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command { - self.base_cmd("clean", cargo, dirs) + pub(crate) fn clean(&self, dirs: &Dirs) { + let _ = fs::remove_dir_all(self.target_dir(dirs)); } #[must_use] @@ -153,6 +176,23 @@ pub(crate) fn hyperfine_command( bench } +#[must_use] +pub(crate) fn git_command<'a>(repo_dir: impl Into>, cmd: &str) -> Command { + let mut git_cmd = Command::new("git"); + git_cmd + .arg("-c") + .arg("user.name=Dummy") + .arg("-c") + .arg("user.email=dummy@example.com") + .arg("-c") + .arg("core.autocrlf=false") + .arg(cmd); + if let Some(repo_dir) = repo_dir.into() { + git_cmd.current_dir(repo_dir); + } + git_cmd +} + #[track_caller] pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { let src = src.as_ref(); @@ -169,6 +209,22 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) { } } +// Based on the retry function in rust's src/ci/shared.sh +#[track_caller] +pub(crate) fn retry_spawn_and_wait(tries: u64, mut cmd: Command) { + for i in 1..tries + 1 { + if i != 1 { + println!("Command failed. Attempt {i}/{tries}:"); + } + if cmd.spawn().unwrap().wait().unwrap().success() { + return; + } + std::thread::sleep(std::time::Duration::from_secs(i * 5)); + } + println!("The command has failed after {tries} attempts."); + process::exit(1); +} + #[track_caller] pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> String { let mut child = cmd @@ -190,6 +246,14 @@ pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> Stri String::from_utf8(output.stdout).unwrap() } +pub(crate) fn remove_dir_if_exists(path: &Path) { + match fs::remove_dir_all(&path) { + Ok(()) => {} + Err(err) if err.kind() == io::ErrorKind::NotFound => {} + Err(err) => panic!("Failed to remove {path}: {err}", path = path.display()), + } +} + pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { for entry in fs::read_dir(from).unwrap() { let entry = entry.unwrap(); diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh index 1760e5836ec..cdfc2e143e6 100755 --- a/compiler/rustc_codegen_cranelift/clean_all.sh +++ b/compiler/rustc_codegen_cranelift/clean_all.sh @@ -1,10 +1,9 @@ #!/usr/bin/env bash set -e -rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} -rm -rf target/ build/ dist/ perf.data{,.old} y.bin -rm -rf download/ +rm -rf target/ download/ build/ dist/ y.bin y.bin.dSYM y.exe y.pdb # 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/ +rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt index 258b67e9314..d49cc90791a 100644 --- a/compiler/rustc_codegen_cranelift/config.txt +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -44,10 +44,8 @@ aot.issue-72793 testsuite.extended_sysroot test.rust-random/rand -bench.simple-raytracer +test.simple-raytracer test.libcore test.regex-shootout-regex-dna test.regex test.portable-simd - -testsuite.abi-cafe 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 deleted file mode 100644 index 89e2b61c1fc..00000000000 --- a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch +++ /dev/null @@ -1,35 +0,0 @@ -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/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/vector.rs b/crates/core_simd/src/vector.rs -index e8e8f68..7173c24 100644 ---- a/crates/core_simd/src/vector.rs -+++ b/crates/core_simd/src/vector.rs -@@ -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. - /// -@@ -473,6 +474,7 @@ where - // Cleared ☢️ *mut T Zone - } - } -+ */ - } - - impl Copy for Simd --- -2.25.1 diff --git a/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch index 8d9ee3f25c4..865aa833a5e 100644 --- a/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch @@ -18,7 +18,7 @@ new file mode 100644 index 0000000..46fd999 --- /dev/null +++ b/library/core/tests/Cargo.toml -@@ -0,0 +1,11 @@ +@@ -0,0 +1,12 @@ +[package] +name = "core" +version = "0.0.0" @@ -29,6 +29,7 @@ index 0000000..46fd999 +path = "lib.rs" + +[dependencies] -+rand = "0.7" ++rand = { version = "0.8.5", default-features = false } ++rand_xorshift = { version = "0.3.0", default-features = false } -- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index d8f28dbcc15..77345b9a17c 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-12-13" +channel = "nightly-2023-01-20" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs index 9362b47fa6d..c993430b830 100644 --- a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs @@ -26,7 +26,7 @@ fn main() { env::set_var("RUSTDOCFLAGS", env::var("RUSTDOCFLAGS").unwrap_or(String::new()) + &rustflags); // Ensure that the right toolchain is used - env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN")); + env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME")); let args: Vec<_> = match env::args().nth(1).as_deref() { Some("jit") => { diff --git a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs index 3abfcd8ddc8..c187f54a60e 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs @@ -24,7 +24,7 @@ fn main() { } // Ensure that the right toolchain is used - env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN")); + env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME")); #[cfg(unix)] Command::new("rustc").args(args).exec(); diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs index a19d72acfa8..a6528ac41ae 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs @@ -24,7 +24,7 @@ fn main() { } // Ensure that the right toolchain is used - env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN")); + env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME")); #[cfg(unix)] Command::new("rustdoc").args(args).exec(); diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index bc4c06ed7d2..34e3981b538 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -17,10 +17,10 @@ case $1 in done ./clean_all.sh + ./y.rs prepare - (cd build_sysroot && cargo update) - + (cd download/sysroot && cargo update && cargo fetch && cp Cargo.lock ../../build_sysroot/) ;; "commit") git add rust-toolchain build_sysroot/Cargo.lock diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index 6c64b7de7da..a08e80dd19a 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -10,7 +10,7 @@ git fetch git checkout -- . git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')" -git am ../patches/*-sysroot-*.patch +git -c user.name=Dummy -c user.email=dummy@example.com am ../patches/*-sysroot-*.patch git apply - < config.toml </dev/null 2>&1 || cargo install ripgrep rm -r tests/ui/{extern/,unsized-locals/,lto/,linkage*} || true -for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" tests/{ui,incremental}); do +for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" tests/{codegen-units,ui,incremental}); do rm $test done @@ -32,20 +32,13 @@ rm tests/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort # requires compiling with -Cpanic=unwind rm -r tests/ui/macros/rfc-2011-nicer-assert-messages/ rm -r tests/run-make/test-benches +rm tests/ui/test-attrs/test-type.rs # vendor intrinsics rm tests/ui/sse2.rs # cpuid not supported, so sse2 not detected rm tests/ui/intrinsics/const-eval-select-x86_64.rs # requires x86_64 vendor intrinsics rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant" -rm tests/ui/simd/intrinsic/generic-bitmask-pass.rs # simd_bitmask unimplemented -rm tests/ui/simd/intrinsic/generic-as.rs # simd_as unimplemented -rm tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs # simd_saturating_add unimplemented rm tests/ui/simd/intrinsic/float-math-pass.rs # simd_fcos unimplemented -rm tests/ui/simd/intrinsic/generic-gather-pass.rs # simd_gather unimplemented -rm tests/ui/simd/intrinsic/generic-select-pass.rs # simd_select_bitmask unimplemented -rm tests/ui/simd/issue-85915-simd-ptrs.rs # simd_gather unimplemented -rm tests/ui/simd/issue-89193.rs # simd_gather unimplemented -rm tests/ui/simd/simd-bitmask.rs # simd_bitmask unimplemented # exotic linkages rm tests/ui/issues/issue-33992.rs # unsupported linkages @@ -64,10 +57,7 @@ rm tests/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and near rm tests/ui/target-feature/missing-plusminus.rs # error not implemented rm tests/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment rm -r tests/run-make/emit-named-files # requires full --emit support -rm tests/ui/abi/stack-probes.rs # stack probes not yet implemented -rm tests/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented rm -r tests/run-make/repr128-dwarf # debuginfo test -rm tests/codegen-units/item-collection/asm-sym.rs # requires support for sym in asm!() # optimization tests # ================== @@ -88,6 +78,20 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same rm tests/ui/consts/issue-33537.rs # same rm tests/ui/layout/valid_range_oob.rs # different ICE message +rm tests/ui/consts/issue-miri-1910.rs # different error message +rm tests/ui/consts/offset_ub.rs # same +rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same +rm tests/ui/lint/lint-const-item-mutation.rs # same +rm tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs # same +rm tests/ui/suggestions/derive-trait-for-method-call.rs # same +rm tests/ui/typeck/issue-46112.rs # same + +rm tests/ui/proc-macro/crt-static.rs # extra warning about -Cpanic=abort for proc macros +rm tests/ui/proc-macro/proc-macro-deprecated-attr.rs # same +rm tests/ui/proc-macro/quote-debug.rs # same +rm tests/ui/proc-macro/no-missing-docs.rs # same +rm tests/ui/rust-2018/proc-macro-crate-in-paths.rs # same + # doesn't work due to the way the rustc test suite is invoked. # should work when using ./x.py test the way it is intended # ============================================================ @@ -102,23 +106,20 @@ rm -r tests/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to b # ============ rm tests/incremental/spike-neg1.rs # errors out for some reason rm tests/incremental/spike-neg2.rs # same -rm tests/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs -rm tests/ui/mir/ssa-analysis-regression-50041.rs # produces ICE -rm tests/ui/type-alias-impl-trait/assoc-projection-ice.rs # produces ICE rm tests/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors -rm tests/ui/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301) +rm tests/ui/simd/intrinsic/generic-as.rs # crash when accessing vector type filed (#1318) +rm tests/ui/simd/simd-bitmask.rs # crash + +rm tests/ui/dyn-star/dyn-star-to-dyn.rs +rm tests/ui/dyn-star/dispatch-on-pin-mut.rs # bugs in the test suite # ====================== rm tests/ui/backtrace.rs # TODO warning rm tests/ui/simple_global_asm.rs # TODO add needs-asm-support -rm tests/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout -# not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason -rm -r tests/run-make/native-link-modifier-bundle rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue -rm tests/ui/dyn-star/dispatch-on-pin-mut.rs # TODO failed assertion in vtable::get_ptr_and_method_ref rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 65cc6b43767..3c34585d419 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -7,6 +7,7 @@ mod returning; use cranelift_module::ModuleError; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::FnAbiOf; +use rustc_session::Session; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; @@ -22,7 +23,7 @@ fn clif_sig_from_fn_abi<'tcx>( default_call_conv: CallConv, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> Signature { - let call_conv = conv_to_call_conv(fn_abi.conv, default_call_conv); + let call_conv = conv_to_call_conv(tcx.sess, fn_abi.conv, default_call_conv); let inputs = fn_abi.args.iter().map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()).flatten(); @@ -33,24 +34,32 @@ fn clif_sig_from_fn_abi<'tcx>( Signature { params, returns, call_conv } } -pub(crate) fn conv_to_call_conv(c: Conv, default_call_conv: CallConv) -> CallConv { +pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: CallConv) -> CallConv { match c { Conv::Rust | Conv::C => default_call_conv, Conv::RustCold => CallConv::Cold, Conv::X86_64SysV => CallConv::SystemV, Conv::X86_64Win64 => CallConv::WindowsFastcall, - Conv::ArmAapcs - | Conv::CCmseNonSecureCall - | Conv::Msp430Intr + + // Should already get a back compat warning + Conv::X86Fastcall | Conv::X86Stdcall | Conv::X86ThisCall | Conv::X86VectorCall => { + default_call_conv + } + + Conv::X86Intr => sess.fatal("x86-interrupt call conv not yet implemented"), + + Conv::ArmAapcs => sess.fatal("aapcs call conv not yet implemented"), + Conv::CCmseNonSecureCall => { + sess.fatal("C-cmse-nonsecure-call call conv is not yet implemented"); + } + + Conv::Msp430Intr | Conv::PtxKernel - | Conv::X86Fastcall - | Conv::X86Intr - | Conv::X86Stdcall - | Conv::X86ThisCall - | Conv::X86VectorCall | Conv::AmdGpuKernel | Conv::AvrInterrupt - | Conv::AvrNonBlockingInterrupt => todo!("{:?}", c), + | Conv::AvrNonBlockingInterrupt => { + unreachable!("tried to use {c:?} call conv which only exists on an unsupported target"); + } } } @@ -161,6 +170,12 @@ fn make_local_place<'tcx>( layout: TyAndLayout<'tcx>, is_ssa: bool, ) -> CPlace<'tcx> { + if layout.is_unsized() { + fx.tcx.sess.span_fatal( + fx.mir.local_decls[local].source_info.span, + "unsized locals are not yet supported", + ); + } let place = if is_ssa { if let rustc_target::abi::Abi::ScalarPair(_, _) = layout.abi { CPlace::new_var_pair(fx, local, layout) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 89d955e8bf2..d3a8c10657e 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -113,6 +113,8 @@ pub(crate) fn codegen_fn<'tcx>( }; tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block)); + fx.bcx.seal_all_blocks(); + fx.bcx.finalize(); // Recover all necessary data from fx, before accessing func will prevent future access to it. let symbol_name = fx.symbol_name; @@ -303,6 +305,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { let source_info = bb_data.terminator().source_info; fx.set_debug_loc(source_info); + let _print_guard = + crate::PrintOnPanic(|| format!("terminator {:?}", bb_data.terminator().kind)); + match &bb_data.terminator().kind { TerminatorKind::Goto { target } => { if let TerminatorKind::Return = fx.mir[*target].terminator().kind { @@ -464,7 +469,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { *destination, ); } - TerminatorKind::Resume | TerminatorKind::Abort => { + TerminatorKind::Abort => { + codegen_panic_cannot_unwind(fx, source_info); + } + TerminatorKind::Resume => { // FIXME implement unwinding fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } @@ -487,9 +495,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } }; } - - fx.bcx.seal_all_blocks(); - fx.bcx.finalize(); } fn codegen_stmt<'tcx>( @@ -932,7 +937,28 @@ pub(crate) fn codegen_panic<'tcx>( codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, source_info.span); } -pub(crate) fn codegen_panic_inner<'tcx>( +pub(crate) fn codegen_panic_nounwind<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + msg_str: &str, + source_info: mir::SourceInfo, +) { + let msg_ptr = fx.anonymous_str(msg_str); + let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap()); + let args = [msg_ptr, msg_len]; + + codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span); +} + +pub(crate) fn codegen_panic_cannot_unwind<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + source_info: mir::SourceInfo, +) { + let args = []; + + codegen_panic_inner(fx, rustc_hir::LangItem::PanicCannotUnwind, &args, source_info.span); +} + +fn codegen_panic_inner<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, lang_item: rustc_hir::LangItem, args: &[Value], @@ -949,11 +975,7 @@ pub(crate) fn codegen_panic_inner<'tcx>( fx.lib_call( &*symbol_name, - vec![ - AbiParam::new(fx.pointer_type), - AbiParam::new(fx.pointer_type), - AbiParam::new(fx.pointer_type), - ], + args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(), vec![], args, ); diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 63ed10cdfcc..f41af3a9e63 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -168,6 +168,15 @@ pub(crate) fn codegen_icmp_imm( } } +pub(crate) fn codegen_bitcast(fx: &mut FunctionCx<'_, '_, '_>, dst_ty: Type, val: Value) -> Value { + let mut flags = MemFlags::new(); + flags.set_endianness(match fx.tcx.data_layout.endian { + rustc_target::abi::Endian::Big => cranelift_codegen::ir::Endianness::Big, + rustc_target::abi::Endian::Little => cranelift_codegen::ir::Endianness::Little, + }); + fx.bcx.ins().bitcast(dst_ty, flags, val) +} + pub(crate) fn type_zero_value(bcx: &mut FunctionBuilder<'_>, ty: Type) -> Value { if ty == types::I128 { let zero = bcx.ins().iconst(types::I64, 0); diff --git a/compiler/rustc_codegen_cranelift/src/cranelift_native.rs b/compiler/rustc_codegen_cranelift/src/cranelift_native.rs new file mode 100644 index 00000000000..6c4efca4424 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/src/cranelift_native.rs @@ -0,0 +1,248 @@ +// Vendored from https://github.com/bytecodealliance/wasmtime/blob/b58a197d33f044193c3d608010f5e6ec394ac07e/cranelift/native/src/lib.rs +// which is licensed as +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// unlike rustc_codegen_cranelift itself. Also applies a small change to remove #![cfg_attr] that +// rust's CI complains about and to fix formatting to match rustc. +// FIXME revert back to the external crate with Cranelift 0.93 +#![allow(warnings)] + +//! Performs autodetection of the host for the purposes of running +//! Cranelift to generate code to run on the same machine. + +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates, unstable_features)] +#![warn(unused_import_braces)] + +use cranelift_codegen::isa; +use target_lexicon::Triple; + +/// Return an `isa` builder configured for the current host +/// machine, or `Err(())` if the host machine is not supported +/// in the current configuration. +pub fn builder() -> Result { + builder_with_options(true) +} + +/// Return an `isa` builder configured for the current host +/// machine, or `Err(())` if the host machine is not supported +/// in the current configuration. +/// +/// Selects the given backend variant specifically; this is +/// useful when more than oen backend exists for a given target +/// (e.g., on x86-64). +pub fn builder_with_options(infer_native_flags: bool) -> Result { + let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err { + isa::LookupError::SupportDisabled => "support for architecture disabled at compile time", + isa::LookupError::Unsupported => "unsupported architecture", + })?; + + #[cfg(target_arch = "x86_64")] + { + use cranelift_codegen::settings::Configurable; + + if !std::is_x86_feature_detected!("sse2") { + return Err("x86 support requires SSE2"); + } + + if !infer_native_flags { + return Ok(isa_builder); + } + + // These are temporarily enabled by default (see #3810 for + // more) so that a default-constructed `Flags` can work with + // default Wasmtime features. Otherwise, the user must + // explicitly use native flags or turn these on when on x86-64 + // platforms to avoid a configuration panic. In order for the + // "enable if detected" logic below to work, we must turn them + // *off* (differing from the default) and then re-enable below + // if present. + isa_builder.set("has_sse3", "false").unwrap(); + isa_builder.set("has_ssse3", "false").unwrap(); + isa_builder.set("has_sse41", "false").unwrap(); + isa_builder.set("has_sse42", "false").unwrap(); + + if std::is_x86_feature_detected!("sse3") { + isa_builder.enable("has_sse3").unwrap(); + } + if std::is_x86_feature_detected!("ssse3") { + isa_builder.enable("has_ssse3").unwrap(); + } + if std::is_x86_feature_detected!("sse4.1") { + isa_builder.enable("has_sse41").unwrap(); + } + if std::is_x86_feature_detected!("sse4.2") { + isa_builder.enable("has_sse42").unwrap(); + } + if std::is_x86_feature_detected!("popcnt") { + isa_builder.enable("has_popcnt").unwrap(); + } + if std::is_x86_feature_detected!("avx") { + isa_builder.enable("has_avx").unwrap(); + } + if std::is_x86_feature_detected!("avx2") { + isa_builder.enable("has_avx2").unwrap(); + } + if std::is_x86_feature_detected!("fma") { + isa_builder.enable("has_fma").unwrap(); + } + if std::is_x86_feature_detected!("bmi1") { + isa_builder.enable("has_bmi1").unwrap(); + } + if std::is_x86_feature_detected!("bmi2") { + isa_builder.enable("has_bmi2").unwrap(); + } + if std::is_x86_feature_detected!("avx512bitalg") { + isa_builder.enable("has_avx512bitalg").unwrap(); + } + if std::is_x86_feature_detected!("avx512dq") { + isa_builder.enable("has_avx512dq").unwrap(); + } + if std::is_x86_feature_detected!("avx512f") { + isa_builder.enable("has_avx512f").unwrap(); + } + if std::is_x86_feature_detected!("avx512vl") { + isa_builder.enable("has_avx512vl").unwrap(); + } + if std::is_x86_feature_detected!("avx512vbmi") { + isa_builder.enable("has_avx512vbmi").unwrap(); + } + if std::is_x86_feature_detected!("lzcnt") { + isa_builder.enable("has_lzcnt").unwrap(); + } + } + + #[cfg(target_arch = "aarch64")] + { + use cranelift_codegen::settings::Configurable; + + if !infer_native_flags { + return Ok(isa_builder); + } + + if std::arch::is_aarch64_feature_detected!("lse") { + isa_builder.enable("has_lse").unwrap(); + } + + if std::arch::is_aarch64_feature_detected!("paca") { + isa_builder.enable("has_pauth").unwrap(); + } + + if cfg!(target_os = "macos") { + // Pointer authentication is always available on Apple Silicon. + isa_builder.enable("sign_return_address").unwrap(); + // macOS enforces the use of the B key for return addresses. + isa_builder.enable("sign_return_address_with_bkey").unwrap(); + } + } + + // There is no is_s390x_feature_detected macro yet, so for now + // we use getauxval from the libc crate directly. + #[cfg(all(target_arch = "s390x", target_os = "linux"))] + { + use cranelift_codegen::settings::Configurable; + + if !infer_native_flags { + return Ok(isa_builder); + } + + let v = unsafe { libc::getauxval(libc::AT_HWCAP) }; + const HWCAP_S390X_VXRS_EXT2: libc::c_ulong = 32768; + if (v & HWCAP_S390X_VXRS_EXT2) != 0 { + isa_builder.enable("has_vxrs_ext2").unwrap(); + // There is no separate HWCAP bit for mie2, so assume + // that any machine with vxrs_ext2 also has mie2. + isa_builder.enable("has_mie2").unwrap(); + } + } + + // `is_riscv_feature_detected` is nightly only for now, use + // getauxval from the libc crate directly as a temporary measure. + #[cfg(all(target_arch = "riscv64", target_os = "linux"))] + { + use cranelift_codegen::settings::Configurable; + + if !infer_native_flags { + return Ok(isa_builder); + } + + let v = unsafe { libc::getauxval(libc::AT_HWCAP) }; + + const HWCAP_RISCV_EXT_A: libc::c_ulong = 1 << (b'a' - b'a'); + const HWCAP_RISCV_EXT_C: libc::c_ulong = 1 << (b'c' - b'a'); + const HWCAP_RISCV_EXT_D: libc::c_ulong = 1 << (b'd' - b'a'); + const HWCAP_RISCV_EXT_F: libc::c_ulong = 1 << (b'f' - b'a'); + const HWCAP_RISCV_EXT_M: libc::c_ulong = 1 << (b'm' - b'a'); + const HWCAP_RISCV_EXT_V: libc::c_ulong = 1 << (b'v' - b'a'); + + if (v & HWCAP_RISCV_EXT_A) != 0 { + isa_builder.enable("has_a").unwrap(); + } + + if (v & HWCAP_RISCV_EXT_C) != 0 { + isa_builder.enable("has_c").unwrap(); + } + + if (v & HWCAP_RISCV_EXT_D) != 0 { + isa_builder.enable("has_d").unwrap(); + } + + if (v & HWCAP_RISCV_EXT_F) != 0 { + isa_builder.enable("has_f").unwrap(); + + // TODO: There doesn't seem to be a bit associated with this extension + // rust enables it with the `f` extension: + // https://github.com/rust-lang/stdarch/blob/790411f93c4b5eada3c23abb4c9a063fb0b24d99/crates/std_detect/src/detect/os/linux/riscv.rs#L43 + isa_builder.enable("has_zicsr").unwrap(); + } + + if (v & HWCAP_RISCV_EXT_M) != 0 { + isa_builder.enable("has_m").unwrap(); + } + + if (v & HWCAP_RISCV_EXT_V) != 0 { + isa_builder.enable("has_v").unwrap(); + } + + // TODO: ZiFencei does not have a bit associated with it + // TODO: Zbkb does not have a bit associated with it + } + + // squelch warnings about unused mut/variables on some platforms. + drop(&mut isa_builder); + drop(infer_native_flags); + + Ok(isa_builder) +} + +#[cfg(test)] +mod tests { + use super::builder; + use cranelift_codegen::isa::CallConv; + use cranelift_codegen::settings; + + #[test] + fn test() { + if let Ok(isa_builder) = builder() { + let flag_builder = settings::builder(); + let isa = isa_builder.finish(settings::Flags::new(flag_builder)).unwrap(); + + if cfg!(all(target_os = "macos", target_arch = "aarch64")) { + assert_eq!(isa.default_call_conv(), CallConv::AppleAarch64); + } else if cfg!(any(unix, target_os = "nebulet")) { + assert_eq!(isa.default_call_conv(), CallConv::SystemV); + } else if cfg!(windows) { + assert_eq!(isa.default_call_conv(), CallConv::WindowsFastcall); + } + + if cfg!(target_pointer_width = "64") { + assert_eq!(isa.pointer_bits(), 64); + } else if cfg!(target_pointer_width = "32") { + assert_eq!(isa.pointer_bits(), 32); + } else if cfg!(target_pointer_width = "16") { + assert_eq!(isa.pointer_bits(), 16); + } + } + } +} + +/// Version number of this crate. +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 28fbcb15b2b..3a7421d8b30 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -20,6 +20,14 @@ use indexmap::IndexSet; pub(crate) use emit::{DebugReloc, DebugRelocName}; pub(crate) use unwind::UnwindContext; +pub(crate) fn producer() -> String { + format!( + "cg_clif (rustc {}, cranelift {})", + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), + cranelift_codegen::VERSION, + ) +} + pub(crate) struct DebugContext { endian: RunTimeEndian, @@ -57,11 +65,7 @@ impl DebugContext { let mut dwarf = DwarfUnit::new(encoding); - let producer = format!( - "cg_clif (rustc {}, cranelift {})", - rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), - cranelift_codegen::VERSION, - ); + let producer = producer(); let comp_dir = tcx .sess .opts diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index f873561c171..d4494a9e45d 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -108,6 +108,8 @@ impl OngoingCodegen { self.concurrency_limiter.finished(); + sess.abort_if_errors(); + ( CodegenResults { modules, @@ -169,10 +171,22 @@ fn emit_cgu( fn emit_module( output_filenames: &OutputFilenames, prof: &SelfProfilerRef, - object: cranelift_object::object::write::Object<'_>, + mut object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, name: String, ) -> Result { + if object.format() == cranelift_object::object::BinaryFormat::Elf { + let comment_section = object.add_section( + Vec::new(), + b".comment".to_vec(), + cranelift_object::object::SectionKind::OtherString, + ); + let mut producer = vec![0]; + producer.extend(crate::debuginfo::producer().as_bytes()); + producer.push(0); + object.set_section_data(comment_section, producer, 1); + } + let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name)); let mut file = match File::create(&tmp_file) { Ok(file) => file, @@ -399,8 +413,6 @@ pub(crate) fn run_aot( .collect::>() }); - tcx.sess.abort_if_errors(); - 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 = diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index 7bc161fbe55..d2ae6978ca2 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -33,8 +33,8 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( // cast float to int let a_lane = match lane_ty { - types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane), - types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane), + types::F32 => codegen_bitcast(fx, types::I32, a_lane), + types::F64 => codegen_bitcast(fx, types::I64, a_lane), _ => a_lane, }; diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index b1adaa193b3..d561cf139b6 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -201,7 +201,7 @@ fn bool_to_zero_or_max_uint<'tcx>( let mut res = fx.bcx.ins().bmask(int_ty, val); if ty.is_float() { - res = fx.bcx.ins().bitcast(ty, res); + res = codegen_bitcast(fx, ty, res); } res @@ -241,10 +241,9 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( substs, args, destination, + target, source_info.span, ); - let ret_block = fx.get_block(target); - fx.bcx.ins().jump(ret_block, &[]); } else if codegen_float_intrinsic_call(fx, intrinsic, args, destination) { let ret_block = fx.get_block(target); fx.bcx.ins().jump(ret_block, &[]); @@ -651,7 +650,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = fx.layout_of(substs.type_at(0)); if layout.abi.is_uninhabited() { with_no_trimmed_paths!({ - crate::base::codegen_panic( + crate::base::codegen_panic_nounwind( fx, &format!("attempted to instantiate uninhabited type `{}`", layout.ty), source_info, @@ -664,7 +663,7 @@ fn codegen_regular_intrinsic_call<'tcx>( && !fx.tcx.permits_zero_init(fx.param_env().and(layout)) { with_no_trimmed_paths!({ - crate::base::codegen_panic( + crate::base::codegen_panic_nounwind( fx, &format!( "attempted to zero-initialize type `{}`, which is invalid", @@ -680,7 +679,7 @@ fn codegen_regular_intrinsic_call<'tcx>( && !fx.tcx.permits_uninit_init(fx.param_env().and(layout)) { with_no_trimmed_paths!({ - crate::base::codegen_panic( + crate::base::codegen_panic_nounwind( fx, &format!( "attempted to leave type `{}` uninitialized, which is invalid", diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 14f5e918739..b33eb29754a 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -24,6 +24,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _substs: SubstsRef<'tcx>, args: &[mir::Operand<'tcx>], ret: CPlace<'tcx>, + target: BasicBlock, span: Span, ) { match intrinsic { @@ -277,16 +278,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } else { fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant"); 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, &[]); + let ret_block = fx.get_block(target); + fx.bcx.ins().jump(ret_block, &[]); fx.bcx.switch_to_block(trap_block); crate::trap::trap_unimplemented( fx, "Index argument for `simd_extract` is not a constant", ); - fx.bcx.switch_to_block(dummy_block); return; }; @@ -770,11 +770,119 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - // simd_arith_offset - // simd_scatter - // simd_gather + sym::simd_expose_addr | sym::simd_from_exposed_addr | sym::simd_cast_ptr => { + intrinsic_args!(fx, args => (arg); intrinsic); + ret.write_cvalue_transmute(fx, arg); + } + + sym::simd_arith_offset => { + intrinsic_args!(fx, args => (ptr, offset); intrinsic); + + let (lane_count, ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx); + let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap().ty; + let pointee_size = fx.layout_of(pointee_ty).size.bytes(); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + assert_eq!(lane_count, ret_lane_count); + + for lane_idx in 0..lane_count { + let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx); + let offset_lane = offset.value_lane(fx, lane_idx).load_scalar(fx); + + let ptr_diff = if pointee_size != 1 { + fx.bcx.ins().imul_imm(offset_lane, pointee_size as i64) + } else { + offset_lane + }; + let res_lane = fx.bcx.ins().iadd(ptr_lane, ptr_diff); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane); + } + } + + sym::simd_gather => { + intrinsic_args!(fx, args => (val, ptr, mask); intrinsic); + + let (val_lane_count, val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx); + let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx); + let (mask_lane_count, _mask_lane_ty) = mask.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!(val_lane_count, ptr_lane_count); + assert_eq!(val_lane_count, mask_lane_count); + assert_eq!(val_lane_count, ret_lane_count); + + let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap(); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + + for lane_idx in 0..ptr_lane_count { + let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx); + let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx); + let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx); + + let if_enabled = fx.bcx.create_block(); + let if_disabled = fx.bcx.create_block(); + let next = fx.bcx.create_block(); + let res_lane = fx.bcx.append_block_param(next, lane_clif_ty); + + fx.bcx.ins().brnz(mask_lane, if_enabled, &[]); + fx.bcx.ins().jump(if_disabled, &[]); + fx.bcx.seal_block(if_enabled); + fx.bcx.seal_block(if_disabled); + + fx.bcx.switch_to_block(if_enabled); + let res = fx.bcx.ins().load(lane_clif_ty, MemFlags::trusted(), ptr_lane, 0); + fx.bcx.ins().jump(next, &[res]); + + fx.bcx.switch_to_block(if_disabled); + fx.bcx.ins().jump(next, &[val_lane]); + + fx.bcx.seal_block(next); + fx.bcx.switch_to_block(next); + + fx.bcx.ins().nop(); + + ret.place_lane(fx, lane_idx) + .write_cvalue(fx, CValue::by_val(res_lane, ret_lane_layout)); + } + } + + sym::simd_scatter => { + intrinsic_args!(fx, args => (val, ptr, mask); intrinsic); + + let (val_lane_count, _val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx); + let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx); + let (mask_lane_count, _mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(val_lane_count, ptr_lane_count); + assert_eq!(val_lane_count, mask_lane_count); + + for lane_idx in 0..ptr_lane_count { + let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx); + let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx); + let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx); + + let if_enabled = fx.bcx.create_block(); + let next = fx.bcx.create_block(); + + fx.bcx.ins().brnz(mask_lane, if_enabled, &[]); + fx.bcx.ins().jump(next, &[]); + fx.bcx.seal_block(if_enabled); + + fx.bcx.switch_to_block(if_enabled); + fx.bcx.ins().store(MemFlags::trusted(), val_lane, ptr_lane, 0); + fx.bcx.ins().jump(next, &[]); + + fx.bcx.seal_block(next); + fx.bcx.switch_to_block(next); + } + } + _ => { - fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic)); + fx.tcx.sess.span_err(span, &format!("Unknown SIMD intrinsic {}", intrinsic)); + // Prevent verifier error + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } } + let ret_block = fx.get_block(target); + fx.bcx.ins().jump(ret_block, &[]); } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 629d79d5012..d3868730557 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -57,6 +57,8 @@ mod compiler_builtins; mod concurrency_limiter; mod config; mod constant; +// FIXME revert back to the external crate with Cranelift 0.93 +mod cranelift_native; mod debuginfo; mod discriminant; mod driver; @@ -278,12 +280,14 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box func_id, + Err(err) => { + tcx.sess + .fatal(&format!("entry symbol `{entry_name}` declared multiple times: {err}")); + } + }; let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx); @@ -162,7 +169,11 @@ pub(crate) fn maybe_create_entry_wrapper( bcx.seal_all_blocks(); bcx.finalize(); } - m.define_function(cmain_func_id, &mut ctx).unwrap(); + + if let Err(err) = m.define_function(cmain_func_id, &mut ctx) { + tcx.sess.fatal(&format!("entry symbol `{entry_name}` defined multiple times: {err}")); + } + unwind_context.add_function(cmain_func_id, &ctx, m.isa()); } } diff --git a/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs b/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs index 7f45bbd8f28..26327dca299 100644 --- a/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs +++ b/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs @@ -7,7 +7,7 @@ use cranelift_frontend::FunctionBuilder; /// otherwise return the given value and false. pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) { if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) { - match bcx.func.dfg[arg_inst] { + match bcx.func.dfg.insts[arg_inst] { // This is the lowering of `Rvalue::Not` InstructionData::IntCompareImm { opcode: Opcode::IcmpImm, @@ -34,7 +34,7 @@ pub(crate) fn maybe_known_branch_taken( return None; }; - match bcx.func.dfg[arg_inst] { + match bcx.func.dfg.insts[arg_inst] { InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => { if test_zero { Some(imm.bits() == 0) diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index fe8af21ac6d..fa06d6c3ba7 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -514,8 +514,8 @@ impl<'tcx> CPlace<'tcx> { (types::I32, types::F32) | (types::F32, types::I32) | (types::I64, types::F64) - | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data), - _ if src_ty.is_vector() && dst_ty.is_vector() => fx.bcx.ins().bitcast(dst_ty, data), + | (types::F64, types::I64) => codegen_bitcast(fx, dst_ty, data), + _ if src_ty.is_vector() && dst_ty.is_vector() => codegen_bitcast(fx, dst_ty, data), _ if src_ty.is_vector() || dst_ty.is_vector() => { // FIXME do something more efficient for transmutes between vectors and integers. let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs index 02e1e21ade1..fd825d02e35 100755 --- a/compiler/rustc_codegen_cranelift/y.rs +++ b/compiler/rustc_codegen_cranelift/y.rs @@ -3,7 +3,7 @@ # This block is ignored by rustc set -e echo "[BUILD] y.rs" 1>&2 -rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021 +rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021 -Cpanic=abort exec ${0/.rs/.bin} $@ */ diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index bc2edf634de..8ce19c8b514 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -59,7 +59,6 @@ const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[ ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"), ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"), ("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-egraph", "Apache-2.0 WITH LLVM-exception"), ("cranelift-entity", "Apache-2.0 WITH LLVM-exception"), ("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"), ("cranelift-isle", "Apache-2.0 WITH LLVM-exception"), @@ -286,7 +285,6 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "cranelift-codegen", "cranelift-codegen-meta", "cranelift-codegen-shared", - "cranelift-egraph", "cranelift-entity", "cranelift-frontend", "cranelift-isle", @@ -321,10 +319,12 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", "windows-sys", + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ];