From ef5ec771bb4828a8464a4b5ed9ec09b7b48826db Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 22 Jan 2023 23:03:58 -0500 Subject: [PATCH 01/31] abi: add `AddressSpace` field to `Primitive::Pointer` ...and remove it from `PointeeInfo`, which isn't meant for this. There are still various places (marked with FIXMEs) that assume all pointers have the same size and alignment. Fixing this requires parsing non-default address spaces in the data layout string, which will be done in a followup. --- src/common.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common.rs b/src/common.rs index 2dcd42fbd8f..63ed10cdfcc 100644 --- a/src/common.rs +++ b/src/common.rs @@ -35,7 +35,8 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type { }, Primitive::F32 => types::F32, Primitive::F64 => types::F64, - Primitive::Pointer => pointer_ty(tcx), + // FIXME(erikdesjardins): handle non-default addrspace ptr sizes + Primitive::Pointer(_) => pointer_ty(tcx), } } From 706d7ff108947704566dbdc361abcb2ecddcef01 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Thu, 29 Dec 2022 23:44:16 +0000 Subject: [PATCH 02/31] Update codegen cranelift for ConstEvalCounter --- src/base.rs | 1 + src/constant.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/base.rs b/src/base.rs index 89d955e8bf2..6e584c308c1 100644 --- a/src/base.rs +++ b/src/base.rs @@ -789,6 +789,7 @@ fn codegen_stmt<'tcx>( StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Deinit(_) + | StatementKind::ConstEvalCounter | StatementKind::Nop | StatementKind::FakeRead(..) | StatementKind::Retag { .. } diff --git a/src/constant.rs b/src/constant.rs index 51450897bfc..49c4f1aaaef 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -530,6 +530,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( | StatementKind::Retag(_, _) | StatementKind::AscribeUserType(_, _) | StatementKind::Coverage(_) + | StatementKind::ConstEvalCounter | StatementKind::Nop => {} } } From 39b34dc7922559b679b9458d2dde755cbf46d0ec Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 22 Jan 2023 17:06:28 -0500 Subject: [PATCH 03/31] Thread a ParamEnv down to might_permit_raw_init --- src/intrinsics/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index e4ac89a7bec..b1adaa193b3 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -21,6 +21,7 @@ mod simd; pub(crate) use cpuid::codegen_cpuid_call; pub(crate) use llvm::codegen_llvm_intrinsic_call; +use rustc_middle::ty::layout::HasParamEnv; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::SubstsRef; use rustc_span::symbol::{kw, sym, Symbol}; @@ -659,7 +660,9 @@ fn codegen_regular_intrinsic_call<'tcx>( return; } - if intrinsic == sym::assert_zero_valid && !fx.tcx.permits_zero_init(layout) { + if intrinsic == sym::assert_zero_valid + && !fx.tcx.permits_zero_init(fx.param_env().and(layout)) + { with_no_trimmed_paths!({ crate::base::codegen_panic( fx, @@ -674,7 +677,7 @@ fn codegen_regular_intrinsic_call<'tcx>( } if intrinsic == sym::assert_mem_uninitialized_valid - && !fx.tcx.permits_uninit_init(layout) + && !fx.tcx.permits_uninit_init(fx.param_env().and(layout)) { with_no_trimmed_paths!({ crate::base::codegen_panic( From b67610f98a53aec3bbd772a5e9efd058bacc2891 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 24 Jan 2023 18:56:42 +0100 Subject: [PATCH 04/31] Merge commit '598f0909568a51de8a2d1148f55a644fd8dffad0' into sync_cg_clif-2023-01-24 --- .cirrus.yml | 9 +- .github/workflows/main.yml | 140 ++--- .github/workflows/nightly-cranelift.yml | 59 -- .github/workflows/rustc.yml | 64 +- .gitignore | 5 +- .vscode/settings.json | 4 +- Cargo.lock | 108 ++-- Cargo.toml | 12 +- Readme.md | 14 +- build_sysroot/Cargo.lock | 12 +- build_system/abi_cafe.rs | 23 +- build_system/bench.rs | 97 +++ build_system/build_backend.rs | 10 +- build_system/build_sysroot.rs | 305 ++++++---- build_system/mod.rs | 113 ++-- build_system/path.rs | 7 +- build_system/prepare.rs | 129 ++-- build_system/rustc_info.rs | 27 +- build_system/tests.rs | 574 ++++++------------ build_system/usage.txt | 35 ++ build_system/utils.rs | 102 +++- clean_all.sh | 5 +- config.txt | 4 +- ...table-simd-Disable-unsupported-tests.patch | 35 -- ...-sysroot-Disable-not-compiling-tests.patch | 5 +- rust-toolchain | 2 +- scripts/cargo-clif.rs | 2 +- scripts/rustc-clif.rs | 2 +- scripts/rustdoc-clif.rs | 2 +- scripts/rustup.sh | 4 +- scripts/setup_rust_fork.sh | 8 +- scripts/test_rustc_tests.sh | 41 +- src/abi/mod.rs | 37 +- src/base.rs | 42 +- src/common.rs | 9 + src/debuginfo/mod.rs | 14 +- src/driver/aot.rs | 18 +- src/intrinsics/llvm_x86.rs | 4 +- src/intrinsics/mod.rs | 11 +- src/intrinsics/simd.rs | 122 +++- src/lib.rs | 6 +- src/main_shim.rs | 15 +- src/optimize/peephole.rs | 4 +- src/value_and_place.rs | 4 +- y.rs | 2 +- 45 files changed, 1139 insertions(+), 1108 deletions(-) delete mode 100644 .github/workflows/nightly-cranelift.yml create mode 100644 build_system/bench.rs create mode 100644 build_system/usage.txt delete mode 100644 patches/0001-portable-simd-Disable-unsupported-tests.patch diff --git a/.cirrus.yml b/.cirrus.yml index d627c2ee09c..7886cae42a1 100644 --- a/.cirrus.yml +++ b/.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/.github/workflows/main.yml b/.github/workflows/main.yml index a6bb12a66a2..c0daf69e98e 100644 --- a/.github/workflows/main.yml +++ b/.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/build_system/build_backend.rs b/build_system/build_backend.rs index fde8ef424cc..514404305a3 100644 --- a/build_system/build_backend.rs +++ b/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/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index cbbf09b9b97..bd04fdbe304 100644 --- a/build_system/build_sysroot.rs +++ b/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/build_system/mod.rs b/build_system/mod.rs index 1afc9a55c73..8dcbe8de189 100644 --- a/build_system/mod.rs +++ b/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/build_system/path.rs b/build_system/path.rs index e93981f1d64..3290723005d 100644 --- a/build_system/path.rs +++ b/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/build_system/prepare.rs b/build_system/prepare.rs index 8ac67e8f942..f25a81dc234 100644 --- a/build_system/prepare.rs +++ b/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/build_system/rustc_info.rs b/build_system/rustc_info.rs index 8e5ab688e13..a70453b4422 100644 --- a/build_system/rustc_info.rs +++ b/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/build_system/tests.rs b/build_system/tests.rs index 1c372736ed6..dcfadd73756 100644 --- a/build_system/tests.rs +++ b/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/build_system/usage.txt b/build_system/usage.txt new file mode 100644 index 00000000000..ab98ccc35a5 --- /dev/null +++ b/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/build_system/utils.rs b/build_system/utils.rs index 2be70e8e421..da2a94a0a4f 100644 --- a/build_system/utils.rs +++ b/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/clean_all.sh b/clean_all.sh index 1760e5836ec..cdfc2e143e6 100755 --- a/clean_all.sh +++ b/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/config.txt b/config.txt index 258b67e9314..d49cc90791a 100644 --- a/config.txt +++ b/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/patches/0001-portable-simd-Disable-unsupported-tests.patch b/patches/0001-portable-simd-Disable-unsupported-tests.patch deleted file mode 100644 index 89e2b61c1fc..00000000000 --- a/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/patches/0022-sysroot-Disable-not-compiling-tests.patch b/patches/0022-sysroot-Disable-not-compiling-tests.patch index 8d9ee3f25c4..865aa833a5e 100644 --- a/patches/0022-sysroot-Disable-not-compiling-tests.patch +++ b/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/rust-toolchain b/rust-toolchain index d8f28dbcc15..77345b9a17c 100644 --- a/rust-toolchain +++ b/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/scripts/cargo-clif.rs b/scripts/cargo-clif.rs index 9362b47fa6d..c993430b830 100644 --- a/scripts/cargo-clif.rs +++ b/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/scripts/rustc-clif.rs b/scripts/rustc-clif.rs index 3abfcd8ddc8..c187f54a60e 100644 --- a/scripts/rustc-clif.rs +++ b/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/scripts/rustdoc-clif.rs b/scripts/rustdoc-clif.rs index a19d72acfa8..a6528ac41ae 100644 --- a/scripts/rustdoc-clif.rs +++ b/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/scripts/rustup.sh b/scripts/rustup.sh index bc4c06ed7d2..34e3981b538 100755 --- a/scripts/rustup.sh +++ b/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/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 6c64b7de7da..a08e80dd19a 100644 --- a/scripts/setup_rust_fork.sh +++ b/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/src/abi/mod.rs b/src/abi/mod.rs index 65cc6b43767..3c34585d419 100644 --- a/src/abi/mod.rs +++ b/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/src/base.rs b/src/base.rs index 89d955e8bf2..d3a8c10657e 100644 --- a/src/base.rs +++ b/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/src/common.rs b/src/common.rs index 2dcd42fbd8f..869977104e3 100644 --- a/src/common.rs +++ b/src/common.rs @@ -167,6 +167,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/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 28fbcb15b2b..3a7421d8b30 100644 --- a/src/debuginfo/mod.rs +++ b/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/src/driver/aot.rs b/src/driver/aot.rs index f873561c171..d4494a9e45d 100644 --- a/src/driver/aot.rs +++ b/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/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 7bc161fbe55..d2ae6978ca2 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/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/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index e4ac89a7bec..52720daac6f 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -200,7 +200,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 @@ -240,10 +240,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, &[]); @@ -650,7 +649,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, @@ -661,7 +660,7 @@ fn codegen_regular_intrinsic_call<'tcx>( if intrinsic == sym::assert_zero_valid && !fx.tcx.permits_zero_init(layout) { with_no_trimmed_paths!({ - crate::base::codegen_panic( + crate::base::codegen_panic_nounwind( fx, &format!( "attempted to zero-initialize type `{}`, which is invalid", @@ -677,7 +676,7 @@ fn codegen_regular_intrinsic_call<'tcx>( && !fx.tcx.permits_uninit_init(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/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 14f5e918739..b33eb29754a 100644 --- a/src/intrinsics/simd.rs +++ b/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/src/lib.rs b/src/lib.rs index 629d79d5012..70d0cc339a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -278,12 +278,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/src/optimize/peephole.rs b/src/optimize/peephole.rs index 7f45bbd8f28..26327dca299 100644 --- a/src/optimize/peephole.rs +++ b/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/src/value_and_place.rs b/src/value_and_place.rs index fe8af21ac6d..fa06d6c3ba7 100644 --- a/src/value_and_place.rs +++ b/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/y.rs b/y.rs index 02e1e21ade1..fd825d02e35 100755 --- a/y.rs +++ b/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} $@ */ From 89e90ede57280a7b79d746b08baf5bb32f91de24 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 25 Jan 2023 15:19:40 +0100 Subject: [PATCH 05/31] Vendor newer version of cranelift-native It fixes a bug that caused compilation on 32bit x86 to fail --- Cargo.lock | 1 - Cargo.toml | 4 +- src/cranelift_native.rs | 268 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 4 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 src/cranelift_native.rs diff --git a/Cargo.lock b/Cargo.lock index 48800725d2c..50249ea1bdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -333,7 +333,6 @@ dependencies = [ "cranelift-frontend", "cranelift-jit", "cranelift-module", - "cranelift-native", "cranelift-object", "gimli", "indexmap", diff --git a/Cargo.toml b/Cargo.toml index eadb4438bc9..34117c2886f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,9 @@ crate-type = ["dylib"] cranelift-codegen = { version = "0.92", features = ["unwind", "all-arch"] } cranelift-frontend = { version = "0.92" } cranelift-module = { version = "0.92" } -cranelift-native = { version = "0.92" } +# NOTE vendored as src/cranelift_native.rs +# FIXME revert back to the external crate with Cranelift 0.93 +#cranelift-native = { version = "0.92" } cranelift-jit = { version = "0.92", optional = true } cranelift-object = { version = "0.92" } target-lexicon = "0.12.0" diff --git a/src/cranelift_native.rs b/src/cranelift_native.rs new file mode 100644 index 00000000000..7c0ca1adc2d --- /dev/null +++ b/src/cranelift_native.rs @@ -0,0 +1,268 @@ +// 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. +// 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)] +#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] +#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))] +#![cfg_attr( + feature = "cargo-clippy", + warn( + clippy::float_arithmetic, + clippy::mut_mut, + clippy::nonminimal_bool, + clippy::map_unwrap_or, + clippy::clippy::print_stdout, + clippy::unicode_not_nfc, + clippy::use_self + ) +)] + +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/src/lib.rs b/src/lib.rs index 70d0cc339a8..d3868730557 100644 --- a/src/lib.rs +++ b/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; From ff56716d034ba6c3c47e177c721bc8dfbc09a057 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 25 Jan 2023 15:56:22 +0100 Subject: [PATCH 06/31] Fix CI --- src/cranelift_native.rs | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/src/cranelift_native.rs b/src/cranelift_native.rs index 7c0ca1adc2d..6c4efca4424 100644 --- a/src/cranelift_native.rs +++ b/src/cranelift_native.rs @@ -1,34 +1,16 @@ // 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. +// 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 -)] +#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates, unstable_features)] #![warn(unused_import_braces)] -#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))] -#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))] -#![cfg_attr( - feature = "cargo-clippy", - warn( - clippy::float_arithmetic, - clippy::mut_mut, - clippy::nonminimal_bool, - clippy::map_unwrap_or, - clippy::clippy::print_stdout, - clippy::unicode_not_nfc, - clippy::use_self - ) -)] use cranelift_codegen::isa; use target_lexicon::Triple; @@ -241,9 +223,7 @@ mod tests { fn test() { if let Ok(isa_builder) = builder() { let flag_builder = settings::builder(); - let isa = isa_builder - .finish(settings::Flags::new(flag_builder)) - .unwrap(); + 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); From a88ec47d4879fcee7ee71fd41b924bdb0f707d26 Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Wed, 18 Jan 2023 15:43:20 -0700 Subject: [PATCH 07/31] replace usages of fn_sig query with bound_fn_sig --- src/main_shim.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main_shim.rs b/src/main_shim.rs index c10054e7f0d..f46e6b6528c 100644 --- a/src/main_shim.rs +++ b/src/main_shim.rs @@ -46,7 +46,7 @@ pub(crate) fn maybe_create_entry_wrapper( is_main_fn: bool, sigpipe: u8, ) { - let main_ret_ty = tcx.fn_sig(rust_main_def_id).output(); + let main_ret_ty = tcx.bound_fn_sig(rust_main_def_id).subst_identity().output(); // Given that `main()` has no arguments, // then its return type cannot have // late-bound regions, since late-bound From 7bb0bfea0417c0e165bb3084b9c471245e8c8ebf Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Wed, 18 Jan 2023 16:52:47 -0700 Subject: [PATCH 08/31] change fn_sig query to use EarlyBinder; remove bound_fn_sig query; add EarlyBinder to fn_sig in metadata --- src/main_shim.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main_shim.rs b/src/main_shim.rs index f46e6b6528c..bc1b1ec7cd5 100644 --- a/src/main_shim.rs +++ b/src/main_shim.rs @@ -46,7 +46,7 @@ pub(crate) fn maybe_create_entry_wrapper( is_main_fn: bool, sigpipe: u8, ) { - let main_ret_ty = tcx.bound_fn_sig(rust_main_def_id).subst_identity().output(); + let main_ret_ty = tcx.fn_sig(rust_main_def_id).subst_identity().output(); // Given that `main()` has no arguments, // then its return type cannot have // late-bound regions, since late-bound From 21575908c62f563fbc6d161c4fa44b2000a04e2f Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Thu, 19 Jan 2023 12:09:01 -0700 Subject: [PATCH 09/31] add EarlyBinder::no_bound_vars --- src/main_shim.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main_shim.rs b/src/main_shim.rs index bc1b1ec7cd5..70cf28267d7 100644 --- a/src/main_shim.rs +++ b/src/main_shim.rs @@ -46,7 +46,7 @@ pub(crate) fn maybe_create_entry_wrapper( is_main_fn: bool, sigpipe: u8, ) { - let main_ret_ty = tcx.fn_sig(rust_main_def_id).subst_identity().output(); + let main_ret_ty = tcx.fn_sig(rust_main_def_id).no_bound_vars().unwrap().output(); // Given that `main()` has no arguments, // then its return type cannot have // late-bound regions, since late-bound From e24fa2f915f896a68dd08e2c1689da1c27c5834b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 27 Jan 2023 12:43:49 +0100 Subject: [PATCH 10/31] Rustup to rustc 1.69.0-nightly (d7948c843 2023-01-26) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 77345b9a17c..f7205cb9800 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-01-20" +channel = "nightly-2023-01-27" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 3ba9b13490b88a902ae74056a86aeaab038a6a40 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:44:19 +0000 Subject: [PATCH 11/31] Don't download abi-cafe and simple-raytracer in ./y.rs prepare Instead download them on the fly --- build_system/abi_cafe.rs | 8 +++++--- build_system/bench.rs | 13 ++++++++++--- build_system/prepare.rs | 18 +++++++----------- build_system/tests.rs | 5 ----- build_system/utils.rs | 12 ++++++++++-- config.txt | 1 - 6 files changed, 32 insertions(+), 25 deletions(-) diff --git a/build_system/abi_cafe.rs b/build_system/abi_cafe.rs index dbee9be04ee..0da27f529b3 100644 --- a/build_system/abi_cafe.rs +++ b/build_system/abi_cafe.rs @@ -6,11 +6,10 @@ use super::prepare::GitRepo; use super::utils::{spawn_and_wait, CargoProject, Compiler}; use super::SysrootKind; -pub(crate) static ABI_CAFE_REPO: GitRepo = +static ABI_CAFE_REPO: GitRepo = GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe"); -pub(crate) static ABI_CAFE: CargoProject = - CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe"); +static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe"); pub(crate) fn run( channel: &str, @@ -19,6 +18,9 @@ pub(crate) fn run( cg_clif_dylib: &Path, bootstrap_host_compiler: &Compiler, ) { + ABI_CAFE_REPO.fetch(dirs); + spawn_and_wait(ABI_CAFE.fetch("cargo", &bootstrap_host_compiler.rustc, dirs)); + eprintln!("Building sysroot for abi-cafe"); build_sysroot::build_sysroot( dirs, diff --git a/build_system/bench.rs b/build_system/bench.rs index 01d44dafbdd..f48f7bece02 100644 --- a/build_system/bench.rs +++ b/build_system/bench.rs @@ -7,7 +7,7 @@ use super::prepare::GitRepo; use super::rustc_info::get_file_name; use super::utils::{hyperfine_command, is_ci, spawn_and_wait, CargoProject, Compiler}; -pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github( +static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github( "ebobby", "simple-raytracer", "804a7a21b9e673a482797aa289a18ed480e4d813", @@ -15,10 +15,10 @@ pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github( ); // Use a separate target dir for the initial LLVM build to reduce unnecessary recompiles -pub(crate) static SIMPLE_RAYTRACER_LLVM: CargoProject = +static SIMPLE_RAYTRACER_LLVM: CargoProject = CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer_llvm"); -pub(crate) static SIMPLE_RAYTRACER: CargoProject = +static SIMPLE_RAYTRACER: CargoProject = CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer"); pub(crate) fn benchmark(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { @@ -32,6 +32,13 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { std::process::exit(1); } + SIMPLE_RAYTRACER_REPO.fetch(dirs); + spawn_and_wait(SIMPLE_RAYTRACER.fetch( + &bootstrap_host_compiler.cargo, + &bootstrap_host_compiler.rustc, + dirs, + )); + eprintln!("[LLVM BUILD] simple-raytracer"); let build_cmd = SIMPLE_RAYTRACER_LLVM.build(bootstrap_host_compiler, dirs); spawn_and_wait(build_cmd); diff --git a/build_system/prepare.rs b/build_system/prepare.rs index f25a81dc234..50b1b7836de 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -11,22 +11,18 @@ use super::utils::{copy_dir_recursively, git_command, retry_spawn_and_wait, spaw pub(crate) fn prepare(dirs: &Dirs) { RelPath::DOWNLOAD.ensure_fresh(dirs); - spawn_and_wait(super::build_backend::CG_CLIF.fetch("cargo", dirs)); + spawn_and_wait(super::build_backend::CG_CLIF.fetch("cargo", "rustc", dirs)); prepare_sysroot(dirs); - spawn_and_wait(super::build_sysroot::STANDARD_LIBRARY.fetch("cargo", dirs)); - spawn_and_wait(super::tests::LIBCORE_TESTS.fetch("cargo", dirs)); + spawn_and_wait(super::build_sysroot::STANDARD_LIBRARY.fetch("cargo", "rustc", dirs)); + spawn_and_wait(super::tests::LIBCORE_TESTS.fetch("cargo", "rustc", 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)); + spawn_and_wait(super::tests::RAND.fetch("cargo", "rustc", dirs)); super::tests::REGEX_REPO.fetch(dirs); - spawn_and_wait(super::tests::REGEX.fetch("cargo", dirs)); + spawn_and_wait(super::tests::REGEX.fetch("cargo", "rustc", dirs)); super::tests::PORTABLE_SIMD_REPO.fetch(dirs); - 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)); + spawn_and_wait(super::tests::PORTABLE_SIMD.fetch("cargo", "rustc", dirs)); } fn prepare_sysroot(dirs: &Dirs) { @@ -80,7 +76,7 @@ impl GitRepo { } } - fn fetch(&self, dirs: &Dirs) { + pub(crate) fn fetch(&self, dirs: &Dirs) { match self.url { GitRepoUrl::Github { user, repo } => { clone_repo_shallow_github( diff --git a/build_system/tests.rs b/build_system/tests.rs index dcfadd73756..e9486888f86 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -1,4 +1,3 @@ -use super::bench::SIMPLE_RAYTRACER; use super::build_sysroot::{self, SYSROOT_SRC}; use super::config; use super::path::{Dirs, RelPath}; @@ -134,10 +133,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::custom("test.simple-raytracer", &|runner| { - SIMPLE_RAYTRACER.clean(&runner.dirs); - spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs)); - }), TestCase::custom("test.libcore", &|runner| { LIBCORE_TESTS.clean(&runner.dirs); diff --git a/build_system/utils.rs b/build_system/utils.rs index da2a94a0a4f..bdff1abeb27 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -121,10 +121,18 @@ impl CargoProject { } #[must_use] - pub(crate) fn fetch(&self, cargo: impl AsRef, dirs: &Dirs) -> Command { + pub(crate) fn fetch( + &self, + cargo: impl AsRef, + rustc: impl AsRef, + dirs: &Dirs, + ) -> Command { let mut cmd = Command::new(cargo.as_ref()); - cmd.arg("fetch").arg("--manifest-path").arg(self.manifest_path(dirs)); + cmd.env("RUSTC", rustc.as_ref()) + .arg("fetch") + .arg("--manifest-path") + .arg(self.manifest_path(dirs)); cmd } diff --git a/config.txt b/config.txt index d49cc90791a..d6e3924a24d 100644 --- a/config.txt +++ b/config.txt @@ -44,7 +44,6 @@ aot.issue-72793 testsuite.extended_sysroot test.rust-random/rand -test.simple-raytracer test.libcore test.regex-shootout-regex-dna test.regex From 572e32b4cd64ddb946a1203652e1aa6d440aa2f5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 31 Jan 2023 17:39:19 +0000 Subject: [PATCH 12/31] Fix rustc test suite --- scripts/test_rustc_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 07c9ae6ee9f..e14a129dbc2 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -91,6 +91,7 @@ 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 +rm tests/ui/proc-macro/allowed-signatures.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 From d1024b6560c0b75b1347841d7ccb0dc36e0dffdd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 31 Jan 2023 17:44:29 +0000 Subject: [PATCH 13/31] Fix y.rs bench --- build_system/bench.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/build_system/bench.rs b/build_system/bench.rs index f48f7bece02..196e2fd9a7d 100644 --- a/build_system/bench.rs +++ b/build_system/bench.rs @@ -32,12 +32,14 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { std::process::exit(1); } - SIMPLE_RAYTRACER_REPO.fetch(dirs); - spawn_and_wait(SIMPLE_RAYTRACER.fetch( - &bootstrap_host_compiler.cargo, - &bootstrap_host_compiler.rustc, - dirs, - )); + if !SIMPLE_RAYTRACER_REPO.source_dir().to_path(dirs).exists() { + SIMPLE_RAYTRACER_REPO.fetch(dirs); + spawn_and_wait(SIMPLE_RAYTRACER.fetch( + &bootstrap_host_compiler.cargo, + &bootstrap_host_compiler.rustc, + dirs, + )); + } eprintln!("[LLVM BUILD] simple-raytracer"); let build_cmd = SIMPLE_RAYTRACER_LLVM.build(bootstrap_host_compiler, dirs); @@ -64,17 +66,17 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { let target_dir = SIMPLE_RAYTRACER.target_dir(dirs); let clean_cmd = format!( - "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}", + "RUSTC=rustc 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}", + "RUSTC=rustc 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}", + "RUSTC=rustc {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(), From 79f4cc0822578199fa9ffee6f0abf909b8976ab9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 31 Jan 2023 17:49:08 +0000 Subject: [PATCH 14/31] Run y.rs bench in CI --- .github/workflows/main.yml | 42 ++++++++++++++++++++++++++++++++++++++ build_system/bench.rs | 11 ++++------ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c0daf69e98e..6e35d1e1dc2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -185,3 +185,45 @@ jobs: env: TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} run: ./y.rs abi-cafe + + bench: + runs-on: ubuntu-latest + timeout-minutes: 60 + + defaults: + run: + shell: bash + + steps: + - uses: actions/checkout@v3 + + - name: Cache cargo target dir + uses: actions/cache@v3 + with: + path: build/cg_clif + key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Cache cargo bin dir + uses: actions/cache@v3 + with: + path: ~/.cargo/bin + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-bin-dir-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Use sparse cargo registry + run: | + cat >> ~/.cargo/config.toml < Date: Wed, 1 Feb 2023 13:55:28 +0000 Subject: [PATCH 15/31] Don't force many scalar pair values to the stack in write_cvalue_maybe_transmute Sometimes it is necessary for handling vector to scalar pair transmutes, but if the types are the same there is no need for this. This improves runtime performance on simple-raytracer by 12%. --- src/abi/comments.rs | 4 ++-- src/value_and_place.rs | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/abi/comments.rs b/src/abi/comments.rs index 7f4619b5c94..abf63e33c35 100644 --- a/src/abi/comments.rs +++ b/src/abi/comments.rs @@ -98,12 +98,12 @@ pub(super) fn add_local_place_comments<'tcx>( } CPlaceInner::VarPair(place_local, var1, var2) => { assert_eq!(local, place_local); - ("ssa", Cow::Owned(format!(",var=({}, {})", var1.index(), var2.index()))) + ("ssa", Cow::Owned(format!("var=({}, {})", var1.index(), var2.index()))) } CPlaceInner::VarLane(_local, _var, _lane) => unreachable!(), CPlaceInner::Addr(ptr, meta) => { let meta = if let Some(meta) = meta { - Cow::Owned(format!(",meta={}", meta)) + Cow::Owned(format!("meta={}", meta)) } else { Cow::Borrowed("") }; diff --git a/src/value_and_place.rs b/src/value_and_place.rs index fa06d6c3ba7..cc4493d442f 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -588,10 +588,13 @@ impl<'tcx> CPlace<'tcx> { return; } CPlaceInner::VarPair(_local, var1, var2) => { - let (ptr, meta) = from.force_stack(fx); - assert!(meta.is_none()); - let (data1, data2) = - CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx); + let (data1, data2) = if self.layout().ty == dst_layout.ty { + CValue(from.0, dst_layout).load_scalar_pair(fx) + } else { + let (ptr, meta) = from.force_stack(fx); + assert!(meta.is_none()); + CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx) + }; let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap(); transmute_value(fx, var1, data1, dst_ty1); transmute_value(fx, var2, data2, dst_ty2); From 78bf4af6592c41e9595091a3b24e689190d8b972 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 1 Feb 2023 13:58:05 +0000 Subject: [PATCH 16/31] Fix hyperfine install on CI --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6e35d1e1dc2..92a1d8c1897 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -217,7 +217,7 @@ jobs: EOF - name: Install hyperfine - run: cargo install hyperfine + run: cargo install hyperfine || true - name: Prepare dependencies run: ./y.rs prepare From 21bdff8bc015b557bfae85b968dc4c100be85caf Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:28:06 +0100 Subject: [PATCH 17/31] Fix transmute from vector to scalar pair again --- src/value_and_place.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index cc4493d442f..320eecaee00 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -588,7 +588,7 @@ impl<'tcx> CPlace<'tcx> { return; } CPlaceInner::VarPair(_local, var1, var2) => { - let (data1, data2) = if self.layout().ty == dst_layout.ty { + let (data1, data2) = if from.layout().ty == dst_layout.ty { CValue(from.0, dst_layout).load_scalar_pair(fx) } else { let (ptr, meta) = from.force_stack(fx); From a465d6a8600faed173f896f4b8dc2db0ee2d5498 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 3 Feb 2023 16:48:35 +0000 Subject: [PATCH 18/31] Move codegen_and_compile_fn to driver/jit.rs --- src/base.rs | 17 ----------------- src/driver/jit.rs | 44 ++++++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/src/base.rs b/src/base.rs index d3a8c10657e..6e9a1bfa7a8 100644 --- a/src/base.rs +++ b/src/base.rs @@ -21,23 +21,6 @@ pub(crate) struct CodegenedFunction { func_debug_cx: Option, } -#[cfg_attr(not(feature = "jit"), allow(dead_code))] -pub(crate) fn codegen_and_compile_fn<'tcx>( - tcx: TyCtxt<'tcx>, - cx: &mut crate::CodegenCx, - cached_context: &mut Context, - module: &mut dyn Module, - instance: Instance<'tcx>, -) { - let _inst_guard = - crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); - - let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); - let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance); - - compile_fn(cx, cached_context, module, codegened_func); -} - pub(crate) fn codegen_fn<'tcx>( tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx, diff --git a/src/driver/jit.rs b/src/driver/jit.rs index be1b8c9ead3..25cb6ecbf6b 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -128,15 +128,13 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { MonoItem::Fn(inst) => match backend_config.codegen_mode { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { - tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn( - tcx, - &mut cx, - &mut cached_context, - &mut jit_module, - inst, - ) - }); + codegen_and_compile_fn( + tcx, + &mut cx, + &mut cached_context, + &mut jit_module, + inst, + ); } CodegenMode::JitLazy => { codegen_shim(tcx, &mut cx, &mut cached_context, &mut jit_module, inst) @@ -219,6 +217,24 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { } } +pub(crate) fn codegen_and_compile_fn<'tcx>( + tcx: TyCtxt<'tcx>, + cx: &mut crate::CodegenCx, + cached_context: &mut Context, + module: &mut dyn Module, + instance: Instance<'tcx>, +) { + tcx.sess.time("codegen and compile fn", || { + let _inst_guard = + crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); + + let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); + let codegened_func = crate::base::codegen_fn(tcx, cx, cached_func, module, instance); + + crate::base::compile_fn(cx, cached_context, module, codegened_func); + }); +} + extern "C" fn clif_jit_fn( instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8, @@ -271,15 +287,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> false, Symbol::intern("dummy_cgu_name"), ); - tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn( - tcx, - &mut cx, - &mut Context::new(), - jit_module, - instance, - ) - }); + codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance); assert!(cx.global_asm.is_empty()); jit_module.finalize_definitions().unwrap(); From d2ffe40864e6dc93881225621a05b833957963a5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 3 Feb 2023 17:16:09 +0000 Subject: [PATCH 19/31] Cleanup -Ztime-passes output --- src/base.rs | 15 +++-- src/config.rs | 8 --- src/driver/aot.rs | 142 ++++++++++++++++++++++++++-------------------- src/driver/jit.rs | 4 +- src/driver/mod.rs | 15 +---- 5 files changed, 91 insertions(+), 93 deletions(-) diff --git a/src/base.rs b/src/base.rs index 6e9a1bfa7a8..184ddbdd280 100644 --- a/src/base.rs +++ b/src/base.rs @@ -95,7 +95,7 @@ pub(crate) fn codegen_fn<'tcx>( next_ssa_var: 0, }; - tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block)); + tcx.prof.generic_activity("codegen clif ir").run(|| codegen_fn_body(&mut fx, start_block)); fx.bcx.seal_all_blocks(); fx.bcx.finalize(); @@ -174,7 +174,7 @@ pub(crate) fn compile_fn( }; // Define function - cx.profiler.verbose_generic_activity("define function").run(|| { + cx.profiler.generic_activity("define function").run(|| { context.want_disasm = cx.should_write_ir; module.define_function(codegened_func.func_id, context).unwrap(); }); @@ -203,7 +203,7 @@ pub(crate) fn compile_fn( let isa = module.isa(); let debug_context = &mut cx.debug_context; let unwind_context = &mut cx.unwind_context; - cx.profiler.verbose_generic_activity("generate debug info").run(|| { + cx.profiler.generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { codegened_func.func_debug_cx.unwrap().finalize( debug_context, @@ -220,7 +220,7 @@ pub(crate) fn verify_func( writer: &crate::pretty_clif::CommentWriter, func: &Function, ) { - tcx.sess.time("verify clif ir", || { + tcx.prof.generic_activity("verify clif ir").run(|| { let flags = cranelift_codegen::settings::Flags::new(cranelift_codegen::settings::builder()); match cranelift_codegen::verify_function(&func, &flags) { Ok(_) => {} @@ -256,7 +256,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); return; } - fx.tcx.sess.time("codegen prelude", || crate::abi::codegen_fn_prelude(fx, start_block)); + fx.tcx + .prof + .generic_activity("codegen prelude") + .run(|| crate::abi::codegen_fn_prelude(fx, start_block)); for (bb, bb_data) in fx.mir.basic_blocks.iter_enumerated() { let block = fx.get_block(bb); @@ -417,7 +420,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { cleanup: _, from_hir_call: _, } => { - fx.tcx.sess.time("codegen call", || { + fx.tcx.prof.generic_activity("codegen call").run(|| { crate::abi::codegen_terminator_call( fx, mir::SourceInfo { span: *fn_span, ..source_info }, diff --git a/src/config.rs b/src/config.rs index 45522fb1a4c..263401e1c4b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,12 +42,6 @@ pub struct BackendConfig { /// Defaults to the value of `CG_CLIF_JIT_ARGS`. pub jit_args: Vec, - /// Display the time it took to perform codegen for a crate. - /// - /// Defaults to true when the `CG_CLIF_DISPLAY_CG_TIME` env var is set to 1 or false otherwise. - /// Can be set using `-Cllvm-args=display_cg_time=...`. - pub display_cg_time: bool, - /// Enable the Cranelift ir verifier for all compilation passes. If not set it will only run /// once before passing the clif ir to Cranelift for compilation. /// @@ -73,7 +67,6 @@ impl Default for BackendConfig { let args = std::env::var("CG_CLIF_JIT_ARGS").unwrap_or_else(|_| String::new()); args.split(' ').map(|arg| arg.to_string()).collect() }, - display_cg_time: bool_env_var("CG_CLIF_DISPLAY_CG_TIME"), enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"), disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"), } @@ -92,7 +85,6 @@ impl BackendConfig { if let Some((name, value)) = opt.split_once('=') { match name { "mode" => config.codegen_mode = value.parse()?, - "display_cg_time" => config.display_cg_time = parse_bool(name, value)?, "enable_verifier" => config.enable_verifier = parse_bool(name, value)?, "disable_incr_cache" => config.disable_incr_cache = parse_bool(name, value)?, _ => return Err(format!("Unknown option `{}`", name)), diff --git a/src/driver/aot.rs b/src/driver/aot.rs index d4494a9e45d..2aa3209e2b1 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -272,80 +272,97 @@ fn module_codegen( ConcurrencyLimiterToken, ), ) -> OngoingModuleCodegen { - let (cgu_name, mut cx, mut module, codegened_functions) = tcx.sess.time("codegen cgu", || { - let cgu = tcx.codegen_unit(cgu_name); - let mono_items = cgu.items_in_deterministic_order(tcx); + let (cgu_name, mut cx, mut module, codegened_functions) = + tcx.prof.verbose_generic_activity_with_arg("codegen cgu", cgu_name.as_str()).run(|| { + let cgu = tcx.codegen_unit(cgu_name); + let mono_items = cgu.items_in_deterministic_order(tcx); - let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string()); + let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string()); - let mut cx = crate::CodegenCx::new( - tcx, - backend_config.clone(), - module.isa(), - tcx.sess.opts.debuginfo != DebugInfo::None, - cgu_name, - ); - super::predefine_mono_items(tcx, &mut module, &mono_items); - let mut codegened_functions = vec![]; - for (mono_item, _) in mono_items { - match mono_item { - MonoItem::Fn(inst) => { - tcx.sess.time("codegen fn", || { - let codegened_function = crate::base::codegen_fn( + let mut cx = crate::CodegenCx::new( + tcx, + backend_config.clone(), + module.isa(), + tcx.sess.opts.debuginfo != DebugInfo::None, + cgu_name, + ); + super::predefine_mono_items(tcx, &mut module, &mono_items); + let mut codegened_functions = vec![]; + for (mono_item, _) in mono_items { + match mono_item { + MonoItem::Fn(inst) => { + tcx.prof.generic_activity("codegen fn").run(|| { + let codegened_function = crate::base::codegen_fn( + tcx, + &mut cx, + Function::new(), + &mut module, + inst, + ); + codegened_functions.push(codegened_function); + }); + } + MonoItem::Static(def_id) => { + crate::constant::codegen_static(tcx, &mut module, def_id) + } + MonoItem::GlobalAsm(item_id) => { + crate::global_asm::codegen_global_asm_item( tcx, - &mut cx, - Function::new(), - &mut module, - inst, + &mut cx.global_asm, + item_id, ); - codegened_functions.push(codegened_function); - }); - } - MonoItem::Static(def_id) => { - crate::constant::codegen_static(tcx, &mut module, def_id) - } - MonoItem::GlobalAsm(item_id) => { - crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id); + } } } - } - crate::main_shim::maybe_create_entry_wrapper( - tcx, - &mut module, - &mut cx.unwind_context, - false, - cgu.is_primary(), - ); + crate::main_shim::maybe_create_entry_wrapper( + tcx, + &mut module, + &mut cx.unwind_context, + false, + cgu.is_primary(), + ); - let cgu_name = cgu.name().as_str().to_owned(); + let cgu_name = cgu.name().as_str().to_owned(); - (cgu_name, cx, module, codegened_functions) - }); - - OngoingModuleCodegen::Async(std::thread::spawn(move || { - cx.profiler.clone().verbose_generic_activity("compile functions").run(|| { - let mut cached_context = Context::new(); - for codegened_func in codegened_functions { - crate::base::compile_fn(&mut cx, &mut cached_context, &mut module, codegened_func); - } + (cgu_name, cx, module, codegened_functions) }); - let global_asm_object_file = - cx.profiler.verbose_generic_activity("compile assembly").run(|| { + OngoingModuleCodegen::Async(std::thread::spawn(move || { + cx.profiler.clone().verbose_generic_activity_with_arg("compile functions", &*cgu_name).run( + || { + let mut cached_context = Context::new(); + for codegened_func in codegened_functions { + crate::base::compile_fn( + &mut cx, + &mut cached_context, + &mut module, + codegened_func, + ); + } + }, + ); + + let global_asm_object_file = cx + .profiler + .verbose_generic_activity_with_arg("compile assembly", &*cgu_name) + .run(|| { crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm) })?; - let codegen_result = cx.profiler.verbose_generic_activity("write object file").run(|| { - emit_cgu( - &global_asm_config.output_filenames, - &cx.profiler, - cgu_name, - module, - cx.debug_context, - cx.unwind_context, - global_asm_object_file, - ) - }); + let codegen_result = cx + .profiler + .verbose_generic_activity_with_arg("write object file", &*cgu_name) + .run(|| { + emit_cgu( + &global_asm_config.output_filenames, + &cx.profiler, + cgu_name, + module, + cx.debug_context, + cx.unwind_context, + global_asm_object_file, + ) + }); std::mem::drop(token); codegen_result })) @@ -375,7 +392,7 @@ pub(crate) fn run_aot( let mut concurrency_limiter = ConcurrencyLimiter::new(tcx.sess, cgus.len()); - let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || { + let modules = tcx.sess.time("codegen mono items", || { cgus.iter() .map(|cgu| { let cgu_reuse = if backend_config.disable_incr_cache { @@ -437,7 +454,6 @@ pub(crate) fn run_aot( }; let metadata_module = if need_metadata_module { - let _timer = tcx.prof.generic_activity("codegen crate metadata"); let (metadata_cgu_name, tmp_file) = tcx.sess.time("write compressed metadata", || { use rustc_middle::mir::mono::CodegenUnitNameBuilder; diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 25cb6ecbf6b..8b5a2da2c59 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -121,7 +121,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { .into_iter() .collect::>(); - super::time(tcx, backend_config.display_cg_time, "codegen mono items", || { + tcx.sess.time("codegen mono items", || { super::predefine_mono_items(tcx, &mut jit_module, &mono_items); for (mono_item, _) in mono_items { match mono_item { @@ -224,7 +224,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( module: &mut dyn Module, instance: Instance<'tcx>, ) { - tcx.sess.time("codegen and compile fn", || { + tcx.prof.generic_activity("codegen and compile fn").run(|| { let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 6e925cea277..d09d3a52975 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -17,7 +17,7 @@ fn predefine_mono_items<'tcx>( module: &mut dyn Module, mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))], ) { - tcx.sess.time("predefine functions", || { + tcx.prof.generic_activity("predefine functions").run(|| { let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE); for &(mono_item, (linkage, visibility)) in mono_items { match mono_item { @@ -39,16 +39,3 @@ fn predefine_mono_items<'tcx>( } }); } - -fn time(tcx: TyCtxt<'_>, display: bool, name: &'static str, f: impl FnOnce() -> R) -> R { - if display { - println!("[{:<30}: {}] start", tcx.crate_name(LOCAL_CRATE), name); - let before = std::time::Instant::now(); - let res = tcx.sess.time(name, f); - let after = std::time::Instant::now(); - println!("[{:<30}: {}] end time: {:?}", tcx.crate_name(LOCAL_CRATE), name, after - before); - res - } else { - tcx.sess.time(name, f) - } -} From 469783c263c3ac0aadde100cbf7e575c21caad1f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 3 Feb 2023 17:33:39 +0000 Subject: [PATCH 20/31] Use generic_activity_with_arg in codegen_fn and compile_fn --- src/base.rs | 7 ++++++- src/driver/aot.rs | 18 ++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/base.rs b/src/base.rs index 184ddbdd280..b43bb5e8668 100644 --- a/src/base.rs +++ b/src/base.rs @@ -30,6 +30,9 @@ pub(crate) fn codegen_fn<'tcx>( ) -> CodegenedFunction { debug_assert!(!instance.substs.needs_infer()); + let symbol_name = tcx.symbol_name(instance).name.to_string(); + let _timer = tcx.prof.generic_activity_with_arg("codegen fn", &*symbol_name); + let mir = tcx.instance_mir(instance.def); let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); @@ -41,7 +44,6 @@ pub(crate) fn codegen_fn<'tcx>( }); // Declare function - let symbol_name = tcx.symbol_name(instance).name.to_string(); let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance); let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap(); @@ -129,6 +131,9 @@ pub(crate) fn compile_fn( module: &mut dyn Module, codegened_func: CodegenedFunction, ) { + let _timer = + cx.profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name); + let clif_comments = codegened_func.clif_comments; // Store function in context diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 2aa3209e2b1..58b01dfb5b0 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -291,16 +291,14 @@ fn module_codegen( for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - tcx.prof.generic_activity("codegen fn").run(|| { - let codegened_function = crate::base::codegen_fn( - tcx, - &mut cx, - Function::new(), - &mut module, - inst, - ); - codegened_functions.push(codegened_function); - }); + let codegened_function = crate::base::codegen_fn( + tcx, + &mut cx, + Function::new(), + &mut module, + inst, + ); + codegened_functions.push(codegened_function); } MonoItem::Static(def_id) => { crate::constant::codegen_static(tcx, &mut module, def_id) From a0d3b0963d68ebf4d63bd8ac4a3ca5ab3cc44873 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 3 Feb 2023 18:35:09 +0000 Subject: [PATCH 21/31] Record cranelift pass timings in self profile results --- src/base.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/base.rs b/src/base.rs index b43bb5e8668..3f5cc38b04c 100644 --- a/src/base.rs +++ b/src/base.rs @@ -182,6 +182,27 @@ pub(crate) fn compile_fn( cx.profiler.generic_activity("define function").run(|| { context.want_disasm = cx.should_write_ir; module.define_function(codegened_func.func_id, context).unwrap(); + + if cx.profiler.enabled() { + let mut recording_args = false; + cx.profiler + .generic_activity_with_arg_recorder( + "define function (clif pass timings)", + |recorder| { + let pass_times = cranelift_codegen::timing::take_current(); + // Replace newlines with | as measureme doesn't allow control characters like + // newlines inside strings. + recorder.record_arg(format!("{}", pass_times).replace("\n", " | ")); + recording_args = true; + }, + ) + .run(|| { + if recording_args { + // Wait a tiny bit to ensure chrome's profiler doesn't hide the event + std::thread::sleep(std::time::Duration::from_nanos(2)) + } + }); + } }); if cx.should_write_ir { From f5669a3548ac853418e4890e142964e27fb2dd2b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 3 Feb 2023 19:59:05 +0000 Subject: [PATCH 22/31] Fix assert_mem_uninitialized_valid in release mode --- src/intrinsics/mod.rs | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index d561cf139b6..892e7c30e2f 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -218,22 +218,6 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( let intrinsic = fx.tcx.item_name(instance.def_id()); let substs = instance.substs; - let target = if let Some(target) = target { - target - } else { - // Insert non returning intrinsics here - match intrinsic { - sym::abort => { - fx.bcx.ins().trap(TrapCode::User(0)); - } - sym::transmute => { - crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info); - } - _ => unimplemented!("unsupported intrinsic {}", intrinsic), - } - return; - }; - if intrinsic.as_str().starts_with("simd_") { self::simd::codegen_simd_intrinsic_call( fx, @@ -241,11 +225,11 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( substs, args, destination, - target, + target.expect("target for simd intrinsic"), source_info.span, ); } else if codegen_float_intrinsic_call(fx, intrinsic, args, destination) { - let ret_block = fx.get_block(target); + let ret_block = fx.get_block(target.expect("target for float intrinsic")); fx.bcx.ins().jump(ret_block, &[]); } else { codegen_regular_intrinsic_call( @@ -255,7 +239,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( substs, args, destination, - Some(target), + target, source_info, ); } @@ -382,6 +366,10 @@ fn codegen_regular_intrinsic_call<'tcx>( let usize_layout = fx.layout_of(fx.tcx.types.usize); match intrinsic { + sym::abort => { + fx.bcx.ins().trap(TrapCode::User(0)); + return; + } sym::likely | sym::unlikely => { intrinsic_args!(fx, args => (a); intrinsic); @@ -579,6 +567,11 @@ fn codegen_regular_intrinsic_call<'tcx>( sym::transmute => { intrinsic_args!(fx, args => (from); intrinsic); + if ret.layout().abi.is_uninhabited() { + crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info); + return; + } + ret.write_cvalue_transmute(fx, from); } sym::write_bytes | sym::volatile_set_memory => { From efb92a1ae85317ec5cbde43655e2975c56443c4c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 3 Feb 2023 20:01:39 +0000 Subject: [PATCH 23/31] Use packed debuginfo for the sysroot on macOS This reduces the sysroot size --- build_system/build_sysroot.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index bd04fdbe304..2e04f2c6811 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -248,6 +248,9 @@ fn build_clif_sysroot_for_triple( build_cmd.arg("--release"); } build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); + if compiler.triple.contains("apple") { + build_cmd.env("CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO", "packed"); + } spawn_and_wait(build_cmd); for entry in fs::read_dir(build_dir.join("deps")).unwrap() { From 761a91ade850d4e21964ebe44fc9ba2e423c9571 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 4 Feb 2023 10:22:24 +0000 Subject: [PATCH 24/31] Build CI dist artifacts without debug assertions This significantly improves performance. For example for the simple-raytracer benchmark it goes from a 13% improvement over LLVM to 39% improvement over LLVM. --- .github/workflows/main.yml | 105 ++++++++++++++++++++++++++++------ build_system/build_backend.rs | 6 +- build_system/mod.rs | 8 ++- build_system/utils.rs | 6 +- 4 files changed, 100 insertions(+), 25 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 92a1d8c1897..9d67886ba86 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,6 +21,7 @@ jobs: cargo fmt --check rustfmt --check build_system/mod.rs + build: runs-on: ${{ matrix.os }} timeout-minutes: 60 @@ -112,23 +113,6 @@ jobs: TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} run: ./y.rs test - - name: Package prebuilt cg_clif - run: tar cvfJ cg_clif.tar.xz dist - - - name: Upload prebuilt cg_clif - if: matrix.os == 'windows-latest' || matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' - uses: actions/upload-artifact@v3 - with: - name: cg_clif-${{ matrix.env.TARGET_TRIPLE }} - path: cg_clif.tar.xz - - - name: Upload prebuilt cg_clif (cross compile) - if: matrix.os != 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' - uses: actions/upload-artifact@v3 - with: - name: cg_clif-${{ runner.os }}-cross-x86_64-mingw - path: cg_clif.tar.xz - abi_cafe: runs-on: ${{ matrix.os }} @@ -186,6 +170,7 @@ jobs: TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} run: ./y.rs abi-cafe + bench: runs-on: ubuntu-latest timeout-minutes: 60 @@ -223,7 +208,89 @@ jobs: run: ./y.rs prepare - name: Build - run: ./y.rs build --sysroot none + run: CI_OPT=1 ./y.rs build --sysroot none - name: Benchmark - run: ./y.rs bench + run: CI_OPT=1 ./y.rs bench + + + dist: + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + + defaults: + run: + shell: bash + + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed + env: + TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: macos-latest + env: + TARGET_TRIPLE: x86_64-apple-darwin + # cross-compile from Linux to Windows using mingw + - os: ubuntu-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-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 target dir + uses: actions/cache@v3 + with: + path: build/cg_clif + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-dist-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 + + - name: Use sparse cargo registry + run: | + cat >> ~/.cargo/config.toml < bool { - env::var("CI").as_deref() == Ok("true") + env::var("CI").is_ok() +} + +pub(crate) fn is_ci_opt() -> bool { + env::var("CI_OPT").is_ok() } From 044a3a65a00e568b66e4bcdf7ee7393105aff6dd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Jan 2023 17:19:52 +0000 Subject: [PATCH 25/31] Support const and sym operands in inline asm --- src/inline_asm.rs | 166 +++++++++++++++++++++++++++++++++------------- 1 file changed, 121 insertions(+), 45 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 3fcc84d3929..aa0b51181f4 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -6,12 +6,37 @@ use std::fmt::Write; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir::InlineAsmOperand; +use rustc_middle::ty::SymbolName; use rustc_span::sym; use rustc_target::asm::*; +enum CInlineAsmOperand<'tcx> { + In { + reg: InlineAsmRegOrRegClass, + value: CValue<'tcx>, + }, + Out { + reg: InlineAsmRegOrRegClass, + late: bool, + place: Option>, + }, + InOut { + reg: InlineAsmRegOrRegClass, + _late: bool, + in_value: CValue<'tcx>, + out_place: Option>, + }, + Const { + value: String, + }, + Symbol { + symbol: SymbolName<'tcx>, + }, +} + pub(crate) fn codegen_inline_asm<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - _span: Span, + span: Span, template: &[InlineAsmTemplatePiece], operands: &[InlineAsmOperand<'tcx>], options: InlineAsmOptions, @@ -198,6 +223,59 @@ pub(crate) fn codegen_inline_asm<'tcx>( } } + let operands = operands + .into_iter() + .map(|operand| match *operand { + InlineAsmOperand::In { reg, ref value } => { + CInlineAsmOperand::In { reg, value: crate::base::codegen_operand(fx, value) } + } + InlineAsmOperand::Out { reg, late, ref place } => CInlineAsmOperand::Out { + reg, + late, + place: place.map(|place| crate::base::codegen_place(fx, place)), + }, + InlineAsmOperand::InOut { reg, late, ref in_value, ref out_place } => { + CInlineAsmOperand::InOut { + reg, + _late: late, + in_value: crate::base::codegen_operand(fx, in_value), + out_place: out_place.map(|place| crate::base::codegen_place(fx, place)), + } + } + InlineAsmOperand::Const { ref value } => { + let (const_value, ty) = crate::constant::eval_mir_constant(fx, &*value) + .unwrap_or_else(|| span_bug!(span, "asm const cannot be resolved")); + let value = rustc_codegen_ssa::common::asm_const_to_str( + fx.tcx, + span, + const_value, + fx.layout_of(ty), + ); + CInlineAsmOperand::Const { value } + } + InlineAsmOperand::SymFn { ref value } => { + let literal = fx.monomorphize(value.literal); + if let ty::FnDef(def_id, substs) = *literal.ty().kind() { + let instance = ty::Instance::resolve_for_fn_ptr( + fx.tcx, + ty::ParamEnv::reveal_all(), + def_id, + substs, + ) + .unwrap(); + CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance) } + } else { + span_bug!(span, "invalid type for asm sym (fn)"); + } + } + InlineAsmOperand::SymStatic { def_id } => { + assert!(fx.tcx.is_static(def_id)); + let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); + CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance) } + } + }) + .collect::>(); + let mut inputs = Vec::new(); let mut outputs = Vec::new(); @@ -206,7 +284,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( arch: fx.tcx.sess.asm_arch.unwrap(), enclosing_def_id: fx.instance.def_id(), template, - operands, + operands: &operands, options, registers: Vec::new(), stack_slots_clobber: Vec::new(), @@ -229,36 +307,22 @@ pub(crate) fn codegen_inline_asm<'tcx>( fx.cx.global_asm.push_str(&generated_asm); for (i, operand) in operands.iter().enumerate() { - match *operand { - InlineAsmOperand::In { reg: _, ref value } => { - inputs.push(( - asm_gen.stack_slots_input[i].unwrap(), - crate::base::codegen_operand(fx, value).load_scalar(fx), - )); + match operand { + CInlineAsmOperand::In { reg: _, value } => { + inputs.push((asm_gen.stack_slots_input[i].unwrap(), value.load_scalar(fx))); } - InlineAsmOperand::Out { reg: _, late: _, place } => { + CInlineAsmOperand::Out { reg: _, late: _, place } => { if let Some(place) = place { - outputs.push(( - asm_gen.stack_slots_output[i].unwrap(), - crate::base::codegen_place(fx, place), - )); + outputs.push((asm_gen.stack_slots_output[i].unwrap(), place.clone())); } } - InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => { - inputs.push(( - asm_gen.stack_slots_input[i].unwrap(), - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - )); + CInlineAsmOperand::InOut { reg: _, _late: _, in_value, out_place } => { + inputs.push((asm_gen.stack_slots_input[i].unwrap(), in_value.load_scalar(fx))); if let Some(out_place) = out_place { - outputs.push(( - asm_gen.stack_slots_output[i].unwrap(), - crate::base::codegen_place(fx, out_place), - )); + outputs.push((asm_gen.stack_slots_output[i].unwrap(), out_place.clone())); } } - InlineAsmOperand::Const { value: _ } => todo!(), - InlineAsmOperand::SymFn { value: _ } => todo!(), - InlineAsmOperand::SymStatic { def_id: _ } => todo!(), + CInlineAsmOperand::Const { value: _ } | CInlineAsmOperand::Symbol { symbol: _ } => {} } } @@ -280,7 +344,7 @@ struct InlineAssemblyGenerator<'a, 'tcx> { arch: InlineAsmArch, enclosing_def_id: DefId, template: &'a [InlineAsmTemplatePiece], - operands: &'a [InlineAsmOperand<'tcx>], + operands: &'a [CInlineAsmOperand<'tcx>], options: InlineAsmOptions, registers: Vec>, stack_slots_clobber: Vec>, @@ -304,18 +368,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { // Add explicit registers to the allocated set. for (i, operand) in self.operands.iter().enumerate() { match *operand { - InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => { + CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => { regs[i] = Some(reg); allocated.entry(reg).or_default().0 = true; } - InlineAsmOperand::Out { - reg: InlineAsmRegOrRegClass::Reg(reg), late: true, .. + CInlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(reg), + late: true, + .. } => { regs[i] = Some(reg); allocated.entry(reg).or_default().1 = true; } - InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(reg), .. } - | InlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => { + CInlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(reg), .. } + | CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => { regs[i] = Some(reg); allocated.insert(reg, (true, true)); } @@ -326,12 +392,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { // Allocate out/inout/inlateout registers first because they are more constrained. for (i, operand) in self.operands.iter().enumerate() { match *operand { - InlineAsmOperand::Out { + CInlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::RegClass(class), late: false, .. } - | InlineAsmOperand::InOut { + | CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => { let mut alloc_reg = None; @@ -360,7 +426,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { // Allocate in/lateout. for (i, operand) in self.operands.iter().enumerate() { match *operand { - InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => { + CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => { let mut alloc_reg = None; for ® in &map[&class] { let mut used = false; @@ -380,7 +446,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { regs[i] = Some(reg); allocated.entry(reg).or_default().0 = true; } - InlineAsmOperand::Out { + CInlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::RegClass(class), late: true, .. @@ -455,7 +521,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { // Allocate stack slots for inout for (i, operand) in self.operands.iter().enumerate() { match *operand { - InlineAsmOperand::InOut { reg, out_place: Some(_), .. } => { + CInlineAsmOperand::InOut { reg, out_place: Some(_), .. } => { let slot = new_slot(reg.reg_class()); slots_input[i] = Some(slot); slots_output[i] = Some(slot); @@ -470,8 +536,8 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { // Allocate stack slots for input for (i, operand) in self.operands.iter().enumerate() { match *operand { - InlineAsmOperand::In { reg, .. } - | InlineAsmOperand::InOut { reg, out_place: None, .. } => { + CInlineAsmOperand::In { reg, .. } + | CInlineAsmOperand::InOut { reg, out_place: None, .. } => { slots_input[i] = Some(new_slot(reg.reg_class())); } _ => (), @@ -487,7 +553,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { // Allocate stack slots for output for (i, operand) in self.operands.iter().enumerate() { match *operand { - InlineAsmOperand::Out { reg, place: Some(_), .. } => { + CInlineAsmOperand::Out { reg, place: Some(_), .. } => { slots_output[i] = Some(new_slot(reg.reg_class())); } _ => (), @@ -549,13 +615,23 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { generated_asm.push_str(s); } InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => { - if self.options.contains(InlineAsmOptions::ATT_SYNTAX) { - generated_asm.push('%'); + match self.operands[*operand_idx] { + CInlineAsmOperand::In { .. } + | CInlineAsmOperand::Out { .. } + | CInlineAsmOperand::InOut { .. } => { + if self.options.contains(InlineAsmOptions::ATT_SYNTAX) { + generated_asm.push('%'); + } + self.registers[*operand_idx] + .unwrap() + .emit(&mut generated_asm, self.arch, *modifier) + .unwrap(); + } + CInlineAsmOperand::Const { ref value } => { + generated_asm.push_str(value); + } + CInlineAsmOperand::Symbol { symbol } => generated_asm.push_str(symbol.name), } - self.registers[*operand_idx] - .unwrap() - .emit(&mut generated_asm, self.arch, *modifier) - .unwrap(); } } } From 2e93be3a4c8f59e3856c22152c3771054577b618 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 5 Feb 2023 17:24:02 +0000 Subject: [PATCH 26/31] Add create_wrapper_function helper --- src/allocator.rs | 75 +++++++++--------------------------------------- src/common.rs | 38 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 61 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index 8508227179a..1c73957ca57 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -70,37 +70,13 @@ fn codegen_inner( params: arg_tys.iter().cloned().map(AbiParam::new).collect(), returns: output.into_iter().map(AbiParam::new).collect(), }; - - let caller_name = format!("__rust_{}", method.name); - let callee_name = kind.fn_name(method.name); - - let func_id = module.declare_function(&caller_name, Linkage::Export, &sig).unwrap(); - - let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap(); - - let mut ctx = Context::new(); - ctx.func.signature = sig.clone(); - { - let mut func_ctx = FunctionBuilderContext::new(); - let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); - - let block = bcx.create_block(); - bcx.switch_to_block(block); - let args = arg_tys - .into_iter() - .map(|ty| bcx.append_block_param(block, ty)) - .collect::>(); - - let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func); - let call_inst = bcx.ins().call(callee_func_ref, &args); - let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error - - bcx.ins().return_(&results); - bcx.seal_all_blocks(); - bcx.finalize(); - } - module.define_function(func_id, &mut ctx).unwrap(); - unwind_context.add_function(func_id, &ctx, module.isa()); + crate::common::create_wrapper_function( + module, + unwind_context, + sig, + &format!("__rust_{}", method.name), + &kind.fn_name(method.name), + ); } let sig = Signature { @@ -108,36 +84,13 @@ fn codegen_inner( params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)], returns: vec![], }; - - let callee_name = alloc_error_handler_kind.fn_name(sym::oom); - - let func_id = - module.declare_function("__rust_alloc_error_handler", Linkage::Export, &sig).unwrap(); - - let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap(); - - let mut ctx = Context::new(); - ctx.func.signature = sig; - { - let mut func_ctx = FunctionBuilderContext::new(); - let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); - - let block = bcx.create_block(); - bcx.switch_to_block(block); - let args = (&[usize_ty, usize_ty]) - .iter() - .map(|&ty| bcx.append_block_param(block, ty)) - .collect::>(); - - let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func); - bcx.ins().call(callee_func_ref, &args); - - bcx.ins().trap(TrapCode::UnreachableCodeReached); - bcx.seal_all_blocks(); - bcx.finalize(); - } - module.define_function(func_id, &mut ctx).unwrap(); - unwind_context.add_function(func_id, &ctx, module.isa()); + crate::common::create_wrapper_function( + module, + unwind_context, + sig, + "__rust_alloc_error_handler", + &alloc_error_handler_kind.fn_name(sym::oom), + ); let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap(); let mut data_ctx = DataContext::new(); diff --git a/src/common.rs b/src/common.rs index f41af3a9e63..16ae526090b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -254,6 +254,44 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool { } } +pub(crate) fn create_wrapper_function( + module: &mut impl Module, + unwind_context: &mut UnwindContext, + sig: Signature, + wrapper_name: &str, + callee_name: &str, +) { + let wrapper_func_id = module.declare_function(wrapper_name, Linkage::Export, &sig).unwrap(); + let callee_func_id = module.declare_function(callee_name, Linkage::Import, &sig).unwrap(); + + let mut ctx = Context::new(); + ctx.func.signature = sig; + { + let mut func_ctx = FunctionBuilderContext::new(); + let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); + + let block = bcx.create_block(); + bcx.switch_to_block(block); + let func = &mut bcx.func.stencil; + let args = func + .signature + .params + .iter() + .map(|param| func.dfg.append_block_param(block, param.value_type)) + .collect::>(); + + let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func); + let call_inst = bcx.ins().call(callee_func_ref, &args); + let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error + + bcx.ins().return_(&results); + bcx.seal_all_blocks(); + bcx.finalize(); + } + module.define_function(wrapper_func_id, &mut ctx).unwrap(); + unwind_context.add_function(wrapper_func_id, &ctx, module.isa()); +} + pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) cx: &'clif mut crate::CodegenCx, pub(crate) module: &'m mut dyn Module, From a2719a285c7baeddb5cb0fd9bdd801b303b74a3e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 5 Feb 2023 17:39:00 +0000 Subject: [PATCH 27/31] Fix linker error when inline asm sym operand is not exported from local CGU --- src/common.rs | 2 +- src/inline_asm.rs | 31 ++++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/common.rs b/src/common.rs index 16ae526090b..a8be0d32cc8 100644 --- a/src/common.rs +++ b/src/common.rs @@ -255,7 +255,7 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool { } pub(crate) fn create_wrapper_function( - module: &mut impl Module, + module: &mut dyn Module, unwind_context: &mut UnwindContext, sig: Signature, wrapper_name: &str, diff --git a/src/inline_asm.rs b/src/inline_asm.rs index aa0b51181f4..6206fbf7dd5 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -6,7 +6,6 @@ use std::fmt::Write; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir::InlineAsmOperand; -use rustc_middle::ty::SymbolName; use rustc_span::sym; use rustc_target::asm::*; @@ -30,7 +29,7 @@ enum CInlineAsmOperand<'tcx> { value: String, }, Symbol { - symbol: SymbolName<'tcx>, + symbol: String, }, } @@ -263,7 +262,29 @@ pub(crate) fn codegen_inline_asm<'tcx>( substs, ) .unwrap(); - CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance) } + let symbol = fx.tcx.symbol_name(instance); + + // Pass a wrapper rather than the function itself as the function itself may not + // be exported from the main codegen unit and may thus be unreachable from the + // object file created by an external assembler. + let inline_asm_index = fx.cx.inline_asm_index.get(); + fx.cx.inline_asm_index.set(inline_asm_index + 1); + let wrapper_name = format!( + "__inline_asm_{}_wrapper_n{}", + fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), + inline_asm_index + ); + let sig = + get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance); + create_wrapper_function( + fx.module, + &mut fx.cx.unwind_context, + sig, + &wrapper_name, + symbol.name, + ); + + CInlineAsmOperand::Symbol { symbol: wrapper_name } } else { span_bug!(span, "invalid type for asm sym (fn)"); } @@ -271,7 +292,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( InlineAsmOperand::SymStatic { def_id } => { assert!(fx.tcx.is_static(def_id)); let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); - CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance) } + CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance).name.to_owned() } } }) .collect::>(); @@ -630,7 +651,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { CInlineAsmOperand::Const { ref value } => { generated_asm.push_str(value); } - CInlineAsmOperand::Symbol { symbol } => generated_asm.push_str(symbol.name), + CInlineAsmOperand::Symbol { ref symbol } => generated_asm.push_str(symbol), } } } From df6b06790057ca32584a6ed6bfdd02045594137d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 5 Feb 2023 18:17:31 +0000 Subject: [PATCH 28/31] Implement const operands for global asm --- src/global_asm.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index dcbcaba30fe..9aee4908c5c 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -7,7 +7,7 @@ use std::process::{Command, Stdio}; use std::sync::Arc; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; -use rustc_hir::ItemId; +use rustc_hir::{InlineAsmOperand, ItemId}; use rustc_session::config::{OutputFilenames, OutputType}; use crate::prelude::*; @@ -23,7 +23,32 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, for piece in asm.template { match *piece { InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s), - InlineAsmTemplatePiece::Placeholder { .. } => todo!(), + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: op_sp } => { + match asm.operands[operand_idx].0 { + InlineAsmOperand::Const { ref anon_const } => { + let const_value = + tcx.const_eval_poly(anon_const.def_id.to_def_id()).unwrap_or_else( + |_| span_bug!(op_sp, "asm const cannot be resolved"), + ); + let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + let string = rustc_codegen_ssa::common::asm_const_to_str( + tcx, + op_sp, + const_value, + RevealAllLayoutCx(tcx).layout_of(ty), + ); + global_asm.push_str(&string); + } + InlineAsmOperand::SymFn { anon_const: _ } => todo!(), + InlineAsmOperand::SymStatic { path: _, def_id: _ } => todo!(), + InlineAsmOperand::In { .. } + | InlineAsmOperand::Out { .. } + | InlineAsmOperand::InOut { .. } + | InlineAsmOperand::SplitInOut { .. } => { + span_bug!(op_sp, "invalid operand type for global_asm!") + } + } + } } } global_asm.push_str("\n.att_syntax\n\n"); From 178e267977c646e34a1440cb10e32e0716e2241e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 5 Feb 2023 18:42:30 +0000 Subject: [PATCH 29/31] Implement sym operands for global asm --- src/global_asm.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index 9aee4908c5c..46c78ce6a1e 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -39,8 +39,22 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, ); global_asm.push_str(&string); } - InlineAsmOperand::SymFn { anon_const: _ } => todo!(), - InlineAsmOperand::SymStatic { path: _, def_id: _ } => todo!(), + InlineAsmOperand::SymFn { anon_const } => { + let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + let instance = match ty.kind() { + &ty::FnDef(def_id, substs) => Instance::new(def_id, substs), + _ => span_bug!(op_sp, "asm sym is not a function"), + }; + let symbol = tcx.symbol_name(instance); + // FIXME handle the case where the function was made private to the + // current codegen unit + global_asm.push_str(symbol.name); + } + InlineAsmOperand::SymStatic { path: _, def_id } => { + let instance = Instance::mono(tcx, def_id).polymorphize(tcx); + let symbol = tcx.symbol_name(instance); + global_asm.push_str(symbol.name); + } InlineAsmOperand::In { .. } | InlineAsmOperand::Out { .. } | InlineAsmOperand::InOut { .. } From 8494882773392b461e9609e4f4a60818b26e964c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 6 Feb 2023 18:32:25 +0100 Subject: [PATCH 30/31] Rustup to rustc 1.69.0-nightly (75a0be98f 2023-02-05) --- build_sysroot/Cargo.lock | 4 ++-- rust-toolchain | 2 +- src/base.rs | 31 ++++++++++++++++++++++--------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index 24f15fc8521..b7e0b68a2a2 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" diff --git a/rust-toolchain b/rust-toolchain index f7205cb9800..40fb54b9159 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-01-27" +channel = "nightly-2023-02-06" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/base.rs b/src/base.rs index 50baa70ab0f..189d952a92f 100644 --- a/src/base.rs +++ b/src/base.rs @@ -790,17 +790,30 @@ fn codegen_stmt<'tcx>( let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into()); lval.write_cvalue(fx, val); } - Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() { - AggregateKind::Array(_ty) => { - for (i, operand) in operands.iter().enumerate() { - let operand = codegen_operand(fx, operand); - let index = fx.bcx.ins().iconst(fx.pointer_type, i as i64); - let to = lval.place_index(fx, index); - to.write_cvalue(fx, operand); + Rvalue::Aggregate(ref kind, ref operands) => { + let (variant_index, variant_dest, active_field_index) = match **kind { + mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { + let variant_dest = lval.downcast_variant(fx, variant_index); + (variant_index, variant_dest, active_field_index) } + _ => (VariantIdx::from_u32(0), lval, None), + }; + if active_field_index.is_some() { + assert_eq!(operands.len(), 1); } - _ => unreachable!("shouldn't exist at codegen {:?}", to_place_and_rval.1), - }, + for (i, operand) in operands.iter().enumerate() { + let operand = codegen_operand(fx, operand); + let field_index = active_field_index.unwrap_or(i); + let to = if let mir::AggregateKind::Array(_) = **kind { + let index = fx.bcx.ins().iconst(fx.pointer_type, field_index as i64); + variant_dest.place_index(fx, index) + } else { + variant_dest.place_field(fx, mir::Field::new(field_index)) + }; + to.write_cvalue(fx, operand); + } + crate::discriminant::codegen_set_discriminant(fx, lval, variant_index); + } } } StatementKind::StorageLive(_) From 7d53619064ab7045c383644cb445052d2a3d46db Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 6 Feb 2023 19:27:27 +0100 Subject: [PATCH 31/31] Force the allocator to be looked up from the perspective of the rustc binary Fixes #1303 --- .github/workflows/main.yml | 5 +++-- src/compiler_builtins.rs | 38 +++++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9d67886ba86..9d3ed3ac5d0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed + - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-unknown-linux-gnu - os: macos-latest @@ -226,7 +226,8 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed + # FIXME update at some point in the future once most distros use a newer glibc + - os: ubuntu-20.04 env: TARGET_TRIPLE: x86_64-unknown-linux-gnu - os: macos-latest diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index c6a247cf59e..8a53baa763a 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -1,14 +1,33 @@ +#[cfg(all(unix, feature = "jit"))] +use std::ffi::c_int; +#[cfg(feature = "jit")] +use std::ffi::c_void; + +// FIXME replace with core::ffi::c_size_t once stablized +#[allow(non_camel_case_types)] +#[cfg(feature = "jit")] +type size_t = usize; + macro_rules! builtin_functions { - ($register:ident; $(fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty;)*) => { + ( + $register:ident; + $( + $(#[$attr:meta])? + fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty; + )* + ) => { #[cfg(feature = "jit")] #[allow(improper_ctypes)] extern "C" { - $(fn $name($($arg_name: $arg_ty),*) -> $ret_ty;)* + $( + $(#[$attr])? + fn $name($($arg_name: $arg_ty),*) -> $ret_ty; + )* } #[cfg(feature = "jit")] pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) { - for (name, val) in [$((stringify!($name), $name as *const u8)),*] { + for (name, val) in [$($(#[$attr])? (stringify!($name), $name as *const u8)),*] { builder.symbol(name, val); } } @@ -40,4 +59,17 @@ builtin_functions! { fn __fixdfti(f: f64) -> i128; fn __fixunssfti(f: f32) -> u128; fn __fixunsdfti(f: f64) -> u128; + + // allocator + // NOTE: These need to be mentioned here despite not being part of compiler_builtins because + // newer glibc resolve dlsym("malloc") to libc.so despite the override in the rustc binary to + // use jemalloc. Libraries opened with dlopen still get the jemalloc version, causing multiple + // allocators to be mixed, resulting in a crash. + fn calloc(nobj: size_t, size: size_t) -> *mut c_void; + #[cfg(unix)] + fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int; + fn malloc(size: size_t) -> *mut c_void; + fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; + fn free(p: *mut c_void) -> (); + }