From 717d36abc95e5eef728842ccc0701c564e7a5cf1 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Wed, 29 Jan 2025 06:22:39 +0100 Subject: [PATCH 01/19] Simplify Rc::as_ptr docs + typo fix --- library/alloc/src/rc.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index ae3318b839dd..36a543774f5c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1462,18 +1462,18 @@ pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { /// Provides a raw pointer to the data. /// /// The counts are not affected in any way and the `Rc` is not consumed. The pointer is valid - /// for as long there are strong counts in the `Rc`. + /// for as long as there are strong counts in the `Rc`. /// /// # Examples /// /// ``` /// use std::rc::Rc; /// - /// let x = Rc::new("hello".to_owned()); + /// let x = Rc::new(0); /// let y = Rc::clone(&x); /// let x_ptr = Rc::as_ptr(&x); /// assert_eq!(x_ptr, Rc::as_ptr(&y)); - /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// assert_eq!(unsafe { *x_ptr }, 0); /// ``` #[stable(feature = "weak_into_raw", since = "1.45.0")] #[rustc_never_returns_null_ptr] From 7d29a2e6926824d34fe92d4703271162a6f12b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:12:26 +0800 Subject: [PATCH 02/19] bootstrap: feed stage number via `--stage` to compiletest --- src/bootstrap/src/core/build_steps/test.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 825e5452f0e6..b0181410be12 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1648,16 +1648,17 @@ fn run(self, builder: &Builder<'_>) { // bootstrap compiler. // NOTE: Only stage 1 is special cased because we need the rustc_private artifacts to match the // running compiler in stage 2 when plugins run. - let stage_id = if suite == "ui-fulldeps" && compiler.stage == 1 { - // At stage 0 (stage - 1) we are using the beta compiler. Using `self.target` can lead finding - // an incorrect compiler path on cross-targets, as the stage 0 beta compiler is always equal - // to `build.build` in the configuration. + let (stage, stage_id) = if suite == "ui-fulldeps" && compiler.stage == 1 { + // At stage 0 (stage - 1) we are using the beta compiler. Using `self.target` can lead + // finding an incorrect compiler path on cross-targets, as the stage 0 beta compiler is + // always equal to `build.build` in the configuration. let build = builder.build.build; - compiler = builder.compiler(compiler.stage - 1, build); - format!("stage{}-{}", compiler.stage + 1, build) + let test_stage = compiler.stage + 1; + (test_stage, format!("stage{}-{}", test_stage, build)) } else { - format!("stage{}-{}", compiler.stage, target) + let stage = compiler.stage; + (stage, format!("stage{}-{}", stage, target)) }; if suite.ends_with("fulldeps") { @@ -1699,6 +1700,9 @@ fn run(self, builder: &Builder<'_>) { // compiletest currently has... a lot of arguments, so let's just pass all // of them! + cmd.arg("--stage").arg(stage.to_string()); + cmd.arg("--stage-id").arg(stage_id); + cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler)); cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(compiler, target)); cmd.arg("--rustc-path").arg(builder.rustc(compiler)); @@ -1767,8 +1771,9 @@ fn run(self, builder: &Builder<'_>) { } else { builder.sysroot(compiler).to_path_buf() }; + cmd.arg("--sysroot-base").arg(sysroot); - cmd.arg("--stage-id").arg(stage_id); + cmd.arg("--suite").arg(suite); cmd.arg("--mode").arg(mode); cmd.arg("--target").arg(target.rustc_target_arg()); From 8a0dc27d57c9fa4b75ed184c16a4f8059eb70174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:13:29 +0800 Subject: [PATCH 03/19] compiletest: use `--stage` number directly instead of deriving from `--stage-id` Notably, this avoids having to do hacky string splitting based on `--stage-id`. --- src/tools/compiletest/src/common.rs | 4 ++- src/tools/compiletest/src/header/cfg.rs | 2 +- src/tools/compiletest/src/header/tests.rs | 10 +++++- src/tools/compiletest/src/lib.rs | 10 ++++++ src/tools/compiletest/src/runtest/run_make.rs | 32 +++---------------- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 00821fc9f9db..cde4f7a665cb 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -224,7 +224,9 @@ pub struct Config { /// The directory containing the compiler sysroot pub sysroot_base: PathBuf, - /// The name of the stage being built (stage1, etc) + /// The number of the stage under test. + pub stage: u32, + /// The id of the stage under test (stage1-xxx, etc). pub stage_id: String, /// The test mode, e.g. ui or debuginfo. diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 6e5ced17c208..cfe51b5655f8 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -192,7 +192,7 @@ macro_rules! condition { message: "on big-endian targets", } condition! { - name: config.stage_id.split('-').next().unwrap(), + name: format!("stage{}", config.stage).as_str(), allowed_names: &["stage0", "stage1", "stage2"], message: "when the bootstrapping stage is {name}", } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index ebba16d41f9e..a9a07ff49564 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -72,6 +72,7 @@ struct ConfigBuilder { channel: Option, host: Option, target: Option, + stage: Option, stage_id: Option, llvm_version: Option, git_hash: bool, @@ -102,6 +103,11 @@ fn target(&mut self, s: &str) -> &mut Self { self } + fn stage(&mut self, n: u32) -> &mut Self { + self.stage = Some(n); + self + } + fn stage_id(&mut self, s: &str) -> &mut Self { self.stage_id = Some(s.to_owned()); self @@ -156,6 +162,8 @@ fn build(&mut self) -> Config { "--cxxflags=", "--llvm-components=", "--android-cross-path=", + "--stage", + &self.stage.unwrap_or(2).to_string(), "--stage-id", self.stage_id.as_deref().unwrap_or("stage2-x86_64-unknown-linux-gnu"), "--channel", @@ -387,7 +395,7 @@ fn std_debug_assertions() { #[test] fn stage() { - let config: Config = cfg().stage_id("stage1-x86_64-unknown-linux-gnu").build(); + let config: Config = cfg().stage(1).stage_id("stage1-x86_64-unknown-linux-gnu").build(); assert!(check_ignore(&config, "//@ ignore-stage1")); assert!(!check_ignore(&config, "//@ ignore-stage2")); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 27a046ba5bc4..d0a83cab9cd9 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -64,6 +64,7 @@ pub fn parse_config(args: Vec) -> Config { .reqopt("", "src-base", "directory to scan for test files", "PATH") .reqopt("", "build-base", "directory to deposit test outputs", "PATH") .reqopt("", "sysroot-base", "directory containing the compiler sysroot", "PATH") + .reqopt("", "stage", "stage number under test", "N") .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET") .reqopt( "", @@ -294,6 +295,11 @@ fn make_absolute(path: PathBuf) -> PathBuf { panic!("`--nocapture` is deprecated; please use `--no-capture`"); } + let stage = match matches.opt_str("stage") { + Some(stage) => stage.parse::().expect("expected `--stage` to be an unsigned integer"), + None => panic!("`--stage` is required"), + }; + Config { bless: matches.opt_present("bless"), compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), @@ -311,7 +317,10 @@ fn make_absolute(path: PathBuf) -> PathBuf { src_base, build_base: opt_path(matches, "build-base"), sysroot_base: opt_path(matches, "sysroot-base"), + + stage, stage_id: matches.opt_str("stage-id").unwrap(), + mode, suite: matches.opt_str("suite").unwrap(), debugger: matches.opt_str("debugger").map(|debugger| { @@ -415,6 +424,7 @@ pub fn log_config(config: &Config) { logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); logv(c, format!("src_base: {:?}", config.src_base.display())); logv(c, format!("build_base: {:?}", config.build_base.display())); + logv(c, format!("stage: {}", config.stage)); logv(c, format!("stage_id: {}", config.stage_id)); logv(c, format!("mode: {}", config.mode)); logv(c, format!("run_ignored: {}", config.run_ignored)); diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 7ef16e4a9667..16c46fc13390 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -239,30 +239,6 @@ fn run_rmake_v2_test(&self) { } } - // `self.config.stage_id` looks like `stage1-`, but we only want - // the `stage1` part as that is what the output directories of bootstrap are prefixed with. - // Note that this *assumes* build layout from bootstrap is produced as: - // - // ``` - // build// // <- this is `build_root` - // ├── stage0 - // ├── stage0-bootstrap-tools - // ├── stage0-codegen - // ├── stage0-rustc - // ├── stage0-std - // ├── stage0-sysroot - // ├── stage0-tools - // ├── stage0-tools-bin - // ├── stage1 - // ├── stage1-std - // ├── stage1-tools - // ├── stage1-tools-bin - // └── test - // ``` - // FIXME(jieyouxu): improve the communication between bootstrap and compiletest here so - // we don't have to hack out a `stageN`. - let stage = self.config.stage_id.split('-').next().unwrap(); - // In order to link in the support library as a rlib when compiling recipes, we need three // paths: // 1. Path of the built support library rlib itself. @@ -284,10 +260,12 @@ fn run_rmake_v2_test(&self) { // support lib and its deps are organized, can't we copy them to the tools-bin dir as // well?), but this seems to work for now. - let stage_tools_bin = build_root.join(format!("{stage}-tools-bin")); + let stage_number = self.config.stage; + + let stage_tools_bin = build_root.join(format!("stage{stage_number}-tools-bin")); let support_lib_path = stage_tools_bin.join("librun_make_support.rlib"); - let stage_tools = build_root.join(format!("{stage}-tools")); + let stage_tools = build_root.join(format!("stage{stage_number}-tools")); let support_lib_deps = stage_tools.join(&self.config.host).join("release").join("deps"); let support_lib_deps_deps = stage_tools.join("release").join("deps"); @@ -368,7 +346,7 @@ fn run_rmake_v2_test(&self) { // provided through env vars. // Compute stage-specific standard library paths. - let stage_std_path = build_root.join(&stage).join("lib"); + let stage_std_path = build_root.join(format!("stage{stage_number}")).join("lib"); // Compute dynamic library search paths for recipes. let recipe_dylib_search_paths = { From 4677d753f9691a1f3c17bd419934e41825fb9cb3 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:06:54 +0100 Subject: [PATCH 04/19] ci: stop mysql before removing it --- src/ci/scripts/free-disk-space.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ci/scripts/free-disk-space.sh b/src/ci/scripts/free-disk-space.sh index 8850e168145b..32d55806b564 100755 --- a/src/ci/scripts/free-disk-space.sh +++ b/src/ci/scripts/free-disk-space.sh @@ -110,6 +110,9 @@ execAndMeasureSpaceChange() { # Remove large packages # REF: https://github.com/apache/flink/blob/master/tools/azure-pipelines/free_disk_space.sh cleanPackages() { + # Stop services to avoid issues when removing their packages. + sudo systemctl stop mysql + local packages=( '^aspnetcore-.*' '^dotnet-.*' From bd6a6777f5cbbec549f123995026cef76d1e6b84 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 4 Feb 2025 18:11:59 +0000 Subject: [PATCH 05/19] Use Option for FindNextFileHandle --- library/std/src/sys/pal/windows/fs.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index f8493c21ad44..fdf789529094 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -44,7 +44,7 @@ pub struct FileType { } pub struct ReadDir { - handle: FindNextFileHandle, + handle: Option, root: Arc, first: Option, } @@ -113,13 +113,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { impl Iterator for ReadDir { type Item = io::Result; fn next(&mut self) -> Option> { - if self.handle.0 == c::INVALID_HANDLE_VALUE { + let Some(handle) = self.handle.as_ref() else { // This iterator was initialized with an `INVALID_HANDLE_VALUE` as its handle. // Simply return `None` because this is only the case when `FindFirstFileExW` in // the construction of this iterator returns `ERROR_FILE_NOT_FOUND` which means // no matchhing files can be found. return None; - } + }; if let Some(first) = self.first.take() { if let Some(e) = DirEntry::new(&self.root, &first) { return Some(Ok(e)); @@ -128,7 +128,7 @@ fn next(&mut self) -> Option> { unsafe { let mut wfd = mem::zeroed(); loop { - if c::FindNextFileW(self.handle.0, &mut wfd) == 0 { + if c::FindNextFileW(handle.0, &mut wfd) == 0 { match api::get_last_error() { WinError::NO_MORE_FILES => return None, WinError { code } => { @@ -1190,7 +1190,7 @@ pub fn readdir(p: &Path) -> io::Result { if find_handle != c::INVALID_HANDLE_VALUE { Ok(ReadDir { - handle: FindNextFileHandle(find_handle), + handle: Some(FindNextFileHandle(find_handle)), root: Arc::new(root), first: Some(wfd), }) @@ -1208,11 +1208,7 @@ pub fn readdir(p: &Path) -> io::Result { // See issue #120040: https://github.com/rust-lang/rust/issues/120040. let last_error = api::get_last_error(); if last_error == WinError::FILE_NOT_FOUND { - return Ok(ReadDir { - handle: FindNextFileHandle(find_handle), - root: Arc::new(root), - first: None, - }); + return Ok(ReadDir { handle: None, root: Arc::new(root), first: None }); } // Just return the error constructed from the raw OS error if the above is not the case. From 62bbaa8091a5d83e5b1b20d05e971b73782e6f86 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Fri, 24 Jan 2025 16:31:12 +0100 Subject: [PATCH 06/19] Removed dependency on the field-offset crate. --- Cargo.lock | 21 --------------------- compiler/rustc_middle/Cargo.toml | 1 - compiler/rustc_middle/src/query/plumbing.rs | 7 ++++--- compiler/rustc_query_impl/Cargo.toml | 1 - compiler/rustc_query_impl/src/lib.rs | 17 ++++++++++++++--- compiler/rustc_query_impl/src/plumbing.rs | 4 ++-- src/tools/tidy/src/deps.rs | 4 ---- 7 files changed, 20 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c8f06a02396..f4c4c9c24abf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1209,16 +1209,6 @@ dependencies = [ "tidy", ] -[[package]] -name = "field-offset" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" -dependencies = [ - "memoffset", - "rustc_version", -] - [[package]] name = "filetime" version = "0.2.25" @@ -2295,15 +2285,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -4176,7 +4157,6 @@ version = "0.0.0" dependencies = [ "bitflags", "either", - "field-offset", "gsgdt", "polonius-engine", "rustc-rayon-core", @@ -4424,7 +4404,6 @@ dependencies = [ name = "rustc_query_impl" version = "0.0.0" dependencies = [ - "field-offset", "measureme", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 2c34df6ea61a..de722e62043c 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" # tidy-alphabetical-start bitflags = "2.4.1" either = "1.5.0" -field-offset = "0.3.5" gsgdt = "0.1.2" polonius-engine = "0.13.0" rustc-rayon-core = { version = "0.5.0" } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 6c019b427dbd..690b8128b1ae 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -1,6 +1,5 @@ use std::ops::Deref; -use field_offset::FieldOffset; use rustc_data_structures::sync::{AtomicU64, WorkerLocal}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::OwnerId; @@ -24,8 +23,10 @@ pub struct DynamicQuery<'tcx, C: QueryCache> { pub eval_always: bool, pub dep_kind: DepKind, pub handle_cycle_error: HandleCycleError, - pub query_state: FieldOffset, QueryState>, - pub query_cache: FieldOffset, C>, + // Offset of this query's state field in the QueryStates struct + pub query_state: usize, + // Offset of this query's cache field in the QueryCaches struct + pub query_cache: usize, pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 6e8fd32610bc..8b0cc9d726b8 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -field-offset = "0.3.5" measureme = "11" rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index bbc83cca99d8..73c205fdb17d 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -11,7 +11,6 @@ #![warn(unreachable_pub)] // tidy-alphabetical-end -use field_offset::offset_of; use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::sync::AtomicU64; use rustc_middle::arena::Arena; @@ -89,7 +88,13 @@ fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState where QueryCtxt<'tcx>: 'a, { - self.dynamic.query_state.apply(&qcx.tcx.query_system.states) + // Safety: + // This is just manually doing the subfield referencing through pointer math. + unsafe { + &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>) + .byte_add(self.dynamic.query_state) + .cast::>() + } } #[inline(always)] @@ -97,7 +102,13 @@ fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache where 'tcx: 'a, { - self.dynamic.query_cache.apply(&qcx.tcx.query_system.caches) + // Safety: + // This is just manually doing the subfield referencing through pointer math. + unsafe { + &*(&qcx.tcx.query_system.caches as *const QueryCaches<'tcx>) + .byte_add(self.dynamic.query_cache) + .cast::() + } } #[inline(always)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 46ec538735a6..e95c186f6b68 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -605,8 +605,8 @@ pub(crate) fn dynamic_query<'tcx>() eval_always: is_eval_always!([$($modifiers)*]), dep_kind: dep_graph::dep_kinds::$name, handle_cycle_error: handle_cycle_error!([$($modifiers)*]), - query_state: offset_of!(QueryStates<'tcx> => $name), - query_cache: offset_of!(QueryCaches<'tcx> => $name), + query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), + query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key), execute_query: |tcx, key| erase(tcx.$name(key)), compute: |tcx, key| { diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index faa0db27b2b0..5478ff4a6c6a 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -285,7 +285,6 @@ "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", - "field-offset", "flate2", "fluent-bundle", "fluent-langneg", @@ -327,7 +326,6 @@ "measureme", "memchr", "memmap2", - "memoffset", "miniz_oxide", "nix", "nu-ansi-term", @@ -367,14 +365,12 @@ "rustc-rayon-core", "rustc-stable-hash", "rustc_apfloat", - "rustc_version", "rustix", "ruzstd", // via object in thorin-dwp "ryu", "scoped-tls", "scopeguard", "self_cell", - "semver", "serde", "serde_derive", "serde_json", From ee7dc06cf181c073b1040669a40bc325d00f8c6d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 20 Jan 2025 22:43:59 +1100 Subject: [PATCH 07/19] coverage: Store BCB node IDs in mappings, and resolve them in codegen Even though the coverage graph itself is no longer available during codegen, its nodes can still be used as opaque IDs. --- .../src/coverageinfo/mapgen/covfun.rs | 29 ++++++----- compiler/rustc_middle/src/mir/coverage.rs | 51 ++++++++++--------- .../src/coverage/counters.rs | 6 +-- .../rustc_mir_transform/src/coverage/graph.rs | 10 +--- .../rustc_mir_transform/src/coverage/mod.rs | 46 +++++++---------- .../rustc_mir_transform/src/coverage/query.rs | 4 +- ...ch_match_arms.main.InstrumentCoverage.diff | 12 ++--- ...ument_coverage.bar.InstrumentCoverage.diff | 2 +- ...ment_coverage.main.InstrumentCoverage.diff | 10 ++-- tests/mir-opt/coverage/instrument_coverage.rs | 4 +- ...rage_cleanup.main.CleanupPostBorrowck.diff | 10 ++-- ...erage_cleanup.main.InstrumentCoverage.diff | 10 ++-- 12 files changed, 91 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 460a46646157..38e7f4f21d43 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -11,7 +11,8 @@ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; use rustc_middle::mir::coverage::{ - CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping, MappingKind, Op, + BasicCoverageBlock, CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping, + MappingKind, Op, }; use rustc_middle::ty::{Instance, TyCtxt}; use rustc_span::Span; @@ -140,7 +141,12 @@ fn fill_region_tables<'tcx>( for &Mapping { ref kind, span } in &fn_cov_info.mappings { // If the mapping refers to counters/expressions that were removed by // MIR opts, replace those occurrences with zero. - let kind = kind.map_terms(|term| if is_zero_term(term) { CovTerm::Zero } else { term }); + let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter { + let term = + fn_cov_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term"); + let term = if is_zero_term(term) { CovTerm::Zero } else { term }; + ffi::Counter::from_term(term) + }; // Convert the `Span` into coordinates that we can pass to LLVM, or // discard the span if conversion fails. In rare, cases _all_ of a @@ -154,23 +160,22 @@ fn fill_region_tables<'tcx>( continue; } - match kind { - MappingKind::Code(term) => { - code_regions - .push(ffi::CodeRegion { cov_span, counter: ffi::Counter::from_term(term) }); + match *kind { + MappingKind::Code { bcb } => { + code_regions.push(ffi::CodeRegion { cov_span, counter: counter_for_bcb(bcb) }); } - MappingKind::Branch { true_term, false_term } => { + MappingKind::Branch { true_bcb, false_bcb } => { branch_regions.push(ffi::BranchRegion { cov_span, - true_counter: ffi::Counter::from_term(true_term), - false_counter: ffi::Counter::from_term(false_term), + true_counter: counter_for_bcb(true_bcb), + false_counter: counter_for_bcb(false_bcb), }); } - MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { + MappingKind::MCDCBranch { true_bcb, false_bcb, mcdc_params } => { mcdc_branch_regions.push(ffi::MCDCBranchRegion { cov_span, - true_counter: ffi::Counter::from_term(true_term), - false_counter: ffi::Counter::from_term(false_term), + true_counter: counter_for_bcb(true_bcb), + false_counter: counter_for_bcb(false_bcb), mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params), }); } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 46534697e1d6..8123707dc73a 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -179,34 +179,19 @@ pub struct Expression { #[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub enum MappingKind { /// Associates a normal region of code with a counter/expression/zero. - Code(CovTerm), + Code { bcb: BasicCoverageBlock }, /// Associates a branch region with separate counters for true and false. - Branch { true_term: CovTerm, false_term: CovTerm }, + Branch { true_bcb: BasicCoverageBlock, false_bcb: BasicCoverageBlock }, /// Associates a branch region with separate counters for true and false. - MCDCBranch { true_term: CovTerm, false_term: CovTerm, mcdc_params: ConditionInfo }, + MCDCBranch { + true_bcb: BasicCoverageBlock, + false_bcb: BasicCoverageBlock, + mcdc_params: ConditionInfo, + }, /// Associates a decision region with a bitmap and number of conditions. MCDCDecision(DecisionInfo), } -impl MappingKind { - /// Returns a copy of this mapping kind, in which all coverage terms have - /// been replaced with ones returned by the given function. - pub fn map_terms(&self, map_fn: impl Fn(CovTerm) -> CovTerm) -> Self { - match *self { - Self::Code(term) => Self::Code(map_fn(term)), - Self::Branch { true_term, false_term } => { - Self::Branch { true_term: map_fn(true_term), false_term: map_fn(false_term) } - } - Self::MCDCBranch { true_term, false_term, mcdc_params } => Self::MCDCBranch { - true_term: map_fn(true_term), - false_term: map_fn(false_term), - mcdc_params, - }, - Self::MCDCDecision(param) => Self::MCDCDecision(param), - } - } -} - #[derive(Clone, Debug)] #[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct Mapping { @@ -222,10 +207,14 @@ pub struct Mapping { pub struct FunctionCoverageInfo { pub function_source_hash: u64, pub body_span: Span, + pub num_counters: usize, - pub mcdc_bitmap_bits: usize, pub expressions: IndexVec, + pub mappings: Vec, + pub term_for_bcb: IndexVec>, + + pub mcdc_bitmap_bits: usize, /// The depth of the deepest decision is used to know how many /// temp condbitmaps should be allocated for the function. pub mcdc_num_condition_bitmaps: usize, @@ -329,3 +318,19 @@ pub fn is_zero_term(&self, term: CovTerm) -> bool { } } } + +rustc_index::newtype_index! { + /// During the `InstrumentCoverage` MIR pass, a BCB is a node in the + /// "coverage graph", which is a refinement of the MIR control-flow graph + /// that merges or omits some blocks that aren't relevant to coverage. + /// + /// After that pass is complete, the coverage graph no longer exists, so a + /// BCB is effectively an opaque ID. + #[derive(HashStable)] + #[encodable] + #[orderable] + #[debug_format = "bcb{}"] + pub struct BasicCoverageBlock { + const START_BCB = 0; + } +} diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index adb99a75a9e4..50d5bf31829e 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -133,7 +133,7 @@ pub(super) struct CoverageCounters { next_counter_id: CounterId, /// Coverage counters/expressions that are associated with individual BCBs. - node_counters: IndexVec>, + pub(crate) node_counters: IndexVec>, /// Table of expression data, associating each expression ID with its /// corresponding operator (+ or -) and its LHS/RHS operands. @@ -203,10 +203,6 @@ fn set_node_counter(&mut self, bcb: BasicCoverageBlock, counter: CovTerm) -> Cov counter } - pub(super) fn term_for_bcb(&self, bcb: BasicCoverageBlock) -> Option { - self.node_counters[bcb] - } - /// Returns an iterator over all the nodes in the coverage graph that /// should have a counter-increment statement injected into MIR, along with /// each site's corresponding counter ID. diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 392b54c8d819..6d84248ddfbd 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -8,6 +8,7 @@ use rustc_data_structures::graph::{self, DirectedGraph, StartNode}; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; +pub(crate) use rustc_middle::mir::coverage::{BasicCoverageBlock, START_BCB}; use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind}; use tracing::debug; @@ -269,15 +270,6 @@ fn predecessors(&self, node: Self::Node) -> impl Iterator { } } -rustc_index::newtype_index! { - /// A node in the control-flow graph of CoverageGraph. - #[orderable] - #[debug_format = "bcb{}"] - pub(crate) struct BasicCoverageBlock { - const START_BCB = 0; - } -} - /// `BasicCoverageBlockData` holds the data indexed by a `BasicCoverageBlock`. /// /// A `BasicCoverageBlock` (BCB) represents the maximal-length sequence of MIR `BasicBlock`s without diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 15487d05a301..b1afcc84b6e2 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -95,12 +95,13 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: let coverage_counters = counters::make_bcb_counters(&graph, &bcbs_with_counter_mappings); - let mappings = create_mappings(&extracted_mappings, &coverage_counters); + let mappings = create_mappings(&extracted_mappings); if mappings.is_empty() { // No spans could be converted into valid mappings, so skip this function. debug!("no spans could be converted into valid mappings; skipping"); return; } + let term_for_bcb = coverage_counters.node_counters.clone(); inject_coverage_statements(mir_body, &graph, &extracted_mappings, &coverage_counters); @@ -116,26 +117,24 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { function_source_hash: hir_info.function_source_hash, body_span: hir_info.body_span, + num_counters: coverage_counters.num_counters(), - mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits, expressions: coverage_counters.into_expressions(), + mappings, + term_for_bcb, + + mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits, mcdc_num_condition_bitmaps, })); } -/// For each coverage span extracted from MIR, create a corresponding -/// mapping. +/// For each coverage span extracted from MIR, create a corresponding mapping. /// -/// Precondition: All BCBs corresponding to those spans have been given -/// coverage counters. -fn create_mappings( - extracted_mappings: &ExtractedMappings, - coverage_counters: &CoverageCounters, -) -> Vec { - let term_for_bcb = - |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); - +/// FIXME(Zalathar): This used to be where BCBs in the extracted mappings were +/// resolved to a `CovTerm`. But that is now handled elsewhere, so this +/// function can potentially be simplified even further. +fn create_mappings(extracted_mappings: &ExtractedMappings) -> Vec { // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { num_bcbs: _, @@ -150,23 +149,18 @@ fn create_mappings( mappings.extend(code_mappings.iter().map( // Ordinary code mappings are the simplest kind. |&mappings::CodeMapping { span, bcb }| { - let kind = MappingKind::Code(term_for_bcb(bcb)); + let kind = MappingKind::Code { bcb }; Mapping { kind, span } }, )); mappings.extend(branch_pairs.iter().map( |&mappings::BranchPair { span, true_bcb, false_bcb }| { - let true_term = term_for_bcb(true_bcb); - let false_term = term_for_bcb(false_bcb); - let kind = MappingKind::Branch { true_term, false_term }; + let kind = MappingKind::Branch { true_bcb, false_bcb }; Mapping { kind, span } }, )); - let term_for_bcb = - |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); - // MCDC branch mappings are appended with their decisions in case decisions were ignored. mappings.extend(mcdc_degraded_branches.iter().map( |&mappings::MCDCBranch { @@ -176,11 +170,7 @@ fn create_mappings( condition_info: _, true_index: _, false_index: _, - }| { - let true_term = term_for_bcb(true_bcb); - let false_term = term_for_bcb(false_bcb); - Mapping { kind: MappingKind::Branch { true_term, false_term }, span } - }, + }| { Mapping { kind: MappingKind::Branch { true_bcb, false_bcb }, span } }, )); for (decision, branches) in mcdc_mappings { @@ -201,12 +191,10 @@ fn create_mappings( true_index: _, false_index: _, }| { - let true_term = term_for_bcb(true_bcb); - let false_term = term_for_bcb(false_bcb); Mapping { kind: MappingKind::MCDCBranch { - true_term, - false_term, + true_bcb, + false_bcb, mcdc_params: condition_info, }, span, diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index a849ed4c3e27..ef2724222ce0 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -101,7 +101,9 @@ fn coverage_ids_info<'tcx>( // to any particular point in the control-flow graph. // (Keep this in sync with the injection of `ExpressionUsed` // statements in the `InstrumentCoverage` MIR pass.) - if let MappingKind::Code(CovTerm::Expression(id)) = mapping.kind { + if let MappingKind::Code { bcb } = mapping.kind + && let Some(CovTerm::Expression(id)) = fn_cov_info.term_for_bcb[bcb] + { expressions_seen.remove(id); } } diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index 138586300ce6..9647e13f75af 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -30,12 +30,12 @@ + coverage ExpressionId(0) => Expression { lhs: Counter(1), op: Add, rhs: Counter(2) }; + coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Add, rhs: Counter(3) }; + coverage ExpressionId(2) => Expression { lhs: Counter(0), op: Subtract, rhs: Expression(1) }; -+ coverage Code(Counter(0)) => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); -+ coverage Code(Counter(1)) => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); -+ coverage Code(Counter(2)) => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); -+ coverage Code(Counter(3)) => $DIR/branch_match_arms.rs:18:17: 18:33 (#0); -+ coverage Code(Expression(2)) => $DIR/branch_match_arms.rs:19:17: 19:33 (#0); -+ coverage Code(Counter(0)) => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); ++ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:33 (#0); ++ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:33 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index a91d88984a8a..16b7a1a63b4a 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -5,7 +5,7 @@ let mut _0: bool; + coverage body span: $DIR/instrument_coverage.rs:29:18: 31:2 (#0) -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:29:1: 31:2 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:1: 31:2 (#0); + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index d7ea442518eb..fe74ad24e916 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage body span: $DIR/instrument_coverage.rs:14:11: 20:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(1), op: Subtract, rhs: Counter(0) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:14:1: 14:11 (#0); -+ coverage Code(Counter(1)) => $DIR/instrument_coverage.rs:16:12: 16:17 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:17:13: 17:18 (#0); -+ coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:18:10: 18:10 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:20:2: 20:2 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:14:1: 14:11 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:16:12: 16:17 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:17:13: 17:18 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:18:10: 18:10 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:20:2: 20:2 (#0); + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.rs b/tests/mir-opt/coverage/instrument_coverage.rs index c49786f96151..20c730645f8f 100644 --- a/tests/mir-opt/coverage/instrument_coverage.rs +++ b/tests/mir-opt/coverage/instrument_coverage.rs @@ -8,7 +8,7 @@ // EMIT_MIR instrument_coverage.main.InstrumentCoverage.diff // CHECK-LABEL: fn main() // CHECK: coverage body span: -// CHECK: coverage Code(Counter({{[0-9]+}})) => +// CHECK: coverage Code { bcb: bcb{{[0-9]+}} } => // CHECK: bb0: // CHECK: Coverage::CounterIncrement fn main() { @@ -22,7 +22,7 @@ fn main() { // EMIT_MIR instrument_coverage.bar.InstrumentCoverage.diff // CHECK-LABEL: fn bar() // CHECK: coverage body span: -// CHECK: coverage Code(Counter({{[0-9]+}})) => +// CHECK: coverage Code { bcb: bcb{{[0-9]+}} } => // CHECK: bb0: // CHECK: Coverage::CounterIncrement #[inline(never)] diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 2c7ec6e85eb0..28a3f3beadea 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -9,11 +9,11 @@ coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; - coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); - coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); - coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); - coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); - coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); + coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); + coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); + coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); bb0: { Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index c08265eb0e95..0f1dea02b8d9 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); -+ coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); -+ coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); -+ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); ++ coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + bb0: { + Coverage::CounterIncrement(0); From 20d051ec870739c8f263e5f6f581ca24a5dd56fd Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 22 Jan 2025 13:55:08 +1100 Subject: [PATCH 08/19] coverage: Defer part of counter-creation until codegen --- .../src/coverageinfo/mapgen/covfun.rs | 13 +- .../src/coverageinfo/mod.rs | 19 +-- compiler/rustc_codegen_llvm/src/lib.rs | 1 + compiler/rustc_middle/src/mir/coverage.rs | 70 +++++++---- compiler/rustc_middle/src/mir/pretty.rs | 6 +- compiler/rustc_middle/src/query/mod.rs | 13 +- .../src/coverage/counters.rs | 69 ++++------- .../src/coverage/counters/node_flow.rs | 25 +--- .../src/coverage/mappings.rs | 61 ---------- .../rustc_mir_transform/src/coverage/mod.rs | 70 +++-------- .../rustc_mir_transform/src/coverage/query.rs | 112 +++++++++++++----- .../src/coverage/spans/from_mir.rs | 3 +- ...ch_match_arms.main.InstrumentCoverage.diff | 14 +-- ...ument_coverage.bar.InstrumentCoverage.diff | 2 +- ...ment_coverage.main.InstrumentCoverage.diff | 8 +- tests/mir-opt/coverage/instrument_coverage.rs | 4 +- ...rage_cleanup.main.CleanupPostBorrowck.diff | 8 +- ...erage_cleanup.main.InstrumentCoverage.diff | 8 +- .../coverage/instrument_coverage_cleanup.rs | 4 +- 19 files changed, 205 insertions(+), 305 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 38e7f4f21d43..1290c6efb09f 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -54,7 +54,7 @@ pub(crate) fn prepare_covfun_record<'tcx>( let fn_cov_info = tcx.instance_mir(instance.def).function_coverage_info.as_deref()?; let ids_info = tcx.coverage_ids_info(instance.def)?; - let expressions = prepare_expressions(fn_cov_info, ids_info, is_used); + let expressions = prepare_expressions(ids_info, is_used); let mut covfun = CovfunRecord { mangled_function_name: tcx.symbol_name(instance).name, @@ -76,11 +76,7 @@ pub(crate) fn prepare_covfun_record<'tcx>( } /// Convert the function's coverage-counter expressions into a form suitable for FFI. -fn prepare_expressions( - fn_cov_info: &FunctionCoverageInfo, - ids_info: &CoverageIdsInfo, - is_used: bool, -) -> Vec { +fn prepare_expressions(ids_info: &CoverageIdsInfo, is_used: bool) -> Vec { // If any counters or expressions were removed by MIR opts, replace their // terms with zero. let counter_for_term = |term| { @@ -95,7 +91,7 @@ fn prepare_expressions( // producing the final coverage map, so there's no need to do the same // thing on the Rust side unless we're confident we can do much better. // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.) - fn_cov_info + ids_info .expressions .iter() .map(move |&Expression { lhs, op, rhs }| ffi::CounterExpression { @@ -142,8 +138,7 @@ fn fill_region_tables<'tcx>( // If the mapping refers to counters/expressions that were removed by // MIR opts, replace those occurrences with zero. let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter { - let term = - fn_cov_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term"); + let term = ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term"); let term = if is_zero_term(term) { CovTerm::Zero } else { term }; ffi::Counter::from_term(term) }; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 021108cd51ca..e404db5e1965 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -160,17 +160,10 @@ fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) { CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!( "marker statement {kind:?} should have been removed by CleanupPostBorrowck" ), - CoverageKind::CounterIncrement { id } => { - // The number of counters passed to `llvm.instrprof.increment` might - // be smaller than the number originally inserted by the instrumentor, - // if some high-numbered counters were removed by MIR optimizations. - // If so, LLVM's profiler runtime will use fewer physical counters. + CoverageKind::VirtualCounter { bcb } + if let Some(&id) = ids_info.phys_counter_for_node.get(&bcb) => + { let num_counters = ids_info.num_counters_after_mir_opts(); - assert!( - num_counters as usize <= function_coverage_info.num_counters, - "num_counters disagreement: query says {num_counters} but function info only has {}", - function_coverage_info.num_counters - ); let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_coverage_info.function_source_hash); @@ -182,10 +175,8 @@ fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) { ); bx.instrprof_increment(fn_name, hash, num_counters, index); } - CoverageKind::ExpressionUsed { id: _ } => { - // Expression-used statements are markers that are handled by - // `coverage_ids_info`, so there's nothing to codegen here. - } + // If a BCB doesn't have an associated physical counter, there's nothing to codegen. + CoverageKind::VirtualCounter { .. } => {} CoverageKind::CondBitmapUpdate { index, decision_depth } => { let cond_bitmap = coverage_cx .try_get_mcdc_condition_bitmap(&instance, decision_depth) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 14346795fda6..f0d04b2b6447 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -13,6 +13,7 @@ #![feature(extern_types)] #![feature(file_buffered)] #![feature(hash_raw_entry)] +#![feature(if_let_guard)] #![feature(impl_trait_in_assoc_type)] #![feature(iter_intersperse)] #![feature(let_chains)] diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 8123707dc73a..31b9eeb715b4 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -2,8 +2,9 @@ use std::fmt::{self, Debug, Formatter}; -use rustc_index::IndexVec; +use rustc_data_structures::fx::FxIndexMap; use rustc_index::bit_set::DenseBitSet; +use rustc_index::{Idx, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::Span; @@ -103,23 +104,12 @@ pub enum CoverageKind { /// Should be erased before codegen (at some point after `InstrumentCoverage`). BlockMarker { id: BlockMarkerId }, - /// Marks the point in MIR control flow represented by a coverage counter. + /// Marks its enclosing basic block with the ID of the coverage graph node + /// that it was part of during the `InstrumentCoverage` MIR pass. /// - /// This is eventually lowered to `llvm.instrprof.increment` in LLVM IR. - /// - /// If this statement does not survive MIR optimizations, any mappings that - /// refer to this counter can have those references simplified to zero. - CounterIncrement { id: CounterId }, - - /// Marks the point in MIR control-flow represented by a coverage expression. - /// - /// If this statement does not survive MIR optimizations, any mappings that - /// refer to this expression can have those references simplified to zero. - /// - /// (This is only inserted for expression IDs that are directly used by - /// mappings. Intermediate expressions with no direct mappings are - /// retained/zeroed based on whether they are transitively used.) - ExpressionUsed { id: ExpressionId }, + /// During codegen, this might be lowered to `llvm.instrprof.increment` or + /// to a no-op, depending on the outcome of counter-creation. + VirtualCounter { bcb: BasicCoverageBlock }, /// Marks the point in MIR control flow represented by a evaluated condition. /// @@ -138,8 +128,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { match self { SpanMarker => write!(fmt, "SpanMarker"), BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()), - CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), - ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()), + VirtualCounter { bcb } => write!(fmt, "VirtualCounter({bcb:?})"), CondBitmapUpdate { index, decision_depth } => { write!(fmt, "CondBitmapUpdate(index={:?}, depth={:?})", index, decision_depth) } @@ -208,11 +197,12 @@ pub struct FunctionCoverageInfo { pub function_source_hash: u64, pub body_span: Span, - pub num_counters: usize, - pub expressions: IndexVec, + /// Used in conjunction with `priority_list` to create physical counters + /// and counter expressions, after MIR optimizations. + pub node_flow_data: NodeFlowData, + pub priority_list: Vec, pub mappings: Vec, - pub term_for_bcb: IndexVec>, pub mcdc_bitmap_bits: usize, /// The depth of the deepest decision is used to know how many @@ -281,15 +271,18 @@ pub struct MCDCDecisionSpan { pub num_conditions: usize, } -/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass -/// (for compiler option `-Cinstrument-coverage`), after MIR optimizations -/// have had a chance to potentially remove some of them. +/// Contains information needed during codegen, obtained by inspecting the +/// function's MIR after MIR optimizations. /// -/// Used by the `coverage_ids_info` query. +/// Returned by the `coverage_ids_info` query. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] pub struct CoverageIdsInfo { pub counters_seen: DenseBitSet, pub zero_expressions: DenseBitSet, + + pub phys_counter_for_node: FxIndexMap, + pub term_for_bcb: IndexVec>, + pub expressions: IndexVec, } impl CoverageIdsInfo { @@ -334,3 +327,28 @@ pub struct BasicCoverageBlock { const START_BCB = 0; } } + +/// Data representing a view of some underlying graph, in which each node's +/// successors have been merged into a single "supernode". +/// +/// The resulting supernodes have no obvious meaning on their own. +/// However, merging successor nodes means that a node's out-edges can all +/// be combined into a single out-edge, whose flow is the same as the flow +/// (execution count) of its corresponding node in the original graph. +/// +/// With all node flows now in the original graph now represented as edge flows +/// in the merged graph, it becomes possible to analyze the original node flows +/// using techniques for analyzing edge flows. +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] +pub struct NodeFlowData { + /// Maps each node to the supernode that contains it, indicated by some + /// arbitrary "root" node that is part of that supernode. + pub supernodes: IndexVec, + /// For each node, stores the single supernode that all of its successors + /// have been merged into. + /// + /// (Note that each node in a supernode can potentially have a _different_ + /// successor supernode from its peers.) + pub succ_supernodes: IndexVec, +} diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 3007b7874968..11ebbbe807db 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -619,13 +619,9 @@ fn write_function_coverage_info( function_coverage_info: &coverage::FunctionCoverageInfo, w: &mut dyn io::Write, ) -> io::Result<()> { - let coverage::FunctionCoverageInfo { body_span, expressions, mappings, .. } = - function_coverage_info; + let coverage::FunctionCoverageInfo { body_span, mappings, .. } = function_coverage_info; writeln!(w, "{INDENT}coverage body span: {body_span:?}")?; - for (id, expression) in expressions.iter_enumerated() { - writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; - } for coverage::Mapping { kind, span } in mappings { writeln!(w, "{INDENT}coverage {kind:?} => {span:?};")?; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6c442fc1047f..228f94a17f8b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -615,9 +615,16 @@ feedable } - /// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass - /// (for compiler option `-Cinstrument-coverage`), after MIR optimizations - /// have had a chance to potentially remove some of them. + /// Scans through a function's MIR after MIR optimizations, to prepare the + /// information needed by codegen when `-Cinstrument-coverage` is active. + /// + /// This includes the details of where to insert `llvm.instrprof.increment` + /// intrinsics, and the expression tables to be embedded in the function's + /// coverage metadata. + /// + /// FIXME(Zalathar): This query's purpose has drifted a bit and should + /// probably be renamed, but that can wait until after the potential + /// follow-ups to #136053 have settled down. /// /// Returns `None` for functions that were not instrumented. query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> Option<&'tcx mir::coverage::CoverageIdsInfo> { diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 50d5bf31829e..fa4f80f827b1 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -2,7 +2,6 @@ use either::Either; use itertools::Itertools; -use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::graph::DirectedGraph; use rustc_index::IndexVec; @@ -11,31 +10,35 @@ use crate::coverage::counters::balanced_flow::BalancedFlowGraph; use crate::coverage::counters::node_flow::{ - CounterTerm, NodeCounters, make_node_counters, node_flow_data_for_balanced_graph, + CounterTerm, NodeCounters, NodeFlowData, node_flow_data_for_balanced_graph, }; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; mod balanced_flow; -mod node_flow; +pub(crate) mod node_flow; mod union_find; -/// Ensures that each BCB node needing a counter has one, by creating physical -/// counters or counter expressions for nodes as required. -pub(super) fn make_bcb_counters( - graph: &CoverageGraph, - bcb_needs_counter: &DenseBitSet, -) -> CoverageCounters { +/// Struct containing the results of [`prepare_bcb_counters_data`]. +pub(crate) struct BcbCountersData { + pub(crate) node_flow_data: NodeFlowData, + pub(crate) priority_list: Vec, +} + +/// Analyzes the coverage graph to create intermediate data structures that +/// will later be used (during codegen) to create physical counters or counter +/// expressions for each BCB node that needs one. +pub(crate) fn prepare_bcb_counters_data(graph: &CoverageGraph) -> BcbCountersData { // Create the derived graphs that are necessary for subsequent steps. let balanced_graph = BalancedFlowGraph::for_graph(graph, |n| !graph[n].is_out_summable); let node_flow_data = node_flow_data_for_balanced_graph(&balanced_graph); - // Use those graphs to determine which nodes get physical counters, and how - // to compute the execution counts of other nodes from those counters. + // Also create a "priority list" of coverage graph nodes, to help determine + // which ones get physical counters or counter expressions. This needs to + // be done now, because the later parts of the counter-creation process + // won't have access to the original coverage graph. let priority_list = make_node_flow_priority_list(graph, balanced_graph); - let node_counters = make_node_counters(&node_flow_data, &priority_list); - // Convert the counters into a form suitable for embedding into MIR. - transcribe_counters(&node_counters, bcb_needs_counter) + BcbCountersData { node_flow_data, priority_list } } /// Arranges the nodes in `balanced_graph` into a list, such that earlier nodes @@ -74,7 +77,7 @@ fn make_node_flow_priority_list( } // Converts node counters into a form suitable for embedding into MIR. -fn transcribe_counters( +pub(crate) fn transcribe_counters( old: &NodeCounters, bcb_needs_counter: &DenseBitSet, ) -> CoverageCounters { @@ -129,7 +132,7 @@ fn transcribe_counters( pub(super) struct CoverageCounters { /// List of places where a counter-increment statement should be injected /// into MIR, each with its corresponding counter ID. - phys_counter_for_node: FxIndexMap, + pub(crate) phys_counter_for_node: FxIndexMap, next_counter_id: CounterId, /// Coverage counters/expressions that are associated with individual BCBs. @@ -137,7 +140,7 @@ pub(super) struct CoverageCounters { /// Table of expression data, associating each expression ID with its /// corresponding operator (+ or -) and its LHS/RHS operands. - expressions: IndexVec, + pub(crate) expressions: IndexVec, /// Remember expressions that have already been created (or simplified), /// so that we don't create unnecessary duplicates. expressions_memo: FxHashMap, @@ -188,12 +191,6 @@ fn make_subtracted_sum(&mut self, lhs: CovTerm, rhs: &[CovTerm]) -> CovTerm { self.make_expression(lhs, Op::Subtract, rhs_sum) } - pub(super) fn num_counters(&self) -> usize { - let num_counters = self.phys_counter_for_node.len(); - assert_eq!(num_counters, self.next_counter_id.as_usize()); - num_counters - } - fn set_node_counter(&mut self, bcb: BasicCoverageBlock, counter: CovTerm) -> CovTerm { let existing = self.node_counters[bcb].replace(counter); assert!( @@ -202,30 +199,4 @@ fn set_node_counter(&mut self, bcb: BasicCoverageBlock, counter: CovTerm) -> Cov ); counter } - - /// Returns an iterator over all the nodes in the coverage graph that - /// should have a counter-increment statement injected into MIR, along with - /// each site's corresponding counter ID. - pub(super) fn counter_increment_sites( - &self, - ) -> impl Iterator + Captures<'_> { - self.phys_counter_for_node.iter().map(|(&site, &id)| (id, site)) - } - - /// Returns an iterator over the subset of BCB nodes that have been associated - /// with a counter *expression*, along with the ID of that expression. - pub(super) fn bcb_nodes_with_coverage_expressions( - &self, - ) -> impl Iterator + Captures<'_> { - self.node_counters.iter_enumerated().filter_map(|(bcb, &counter)| match counter { - // Yield the BCB along with its associated expression ID. - Some(CovTerm::Expression(id)) => Some((bcb, id)), - // This BCB is associated with a counter or nothing, so skip it. - Some(CovTerm::Counter { .. } | CovTerm::Zero) | None => None, - }) - } - - pub(super) fn into_expressions(self) -> IndexVec { - self.expressions - } } diff --git a/compiler/rustc_mir_transform/src/coverage/counters/node_flow.rs b/compiler/rustc_mir_transform/src/coverage/counters/node_flow.rs index 9d80b3af42d8..91ed54b8b59f 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters/node_flow.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters/node_flow.rs @@ -9,6 +9,7 @@ use rustc_data_structures::graph; use rustc_index::bit_set::DenseBitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; +pub(crate) use rustc_middle::mir::coverage::NodeFlowData; use rustc_middle::mir::coverage::Op; use crate::coverage::counters::union_find::UnionFind; @@ -16,30 +17,6 @@ #[cfg(test)] mod tests; -/// Data representing a view of some underlying graph, in which each node's -/// successors have been merged into a single "supernode". -/// -/// The resulting supernodes have no obvious meaning on their own. -/// However, merging successor nodes means that a node's out-edges can all -/// be combined into a single out-edge, whose flow is the same as the flow -/// (execution count) of its corresponding node in the original graph. -/// -/// With all node flows now in the original graph now represented as edge flows -/// in the merged graph, it becomes possible to analyze the original node flows -/// using techniques for analyzing edge flows. -#[derive(Debug)] -pub(crate) struct NodeFlowData { - /// Maps each node to the supernode that contains it, indicated by some - /// arbitrary "root" node that is part of that supernode. - supernodes: IndexVec, - /// For each node, stores the single supernode that all of its successors - /// have been merged into. - /// - /// (Note that each node in a supernode can potentially have a _different_ - /// successor supernode from its peers.) - succ_supernodes: IndexVec, -} - /// Creates a "merged" view of an underlying graph. /// /// The given graph is assumed to have [“balanced flow”](balanced-flow), diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index 8d0d92dc3677..d83c0d40a7e5 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -1,9 +1,7 @@ use std::collections::BTreeSet; use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::graph::DirectedGraph; use rustc_index::IndexVec; -use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::coverage::{ BlockMarkerId, BranchSpan, ConditionId, ConditionInfo, CoverageInfoHi, CoverageKind, }; @@ -63,10 +61,6 @@ pub(super) struct MCDCDecision { #[derive(Default)] pub(super) struct ExtractedMappings { - /// Store our own copy of [`CoverageGraph::num_nodes`], so that we don't - /// need access to the whole graph when allocating per-BCB data. This is - /// only public so that other code can still use exhaustive destructuring. - pub(super) num_bcbs: usize, pub(super) code_mappings: Vec, pub(super) branch_pairs: Vec, pub(super) mcdc_bitmap_bits: usize, @@ -118,7 +112,6 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>( ); ExtractedMappings { - num_bcbs: graph.num_nodes(), code_mappings, branch_pairs, mcdc_bitmap_bits, @@ -127,60 +120,6 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>( } } -impl ExtractedMappings { - pub(super) fn all_bcbs_with_counter_mappings(&self) -> DenseBitSet { - // Fully destructure self to make sure we don't miss any fields that have mappings. - let Self { - num_bcbs, - code_mappings, - branch_pairs, - mcdc_bitmap_bits: _, - mcdc_degraded_branches, - mcdc_mappings, - } = self; - - // Identify which BCBs have one or more mappings. - let mut bcbs_with_counter_mappings = DenseBitSet::new_empty(*num_bcbs); - let mut insert = |bcb| { - bcbs_with_counter_mappings.insert(bcb); - }; - - for &CodeMapping { span: _, bcb } in code_mappings { - insert(bcb); - } - for &BranchPair { true_bcb, false_bcb, .. } in branch_pairs { - insert(true_bcb); - insert(false_bcb); - } - for &MCDCBranch { true_bcb, false_bcb, .. } in mcdc_degraded_branches - .iter() - .chain(mcdc_mappings.iter().map(|(_, branches)| branches.into_iter()).flatten()) - { - insert(true_bcb); - insert(false_bcb); - } - - // MC/DC decisions refer to BCBs, but don't require those BCBs to have counters. - if bcbs_with_counter_mappings.is_empty() { - debug_assert!( - mcdc_mappings.is_empty(), - "A function with no counter mappings shouldn't have any decisions: {mcdc_mappings:?}", - ); - } - - bcbs_with_counter_mappings - } - - /// Returns the set of BCBs that have one or more `Code` mappings. - pub(super) fn bcbs_with_ordinary_code_mappings(&self) -> DenseBitSet { - let mut bcbs = DenseBitSet::new_empty(self.num_bcbs); - for &CodeMapping { span: _, bcb } in &self.code_mappings { - bcbs.insert(bcb); - } - bcbs - } -} - fn resolve_block_markers( coverage_info_hi: &CoverageInfoHi, mir_body: &mir::Body<'_>, diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index b1afcc84b6e2..e195681bc92c 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -21,7 +21,7 @@ use rustc_span::def_id::LocalDefId; use tracing::{debug, debug_span, trace}; -use crate::coverage::counters::CoverageCounters; +use crate::coverage::counters::BcbCountersData; use crate::coverage::graph::CoverageGraph; use crate::coverage::mappings::ExtractedMappings; @@ -82,29 +82,21 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: let extracted_mappings = mappings::extract_all_mapping_info_from_mir(tcx, mir_body, &hir_info, &graph); - //////////////////////////////////////////////////// - // Create an optimized mix of `Counter`s and `Expression`s for the `CoverageGraph`. Ensure - // every coverage span has a `Counter` or `Expression` assigned to its `BasicCoverageBlock` - // and all `Expression` dependencies (operands) are also generated, for any other - // `BasicCoverageBlock`s not already associated with a coverage span. - let bcbs_with_counter_mappings = extracted_mappings.all_bcbs_with_counter_mappings(); - if bcbs_with_counter_mappings.is_empty() { - // No relevant spans were found in MIR, so skip instrumenting this function. - return; - } - - let coverage_counters = counters::make_bcb_counters(&graph, &bcbs_with_counter_mappings); - let mappings = create_mappings(&extracted_mappings); if mappings.is_empty() { // No spans could be converted into valid mappings, so skip this function. debug!("no spans could be converted into valid mappings; skipping"); return; } - let term_for_bcb = coverage_counters.node_counters.clone(); - inject_coverage_statements(mir_body, &graph, &extracted_mappings, &coverage_counters); + // Use the coverage graph to prepare intermediate data that will eventually + // be used to assign physical counters and counter expressions to points in + // the control-flow graph + let BcbCountersData { node_flow_data, priority_list } = + counters::prepare_bcb_counters_data(&graph); + // Inject coverage statements into MIR. + inject_coverage_statements(mir_body, &graph); inject_mcdc_statements(mir_body, &graph, &extracted_mappings); let mcdc_num_condition_bitmaps = extracted_mappings @@ -118,11 +110,10 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: function_source_hash: hir_info.function_source_hash, body_span: hir_info.body_span, - num_counters: coverage_counters.num_counters(), - expressions: coverage_counters.into_expressions(), + node_flow_data, + priority_list, mappings, - term_for_bcb, mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits, mcdc_num_condition_bitmaps, @@ -137,7 +128,6 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: fn create_mappings(extracted_mappings: &ExtractedMappings) -> Vec { // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { - num_bcbs: _, code_mappings, branch_pairs, mcdc_bitmap_bits: _, @@ -215,41 +205,11 @@ fn create_mappings(extracted_mappings: &ExtractedMappings) -> Vec { mappings } -/// For each BCB node or BCB edge that has an associated coverage counter, -/// inject any necessary coverage statements into MIR. -fn inject_coverage_statements<'tcx>( - mir_body: &mut mir::Body<'tcx>, - graph: &CoverageGraph, - extracted_mappings: &ExtractedMappings, - coverage_counters: &CoverageCounters, -) { - // Inject counter-increment statements into MIR. - for (id, bcb) in coverage_counters.counter_increment_sites() { - let target_bb = graph[bcb].leader_bb(); - inject_statement(mir_body, CoverageKind::CounterIncrement { id }, target_bb); - } - - // For each counter expression that is directly associated with at least one - // span, we inject an "expression-used" statement, so that coverage codegen - // can check whether the injected statement survived MIR optimization. - // (BCB edges can't have spans, so we only need to process BCB nodes here.) - // - // We only do this for ordinary `Code` mappings, because branch and MC/DC - // mappings might have expressions that don't correspond to any single - // point in the control-flow graph. - // - // See the code in `rustc_codegen_llvm::coverageinfo::map_data` that deals - // with "expressions seen" and "zero terms". - let eligible_bcbs = extracted_mappings.bcbs_with_ordinary_code_mappings(); - for (bcb, expression_id) in coverage_counters - .bcb_nodes_with_coverage_expressions() - .filter(|&(bcb, _)| eligible_bcbs.contains(bcb)) - { - inject_statement( - mir_body, - CoverageKind::ExpressionUsed { id: expression_id }, - graph[bcb].leader_bb(), - ); +/// Inject any necessary coverage statements into MIR, so that they influence codegen. +fn inject_coverage_statements<'tcx>(mir_body: &mut mir::Body<'tcx>, graph: &CoverageGraph) { + for (bcb, data) in graph.iter_enumerated() { + let target_bb = data.leader_bb(); + inject_statement(mir_body, CoverageKind::VirtualCounter { bcb }, target_bb); } } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index ef2724222ce0..f362f4ccfa28 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,9 +1,10 @@ use rustc_data_structures::captures::Captures; +use rustc_index::IndexSlice; use rustc_index::bit_set::DenseBitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::{ - CounterId, CovTerm, CoverageIdsInfo, CoverageKind, Expression, ExpressionId, - FunctionCoverageInfo, MappingKind, Op, + BasicCoverageBlock, CounterId, CovTerm, CoverageIdsInfo, CoverageKind, Expression, + ExpressionId, MappingKind, Op, }; use rustc_middle::mir::{Body, Statement, StatementKind}; use rustc_middle::ty::{self, TyCtxt}; @@ -12,6 +13,9 @@ use rustc_span::sym; use tracing::trace; +use crate::coverage::counters::node_flow::make_node_counters; +use crate::coverage::counters::{CoverageCounters, transcribe_counters}; + /// Registers query/hook implementations related to coverage. pub(crate) fn provide(providers: &mut Providers) { providers.hooks.is_eligible_for_coverage = is_eligible_for_coverage; @@ -89,41 +93,85 @@ fn coverage_ids_info<'tcx>( let mir_body = tcx.instance_mir(instance_def); let fn_cov_info = mir_body.function_coverage_info.as_deref()?; - let mut counters_seen = DenseBitSet::new_empty(fn_cov_info.num_counters); - let mut expressions_seen = DenseBitSet::new_filled(fn_cov_info.expressions.len()); - - // For each expression ID that is directly used by one or more mappings, - // mark it as not-yet-seen. This indicates that we expect to see a - // corresponding `ExpressionUsed` statement during MIR traversal. - for mapping in fn_cov_info.mappings.iter() { - // Currently we only worry about ordinary code mappings. - // For branch and MC/DC mappings, expressions might not correspond - // to any particular point in the control-flow graph. - // (Keep this in sync with the injection of `ExpressionUsed` - // statements in the `InstrumentCoverage` MIR pass.) - if let MappingKind::Code { bcb } = mapping.kind - && let Some(CovTerm::Expression(id)) = fn_cov_info.term_for_bcb[bcb] - { - expressions_seen.remove(id); - } - } - + // Scan through the final MIR to see which BCBs survived MIR opts. + // Any BCB not in this set was optimized away. + let mut bcbs_seen = DenseBitSet::new_empty(fn_cov_info.priority_list.len()); for kind in all_coverage_in_mir_body(mir_body) { match *kind { - CoverageKind::CounterIncrement { id } => { - counters_seen.insert(id); - } - CoverageKind::ExpressionUsed { id } => { - expressions_seen.insert(id); + CoverageKind::VirtualCounter { bcb } => { + bcbs_seen.insert(bcb); } _ => {} } } - let zero_expressions = - identify_zero_expressions(fn_cov_info, &counters_seen, &expressions_seen); + // Determine the set of BCBs that are referred to by mappings, and therefore + // need a counter. Any node not in this set will only get a counter if it + // is part of the counter expression for a node that is in the set. + let mut bcb_needs_counter = + DenseBitSet::::new_empty(fn_cov_info.priority_list.len()); + for mapping in &fn_cov_info.mappings { + match mapping.kind { + MappingKind::Code { bcb } => { + bcb_needs_counter.insert(bcb); + } + MappingKind::Branch { true_bcb, false_bcb } => { + bcb_needs_counter.insert(true_bcb); + bcb_needs_counter.insert(false_bcb); + } + MappingKind::MCDCBranch { true_bcb, false_bcb, mcdc_params: _ } => { + bcb_needs_counter.insert(true_bcb); + bcb_needs_counter.insert(false_bcb); + } + MappingKind::MCDCDecision(_) => {} + } + } - Some(CoverageIdsInfo { counters_seen, zero_expressions }) + let node_counters = make_node_counters(&fn_cov_info.node_flow_data, &fn_cov_info.priority_list); + let coverage_counters = transcribe_counters(&node_counters, &bcb_needs_counter); + + let mut counters_seen = DenseBitSet::new_empty(coverage_counters.node_counters.len()); + let mut expressions_seen = DenseBitSet::new_filled(coverage_counters.expressions.len()); + + // For each expression ID that is directly used by one or more mappings, + // mark it as not-yet-seen. This indicates that we expect to see a + // corresponding `VirtualCounter` statement during MIR traversal. + for mapping in fn_cov_info.mappings.iter() { + // Currently we only worry about ordinary code mappings. + // For branch and MC/DC mappings, expressions might not correspond + // to any particular point in the control-flow graph. + if let MappingKind::Code { bcb } = mapping.kind + && let Some(CovTerm::Expression(id)) = coverage_counters.node_counters[bcb] + { + expressions_seen.remove(id); + } + } + + for bcb in bcbs_seen.iter() { + if let Some(&id) = coverage_counters.phys_counter_for_node.get(&bcb) { + counters_seen.insert(id); + } + if let Some(CovTerm::Expression(id)) = coverage_counters.node_counters[bcb] { + expressions_seen.insert(id); + } + } + + let zero_expressions = identify_zero_expressions( + &coverage_counters.expressions, + &counters_seen, + &expressions_seen, + ); + + let CoverageCounters { phys_counter_for_node, node_counters, expressions, .. } = + coverage_counters; + + Some(CoverageIdsInfo { + counters_seen, + zero_expressions, + phys_counter_for_node, + term_for_bcb: node_counters, + expressions, + }) } fn all_coverage_in_mir_body<'a, 'tcx>( @@ -150,7 +198,7 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { /// already being performed by the Rust-side expression renumbering, so that /// the resulting coverage mappings don't get worse. fn identify_zero_expressions( - fn_cov_info: &FunctionCoverageInfo, + expressions: &IndexSlice, counters_seen: &DenseBitSet, expressions_seen: &DenseBitSet, ) -> DenseBitSet { @@ -158,13 +206,13 @@ fn identify_zero_expressions( // have zero as both of their operands, and will therefore always have // a value of zero. Other expressions that refer to these as operands // can have those operands replaced with `CovTerm::Zero`. - let mut zero_expressions = DenseBitSet::new_empty(fn_cov_info.expressions.len()); + let mut zero_expressions = DenseBitSet::new_empty(expressions.len()); // Simplify a copy of each expression based on lower-numbered expressions, // and then update the set of always-zero expressions if necessary. // (By construction, expressions can only refer to other expressions // that have lower IDs, so one pass is sufficient.) - for (id, expression) in fn_cov_info.expressions.iter_enumerated() { + for (id, expression) in expressions.iter_enumerated() { if !expressions_seen.contains(id) { // If an expression was not seen, it must have been optimized away, // so any operand that refers to it can be replaced with zero. diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 26ce743be361..73b68d7155cf 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -137,8 +137,7 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option { // These coverage statements should not exist prior to coverage instrumentation. StatementKind::Coverage( - CoverageKind::CounterIncrement { .. } - | CoverageKind::ExpressionUsed { .. } + CoverageKind::VirtualCounter { .. } | CoverageKind::CondBitmapUpdate { .. } | CoverageKind::TestVectorBitmapUpdate { .. }, ) => bug!( diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index 9647e13f75af..e9f48a85f9cf 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -27,9 +27,6 @@ } + coverage body span: $DIR/branch_match_arms.rs:14:11: 21:2 (#0) -+ coverage ExpressionId(0) => Expression { lhs: Counter(1), op: Add, rhs: Counter(2) }; -+ coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Add, rhs: Counter(3) }; -+ coverage ExpressionId(2) => Expression { lhs: Counter(0), op: Subtract, rhs: Expression(1) }; + coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); + coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); + coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); @@ -38,7 +35,7 @@ + coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); + bb0: { -+ Coverage::CounterIncrement(0); ++ Coverage::VirtualCounter(bcb0); StorageLive(_1); _1 = Enum::A(const 0_u32); PlaceMention(_1); @@ -52,22 +49,22 @@ } bb2: { -+ Coverage::CounterIncrement(1); ++ Coverage::VirtualCounter(bcb1); falseEdge -> [real: bb8, imaginary: bb3]; } bb3: { -+ Coverage::CounterIncrement(2); ++ Coverage::VirtualCounter(bcb3); falseEdge -> [real: bb7, imaginary: bb4]; } bb4: { -+ Coverage::CounterIncrement(3); ++ Coverage::VirtualCounter(bcb4); falseEdge -> [real: bb6, imaginary: bb5]; } bb5: { -+ Coverage::ExpressionUsed(2); ++ Coverage::VirtualCounter(bcb5); StorageLive(_9); _9 = copy ((_1 as A).0: u32); StorageLive(_10); @@ -124,6 +121,7 @@ } bb13: { ++ Coverage::VirtualCounter(bcb2); StorageDead(_1); return; } diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index 16b7a1a63b4a..cbef6de917df 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -8,7 +8,7 @@ + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:1: 31:2 (#0); + bb0: { -+ Coverage::CounterIncrement(0); ++ Coverage::VirtualCounter(bcb0); _0 = const true; return; } diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index fe74ad24e916..b166d79a412c 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -8,7 +8,6 @@ let mut _3: !; + coverage body span: $DIR/instrument_coverage.rs:14:11: 20:2 (#0) -+ coverage ExpressionId(0) => Expression { lhs: Counter(1), op: Subtract, rhs: Counter(0) }; + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:14:1: 14:11 (#0); + coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:16:12: 16:17 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:17:13: 17:18 (#0); @@ -16,12 +15,12 @@ + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:20:2: 20:2 (#0); + bb0: { -+ Coverage::CounterIncrement(0); ++ Coverage::VirtualCounter(bcb0); goto -> bb1; } bb1: { -+ Coverage::CounterIncrement(1); ++ Coverage::VirtualCounter(bcb1); falseUnwind -> [real: bb2, unwind: bb6]; } @@ -35,13 +34,14 @@ } bb4: { ++ Coverage::VirtualCounter(bcb2); _0 = const (); StorageDead(_2); return; } bb5: { -+ Coverage::ExpressionUsed(0); ++ Coverage::VirtualCounter(bcb3); _1 = const (); StorageDead(_2); goto -> bb1; diff --git a/tests/mir-opt/coverage/instrument_coverage.rs b/tests/mir-opt/coverage/instrument_coverage.rs index 20c730645f8f..48647402d0fe 100644 --- a/tests/mir-opt/coverage/instrument_coverage.rs +++ b/tests/mir-opt/coverage/instrument_coverage.rs @@ -10,7 +10,7 @@ // CHECK: coverage body span: // CHECK: coverage Code { bcb: bcb{{[0-9]+}} } => // CHECK: bb0: -// CHECK: Coverage::CounterIncrement +// CHECK: Coverage::VirtualCounter fn main() { loop { if bar() { @@ -24,7 +24,7 @@ fn main() { // CHECK: coverage body span: // CHECK: coverage Code { bcb: bcb{{[0-9]+}} } => // CHECK: bb0: -// CHECK: Coverage::CounterIncrement +// CHECK: Coverage::VirtualCounter #[inline(never)] fn bar() -> bool { true diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 28a3f3beadea..855f806aae10 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -8,7 +8,6 @@ coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0) coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) - coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); @@ -16,7 +15,7 @@ coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); bb0: { - Coverage::CounterIncrement(0); + Coverage::VirtualCounter(bcb0); - Coverage::SpanMarker; + nop; StorageLive(_1); @@ -28,7 +27,7 @@ } bb2: { - Coverage::CounterIncrement(1); + Coverage::VirtualCounter(bcb1); - Coverage::BlockMarker(1); + nop; _0 = const (); @@ -36,7 +35,7 @@ } bb3: { - Coverage::ExpressionUsed(0); + Coverage::VirtualCounter(bcb3); - Coverage::BlockMarker(0); + nop; _0 = const (); @@ -44,6 +43,7 @@ } bb4: { + Coverage::VirtualCounter(bcb2); StorageDead(_1); return; } diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index 0f1dea02b8d9..df1f1e8bc504 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -8,7 +8,6 @@ coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0) + coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) -+ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); + coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); + coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); @@ -16,7 +15,7 @@ + coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + bb0: { -+ Coverage::CounterIncrement(0); ++ Coverage::VirtualCounter(bcb0); Coverage::SpanMarker; StorageLive(_1); _1 = std::hint::black_box::(const true) -> [return: bb1, unwind: bb5]; @@ -27,20 +26,21 @@ } bb2: { -+ Coverage::CounterIncrement(1); ++ Coverage::VirtualCounter(bcb1); Coverage::BlockMarker(1); _0 = const (); goto -> bb4; } bb3: { -+ Coverage::ExpressionUsed(0); ++ Coverage::VirtualCounter(bcb3); Coverage::BlockMarker(0); _0 = const (); goto -> bb4; } bb4: { ++ Coverage::VirtualCounter(bcb2); StorageDead(_1); return; } diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.rs b/tests/mir-opt/coverage/instrument_coverage_cleanup.rs index acc544a28af6..e8af4d6174f4 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.rs +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.rs @@ -3,7 +3,7 @@ // but leaves the statements that were added by InstrumentCoverage. // // Removed statement kinds: BlockMarker, SpanMarker -// Retained statement kinds: CounterIncrement, ExpressionUsed +// Retained statement kinds: VirtualCounter //@ test-mir-pass: InstrumentCoverage //@ compile-flags: -Cinstrument-coverage -Zcoverage-options=branch -Zno-profiler-runtime @@ -16,6 +16,6 @@ fn main() { // CHECK-NOT: Coverage::BlockMarker // CHECK-NOT: Coverage::SpanMarker -// CHECK: Coverage::CounterIncrement +// CHECK: Coverage::VirtualCounter // CHECK-NOT: Coverage::BlockMarker // CHECK-NOT: Coverage::SpanMarker From bf1f254b13d09aedfd8b44611f39736c32d5d0f6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 25 Jan 2025 18:24:02 +1100 Subject: [PATCH 09/19] coverage: Don't create counters for code that was removed by MIR opts --- .../src/coverage/counters.rs | 26 ++--- .../rustc_mir_transform/src/coverage/query.rs | 6 +- tests/coverage/assert_not.cov-map | 8 +- tests/coverage/bad_counter_ids.cov-map | 24 ++--- tests/coverage/fn_sig_into_try.cov-map | 24 ++--- tests/coverage/inline-dead.cov-map | 9 +- tests/coverage/issue-84561.cov-map | 29 +++--- tests/coverage/loops_branches.cov-map | 95 ++++++++----------- tests/coverage/no_spans_if_not.cov-map | 8 +- tests/coverage/tight_inf_loop.cov-map | 8 +- 10 files changed, 103 insertions(+), 134 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index fa4f80f827b1..ac0039fd0073 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -80,28 +80,30 @@ fn make_node_flow_priority_list( pub(crate) fn transcribe_counters( old: &NodeCounters, bcb_needs_counter: &DenseBitSet, + bcbs_seen: &DenseBitSet, ) -> CoverageCounters { let mut new = CoverageCounters::with_num_bcbs(bcb_needs_counter.domain_size()); for bcb in bcb_needs_counter.iter() { + if !bcbs_seen.contains(bcb) { + // This BCB's code was removed by MIR opts, so its counter is always zero. + new.set_node_counter(bcb, CovTerm::Zero); + continue; + } + // Our counter-creation algorithm doesn't guarantee that a node's list // of terms starts or ends with a positive term, so partition the // counters into "positive" and "negative" lists for easier handling. - let (mut pos, mut neg): (Vec<_>, Vec<_>) = - old.counter_terms[bcb].iter().partition_map(|&CounterTerm { node, op }| match op { + let (mut pos, mut neg): (Vec<_>, Vec<_>) = old.counter_terms[bcb] + .iter() + // Filter out any BCBs that were removed by MIR opts; + // this treats them as having an execution count of 0. + .filter(|term| bcbs_seen.contains(term.node)) + .partition_map(|&CounterTerm { node, op }| match op { Op::Add => Either::Left(node), Op::Subtract => Either::Right(node), }); - if pos.is_empty() { - // If we somehow end up with no positive terms, fall back to - // creating a physical counter. There's no known way for this - // to happen, but we can avoid an ICE if it does. - debug_assert!(false, "{bcb:?} has no positive counter terms"); - pos = vec![bcb]; - neg = vec![]; - } - // These intermediate sorts are not strictly necessary, but were helpful // in reducing churn when switching to the current counter-creation scheme. // They also help to slightly decrease the overall size of the expression @@ -119,7 +121,7 @@ pub(crate) fn transcribe_counters( pos.sort(); neg.sort(); - let pos_counter = new.make_sum(&pos).expect("`pos` should not be empty"); + let pos_counter = new.make_sum(&pos).unwrap_or(CovTerm::Zero); let new_counter = new.make_subtracted_sum(pos_counter, &neg); new.set_node_counter(bcb, new_counter); } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index f362f4ccfa28..995fa91e0a07 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -127,8 +127,12 @@ fn coverage_ids_info<'tcx>( } } + // FIXME(Zalathar): It should be possible to sort `priority_list[1..]` by + // `!bcbs_seen.contains(bcb)` to simplify the mappings even further, at the + // expense of some churn in the tests. When doing so, also consider removing + // the sorts in `transcribe_counters`. let node_counters = make_node_counters(&fn_cov_info.node_flow_data, &fn_cov_info.priority_list); - let coverage_counters = transcribe_counters(&node_counters, &bcb_needs_counter); + let coverage_counters = transcribe_counters(&node_counters, &bcb_needs_counter, &bcbs_seen); let mut counters_seen = DenseBitSet::new_empty(coverage_counters.node_counters.len()); let mut expressions_seen = DenseBitSet::new_filled(coverage_counters.expressions.len()); diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map index 397eaa17caf6..35568a98af44 100644 --- a/tests/coverage/assert_not.cov-map +++ b/tests/coverage/assert_not.cov-map @@ -1,15 +1,13 @@ Function name: assert_not::main -Raw bytes (31): 0x[01, 01, 01, 0d, 00, 05, 01, 06, 01, 01, 12, 05, 02, 05, 00, 14, 09, 01, 05, 00, 14, 0d, 01, 05, 00, 16, 02, 01, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 12, 05, 02, 05, 00, 14, 09, 01, 05, 00, 14, 0d, 01, 05, 00, 16, 0d, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(3), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 6, 1) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 5) to (start + 0, 20) - Code(Counter(2)) at (prev + 1, 5) to (start + 0, 20) - Code(Counter(3)) at (prev + 1, 5) to (start + 0, 22) -- Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2) - = (c3 - Zero) +- Code(Counter(3)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c3 diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index 2b5399f33bbd..ba3062784493 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -9,15 +9,13 @@ Number of file 0 mappings: 2 Highest counter ID seen: c0 Function name: bad_counter_ids::eq_bad_message -Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 29, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 29, 01, 02, 0f, 01, 02, 20, 00, 2b, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 41, 1) to (start + 2, 15) -- Code(Expression(0, Sub)) at (prev + 2, 32) to (start + 0, 43) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 2, 32) to (start + 0, 43) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 @@ -64,27 +62,23 @@ Number of file 0 mappings: 3 Highest counter ID seen: c1 Function name: bad_counter_ids::ne_good -Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 1a, 01, 02, 1f, 02, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 1f, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31) -- Code(Expression(0, Sub)) at (prev + 3, 1) to (start + 0, 2) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: bad_counter_ids::ne_good_message -Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1f, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 1f, 01, 02, 0f, 00, 02, 20, 00, 2b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 31, 1) to (start + 2, 15) - Code(Zero) at (prev + 2, 32) to (start + 0, 43) -- Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map index 374811dba9ef..6d6034928c9a 100644 --- a/tests/coverage/fn_sig_into_try.cov-map +++ b/tests/coverage/fn_sig_into_try.cov-map @@ -8,44 +8,38 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: fn_sig_into_try::b -Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 11, 01, 03, 0f, 00, 03, 0f, 00, 10, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 11, 01, 03, 0f, 00, 03, 0f, 00, 10, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 17, 1) to (start + 3, 15) - Code(Zero) at (prev + 3, 15) to (start + 0, 16) -- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: fn_sig_into_try::c -Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 18, 01, 03, 17, 00, 03, 17, 00, 18, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 18, 01, 03, 17, 00, 03, 17, 00, 18, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 24, 1) to (start + 3, 23) - Code(Zero) at (prev + 3, 23) to (start + 0, 24) -- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 Function name: fn_sig_into_try::d -Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 1f, 01, 04, 0f, 00, 04, 0f, 00, 10, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 01, 04, 0f, 00, 04, 0f, 00, 10, 01, 01, 05, 00, 0c, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 31, 1) to (start + 4, 15) - Code(Zero) at (prev + 4, 15) to (start + 0, 16) -- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 12) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 3e2ca2bc992e..49cdc514fedb 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -32,16 +32,13 @@ Number of file 0 mappings: 2 Highest counter ID seen: c0 Function name: inline_dead::main::{closure#0} -Raw bytes (23): 0x[01, 01, 02, 07, 00, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 02, 01, 05, 00, 06] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 2 -- expression 0 operands: lhs = Expression(1, Add), rhs = Zero -- expression 1 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 7, 23) to (start + 1, 22) - Code(Zero) at (prev + 1, 23) to (start + 0, 24) -- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) - = ((c0 + Zero) - Zero) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) Highest counter ID seen: c0 diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index efb9d43bf5be..c8f75cddcb5b 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -59,10 +59,10 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: issue_84561::test3 -Raw bytes (317): 0x[01, 01, 1c, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 5f, 6d, 00, 67, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 09, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 11, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 19, 02, 05, 00, 1f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 05, 06, 35, 06, 05, 03, 06, 39, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 41, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 1a, 05, 09, 03, 0a, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 67, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 71, 04, 0d, 00, 13, 56, 02, 0d, 00, 17, 56, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 62, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 6a, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6e, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02] +Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 09, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 11, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 19, 02, 05, 00, 1f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 05, 06, 35, 06, 05, 03, 06, 39, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 41, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 1a, 05, 09, 03, 0a, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 28 +Number of expressions: 27 - expression 0 operands: lhs = Counter(7), rhs = Counter(8) - expression 1 operands: lhs = Counter(9), rhs = Counter(10) - expression 2 operands: lhs = Counter(8), rhs = Counter(9) @@ -85,12 +85,11 @@ Number of expressions: 28 - expression 19 operands: lhs = Counter(28), rhs = Counter(29) - expression 20 operands: lhs = Counter(26), rhs = Counter(27) - expression 21 operands: lhs = Counter(26), rhs = Counter(27) -- expression 22 operands: lhs = Counter(26), rhs = Expression(23, Add) -- expression 23 operands: lhs = Counter(27), rhs = Zero -- expression 24 operands: lhs = Expression(25, Add), rhs = Counter(30) -- expression 25 operands: lhs = Counter(28), rhs = Counter(29) -- expression 26 operands: lhs = Counter(30), rhs = Counter(31) -- expression 27 operands: lhs = Counter(31), rhs = Counter(32) +- expression 22 operands: lhs = Counter(26), rhs = Counter(27) +- expression 23 operands: lhs = Expression(24, Add), rhs = Counter(30) +- expression 24 operands: lhs = Counter(28), rhs = Counter(29) +- expression 25 operands: lhs = Counter(30), rhs = Counter(31) +- expression 26 operands: lhs = Counter(31), rhs = Counter(32) Number of file 0 mappings: 51 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28) - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28) @@ -142,26 +141,26 @@ Number of file 0 mappings: 51 - Code(Counter(25)) at (prev + 3, 13) to (start + 0, 19) - Code(Expression(18, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c24 - c25) -- Code(Expression(25, Add)) at (prev + 3, 5) to (start + 0, 15) +- Code(Expression(24, Add)) at (prev + 3, 5) to (start + 0, 15) = (c28 + c29) - Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19) - Code(Counter(27)) at (prev + 1, 13) to (start + 3, 14) - Code(Counter(28)) at (prev + 4, 13) to (start + 0, 19) -- Code(Expression(21, Sub)) at (prev + 2, 13) to (start + 0, 23) +- Code(Expression(22, Sub)) at (prev + 2, 13) to (start + 0, 23) = (c26 - c27) -- Code(Expression(21, Sub)) at (prev + 1, 20) to (start + 0, 27) +- Code(Expression(22, Sub)) at (prev + 1, 20) to (start + 0, 27) = (c26 - c27) - Code(Zero) at (prev + 1, 21) to (start + 0, 27) - Code(Expression(22, Sub)) at (prev + 2, 21) to (start + 0, 27) - = (c26 - (c27 + Zero)) + = (c26 - c27) - Code(Counter(29)) at (prev + 4, 13) to (start + 0, 19) -- Code(Expression(24, Sub)) at (prev + 3, 9) to (start + 0, 25) +- Code(Expression(23, Sub)) at (prev + 3, 9) to (start + 0, 25) = ((c28 + c29) - c30) - Code(Counter(30)) at (prev + 2, 5) to (start + 0, 15) -- Code(Expression(26, Sub)) at (prev + 3, 9) to (start + 0, 34) +- Code(Expression(25, Sub)) at (prev + 3, 9) to (start + 0, 34) = (c30 - c31) - Code(Counter(31)) at (prev + 2, 5) to (start + 0, 15) -- Code(Expression(27, Sub)) at (prev + 3, 9) to (start + 0, 44) +- Code(Expression(26, Sub)) at (prev + 3, 9) to (start + 0, 44) = (c31 - c32) - Code(Counter(32)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c32 diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map index 912141b6d5f3..640d5f15be0e 100644 --- a/tests/coverage/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map @@ -1,85 +1,70 @@ Function name: ::fmt -Raw bytes (116): 0x[01, 01, 06, 05, 00, 1d, 00, 0f, 13, 01, 19, 11, 15, 15, 19, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0d, 00, 0e, 05, 01, 0d, 00, 1e, 11, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 19, 03, 0d, 00, 0e, 15, 00, 12, 00, 17, 19, 01, 10, 00, 14, 1d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 06, 01, 11, 00, 12, 1d, 01, 11, 00, 22, 0a, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 16, 03, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 11, 09, 0d, 0d, 11, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 05, 01, 0d, 00, 0e, 05, 01, 0d, 00, 1e, 09, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 11, 03, 0d, 00, 0e, 0d, 00, 12, 00, 17, 11, 01, 10, 00, 14, 15, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 15, 01, 11, 00, 12, 15, 01, 11, 00, 22, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 6 -- expression 0 operands: lhs = Counter(1), rhs = Zero -- expression 1 operands: lhs = Counter(7), rhs = Zero -- expression 2 operands: lhs = Expression(3, Add), rhs = Expression(4, Add) -- expression 3 operands: lhs = Counter(0), rhs = Counter(6) -- expression 4 operands: lhs = Counter(4), rhs = Counter(5) -- expression 5 operands: lhs = Counter(5), rhs = Counter(6) +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(2, Add) +- expression 1 operands: lhs = Counter(0), rhs = Counter(4) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Counter(3), rhs = Counter(4) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) -- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 14) - = (c1 - Zero) +- Code(Counter(1)) at (prev + 1, 13) to (start + 0, 14) - Code(Counter(1)) at (prev + 1, 13) to (start + 0, 30) -- Code(Counter(4)) at (prev + 0, 30) to (start + 0, 31) +- Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31) - Code(Zero) at (prev + 1, 16) to (start + 1, 10) -- Code(Counter(6)) at (prev + 3, 13) to (start + 0, 14) -- Code(Counter(5)) at (prev + 0, 18) to (start + 0, 23) -- Code(Counter(6)) at (prev + 1, 16) to (start + 0, 20) -- Code(Counter(7)) at (prev + 1, 20) to (start + 0, 25) +- Code(Counter(4)) at (prev + 3, 13) to (start + 0, 14) +- Code(Counter(3)) at (prev + 0, 18) to (start + 0, 23) +- Code(Counter(4)) at (prev + 1, 16) to (start + 0, 20) +- Code(Counter(5)) at (prev + 1, 20) to (start + 0, 25) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(1, Sub)) at (prev + 1, 17) to (start + 0, 18) - = (c7 - Zero) -- Code(Counter(7)) at (prev + 1, 17) to (start + 0, 34) -- Code(Expression(2, Sub)) at (prev + 0, 34) to (start + 0, 35) - = ((c0 + c6) - (c4 + c5)) +- Code(Counter(5)) at (prev + 1, 17) to (start + 0, 18) +- Code(Counter(5)) at (prev + 1, 17) to (start + 0, 34) +- Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35) + = ((c0 + c4) - (c2 + c3)) - Code(Zero) at (prev + 1, 20) to (start + 1, 14) -- Code(Expression(5, Sub)) at (prev + 3, 9) to (start + 0, 15) - = (c5 - c6) +- Code(Expression(3, Sub)) at (prev + 3, 9) to (start + 0, 15) + = (c3 - c4) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) -Highest counter ID seen: c7 +Highest counter ID seen: c5 Function name: ::fmt -Raw bytes (122): 0x[01, 01, 09, 01, 00, 01, 00, 0d, 00, 0d, 00, 0d, 00, 1b, 1f, 01, 0d, 09, 1d, 09, 0d, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 06, 01, 0d, 00, 0e, 02, 01, 0d, 00, 1e, 1d, 00, 1e, 00, 1f, 0d, 02, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 12, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0e, 01, 11, 00, 12, 12, 01, 11, 00, 22, 16, 00, 22, 00, 23, 22, 03, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 22, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 -Number of expressions: 9 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Counter(0), rhs = Zero -- expression 2 operands: lhs = Counter(3), rhs = Zero -- expression 3 operands: lhs = Counter(3), rhs = Zero -- expression 4 operands: lhs = Counter(3), rhs = Zero -- expression 5 operands: lhs = Expression(6, Add), rhs = Expression(7, Add) -- expression 6 operands: lhs = Counter(0), rhs = Counter(3) -- expression 7 operands: lhs = Counter(2), rhs = Counter(7) -- expression 8 operands: lhs = Counter(2), rhs = Counter(3) +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(2, Add) +- expression 1 operands: lhs = Counter(0), rhs = Counter(2) +- expression 2 operands: lhs = Counter(1), rhs = Counter(3) +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 34, 5) to (start + 1, 17) - Code(Zero) at (prev + 1, 18) to (start + 1, 10) -- Code(Expression(0, Sub)) at (prev + 2, 16) to (start + 0, 21) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 2, 16) to (start + 0, 21) - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) -- Code(Expression(1, Sub)) at (prev + 1, 13) to (start + 0, 14) - = (c0 - Zero) -- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 30) - = (c0 - Zero) -- Code(Counter(7)) at (prev + 0, 30) to (start + 0, 31) -- Code(Counter(3)) at (prev + 2, 13) to (start + 0, 14) -- Code(Counter(2)) at (prev + 0, 18) to (start + 0, 23) -- Code(Counter(3)) at (prev + 1, 16) to (start + 0, 21) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30) +- Code(Counter(3)) at (prev + 0, 30) to (start + 0, 31) +- Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 23) +- Code(Counter(2)) at (prev + 1, 16) to (start + 0, 21) - Code(Zero) at (prev + 0, 22) to (start + 1, 14) -- Code(Expression(4, Sub)) at (prev + 2, 20) to (start + 0, 25) - = (c3 - Zero) +- Code(Counter(2)) at (prev + 2, 20) to (start + 0, 25) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(3, Sub)) at (prev + 1, 17) to (start + 0, 18) - = (c3 - Zero) -- Code(Expression(4, Sub)) at (prev + 1, 17) to (start + 0, 34) - = (c3 - Zero) -- Code(Expression(5, Sub)) at (prev + 0, 34) to (start + 0, 35) - = ((c0 + c3) - (c2 + c7)) -- Code(Expression(8, Sub)) at (prev + 3, 9) to (start + 0, 15) - = (c2 - c3) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 34) +- Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35) + = ((c0 + c2) - (c1 + c3)) +- Code(Expression(3, Sub)) at (prev + 3, 9) to (start + 0, 15) + = (c1 - c2) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) -Highest counter ID seen: c7 +Highest counter ID seen: c3 Function name: loops_branches::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 01, 05, 02] diff --git a/tests/coverage/no_spans_if_not.cov-map b/tests/coverage/no_spans_if_not.cov-map index 9cb7e6a6cff2..6c389a243172 100644 --- a/tests/coverage/no_spans_if_not.cov-map +++ b/tests/coverage/no_spans_if_not.cov-map @@ -1,13 +1,11 @@ Function name: no_spans_if_not::affected_function -Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 16, 1c, 01, 12, 02, 02, 0d, 00, 0f, 00, 02, 0d, 00, 0f] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 16, 1c, 01, 12, 01, 02, 0d, 00, 0f, 00, 02, 0d, 00, 0f] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 22, 28) to (start + 1, 18) -- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 15) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 2, 13) to (start + 0, 15) - Code(Zero) at (prev + 2, 13) to (start + 0, 15) Highest counter ID seen: c0 diff --git a/tests/coverage/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map index 2d2d59bf013e..77a8ffb83581 100644 --- a/tests/coverage/tight_inf_loop.cov-map +++ b/tests/coverage/tight_inf_loop.cov-map @@ -1,13 +1,11 @@ Function name: tight_inf_loop::main -Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 01, 01, 01, 0d, 00, 02, 09, 00, 10, 02, 01, 06, 01, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 01, 01, 01, 0d, 00, 02, 09, 00, 10, 01, 01, 06, 01, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +Number of expressions: 0 Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 1, 1) to (start + 1, 13) - Code(Zero) at (prev + 2, 9) to (start + 0, 16) -- Code(Expression(0, Sub)) at (prev + 1, 6) to (start + 1, 2) - = (c0 - Zero) +- Code(Counter(0)) at (prev + 1, 6) to (start + 1, 2) Highest counter ID seen: c0 From bd855b6c9efc25a9f1eba3febd3d04f1b23a1ec5 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 25 Jan 2025 18:41:35 +1100 Subject: [PATCH 10/19] coverage: Remove the old code for simplifying counters after MIR opts --- .../src/coverageinfo/mapgen/covfun.rs | 25 ++-- .../src/coverageinfo/mod.rs | 4 +- compiler/rustc_middle/src/mir/coverage.rs | 32 +--- .../src/coverage/counters.rs | 2 +- .../rustc_mir_transform/src/coverage/query.rs | 137 +----------------- 5 files changed, 17 insertions(+), 183 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 1290c6efb09f..c53ea6d46661 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -54,7 +54,7 @@ pub(crate) fn prepare_covfun_record<'tcx>( let fn_cov_info = tcx.instance_mir(instance.def).function_coverage_info.as_deref()?; let ids_info = tcx.coverage_ids_info(instance.def)?; - let expressions = prepare_expressions(ids_info, is_used); + let expressions = prepare_expressions(ids_info); let mut covfun = CovfunRecord { mangled_function_name: tcx.symbol_name(instance).name, @@ -76,16 +76,8 @@ pub(crate) fn prepare_covfun_record<'tcx>( } /// Convert the function's coverage-counter expressions into a form suitable for FFI. -fn prepare_expressions(ids_info: &CoverageIdsInfo, is_used: bool) -> Vec { - // If any counters or expressions were removed by MIR opts, replace their - // terms with zero. - let counter_for_term = |term| { - if !is_used || ids_info.is_zero_term(term) { - ffi::Counter::ZERO - } else { - ffi::Counter::from_term(term) - } - }; +fn prepare_expressions(ids_info: &CoverageIdsInfo) -> Vec { + let counter_for_term = ffi::Counter::from_term; // We know that LLVM will optimize out any unused expressions before // producing the final coverage map, so there's no need to do the same @@ -133,13 +125,14 @@ fn fill_region_tables<'tcx>( // For each counter/region pair in this function+file, convert it to a // form suitable for FFI. - let is_zero_term = |term| !covfun.is_used || ids_info.is_zero_term(term); for &Mapping { ref kind, span } in &fn_cov_info.mappings { - // If the mapping refers to counters/expressions that were removed by - // MIR opts, replace those occurrences with zero. + // If this function is unused, replace all counters with zero. let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter { - let term = ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term"); - let term = if is_zero_term(term) { CovTerm::Zero } else { term }; + let term = if covfun.is_used { + ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term") + } else { + CovTerm::Zero + }; ffi::Counter::from_term(term) }; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index e404db5e1965..ea7f581a3cb5 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -163,11 +163,9 @@ fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) { CoverageKind::VirtualCounter { bcb } if let Some(&id) = ids_info.phys_counter_for_node.get(&bcb) => { - let num_counters = ids_info.num_counters_after_mir_opts(); - let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_coverage_info.function_source_hash); - let num_counters = bx.const_u32(num_counters); + let num_counters = bx.const_u32(ids_info.num_counters); let index = bx.const_u32(id.as_u32()); debug!( "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 31b9eeb715b4..8c6b11a681ef 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -3,7 +3,6 @@ use std::fmt::{self, Debug, Formatter}; use rustc_data_structures::fx::FxIndexMap; -use rustc_index::bit_set::DenseBitSet; use rustc_index::{Idx, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::Span; @@ -277,41 +276,12 @@ pub struct MCDCDecisionSpan { /// Returned by the `coverage_ids_info` query. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] pub struct CoverageIdsInfo { - pub counters_seen: DenseBitSet, - pub zero_expressions: DenseBitSet, - + pub num_counters: u32, pub phys_counter_for_node: FxIndexMap, pub term_for_bcb: IndexVec>, pub expressions: IndexVec, } -impl CoverageIdsInfo { - /// Coverage codegen needs to know how many coverage counters are ever - /// incremented within a function, so that it can set the `num-counters` - /// argument of the `llvm.instrprof.increment` intrinsic. - /// - /// This may be less than the highest counter ID emitted by the - /// InstrumentCoverage MIR pass, if the highest-numbered counter increments - /// were removed by MIR optimizations. - pub fn num_counters_after_mir_opts(&self) -> u32 { - // FIXME(Zalathar): Currently this treats an unused counter as "used" - // if its ID is less than that of the highest counter that really is - // used. Fixing this would require adding a renumbering step somewhere. - self.counters_seen.last_set_in(..).map_or(0, |max| max.as_u32() + 1) - } - - /// Returns `true` if the given term is known to have a value of zero, taking - /// into account knowledge of which counters are unused and which expressions - /// are always zero. - pub fn is_zero_term(&self, term: CovTerm) -> bool { - match term { - CovTerm::Zero => true, - CovTerm::Counter(id) => !self.counters_seen.contains(id), - CovTerm::Expression(id) => self.zero_expressions.contains(id), - } - } -} - rustc_index::newtype_index! { /// During the `InstrumentCoverage` MIR pass, a BCB is a node in the /// "coverage graph", which is a refinement of the MIR control-flow graph diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index ac0039fd0073..6f9984d5d0ac 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -135,7 +135,7 @@ pub(super) struct CoverageCounters { /// List of places where a counter-increment statement should be injected /// into MIR, each with its corresponding counter ID. pub(crate) phys_counter_for_node: FxIndexMap, - next_counter_id: CounterId, + pub(crate) next_counter_id: CounterId, /// Coverage counters/expressions that are associated with individual BCBs. pub(crate) node_counters: IndexVec>, diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 995fa91e0a07..cd89fbe772d4 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,11 +1,7 @@ use rustc_data_structures::captures::Captures; -use rustc_index::IndexSlice; use rustc_index::bit_set::DenseBitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::coverage::{ - BasicCoverageBlock, CounterId, CovTerm, CoverageIdsInfo, CoverageKind, Expression, - ExpressionId, MappingKind, Op, -}; +use rustc_middle::mir::coverage::{BasicCoverageBlock, CoverageIdsInfo, CoverageKind, MappingKind}; use rustc_middle::mir::{Body, Statement, StatementKind}; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; @@ -134,44 +130,12 @@ fn coverage_ids_info<'tcx>( let node_counters = make_node_counters(&fn_cov_info.node_flow_data, &fn_cov_info.priority_list); let coverage_counters = transcribe_counters(&node_counters, &bcb_needs_counter, &bcbs_seen); - let mut counters_seen = DenseBitSet::new_empty(coverage_counters.node_counters.len()); - let mut expressions_seen = DenseBitSet::new_filled(coverage_counters.expressions.len()); - - // For each expression ID that is directly used by one or more mappings, - // mark it as not-yet-seen. This indicates that we expect to see a - // corresponding `VirtualCounter` statement during MIR traversal. - for mapping in fn_cov_info.mappings.iter() { - // Currently we only worry about ordinary code mappings. - // For branch and MC/DC mappings, expressions might not correspond - // to any particular point in the control-flow graph. - if let MappingKind::Code { bcb } = mapping.kind - && let Some(CovTerm::Expression(id)) = coverage_counters.node_counters[bcb] - { - expressions_seen.remove(id); - } - } - - for bcb in bcbs_seen.iter() { - if let Some(&id) = coverage_counters.phys_counter_for_node.get(&bcb) { - counters_seen.insert(id); - } - if let Some(CovTerm::Expression(id)) = coverage_counters.node_counters[bcb] { - expressions_seen.insert(id); - } - } - - let zero_expressions = identify_zero_expressions( - &coverage_counters.expressions, - &counters_seen, - &expressions_seen, - ); - - let CoverageCounters { phys_counter_for_node, node_counters, expressions, .. } = - coverage_counters; + let CoverageCounters { + phys_counter_for_node, next_counter_id, node_counters, expressions, .. + } = coverage_counters; Some(CoverageIdsInfo { - counters_seen, - zero_expressions, + num_counters: next_counter_id.as_u32(), phys_counter_for_node, term_for_bcb: node_counters, expressions, @@ -193,94 +157,3 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { let scope_data = &body.source_scopes[statement.source_info.scope]; scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some() } - -/// Identify expressions that will always have a value of zero, and note their -/// IDs in a `DenseBitSet`. Mappings that refer to a zero expression can instead -/// become mappings to a constant zero value. -/// -/// This function mainly exists to preserve the simplifications that were -/// already being performed by the Rust-side expression renumbering, so that -/// the resulting coverage mappings don't get worse. -fn identify_zero_expressions( - expressions: &IndexSlice, - counters_seen: &DenseBitSet, - expressions_seen: &DenseBitSet, -) -> DenseBitSet { - // The set of expressions that either were optimized out entirely, or - // have zero as both of their operands, and will therefore always have - // a value of zero. Other expressions that refer to these as operands - // can have those operands replaced with `CovTerm::Zero`. - let mut zero_expressions = DenseBitSet::new_empty(expressions.len()); - - // Simplify a copy of each expression based on lower-numbered expressions, - // and then update the set of always-zero expressions if necessary. - // (By construction, expressions can only refer to other expressions - // that have lower IDs, so one pass is sufficient.) - for (id, expression) in expressions.iter_enumerated() { - if !expressions_seen.contains(id) { - // If an expression was not seen, it must have been optimized away, - // so any operand that refers to it can be replaced with zero. - zero_expressions.insert(id); - continue; - } - - // We don't need to simplify the actual expression data in the - // expressions list; we can just simplify a temporary copy and then - // use that to update the set of always-zero expressions. - let Expression { mut lhs, op, mut rhs } = *expression; - - // If an expression has an operand that is also an expression, the - // operand's ID must be strictly lower. This is what lets us find - // all zero expressions in one pass. - let assert_operand_expression_is_lower = |operand_id: ExpressionId| { - assert!( - operand_id < id, - "Operand {operand_id:?} should be less than {id:?} in {expression:?}", - ) - }; - - // If an operand refers to a counter or expression that is always - // zero, then that operand can be replaced with `CovTerm::Zero`. - let maybe_set_operand_to_zero = |operand: &mut CovTerm| { - if let CovTerm::Expression(id) = *operand { - assert_operand_expression_is_lower(id); - } - - if is_zero_term(&counters_seen, &zero_expressions, *operand) { - *operand = CovTerm::Zero; - } - }; - maybe_set_operand_to_zero(&mut lhs); - maybe_set_operand_to_zero(&mut rhs); - - // Coverage counter values cannot be negative, so if an expression - // involves subtraction from zero, assume that its RHS must also be zero. - // (Do this after simplifications that could set the LHS to zero.) - if lhs == CovTerm::Zero && op == Op::Subtract { - rhs = CovTerm::Zero; - } - - // After the above simplifications, if both operands are zero, then - // we know that this expression is always zero too. - if lhs == CovTerm::Zero && rhs == CovTerm::Zero { - zero_expressions.insert(id); - } - } - - zero_expressions -} - -/// Returns `true` if the given term is known to have a value of zero, taking -/// into account knowledge of which counters are unused and which expressions -/// are always zero. -fn is_zero_term( - counters_seen: &DenseBitSet, - zero_expressions: &DenseBitSet, - term: CovTerm, -) -> bool { - match term { - CovTerm::Zero => true, - CovTerm::Counter(id) => !counters_seen.contains(id), - CovTerm::Expression(id) => zero_expressions.contains(id), - } -} From 9c486a74dac6f11276df4bbd2abc526a82cd000f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 7 Feb 2025 18:00:20 +0000 Subject: [PATCH 11/19] Mark link_section attr with unsafe --- library/rtstartup/rsbegin.rs | 6 +++--- library/rtstartup/rsend.rs | 2 +- library/std/src/sys/pal/unix/args.rs | 2 +- library/std/src/sys/pal/windows/compat.rs | 2 +- library/std/src/sys/thread_local/guard/windows.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs index d3ff5c14aa4a..83ec21ade402 100644 --- a/library/rtstartup/rsbegin.rs +++ b/library/rtstartup/rsbegin.rs @@ -52,7 +52,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { #[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))] pub mod eh_frames { #[no_mangle] - #[link_section = ".eh_frame"] + #[unsafe(link_section = ".eh_frame")] // Marks beginning of the stack frame unwind info section pub static __EH_FRAME_BEGIN__: [u8; 0] = []; @@ -101,10 +101,10 @@ pub mod mingw_init { // end of the list. Since constructors are run in reverse order, this ensures that our // callbacks are the first and last ones executed. - #[link_section = ".ctors.65535"] // .ctors.* : C initialization callbacks + #[unsafe(link_section = ".ctors.65535")] // .ctors.* : C initialization callbacks pub static P_INIT: unsafe extern "C" fn() = super::init; - #[link_section = ".dtors.65535"] // .dtors.* : C termination callbacks + #[unsafe(link_section = ".dtors.65535")] // .dtors.* : C termination callbacks pub static P_UNINIT: unsafe extern "C" fn() = super::uninit; } } diff --git a/library/rtstartup/rsend.rs b/library/rtstartup/rsend.rs index 81acfbed4477..a6f7d103356b 100644 --- a/library/rtstartup/rsend.rs +++ b/library/rtstartup/rsend.rs @@ -32,6 +32,6 @@ pub mod eh_frames { // Terminate the frame unwind info section with a 0 as a sentinel; // this would be the 'length' field in a real FDE. #[no_mangle] - #[link_section = ".eh_frame"] + #[unsafe(link_section = ".eh_frame")] pub static __EH_FRAME_END__: u32 = 0; } diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs index 8438a61e90fe..608173b6376d 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/pal/unix/args.rs @@ -147,7 +147,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { /// This allows `std::env::args` to work even in a `cdylib`, as it does on macOS and Windows. #[cfg(all(target_os = "linux", target_env = "gnu"))] #[used] - #[link_section = ".init_array.00099"] + #[unsafe(link_section = ".init_array.00099")] static ARGV_INIT_ARRAY: extern "C" fn( crate::os::raw::c_int, *const *const u8, diff --git a/library/std/src/sys/pal/windows/compat.rs b/library/std/src/sys/pal/windows/compat.rs index 42999da16645..2b9838437e9c 100644 --- a/library/std/src/sys/pal/windows/compat.rs +++ b/library/std/src/sys/pal/windows/compat.rs @@ -39,7 +39,7 @@ // See https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-170 #[cfg(target_vendor = "win7")] #[used] -#[link_section = ".CRT$XCT"] +#[unsafe(link_section = ".CRT$XCT")] static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init; /// Preload some imported functions. diff --git a/library/std/src/sys/thread_local/guard/windows.rs b/library/std/src/sys/thread_local/guard/windows.rs index 1752b0e1208a..b15a0d7c0bdf 100644 --- a/library/std/src/sys/thread_local/guard/windows.rs +++ b/library/std/src/sys/thread_local/guard/windows.rs @@ -74,7 +74,7 @@ pub fn enable() { unsafe { ptr::from_ref(&CALLBACK).read_volatile() }; } -#[link_section = ".CRT$XLB"] +#[unsafe(link_section = ".CRT$XLB")] #[cfg_attr(miri, used)] // Miri only considers explicitly `#[used]` statics for `lookup_link_section` pub static CALLBACK: unsafe extern "system" fn(*mut c_void, u32, *mut c_void) = tls_callback; From 04bbc8340a0e0031aef7f406c087a0ba64c1b491 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 7 Feb 2025 18:00:38 +0000 Subject: [PATCH 12/19] Rename field in OnceWith from gen to make --- library/core/src/iter/sources/once_with.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/core/src/iter/sources/once_with.rs b/library/core/src/iter/sources/once_with.rs index 8b31ab2ff90c..c9698b4fd431 100644 --- a/library/core/src/iter/sources/once_with.rs +++ b/library/core/src/iter/sources/once_with.rs @@ -58,8 +58,8 @@ /// ``` #[inline] #[stable(feature = "iter_once_with", since = "1.43.0")] -pub fn once_with A>(gen: F) -> OnceWith { - OnceWith { gen: Some(gen) } +pub fn once_with A>(make: F) -> OnceWith { + OnceWith { make: Some(make) } } /// An iterator that yields a single element of type `A` by @@ -70,13 +70,13 @@ pub fn once_with A>(gen: F) -> OnceWith { #[derive(Clone)] #[stable(feature = "iter_once_with", since = "1.43.0")] pub struct OnceWith { - gen: Option, + make: Option, } #[stable(feature = "iter_once_with_debug", since = "1.68.0")] impl fmt::Debug for OnceWith { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.gen.is_some() { + if self.make.is_some() { f.write_str("OnceWith(Some(_))") } else { f.write_str("OnceWith(None)") @@ -90,13 +90,13 @@ impl A> Iterator for OnceWith { #[inline] fn next(&mut self) -> Option { - let f = self.gen.take()?; + let f = self.make.take()?; Some(f()) } #[inline] fn size_hint(&self) -> (usize, Option) { - self.gen.iter().size_hint() + self.make.iter().size_hint() } } @@ -110,7 +110,7 @@ fn next_back(&mut self) -> Option { #[stable(feature = "iter_once_with", since = "1.43.0")] impl A> ExactSizeIterator for OnceWith { fn len(&self) -> usize { - self.gen.iter().len() + self.make.iter().len() } } From a4e7f8f9bf10588cb5519ae09a15be155499901f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 7 Feb 2025 19:42:33 +0000 Subject: [PATCH 13/19] Mark extern blocks as unsafe --- library/alloc/src/alloc.rs | 6 +-- library/alloc/src/ffi/c_str.rs | 2 +- library/core/src/ffi/c_str.rs | 2 +- library/core/src/ffi/mod.rs | 2 +- library/core/src/intrinsics/mod.rs | 2 +- library/core/src/panicking.rs | 4 +- library/core/src/ptr/metadata.rs | 2 +- library/coretests/tests/mem.rs | 2 +- library/coretests/tests/num/flt2dec/mod.rs | 2 +- library/coretests/tests/ptr.rs | 6 +-- library/panic_abort/src/lib.rs | 4 +- library/panic_abort/src/zkvm.rs | 2 +- library/panic_unwind/src/emcc.rs | 4 +- library/panic_unwind/src/hermit.rs | 4 +- library/panic_unwind/src/lib.rs | 2 +- library/panic_unwind/src/miri.rs | 2 +- library/panic_unwind/src/seh.rs | 6 +-- library/rtstartup/rsbegin.rs | 2 +- library/std/src/alloc.rs | 2 +- library/std/src/panicking.rs | 4 +- library/std/src/sys/alloc/xous.rs | 2 +- library/std/src/sys/cmath.rs | 2 +- library/std/src/sys/pal/hermit/mod.rs | 2 +- library/std/src/sys/pal/itron/abi.rs | 2 +- library/std/src/sys/pal/sgx/abi/mem.rs | 2 +- library/std/src/sys/pal/sgx/abi/mod.rs | 2 +- library/std/src/sys/pal/sgx/abi/panic.rs | 2 +- library/std/src/sys/pal/sgx/abi/reloc.rs | 2 +- library/std/src/sys/pal/sgx/abi/thread.rs | 2 +- library/std/src/sys/pal/sgx/abi/tls/mod.rs | 2 +- .../std/src/sys/pal/sgx/abi/usercalls/raw.rs | 2 +- library/std/src/sys/pal/solid/abi/fs.rs | 2 +- library/std/src/sys/pal/solid/abi/mod.rs | 10 ++-- library/std/src/sys/pal/solid/abi/sockets.rs | 2 +- library/std/src/sys/pal/solid/os.rs | 2 +- library/std/src/sys/pal/teeos/thread.rs | 2 +- library/std/src/sys/pal/unix/args.rs | 2 +- library/std/src/sys/pal/unix/futex.rs | 4 +- library/std/src/sys/pal/unix/mod.rs | 20 ++++---- library/std/src/sys/pal/unix/os.rs | 14 +++--- .../std/src/sys/pal/unix/process/zircon.rs | 4 +- library/std/src/sys/pal/unix/thread.rs | 6 +-- .../std/src/sys/pal/unix/thread_parking.rs | 2 +- library/std/src/sys/pal/unix/weak.rs | 2 +- library/std/src/sys/pal/wasi/fs.rs | 2 +- library/std/src/sys/pal/wasi/os.rs | 4 +- library/std/src/sys/pal/wasi/thread.rs | 2 +- library/std/src/sys/pal/windows/c.rs | 4 +- .../std/src/sys/pal/windows/process/tests.rs | 2 +- library/std/src/sys/pal/xous/os.rs | 2 +- library/std/src/sys/pal/zkvm/abi.rs | 2 +- library/std/src/sys/personality/gcc.rs | 2 +- library/std/src/sys/random/arc4random.rs | 2 +- library/std/src/sys/random/espidf.rs | 2 +- library/std/src/sys/random/fuchsia.rs | 2 +- library/std/src/sys/random/teeos.rs | 2 +- .../std/src/sys/sync/thread_parking/darwin.rs | 2 +- .../thread_local/destructors/linux_like.rs | 2 +- .../std/src/sys/thread_local/guard/apple.rs | 2 +- library/std/src/sys/thread_local/key/unix.rs | 2 +- library/std/src/sys/thread_local/key/xous.rs | 2 +- library/std/tests/switch-stdout.rs | 4 +- library/test/src/term/win.rs | 2 +- library/unwind/src/lib.rs | 46 +++++++++---------- library/unwind/src/libunwind.rs | 16 +++---- library/windows_targets/src/lib.rs | 2 +- 66 files changed, 132 insertions(+), 132 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index e9b7f9856677..e686a02f29b0 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -10,7 +10,7 @@ #[cfg(not(test))] use core::ptr::{self, NonNull}; -extern "Rust" { +unsafe extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute // (the code expanding that attribute macro generates those functions), or to call @@ -355,7 +355,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { // # Allocation error handler #[cfg(not(no_global_oom_handling))] -extern "Rust" { +unsafe extern "Rust" { // This is the magic symbol to call the global alloc error handler. rustc generates // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the // default implementations below (`__rdl_oom`) otherwise. @@ -426,7 +426,7 @@ pub mod __alloc_error_handler { // `#[alloc_error_handler]`. #[rustc_std_internal_symbol] pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { - extern "Rust" { + unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. static __rust_alloc_error_handler_should_panic: u8; diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 07c75677d053..fd93045a5ac4 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -397,7 +397,7 @@ pub unsafe fn from_raw(ptr: *mut c_char) -> CString { // information about the size of the allocation is correct on Rust's // side. unsafe { - extern "C" { + unsafe extern "C" { /// Provided by libc or compiler_builtins. fn strlen(s: *const c_char) -> usize; } diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 7180593edf0d..75338e492ee0 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -731,7 +731,7 @@ fn as_ref(&self) -> &CStr { len } else { - extern "C" { + unsafe extern "C" { /// Provided by libc or compiler_builtins. fn strlen(s: *const c_char) -> usize; } diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 50968c57adc6..9bae5fd466a1 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -90,4 +90,4 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { cfg(not(target_feature = "crt-static")) )] #[link(name = "/defaultlib:libcmt", modifiers = "+verbatim", cfg(target_feature = "crt-static"))] -extern "C" {} +unsafe extern "C" {} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 3b249c835f23..6c9c6d0edc23 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -4855,7 +4855,7 @@ pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { #[cfg(miri)] #[rustc_allow_const_fn_unstable(const_eval_select)] pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) { - extern "Rust" { + unsafe extern "Rust" { /// Miri-provided extern function to promise that a given pointer is properly aligned for /// "symbolic" alignment checks. Will fail if the pointer is not actually aligned or `align` is /// not a power of two. Has no effect when alignment checks are concrete (which is the default). diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index b97f19e1baa9..d36e677d21a1 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -59,7 +59,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call // that gets resolved to the `#[panic_handler]` function. - extern "Rust" { + unsafe extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; } @@ -100,7 +100,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call // that gets resolved to the `#[panic_handler]` function. - extern "Rust" { + unsafe extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; } diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index e93b5658e243..9eee29d485f4 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -155,7 +155,7 @@ pub struct DynMetadata { _phantom: crate::marker::PhantomData, } -extern "C" { +unsafe extern "C" { /// Opaque type for accessing vtables. /// /// Private implementation detail of `DynMetadata::size_of` etc. diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index 1b5c5fc82a69..9cb94ca3b0ff 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -648,7 +648,7 @@ struct Beta { z: dyn Trait, } - extern "C" { + unsafe extern "C" { type Extern; } diff --git a/library/coretests/tests/num/flt2dec/mod.rs b/library/coretests/tests/num/flt2dec/mod.rs index 3d8252248131..6041923117c2 100644 --- a/library/coretests/tests/num/flt2dec/mod.rs +++ b/library/coretests/tests/num/flt2dec/mod.rs @@ -80,7 +80,7 @@ fn ldexp_f32(a: f32, b: i32) -> f32 { } fn ldexp_f64(a: f64, b: i32) -> f64 { - extern "C" { + unsafe extern "C" { fn ldexp(x: f64, n: i32) -> f64; } // SAFETY: assuming a correct `ldexp` has been supplied, the given arguments cannot possibly diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index 345bec345d12..0c9f9b338b0c 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -97,7 +97,7 @@ fn test_is_null() { let nmi: *mut dyn ToString = null_mut::(); assert!(nmi.is_null()); - extern "C" { + unsafe extern "C" { type Extern; } let ec: *const Extern = null::(); @@ -308,7 +308,7 @@ fn test_const_nonnull_new() { pub fn test_variadic_fnptr() { use core::ffi; use core::hash::{Hash, SipHasher}; - extern "C" { + unsafe extern "C" { // This needs to use the correct function signature even though it isn't called as some // codegen backends make it UB to declare a function with multiple conflicting signatures // (like LLVM) while others straight up return an error (like Cranelift). @@ -506,7 +506,7 @@ fn offset_from() { fn ptr_metadata() { struct Unit; struct Pair(A, B); - extern "C" { + unsafe extern "C" { type Extern; } let () = metadata(&()); diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index dc2b42bb90ae..7718d68aef8e 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -54,7 +54,7 @@ unsafe fn abort() -> ! { ))] { unsafe fn abort() -> ! { // call std::sys::abort_internal - extern "C" { + unsafe extern "C" { pub fn __rust_abort() -> !; } __rust_abort(); @@ -87,7 +87,7 @@ unsafe fn abort() -> ! { } } else if #[cfg(target_os = "teeos")] { mod teeos { - extern "C" { + unsafe extern "C" { pub fn TEE_Panic(code: u32) -> !; } } diff --git a/library/panic_abort/src/zkvm.rs b/library/panic_abort/src/zkvm.rs index a6a02abf1097..11150eafd0b8 100644 --- a/library/panic_abort/src/zkvm.rs +++ b/library/panic_abort/src/zkvm.rs @@ -16,7 +16,7 @@ pub(crate) unsafe fn zkvm_set_abort_message(payload: &mut dyn PanicPayload) { return; } - extern "C" { + unsafe extern "C" { fn sys_panic(msg_ptr: *const u8, len: usize) -> !; } diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 9127449edb1a..0bb256f0eb83 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -21,7 +21,7 @@ struct TypeInfo { } unsafe impl Sync for TypeInfo {} -extern "C" { +unsafe extern "C" { // The leading `\x01` byte here is actually a magical signal to LLVM to // *not* apply any other mangling like prefixing with a `_` character. // @@ -116,7 +116,7 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> *mut libc::c_void { } } -extern "C" { +unsafe extern "C" { fn __cxa_allocate_exception(thrown_size: libc::size_t) -> *mut libc::c_void; fn __cxa_begin_catch(thrown_exception: *mut libc::c_void) -> *mut libc::c_void; fn __cxa_end_catch(); diff --git a/library/panic_unwind/src/hermit.rs b/library/panic_unwind/src/hermit.rs index 7e08ad66577f..9719c1334152 100644 --- a/library/panic_unwind/src/hermit.rs +++ b/library/panic_unwind/src/hermit.rs @@ -6,14 +6,14 @@ use core::any::Any; pub(crate) unsafe fn cleanup(_ptr: *mut u8) -> Box { - extern "C" { + unsafe extern "C" { fn __rust_abort() -> !; } __rust_abort(); } pub(crate) unsafe fn panic(_data: Box) -> u32 { - extern "C" { + unsafe extern "C" { fn __rust_abort() -> !; } __rust_abort(); diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index d68281641956..45e2a466b4df 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -75,7 +75,7 @@ } } -extern "C" { +unsafe extern "C" { /// Handler in std called when a panic object is dropped outside of /// `catch_unwind`. fn __rust_drop_panic() -> !; diff --git a/library/panic_unwind/src/miri.rs b/library/panic_unwind/src/miri.rs index a86f0e91eefc..ec48b1105ab4 100644 --- a/library/panic_unwind/src/miri.rs +++ b/library/panic_unwind/src/miri.rs @@ -7,7 +7,7 @@ // Must be pointer-sized. type Payload = Box>; -extern "Rust" { +unsafe extern "Rust" { /// Miri-provided extern function to begin unwinding. fn miri_start_unwind(payload: *mut u8) -> !; } diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 21bfe74e1a25..c8dfddf821e6 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -135,7 +135,7 @@ mod imp { #[derive(Copy, Clone)] pub(super) struct ptr_t(u32); - extern "C" { + unsafe extern "C" { static __ImageBase: u8; } @@ -229,7 +229,7 @@ struct _TypeDescriptor { copyFunction: ptr_t::null(), }; -extern "C" { +unsafe extern "C" { // The leading `\x01` byte here is actually a magical signal to LLVM to // *not* apply any other mangling like prefixing with a `_` character. // @@ -343,7 +343,7 @@ pub(crate) unsafe fn panic(data: Box) -> u32 { ptr_t::new(exception_copy as *mut u8).raw(), ); - extern "system-unwind" { + unsafe extern "system-unwind" { fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8) -> !; } diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs index 83ec21ade402..67b09599d9d2 100644 --- a/library/rtstartup/rsbegin.rs +++ b/library/rtstartup/rsbegin.rs @@ -76,7 +76,7 @@ impl ::Copy for $t {} } // Unwind info registration/deregistration routines. - extern "C" { + unsafe extern "C" { fn __register_frame_info(eh_frame_begin: *const u8, object: *mut u8); fn __deregister_frame_info(eh_frame_begin: *const u8, object: *mut u8); } diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 5d51d6a0c78a..3936ed057e6e 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -345,7 +345,7 @@ pub fn take_alloc_error_hook() -> fn(Layout) { } fn default_alloc_error_hook(layout: Layout) { - extern "Rust" { + unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. static __rust_alloc_error_handler_should_panic: u8; diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 8e50bf11dd08..b47b41d4bc5b 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -54,11 +54,11 @@ // One day this may look a little less ad-hoc with the compiler helping out to // hook up these functions, but it is not this day! #[allow(improper_ctypes)] -extern "C" { +unsafe extern "C" { fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); } -extern "Rust" { +unsafe extern "Rust" { /// `PanicPayload` lazily performs allocation only when needed (this avoids /// allocations when using the "abort" panic runtime). fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32; diff --git a/library/std/src/sys/alloc/xous.rs b/library/std/src/sys/alloc/xous.rs index 321d30e0b11b..9d22e16fdf2f 100644 --- a/library/std/src/sys/alloc/xous.rs +++ b/library/std/src/sys/alloc/xous.rs @@ -8,7 +8,7 @@ static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new(); #[cfg(test)] -extern "Rust" { +unsafe extern "Rust" { #[link_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE"] static mut DLMALLOC: dlmalloc::Dlmalloc; } diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index ee36127cfdf1..e3f41f4fdbbb 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -2,7 +2,7 @@ // These symbols are all defined by `libm`, // or by `compiler-builtins` on unsupported platforms. -extern "C" { +unsafe extern "C" { pub fn acos(n: f64) -> f64; pub fn asin(n: f64) -> f64; pub fn atan(n: f64) -> f64; diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 3d555ad5050c..a746b853cbdc 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -78,7 +78,7 @@ pub unsafe fn cleanup() {} argv: *const *const c_char, env: *const *const c_char, ) -> ! { - extern "C" { + unsafe extern "C" { fn main(argc: isize, argv: *const *const c_char) -> i32; } diff --git a/library/std/src/sys/pal/itron/abi.rs b/library/std/src/sys/pal/itron/abi.rs index 5eb14bb7e534..49b5251fc0eb 100644 --- a/library/std/src/sys/pal/itron/abi.rs +++ b/library/std/src/sys/pal/itron/abi.rs @@ -132,7 +132,7 @@ pub struct T_CTSK { pub stk: *mut u8, } -extern "C" { +unsafe extern "C" { #[link_name = "__asp3_acre_tsk"] pub fn acre_tsk(pk_ctsk: *const T_CTSK) -> ER_ID; #[link_name = "__asp3_get_tid"] diff --git a/library/std/src/sys/pal/sgx/abi/mem.rs b/library/std/src/sys/pal/sgx/abi/mem.rs index 18e6d5b3fa24..e6ce15bed3cf 100644 --- a/library/std/src/sys/pal/sgx/abi/mem.rs +++ b/library/std/src/sys/pal/sgx/abi/mem.rs @@ -12,7 +12,7 @@ pub(crate) unsafe fn rel_ptr_mut(offset: u64) -> *mut T { (image_base() + offset) as *mut T } -extern "C" { +unsafe extern "C" { static ENCLAVE_SIZE: usize; static HEAP_BASE: u64; static HEAP_SIZE: usize; diff --git a/library/std/src/sys/pal/sgx/abi/mod.rs b/library/std/src/sys/pal/sgx/abi/mod.rs index d8836452e755..f52acc415097 100644 --- a/library/std/src/sys/pal/sgx/abi/mod.rs +++ b/library/std/src/sys/pal/sgx/abi/mod.rs @@ -73,7 +73,7 @@ extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64 EntryReturn(0, 0) } else { - extern "C" { + unsafe extern "C" { fn main(argc: isize, argv: *const *const u8) -> isize; } diff --git a/library/std/src/sys/pal/sgx/abi/panic.rs b/library/std/src/sys/pal/sgx/abi/panic.rs index c06b97ee3674..67af062b0fff 100644 --- a/library/std/src/sys/pal/sgx/abi/panic.rs +++ b/library/std/src/sys/pal/sgx/abi/panic.rs @@ -2,7 +2,7 @@ use crate::io::{self, Write}; use crate::{cmp, mem}; -extern "C" { +unsafe extern "C" { fn take_debug_panic_buf_ptr() -> *mut u8; static DEBUG: u8; } diff --git a/library/std/src/sys/pal/sgx/abi/reloc.rs b/library/std/src/sys/pal/sgx/abi/reloc.rs index 02dff0ad29fc..a4f5e4a0936f 100644 --- a/library/std/src/sys/pal/sgx/abi/reloc.rs +++ b/library/std/src/sys/pal/sgx/abi/reloc.rs @@ -11,7 +11,7 @@ struct Rela { } pub fn relocate_elf_rela() { - extern "C" { + unsafe extern "C" { static RELA: u64; static RELACOUNT: usize; } diff --git a/library/std/src/sys/pal/sgx/abi/thread.rs b/library/std/src/sys/pal/sgx/abi/thread.rs index 2b23e368cc31..9b37e2baf364 100644 --- a/library/std/src/sys/pal/sgx/abi/thread.rs +++ b/library/std/src/sys/pal/sgx/abi/thread.rs @@ -6,7 +6,7 @@ /// is a one-to-one correspondence of the ID to the address of the TCS. #[unstable(feature = "sgx_platform", issue = "56975")] pub fn current() -> Tcs { - extern "C" { + unsafe extern "C" { fn get_tcs_addr() -> *mut u8; } let addr = unsafe { get_tcs_addr() }; diff --git a/library/std/src/sys/pal/sgx/abi/tls/mod.rs b/library/std/src/sys/pal/sgx/abi/tls/mod.rs index 34fc2f20d221..7131797003bf 100644 --- a/library/std/src/sys/pal/sgx/abi/tls/mod.rs +++ b/library/std/src/sys/pal/sgx/abi/tls/mod.rs @@ -22,7 +22,7 @@ macro_rules! dup { #[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"] static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0))); -extern "C" { +unsafe extern "C" { fn get_tls_ptr() -> *const u8; fn set_tls_ptr(tls: *const u8); } diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/raw.rs b/library/std/src/sys/pal/sgx/abi/usercalls/raw.rs index 943b771498f8..28fbbc3c5181 100644 --- a/library/std/src/sys/pal/sgx/abi/usercalls/raw.rs +++ b/library/std/src/sys/pal/sgx/abi/usercalls/raw.rs @@ -9,7 +9,7 @@ #[repr(C)] struct UsercallReturn(u64, u64); -extern "C" { +unsafe extern "C" { fn usercall(nr: NonZero, p1: u64, p2: u64, abort: u64, p3: u64, p4: u64) -> UsercallReturn; } diff --git a/library/std/src/sys/pal/solid/abi/fs.rs b/library/std/src/sys/pal/solid/abi/fs.rs index 6864a3e7745b..7f2b1f83e856 100644 --- a/library/std/src/sys/pal/solid/abi/fs.rs +++ b/library/std/src/sys/pal/solid/abi/fs.rs @@ -31,7 +31,7 @@ pub struct dirent { pub type S_DIR = c_int; -extern "C" { +unsafe extern "C" { pub fn SOLID_FS_Open(fd: *mut c_int, path: *const c_char, mode: c_int) -> c_int; pub fn SOLID_FS_Close(fd: c_int) -> c_int; pub fn SOLID_FS_Read(fd: c_int, buf: *mut u8, size: usize, result: *mut usize) -> c_int; diff --git a/library/std/src/sys/pal/solid/abi/mod.rs b/library/std/src/sys/pal/solid/abi/mod.rs index 4d0970572174..819f93f40742 100644 --- a/library/std/src/sys/pal/solid/abi/mod.rs +++ b/library/std/src/sys/pal/solid/abi/mod.rs @@ -33,27 +33,27 @@ pub struct SOLID_RTC_TIME { pub tm_wday: c_int, } -extern "C" { +unsafe extern "C" { pub fn SOLID_RTC_ReadTime(time: *mut SOLID_RTC_TIME) -> c_int; } // `solid_log.h` -extern "C" { +unsafe extern "C" { pub fn SOLID_LOG_write(s: *const u8, l: usize); } // `solid_mem.h` -extern "C" { +unsafe extern "C" { pub fn SOLID_TLS_AddDestructor(id: i32, dtor: unsafe extern "C" fn(*mut u8)); } // `solid_rng.h` -extern "C" { +unsafe extern "C" { pub fn SOLID_RNG_SampleRandomBytes(buffer: *mut u8, length: usize) -> c_int; } // `rwlock.h` -extern "C" { +unsafe extern "C" { pub fn rwl_loc_rdl(id: ID) -> ER; pub fn rwl_loc_wrl(id: ID) -> ER; pub fn rwl_ploc_rdl(id: ID) -> ER; diff --git a/library/std/src/sys/pal/solid/abi/sockets.rs b/library/std/src/sys/pal/solid/abi/sockets.rs index 3c9e3f9ffb95..80802dd42e24 100644 --- a/library/std/src/sys/pal/solid/abi/sockets.rs +++ b/library/std/src/sys/pal/solid/abi/sockets.rs @@ -158,7 +158,7 @@ pub struct fd_set { pub fds: [c_int; SOLID_NET_FD_SETSIZE], } -extern "C" { +unsafe extern "C" { #[link_name = "SOLID_NET_StrError"] pub fn strerror(errnum: c_int) -> *const c_char; diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs index 57c28aed3b29..e3b2e0aa50f4 100644 --- a/library/std/src/sys/pal/solid/os.rs +++ b/library/std/src/sys/pal/solid/os.rs @@ -129,7 +129,7 @@ fn size_hint(&self) -> (usize, Option) { /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { - extern "C" { + unsafe extern "C" { static mut environ: *const *const c_char; } diff --git a/library/std/src/sys/pal/teeos/thread.rs b/library/std/src/sys/pal/teeos/thread.rs index 15c65240ddd2..c779c5f3ed89 100644 --- a/library/std/src/sys/pal/teeos/thread.rs +++ b/library/std/src/sys/pal/teeos/thread.rs @@ -16,7 +16,7 @@ pub struct Thread { unsafe impl Send for Thread {} unsafe impl Sync for Thread {} -extern "C" { +unsafe extern "C" { pub fn TEE_Wait(timeout: u32) -> u32; } diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs index 608173b6376d..1c87a79803c0 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/pal/unix/args.rs @@ -204,7 +204,7 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8) { } pub fn argc_argv() -> (isize, *const *const c_char) { - extern "C" { + unsafe extern "C" { // These functions are in crt_externs.h. fn _NSGetArgc() -> *mut c_int; fn _NSGetArgv() -> *mut *mut *mut c_char; diff --git a/library/std/src/sys/pal/unix/futex.rs b/library/std/src/sys/pal/unix/futex.rs index 0fc765dc87a5..d4551dd6a38b 100644 --- a/library/std/src/sys/pal/unix/futex.rs +++ b/library/std/src/sys/pal/unix/futex.rs @@ -219,7 +219,7 @@ pub fn futex_wake_all(futex: &AtomicU32) { } #[cfg(target_os = "emscripten")] -extern "C" { +unsafe extern "C" { fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int; fn emscripten_futex_wait( addr: *const AtomicU32, @@ -267,7 +267,7 @@ pub mod zircon { pub const ZX_ERR_BAD_STATE: zx_status_t = -20; pub const ZX_ERR_TIMED_OUT: zx_status_t = -21; - extern "C" { + unsafe extern "C" { pub fn zx_clock_get_monotonic() -> zx_time_t; pub fn zx_futex_wait( value_ptr: *const zx_futex_t, diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 027df6c5691c..c0b56d8d2b28 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -373,24 +373,24 @@ pub fn abort_internal() -> ! { cfg(target_feature = "crt-static"))] #[link(name = "dl", cfg(not(target_feature = "crt-static")))] #[link(name = "log", cfg(not(target_feature = "crt-static")))] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(target_os = "freebsd")] { #[link(name = "execinfo")] #[link(name = "pthread")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(target_os = "netbsd")] { #[link(name = "pthread")] #[link(name = "rt")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] { #[link(name = "pthread")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(target_os = "solaris")] { #[link(name = "socket")] #[link(name = "posix4")] #[link(name = "pthread")] #[link(name = "resolv")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(target_os = "illumos")] { #[link(name = "socket")] #[link(name = "posix4")] @@ -399,24 +399,24 @@ pub fn abort_internal() -> ! { #[link(name = "nsl")] // Use libumem for the (malloc-compatible) allocator #[link(name = "umem")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(target_vendor = "apple")] { // Link to `libSystem.dylib`. // // Don't get confused by the presence of `System.framework`, // it is a deprecated wrapper over the dynamic library. #[link(name = "System")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(target_os = "fuchsia")] { #[link(name = "zircon")] #[link(name = "fdio")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(all(target_os = "linux", target_env = "uclibc"))] { #[link(name = "dl")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(target_os = "vita")] { #[link(name = "pthread", kind = "static", modifiers = "-bundle")] - extern "C" {} + unsafe extern "C" {} } } diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index b83772e34c17..04199c563303 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -30,7 +30,7 @@ } } -extern "C" { +unsafe extern "C" { #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] #[cfg_attr( any( @@ -82,7 +82,7 @@ pub fn errno() -> i32 { #[cfg(target_os = "rtems")] pub fn errno() -> i32 { - extern "C" { + unsafe extern "C" { #[thread_local] static _tls_errno: c_int; } @@ -92,7 +92,7 @@ pub fn errno() -> i32 { #[cfg(target_os = "dragonfly")] pub fn errno() -> i32 { - extern "C" { + unsafe extern "C" { #[thread_local] static errno: c_int; } @@ -103,7 +103,7 @@ pub fn errno() -> i32 { #[cfg(target_os = "dragonfly")] #[allow(dead_code)] pub fn set_errno(e: i32) { - extern "C" { + unsafe extern "C" { #[thread_local] static mut errno: c_int; } @@ -115,7 +115,7 @@ pub fn set_errno(e: i32) { /// Gets a detailed string description for the given error number. pub fn error_string(errno: i32) -> String { - extern "C" { + unsafe extern "C" { #[cfg_attr( all( any(target_os = "linux", target_os = "hurd", target_env = "newlib"), @@ -610,7 +610,7 @@ pub unsafe fn environ() -> *mut *const *const c_char { // Use the `environ` static which is part of POSIX. #[cfg(not(target_vendor = "apple"))] pub unsafe fn environ() -> *mut *const *const c_char { - extern "C" { + unsafe extern "C" { static mut environ: *const *const c_char; } &raw mut environ @@ -847,7 +847,7 @@ pub fn getppid() -> u32 { #[cfg(all(target_os = "linux", target_env = "gnu"))] pub fn glibc_version() -> Option<(usize, usize)> { - extern "C" { + unsafe extern "C" { fn gnu_get_libc_version() -> *const libc::c_char; } let version_cstr = unsafe { CStr::from_ptr(gnu_get_libc_version()) }; diff --git a/library/std/src/sys/pal/unix/process/zircon.rs b/library/std/src/sys/pal/unix/process/zircon.rs index 4035e2370a3c..7932bd26d76c 100644 --- a/library/std/src/sys/pal/unix/process/zircon.rs +++ b/library/std/src/sys/pal/unix/process/zircon.rs @@ -75,7 +75,7 @@ pub struct zx_info_process_t { pub reserved1: u32, } -extern "C" { +unsafe extern "C" { pub fn zx_job_default() -> zx_handle_t; pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t; @@ -115,7 +115,7 @@ pub struct fdio_spawn_action_t { pub reserved1: u64, } -extern "C" { +unsafe extern "C" { pub fn fdio_spawn_etc( job: zx_handle_t, flags: u32, diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 356669980c7d..479021af040a 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -23,7 +23,7 @@ mod zircon { type zx_status_t = i32; pub const ZX_PROP_NAME: u32 = 3; - extern "C" { + unsafe extern "C" { pub fn zx_object_set_property( handle: zx_handle_t, property: u32, @@ -230,7 +230,7 @@ pub fn set_name(name: &CStr) { #[cfg(target_os = "vxworks")] pub fn set_name(name: &CStr) { // FIXME(libc): adding real STATUS, ERROR type eventually. - extern "C" { + unsafe extern "C" { fn taskNameSet(task_id: libc::TASK_ID, task_name: *mut libc::c_char) -> libc::c_int; } @@ -506,7 +506,7 @@ pub fn available_parallelism() -> io::Result> { } else if #[cfg(target_os = "vxworks")] { // Note: there is also `vxCpuConfiguredGet`, closer to _SC_NPROCESSORS_CONF // expectations than the actual cores availability. - extern "C" { + unsafe extern "C" { fn vxCpuEnabledGet() -> libc::cpuset_t; } diff --git a/library/std/src/sys/pal/unix/thread_parking.rs b/library/std/src/sys/pal/unix/thread_parking.rs index 72dd2031479e..bef8b4fb3639 100644 --- a/library/std/src/sys/pal/unix/thread_parking.rs +++ b/library/std/src/sys/pal/unix/thread_parking.rs @@ -8,7 +8,7 @@ use crate::ptr; use crate::time::Duration; -extern "C" { +unsafe extern "C" { fn ___lwp_park60( clock_id: clockid_t, flags: c_int, diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index 35762f5a53b5..5a37598f4382 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -31,7 +31,7 @@ pub(crate) macro weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( let ref $name: ExternWeak $ret> = { - extern "C" { + unsafe extern "C" { #[linkage = "extern_weak"] static $name: Option $ret>; } diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs index 7779d2b97d7f..7705e7f6b880 100644 --- a/library/std/src/sys/pal/wasi/fs.rs +++ b/library/std/src/sys/pal/wasi/fs.rs @@ -787,7 +787,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { } } - extern "C" { + unsafe extern "C" { pub fn __wasilibc_find_relpath( path: *const libc::c_char, abs_prefix: *mut *const libc::c_char, diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs index f7701360f5a9..ba2b65a1f40d 100644 --- a/library/std/src/sys/pal/wasi/os.rs +++ b/library/std/src/sys/pal/wasi/os.rs @@ -16,7 +16,7 @@ mod libc { pub use libc::*; - extern "C" { + unsafe extern "C" { pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; pub fn chdir(dir: *const c_char) -> c_int; pub fn __wasilibc_get_environ() -> *mut *mut c_char; @@ -46,7 +46,7 @@ pub fn env_write_lock() -> impl Drop { } pub fn errno() -> i32 { - extern "C" { + unsafe extern "C" { #[thread_local] static errno: libc::c_int; } diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index f5e19f26bfe1..0ae023694106 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -35,7 +35,7 @@ pub struct pthread_attr_t { pub const _SC_NPROCESSORS_ONLN: ffi::c_int = 84; - extern "C" { + unsafe extern "C" { pub fn pthread_create( native: *mut pthread_t, attr: *const pthread_attr_t, diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 9ce3e912caf1..8dc61edb603f 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -115,7 +115,7 @@ pub struct MOUNT_POINT_REPARSE_BUFFER { link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated") )] #[cfg_attr(not(target_arch = "x86"), link(name = "bcryptprimitives", kind = "raw-dylib"))] -extern "system" { +unsafe extern "system" { pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; } @@ -164,7 +164,7 @@ pub fn GetTempPath2W(bufferlength: u32, buffer: PWSTR) -> u32 { not(target_arch = "x86"), link(name = "api-ms-win-core-synch-l1-2-0", kind = "raw-dylib") )] -extern "system" { +unsafe extern "system" { pub fn WaitOnAddress( address: *const c_void, compareaddress: *const c_void, diff --git a/library/std/src/sys/pal/windows/process/tests.rs b/library/std/src/sys/pal/windows/process/tests.rs index 9a1eaf42fd9a..90f1157d7c47 100644 --- a/library/std/src/sys/pal/windows/process/tests.rs +++ b/library/std/src/sys/pal/windows/process/tests.rs @@ -33,7 +33,7 @@ fn test_thread_handle() { assert!(p.is_ok()); let mut p = p.unwrap(); - extern "system" { + unsafe extern "system" { fn ResumeThread(_: BorrowedHandle<'_>) -> u32; } unsafe { diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs index b0ab01a6383d..307623c0425e 100644 --- a/library/std/src/sys/pal/xous/os.rs +++ b/library/std/src/sys/pal/xous/os.rs @@ -37,7 +37,7 @@ fn find(&self, _pc: usize) -> Option { #[cfg(not(test))] mod c_compat { use crate::os::xous::ffi::exit; - extern "C" { + unsafe extern "C" { fn main() -> u32; } diff --git a/library/std/src/sys/pal/zkvm/abi.rs b/library/std/src/sys/pal/zkvm/abi.rs index 53332d90e02c..d000574f6844 100644 --- a/library/std/src/sys/pal/zkvm/abi.rs +++ b/library/std/src/sys/pal/zkvm/abi.rs @@ -18,7 +18,7 @@ pub mod fileno { pub const JOURNAL: u32 = 3; } -extern "C" { +unsafe extern "C" { // Wrappers around syscalls provided by risc0-zkvm-platform: pub fn sys_halt(); pub fn sys_output(output_id: u32, output_value: u32); diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index 88a25caeff0d..cd2c7899f4bf 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -194,7 +194,7 @@ unsafe fn continue_unwind( } } // defined in libgcc - extern "C" { + unsafe extern "C" { fn __gnu_unwind_frame( exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, diff --git a/library/std/src/sys/random/arc4random.rs b/library/std/src/sys/random/arc4random.rs index 32467e9ebaa6..e1957bceb900 100644 --- a/library/std/src/sys/random/arc4random.rs +++ b/library/std/src/sys/random/arc4random.rs @@ -25,7 +25,7 @@ target_os = "vita", // See https://github.com/vitasdk/newlib/blob/b89e5bc183b516945f9ee07eef483ecb916e45ff/newlib/libc/include/stdlib.h#L74 ))] #[cfg_attr(target_os = "haiku", link(name = "bsd"))] -extern "C" { +unsafe extern "C" { fn arc4random_buf(buf: *mut core::ffi::c_void, nbytes: libc::size_t); } diff --git a/library/std/src/sys/random/espidf.rs b/library/std/src/sys/random/espidf.rs index fd52cb5559ce..6f48f7f1f295 100644 --- a/library/std/src/sys/random/espidf.rs +++ b/library/std/src/sys/random/espidf.rs @@ -1,6 +1,6 @@ use crate::ffi::c_void; -extern "C" { +unsafe extern "C" { fn esp_fill_random(buf: *mut c_void, len: usize); } diff --git a/library/std/src/sys/random/fuchsia.rs b/library/std/src/sys/random/fuchsia.rs index 77d72b3c5b78..269e0d9aeeb5 100644 --- a/library/std/src/sys/random/fuchsia.rs +++ b/library/std/src/sys/random/fuchsia.rs @@ -4,7 +4,7 @@ //! . #[link(name = "zircon")] -extern "C" { +unsafe extern "C" { fn zx_cprng_draw(buffer: *mut u8, len: usize); } diff --git a/library/std/src/sys/random/teeos.rs b/library/std/src/sys/random/teeos.rs index fd6b24e19e98..6ca59cc12c98 100644 --- a/library/std/src/sys/random/teeos.rs +++ b/library/std/src/sys/random/teeos.rs @@ -1,4 +1,4 @@ -extern "C" { +unsafe extern "C" { fn TEE_GenerateRandom(randomBuffer: *mut core::ffi::c_void, randomBufferLen: libc::size_t); } diff --git a/library/std/src/sys/sync/thread_parking/darwin.rs b/library/std/src/sys/sync/thread_parking/darwin.rs index 0553c5e19a91..a0d24a91e7c6 100644 --- a/library/std/src/sys/sync/thread_parking/darwin.rs +++ b/library/std/src/sys/sync/thread_parking/darwin.rs @@ -24,7 +24,7 @@ const DISPATCH_TIME_FOREVER: dispatch_time_t = !0; // Contained in libSystem.dylib, which is linked by default. -extern "C" { +unsafe extern "C" { fn dispatch_time(when: dispatch_time_t, delta: i64) -> dispatch_time_t; fn dispatch_semaphore_create(val: isize) -> dispatch_semaphore_t; fn dispatch_semaphore_wait(dsema: dispatch_semaphore_t, timeout: dispatch_time_t) -> isize; diff --git a/library/std/src/sys/thread_local/destructors/linux_like.rs b/library/std/src/sys/thread_local/destructors/linux_like.rs index f473dc4d79df..817941229eef 100644 --- a/library/std/src/sys/thread_local/destructors/linux_like.rs +++ b/library/std/src/sys/thread_local/destructors/linux_like.rs @@ -27,7 +27,7 @@ pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { #[allow(non_camel_case_types)] pub struct c_int(#[allow(dead_code)] pub core::ffi::c_int); - extern "C" { + unsafe extern "C" { #[linkage = "extern_weak"] static __dso_handle: *mut u8; #[linkage = "extern_weak"] diff --git a/library/std/src/sys/thread_local/guard/apple.rs b/library/std/src/sys/thread_local/guard/apple.rs index fa25b116622f..edcedf21e9ec 100644 --- a/library/std/src/sys/thread_local/guard/apple.rs +++ b/library/std/src/sys/thread_local/guard/apple.rs @@ -10,7 +10,7 @@ pub fn enable() { #[thread_local] static REGISTERED: Cell = Cell::new(false); - extern "C" { + unsafe extern "C" { fn _tlv_atexit(dtor: unsafe extern "C" fn(*mut u8), arg: *mut u8); } diff --git a/library/std/src/sys/thread_local/key/unix.rs b/library/std/src/sys/thread_local/key/unix.rs index b4b58b347063..93bd0d1f6685 100644 --- a/library/std/src/sys/thread_local/key/unix.rs +++ b/library/std/src/sys/thread_local/key/unix.rs @@ -8,7 +8,7 @@ mod libc { #[allow(non_camel_case_types)] pub type pthread_key_t = ffi::c_uint; - extern "C" { + unsafe extern "C" { pub fn pthread_key_create( key: *mut pthread_key_t, destructor: unsafe extern "C" fn(*mut ffi::c_void), diff --git a/library/std/src/sys/thread_local/key/xous.rs b/library/std/src/sys/thread_local/key/xous.rs index 2ab4bba7d8e9..6c5e6447d191 100644 --- a/library/std/src/sys/thread_local/key/xous.rs +++ b/library/std/src/sys/thread_local/key/xous.rs @@ -59,7 +59,7 @@ static DTORS: AtomicPtr = AtomicPtr::new(ptr::null_mut()); #[cfg(test)] -extern "Rust" { +unsafe extern "Rust" { #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"] static TLS_KEY_INDEX: AtomicUsize; diff --git a/library/std/tests/switch-stdout.rs b/library/std/tests/switch-stdout.rs index 42011a9b3da6..91fe0200f6ca 100644 --- a/library/std/tests/switch-stdout.rs +++ b/library/std/tests/switch-stdout.rs @@ -14,7 +14,7 @@ fn switch_stdout_to(file: OwnedFd) -> OwnedFd { use std::os::unix::prelude::*; - extern "C" { + unsafe extern "C" { fn dup(old: i32) -> i32; fn dup2(old: i32, new: i32) -> i32; } @@ -32,7 +32,7 @@ fn switch_stdout_to(file: OwnedFd) -> OwnedFd { fn switch_stdout_to(file: OwnedHandle) -> OwnedHandle { use std::os::windows::prelude::*; - extern "system" { + unsafe extern "system" { fn GetStdHandle(nStdHandle: u32) -> *mut u8; fn SetStdHandle(nStdHandle: u32, handle: *mut u8) -> i32; } diff --git a/library/test/src/term/win.rs b/library/test/src/term/win.rs index c77e6aac478b..62e5c43ea274 100644 --- a/library/test/src/term/win.rs +++ b/library/test/src/term/win.rs @@ -52,7 +52,7 @@ struct CONSOLE_SCREEN_BUFFER_INFO { #[allow(non_snake_case)] #[link(name = "kernel32")] -extern "system" { +unsafe extern "system" { fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL; fn GetStdHandle(which: DWORD) -> HANDLE; fn GetConsoleScreenBufferInfo(handle: HANDLE, info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL; diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index e4ba2bc1ed87..2650b273a4db 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -56,15 +56,15 @@ compile_error!("`llvm-libunwind` and `system-llvm-libunwind` cannot be enabled at the same time"); } else if #[cfg(feature = "llvm-libunwind")] { #[link(name = "unwind", kind = "static", modifiers = "-bundle")] - extern "C" {} + unsafe extern "C" {} } else if #[cfg(feature = "system-llvm-libunwind")] { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] - extern "C" {} + unsafe extern "C" {} } else { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] - extern "C" {} + unsafe extern "C" {} } } @@ -76,11 +76,11 @@ compile_error!("`llvm-libunwind` and `system-llvm-libunwind` cannot be enabled at the same time"); } else if #[cfg(feature = "llvm-libunwind")] { #[link(name = "unwind", kind = "static", modifiers = "-bundle")] - extern "C" {} + unsafe extern "C" {} } else { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] - extern "C" {} + unsafe extern "C" {} } } @@ -91,14 +91,14 @@ } else { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] - extern "C" {} + unsafe extern "C" {} } } // Android's unwinding library depends on dl_iterate_phdr in `libdl`. #[cfg(target_os = "android")] #[link(name = "dl", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "dl", cfg(not(target_feature = "crt-static")))] -extern "C" {} +unsafe extern "C" {} // When building with crt-static, we get `gcc_eh` from the `libc` crate, since // glibc needs it, and needs it listed later on the linker command line. We @@ -110,7 +110,7 @@ not(feature = "system-llvm-libunwind") ))] #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] -extern "C" {} +unsafe extern "C" {} #[cfg(all( target_os = "linux", @@ -119,67 +119,67 @@ feature = "system-llvm-libunwind" ))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] -extern "C" {} +unsafe extern "C" {} #[cfg(target_os = "redox")] #[link(name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] -extern "C" {} +unsafe extern "C" {} #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] #[link(name = "unwind", kind = "static", modifiers = "-bundle")] -extern "C" {} +unsafe extern "C" {} #[cfg(target_os = "netbsd")] #[link(name = "gcc_s")] -extern "C" {} +unsafe extern "C" {} #[cfg(target_os = "freebsd")] #[link(name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] -extern "C" {} +unsafe extern "C" {} #[cfg(all(target_os = "openbsd", target_arch = "sparc64"))] #[link(name = "gcc")] -extern "C" {} +unsafe extern "C" {} #[cfg(all(target_os = "openbsd", not(target_arch = "sparc64")))] #[link(name = "c++abi")] -extern "C" {} +unsafe extern "C" {} #[cfg(any(target_os = "solaris", target_os = "illumos"))] #[link(name = "gcc_s")] -extern "C" {} +unsafe extern "C" {} #[cfg(target_os = "dragonfly")] #[link(name = "gcc_pic")] -extern "C" {} +unsafe extern "C" {} #[cfg(target_os = "haiku")] #[link(name = "gcc_s")] -extern "C" {} +unsafe extern "C" {} #[cfg(target_os = "aix")] #[link(name = "unwind")] -extern "C" {} +unsafe extern "C" {} #[cfg(target_os = "nto")] cfg_if::cfg_if! { if #[cfg(target_env = "nto70")] { #[link(name = "gcc")] - extern "C" {} + unsafe extern "C" {} } else { #[link(name = "gcc_s")] - extern "C" {} + unsafe extern "C" {} } } #[cfg(target_os = "hurd")] #[link(name = "gcc_s")] -extern "C" {} +unsafe extern "C" {} #[cfg(all(target_os = "windows", target_env = "gnu", target_abi = "llvm"))] #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] -extern "C" {} +unsafe extern "C" {} diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 1fa9e480166b..62165f8a2003 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -108,10 +108,10 @@ pub enum _Unwind_Context {} ), link(name = "unwind", kind = "static", modifiers = "-bundle") )] -extern "C-unwind" { +unsafe extern "C-unwind" { pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; } -extern "C" { +unsafe extern "C" { pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception); pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void; pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr; @@ -140,7 +140,7 @@ pub enum _Unwind_Action { all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] - extern "C" { + unsafe extern "C" { pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word; pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word); pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word; @@ -198,7 +198,7 @@ enum _Unwind_VRS_DataRepresentation { all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] - extern "C" { + unsafe extern "C" { fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context, regclass: _Unwind_VRS_RegClass, regno: _Unwind_Word, @@ -261,7 +261,7 @@ pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void { if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"))] { // 32-bit ARM Apple (except for watchOS armv7k specifically) uses SjLj and // does not provide _Unwind_Backtrace() - extern "C-unwind" { + unsafe extern "C-unwind" { pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; } @@ -271,14 +271,14 @@ pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void { all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] - extern "C-unwind" { + unsafe extern "C-unwind" { pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; } #[cfg_attr( all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] - extern "C" { + unsafe extern "C" { pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, trace_argument: *mut c_void) -> _Unwind_Reason_Code; @@ -302,7 +302,7 @@ pub enum DISPATCHER_CONTEXT {} context: *mut _Unwind_Context) -> _Unwind_Reason_Code; - extern "C" { + unsafe extern "C" { pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD, establisherFrame: LPVOID, contextRecord: *mut CONTEXT, diff --git a/library/windows_targets/src/lib.rs b/library/windows_targets/src/lib.rs index 395cd6a4bab5..e89bde8b1abf 100644 --- a/library/windows_targets/src/lib.rs +++ b/library/windows_targets/src/lib.rs @@ -39,4 +39,4 @@ #[link(name = "userenv")] #[link(name = "ws2_32")] #[link(name = "dbghelp")] // required for backtrace-rs symbolization -extern "C" {} +unsafe extern "C" {} From 4312d7b541cda5444c29b8bec12b72b46e33caff Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 7 Feb 2025 18:35:46 +0000 Subject: [PATCH 14/19] Fix pattern matching mode changes and unsafe_op_in_unsafe_fn --- library/alloc/src/collections/btree/merge_iter.rs | 2 +- library/std/src/sync/mpmc/mod.rs | 6 +++--- library/test/src/lib.rs | 8 ++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/collections/btree/merge_iter.rs b/library/alloc/src/collections/btree/merge_iter.rs index c5b93d30a118..5077062e25d8 100644 --- a/library/alloc/src/collections/btree/merge_iter.rs +++ b/library/alloc/src/collections/btree/merge_iter.rs @@ -74,7 +74,7 @@ pub(super) fn nexts Ordering>( b_next = self.b.next(); } } - if let (Some(ref a1), Some(ref b1)) = (&a_next, &b_next) { + if let (Some(a1), Some(b1)) = (&a_next, &b_next) { match cmp(a1, b1) { Ordering::Less => self.peeked = b_next.take().map(Peeked::B), Ordering::Greater => self.peeked = a_next.take().map(Peeked::A), diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index 00966ee3ecff..8caa2dcfad99 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -616,9 +616,9 @@ pub fn capacity(&self) -> Option { #[unstable(feature = "mpmc_channel", issue = "126840")] pub fn same_channel(&self, other: &Sender) -> bool { match (&self.flavor, &other.flavor) { - (SenderFlavor::Array(ref a), SenderFlavor::Array(ref b)) => a == b, - (SenderFlavor::List(ref a), SenderFlavor::List(ref b)) => a == b, - (SenderFlavor::Zero(ref a), SenderFlavor::Zero(ref b)) => a == b, + (SenderFlavor::Array(a), SenderFlavor::Array(b)) => a == b, + (SenderFlavor::List(a), SenderFlavor::List(b)) => a == b, + (SenderFlavor::Zero(a), SenderFlavor::Zero(b)) => a == b, _ => false, } } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 54f7e4ae79f1..e523d3028661 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -184,12 +184,16 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) { // If we're being run in SpawnedSecondary mode, run the test here. run_test // will then exit the process. if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) { - env::remove_var(SECONDARY_TEST_INVOKER_VAR); + unsafe { + env::remove_var(SECONDARY_TEST_INVOKER_VAR); + } // Convert benchmarks to tests if we're not benchmarking. let mut tests = tests.iter().map(make_owned_test).collect::>(); if env::var(SECONDARY_TEST_BENCH_BENCHMARKS_VAR).is_ok() { - env::remove_var(SECONDARY_TEST_BENCH_BENCHMARKS_VAR); + unsafe { + env::remove_var(SECONDARY_TEST_BENCH_BENCHMARKS_VAR); + } } else { tests = convert_benchmarks_to_tests(tests); }; From 9a73f5a72dfe36b12338c1041a3cd56a98585d17 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 9 Feb 2025 12:00:23 -0800 Subject: [PATCH 15/19] Git blame ignore recent formatting commit --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 8612a40923a8..d2a017bd2a02 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -29,3 +29,5 @@ ec2cc761bc7067712ecc7734502f703fe3b024c8 99cb0c6bc399fb94a0ddde7e9b38e9c00d523bad # reformat with rustfmt edition 2024 c682aa162b0d41e21cc6748f4fecfe01efb69d1f +# reformat with updated edition 2024 +1fcae03369abb4c2cc180cd5a49e1f4440a81300 From b01c7f6b9c6ac837511e7bb75c15e9cd537fc974 Mon Sep 17 00:00:00 2001 From: Alisa Sireneva Date: Fri, 31 Jan 2025 14:16:19 +0300 Subject: [PATCH 16/19] fix(libtest): Enable Instant on Emscripten targets `Instant::now()` works correctly on Emscripten since https://github.com/rust-lang/libc/pull/3962. All wasm-family targets with OS support can now handle instants. --- library/test/src/console.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 024ef48fc510..8f29f1dada52 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -314,9 +314,10 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu let mut st = ConsoleTestState::new(opts)?; // Prevent the usage of `Instant` in some cases: - // - It's currently not supported for wasm targets. + // - It's currently not supported for wasm targets without Emscripten nor WASI. + // - It's currently not supported for zkvm targets. let is_instant_unsupported = - (cfg!(target_family = "wasm") && !cfg!(target_os = "wasi")) || cfg!(target_os = "zkvm"); + (cfg!(target_family = "wasm") && cfg!(target_os = "unknown")) || cfg!(target_os = "zkvm"); let start_time = (!is_instant_unsupported).then(Instant::now); run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?; From df94005f1d95cdced37c2d237335edfa3e3f20cf Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Feb 2025 16:21:14 -0500 Subject: [PATCH 17/19] Don't apply editorconfig to llvm They use 2 spaces by default, not 4. --- .editorconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.editorconfig b/.editorconfig index eadd72e49937..ef8ed24c52a5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,6 +9,8 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +[!src/llvm-project] indent_style = space indent_size = 4 From 2f3c943f425d78f93d3f3c40121b68be1bf7403b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Feb 2025 08:08:32 +0100 Subject: [PATCH 18/19] ignore win_delete_self test in Miri --- library/std/tests/win_delete_self.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/tests/win_delete_self.rs b/library/std/tests/win_delete_self.rs index 1c3ce4d710c3..ce505de69a22 100644 --- a/library/std/tests/win_delete_self.rs +++ b/library/std/tests/win_delete_self.rs @@ -2,6 +2,7 @@ /// Attempting to delete a running binary should return an error on Windows. #[test] +#[cfg_attr(miri, ignore)] // `remove_file` does not work in Miri on Windows fn win_delete_self() { let path = std::env::current_exe().unwrap(); assert!(std::fs::remove_file(path).is_err()); From 09f57b2e5cd1cdb631ad06f7b5d555ce22141a60 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 7 Feb 2025 19:46:07 +0000 Subject: [PATCH 19/19] Bump `cc` to v1.2.13 for the compiler workspace --- Cargo.lock | 4 ++-- compiler/rustc_codegen_ssa/Cargo.toml | 2 +- compiler/rustc_llvm/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89eb514917d6..1b98ea5e5568 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -420,9 +420,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.2.7" +version = "1.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" dependencies = [ "shlex", ] diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index b22357acdc26..2afc1efc1b34 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -11,7 +11,7 @@ bitflags = "2.4.1" bstr = "1.11.3" # Pinned so `cargo update` bumps don't cause breakage. Please also update the # `cc` in `rustc_llvm` if you update the `cc` here. -cc = "=1.2.7" +cc = "=1.2.13" either = "1.5.0" itertools = "0.12" pathdiff = "0.2.0" diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 7c402310436d..2168a0df9ec8 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -12,5 +12,5 @@ libc = "0.2.73" # tidy-alphabetical-start # Pinned so `cargo update` bumps don't cause breakage. Please also update the # pinned `cc` in `rustc_codegen_ssa` if you update `cc` here. -cc = "=1.2.7" +cc = "=1.2.13" # tidy-alphabetical-end