diff --git a/.editorconfig b/.editorconfig index eadd72e499373..ef8ed24c52a50 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 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 8612a40923a8d..d2a017bd2a023 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 diff --git a/Cargo.lock b/Cargo.lock index fc4c7c9888fa6..2ee2c52b32ade 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", ] @@ -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" @@ -4173,7 +4154,6 @@ version = "0.0.0" dependencies = [ "bitflags", "either", - "field-offset", "gsgdt", "polonius-engine", "rustc-rayon-core", @@ -4421,7 +4401,6 @@ dependencies = [ name = "rustc_query_impl" version = "0.0.0" dependencies = [ - "field-offset", "measureme", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 460a466461571..c53ea6d466610 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 @@ use rustc_codegen_ssa::traits::{ 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; @@ -53,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); let mut covfun = CovfunRecord { mangled_function_name: tcx.symbol_name(instance).name, @@ -75,26 +76,14 @@ 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 { - // 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 // 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 { @@ -136,11 +125,16 @@ 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. - let kind = kind.map_terms(|term| if is_zero_term(term) { CovTerm::Zero } else { term }); + // If this function is unused, replace all counters with zero. + let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter { + 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) + }; // 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 +148,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_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 021108cd51caf..ea7f581a3cb51 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -160,21 +160,12 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { 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. - 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 - ); - + CoverageKind::VirtualCounter { bcb } + if let Some(&id) = ids_info.phys_counter_for_node.get(&bcb) => + { 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={:?})", @@ -182,10 +173,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { ); 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 14346795fda62..f0d04b2b64476 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_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index b22357acdc268..2afc1efc1b34d 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 7c402310436df..2168a0df9ec87 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 diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 2c34df6ea61a3..de722e62043cd 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/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 46534697e1d60..8c6b11a681ef6 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -2,8 +2,8 @@ use std::fmt::{self, Debug, Formatter}; -use rustc_index::IndexVec; -use rustc_index::bit_set::DenseBitSet; +use rustc_data_structures::fx::FxIndexMap; +use rustc_index::{Idx, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::Span; @@ -103,23 +103,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 +127,7 @@ impl Debug for CoverageKind { 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) } @@ -179,34 +167,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 +195,15 @@ 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, + + /// 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 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, @@ -292,40 +270,55 @@ 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 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. +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. /// - /// 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) + /// 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; } +} - /// 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), - } - } +/// 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 3007b78749683..11ebbbe807db7 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 d94efe2d7d6f8..478ac19d199bd 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -614,9 +614,16 @@ rustc_queries! { 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_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 6c019b427dbd1..690b8128b1aef 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_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index adb99a75a9e47..6f9984d5d0ac3 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -2,7 +2,6 @@ use std::cmp::Ordering; 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 rustc_middle::mir::coverage::{CounterId, CovTerm, Expression, ExpressionId, 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,31 +77,33 @@ 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, + 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 @@ -116,7 +121,7 @@ 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); } @@ -129,15 +134,15 @@ 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, - next_counter_id: CounterId, + pub(crate) phys_counter_for_node: FxIndexMap, + pub(crate) 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. - 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 +193,6 @@ impl CoverageCounters { 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,34 +201,4 @@ impl CoverageCounters { ); 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. - 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 9d80b3af42d8b..91ed54b8b59f5 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 @@ use crate::coverage::counters::union_find::UnionFind; #[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/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 392b54c8d819b..6d84248ddfbdd 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::dominators::Dominators; 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 @@ impl graph::Predecessors for CoverageGraph { } } -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/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index 8d0d92dc36772..d83c0d40a7e54 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 @@ const MCDC_MAX_BITMAP_SIZE: usize = i32::MAX as usize; #[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 15487d05a301d..e195681bc92c7 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::Span; 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,28 +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, &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; } - 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 @@ -116,29 +109,25 @@ 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(), + + node_flow_data, + priority_list, + mappings, + + 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: _, code_mappings, branch_pairs, mcdc_bitmap_bits: _, @@ -150,23 +139,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 +160,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 +181,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, @@ -227,41 +205,11 @@ fn create_mappings( 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 a849ed4c3e27c..cd89fbe772d4c 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,10 +1,7 @@ use rustc_data_structures::captures::Captures; 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, -}; +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; @@ -12,6 +9,9 @@ use rustc_span::def_id::LocalDefId; 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,39 +89,57 @@ 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(CovTerm::Expression(id)) = mapping.kind { - 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 }) + // 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, &bcbs_seen); + + let CoverageCounters { + phys_counter_for_node, next_counter_id, node_counters, expressions, .. + } = coverage_counters; + + Some(CoverageIdsInfo { + num_counters: next_counter_id.as_u32(), + phys_counter_for_node, + term_for_bcb: node_counters, + expressions, + }) } fn all_coverage_in_mir_body<'a, 'tcx>( @@ -139,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( - fn_cov_info: &FunctionCoverageInfo, - 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(fn_cov_info.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() { - 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), - } -} 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 26ce743be3613..73b68d7155cfb 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/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 6e8fd32610bc1..8b0cc9d726b80 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 bbc83cca99d86..73c205fdb17d1 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 @@ where 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 @@ where 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 46ec538735a65..e95c186f6b680 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -605,8 +605,8 @@ macro_rules! define_queries { 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/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index e9b7f9856677c..e686a02f29b0c 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -10,7 +10,7 @@ use core::hint; #[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/collections/btree/merge_iter.rs b/library/alloc/src/collections/btree/merge_iter.rs index c5b93d30a1185..5077062e25d87 100644 --- a/library/alloc/src/collections/btree/merge_iter.rs +++ b/library/alloc/src/collections/btree/merge_iter.rs @@ -74,7 +74,7 @@ impl MergeIterInner { 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/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 07c75677d0532..fd93045a5ac4d 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -397,7 +397,7 @@ impl 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/alloc/src/rc.rs b/library/alloc/src/rc.rs index 6d82f514aa683..09206c2f8b290 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1462,18 +1462,18 @@ impl Rc { /// 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] diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 7180593edf0d0..75338e492ee0a 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -731,7 +731,7 @@ const unsafe fn strlen(ptr: *const c_char) -> usize { 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 50968c57adc62..9bae5fd466a18 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -90,4 +90,4 @@ impl fmt::Debug for c_void { 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 3b249c835f237..6c9c6d0edc235 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -4855,7 +4855,7 @@ pub const unsafe fn copysignf128(_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/iter/sources/once_with.rs b/library/core/src/iter/sources/once_with.rs index 8b31ab2ff90c0..c9698b4fd431b 100644 --- a/library/core/src/iter/sources/once_with.rs +++ b/library/core/src/iter/sources/once_with.rs @@ -58,8 +58,8 @@ use crate::iter::{FusedIterator, TrustedLen}; /// ``` #[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 @@ impl A> DoubleEndedIterator for OnceWith { #[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() } } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index b97f19e1baa93..d36e677d21a18 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 e93b5658e2436..9eee29d485f41 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 1b5c5fc82a69d..9cb94ca3b0ff0 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -648,7 +648,7 @@ fn offset_of_dst() { 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 3d82522481316..6041923117c2a 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 345bec345d128..0c9f9b338b0c1 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 dc2b42bb90ae8..7718d68aef8e5 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -54,7 +54,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 { ))] { unsafe fn abort() -> ! { // call std::sys::abort_internal - extern "C" { + unsafe extern "C" { pub fn __rust_abort() -> !; } __rust_abort(); @@ -87,7 +87,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 { } } 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 a6a02abf10976..11150eafd0b80 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 86906b46d66ba..4140b004ad13e 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. // @@ -119,7 +119,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 7e08ad66577f1..9719c13341520 100644 --- a/library/panic_unwind/src/hermit.rs +++ b/library/panic_unwind/src/hermit.rs @@ -6,14 +6,14 @@ use alloc::boxed::Box; 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 d682816419565..45e2a466b4df6 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -75,7 +75,7 @@ cfg_if::cfg_if! { } } -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 a86f0e91eefcc..ec48b1105ab47 100644 --- a/library/panic_unwind/src/miri.rs +++ b/library/panic_unwind/src/miri.rs @@ -7,7 +7,7 @@ use core::any::Any; // 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 21bfe74e1a259..c8dfddf821e68 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 @@ static mut CATCHABLE_TYPE: _CatchableType = _CatchableType { 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 d3ff5c14aa4a8..67b09599d9d2b 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] = []; @@ -76,7 +76,7 @@ pub mod eh_frames { } // 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); } @@ -101,10 +101,10 @@ pub mod eh_frames { // 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 81acfbed4477d..a6f7d103356bf 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/alloc.rs b/library/std/src/alloc.rs index 5d51d6a0c78a8..3936ed057e6e2 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 8e50bf11dd082..b47b41d4bc5b7 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -54,11 +54,11 @@ pub static EMPTY_PANIC: fn(&'static str) -> ! = // 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/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index 00966ee3ecffd..8caa2dcfad99c 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -616,9 +616,9 @@ impl Sender { #[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/std/src/sys/alloc/xous.rs b/library/std/src/sys/alloc/xous.rs index 321d30e0b11b2..9d22e16fdf2f0 100644 --- a/library/std/src/sys/alloc/xous.rs +++ b/library/std/src/sys/alloc/xous.rs @@ -8,7 +8,7 @@ use crate::alloc::{GlobalAlloc, Layout, System}; 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 ee36127cfdf1e..e3f41f4fdbbb6 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 3d555ad5050c2..a746b853cbdc1 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 extern "C" fn runtime_entry( 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 5eb14bb7e534b..49b5251fc0eb6 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 18e6d5b3fa24d..e6ce15bed3cfd 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 d8836452e7555..f52acc4150972 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 c06b97ee3674a..67af062b0fffe 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 super::usercalls::alloc::UserRef; 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 02dff0ad29fc3..a4f5e4a0936f4 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 2b23e368cc31a..9b37e2baf3642 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 @@ use fortanix_sgx_abi::Tcs; /// 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 34fc2f20d2214..7131797003bf0 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 943b771498f8f..28fbbc3c51816 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 @@ use crate::ptr::NonNull; #[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 6864a3e7745b9..7f2b1f83e8561 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 const DT_WHT: c_uchar = 14; 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 4d09705721748..819f93f407423 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 3c9e3f9ffb95d..80802dd42e248 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 57c28aed3b293..e3b2e0aa50f4a 100644 --- a/library/std/src/sys/pal/solid/os.rs +++ b/library/std/src/sys/pal/solid/os.rs @@ -129,7 +129,7 @@ impl Iterator for Env { /// 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 15c65240ddd2a..c779c5f3ed89c 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 8438a61e90feb..1c87a79803c0d 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/pal/unix/args.rs @@ -147,7 +147,7 @@ mod imp { /// 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, @@ -204,7 +204,7 @@ mod imp { } 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 0fc765dc87a5d..d4551dd6a38bb 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 027df6c5691c6..c0b56d8d2b28a 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -373,24 +373,24 @@ cfg_if::cfg_if! { 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 @@ cfg_if::cfg_if! { #[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 b83772e34c173..04199c563303f 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -30,7 +30,7 @@ cfg_if::cfg_if! { } } -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 4035e2370a3c6..7932bd26d76c3 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 356669980c7d9..479021af040a7 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 @@ impl Thread { #[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 72dd2031479ee..bef8b4fb36391 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::ffi::{c_int, c_void}; 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 35762f5a53b5b..5a37598f43827 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -31,7 +31,7 @@ use crate::{mem, ptr}; 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 7779d2b97d7f9..7705e7f6b8806 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 f7701360f5a9c..ba2b65a1f40dc 100644 --- a/library/std/src/sys/pal/wasi/os.rs +++ b/library/std/src/sys/pal/wasi/os.rs @@ -16,7 +16,7 @@ use crate::{fmt, io, str, vec}; 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 @@ cfg_if::cfg_if! { } 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 f5e19f26bfe17..0ae0236941061 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -35,7 +35,7 @@ cfg_if::cfg_if! { 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 9ce3e912caf1b..8dc61edb603f4 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -115,7 +115,7 @@ if #[cfg(not(target_vendor = "uwp"))] { 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 @@ compat_fn_with_fallback! { 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/compat.rs b/library/std/src/sys/pal/windows/compat.rs index 42999da166451..2b9838437e9c1 100644 --- a/library/std/src/sys/pal/windows/compat.rs +++ b/library/std/src/sys/pal/windows/compat.rs @@ -39,7 +39,7 @@ use crate::sys::c; // 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/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index bdb55643bb101..b786c79004f69 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 @@ impl fmt::Debug for ReadDir { 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 @@ impl Iterator for ReadDir { 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 } => { @@ -1194,7 +1194,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), }) @@ -1212,11 +1212,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. diff --git a/library/std/src/sys/pal/windows/process/tests.rs b/library/std/src/sys/pal/windows/process/tests.rs index 9a1eaf42fd9a8..90f1157d7c47a 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 b0ab01a6383d2..307623c0425ed 100644 --- a/library/std/src/sys/pal/xous/os.rs +++ b/library/std/src/sys/pal/xous/os.rs @@ -37,7 +37,7 @@ mod eh_unwinding { #[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 53332d90e02c0..d000574f6844d 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 88a25caeff0df..cd2c7899f4bf1 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -194,7 +194,7 @@ cfg_if::cfg_if! { } } // 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 32467e9ebaa64..e1957bceb9002 100644 --- a/library/std/src/sys/random/arc4random.rs +++ b/library/std/src/sys/random/arc4random.rs @@ -25,7 +25,7 @@ use libc::arc4random_buf; 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 fd52cb5559ce5..6f48f7f1f2952 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 77d72b3c5b784..269e0d9aeeb57 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 fd6b24e19e982..6ca59cc12c98f 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 0553c5e19a91f..a0d24a91e7c69 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_NOW: dispatch_time_t = 0; 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 f473dc4d79df5..817941229eefe 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 fa25b116622fc..edcedf21e9ec6 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/guard/windows.rs b/library/std/src/sys/thread_local/guard/windows.rs index 1752b0e1208af..b15a0d7c0bdfb 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; diff --git a/library/std/src/sys/thread_local/key/unix.rs b/library/std/src/sys/thread_local/key/unix.rs index b4b58b3470631..93bd0d1f66850 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 2ab4bba7d8e98..6c5e6447d191e 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 TLS_KEY_INDEX: AtomicUsize = AtomicUsize::new(1); 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 42011a9b3da62..91fe0200f6cae 100644 --- a/library/std/tests/switch-stdout.rs +++ b/library/std/tests/switch-stdout.rs @@ -14,7 +14,7 @@ use std::os::windows::io::OwnedHandle; 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/std/tests/win_delete_self.rs b/library/std/tests/win_delete_self.rs index 1c3ce4d710c38..ce505de69a22d 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()); diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 024ef48fc5104..8f29f1dada528 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))?; diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 54f7e4ae79f18..e523d30286619 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); }; diff --git a/library/test/src/term/win.rs b/library/test/src/term/win.rs index c77e6aac478bc..62e5c43ea2745 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 e4ba2bc1ed874..2650b273a4dbe 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -56,15 +56,15 @@ cfg_if::cfg_if! { 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 @@ cfg_if::cfg_if! { 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 @@ cfg_if::cfg_if! { } 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 @@ extern "C" {} 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 @@ extern "C" {} 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 1fa9e480166b7..62165f8a20039 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -108,10 +108,10 @@ pub type _Unwind_Exception_Cleanup_Fn = ), 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 @@ if #[cfg(any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "a 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 @@ if #[cfg(any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "a 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 @@ cfg_if::cfg_if! { 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 @@ if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = 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 @@ if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), targ 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 395cd6a4bab55..e89bde8b1abf4 100644 --- a/library/windows_targets/src/lib.rs +++ b/library/windows_targets/src/lib.rs @@ -39,4 +39,4 @@ pub macro link { #[link(name = "userenv")] #[link(name = "ws2_32")] #[link(name = "dbghelp")] // required for backtrace-rs symbolization -extern "C" {} +unsafe extern "C" {} diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 825e5452f0e6a..b0181410be124 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1648,16 +1648,17 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // 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 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // 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 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } 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()); diff --git a/src/ci/scripts/free-disk-space.sh b/src/ci/scripts/free-disk-space.sh index 8850e168145bd..32d55806b5649 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-.*' diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 00821fc9f9db2..cde4f7a665cbf 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 6e5ced17c2084..cfe51b5655f82 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -192,7 +192,7 @@ fn parse_cfg_name_directive<'a>( 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 023658a3dd4c6..522d340b678f9 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 @@ impl ConfigBuilder { 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 @@ impl ConfigBuilder { "--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", @@ -388,7 +396,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 27a046ba5bc4a..d0a83cab9cd99 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 @@ pub fn parse_config(args: Vec) -> Config { 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 @@ pub fn parse_config(args: Vec) -> Config { 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 7ef16e4a9667b..16c46fc13390f 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -239,30 +239,6 @@ impl TestCx<'_> { } } - // `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 @@ impl TestCx<'_> { // 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 @@ impl TestCx<'_> { // 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 = { diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index faa0db27b2b05..5478ff4a6c6a9 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -285,7 +285,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", - "field-offset", "flate2", "fluent-bundle", "fluent-langneg", @@ -327,7 +326,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "measureme", "memchr", "memmap2", - "memoffset", "miniz_oxide", "nix", "nu-ansi-term", @@ -367,14 +365,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "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", diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map index 397eaa17caf6d..35568a98af444 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 2b5399f33bbd3..ba30627844937 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 374811dba9efa..6d6034928c9a5 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 3e2ca2bc992e5..49cdc514fedbb 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 efb9d43bf5bea..c8f75cddcb5b9 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 912141b6d5f36..640d5f15be0ee 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 9cb7e6a6cff2e..6c389a2431727 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 2d2d59bf013ec..77a8ffb835817 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 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 138586300ce66..e9f48a85f9cf1 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -27,18 +27,15 @@ } + 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(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); ++ 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 a91d88984a8a7..cbef6de917dfa 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -5,10 +5,10 @@ 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); ++ 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 d7ea442518ebe..b166d79a412ce 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -8,20 +8,19 @@ 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(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); ++ 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 c49786f961511..48647402d0fe7 100644 --- a/tests/mir-opt/coverage/instrument_coverage.rs +++ b/tests/mir-opt/coverage/instrument_coverage.rs @@ -8,9 +8,9 @@ // 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 +// CHECK: Coverage::VirtualCounter fn main() { loop { if bar() { @@ -22,9 +22,9 @@ 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 +// 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 2c7ec6e85eb0a..855f806aae10b 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -8,15 +8,14 @@ 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(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); + 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 c08265eb0e953..df1f1e8bc5048 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -8,15 +8,14 @@ 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(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); ++ 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 acc544a28af65..e8af4d6174f43 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