Skip to content

Commit

Permalink
Auto merge of #134516 - matthiaskrgr:rollup-aqwxii0, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #134463 (compiletest: don't register predefined `MSVC`/`NONMSVC` FileCheck prefixes)
 - #134487 (Add reference annotations for the `coverage` attribute)
 - #134497 (coverage: Store coverage source regions as `Span` until codegen (take 2))
 - #134502 (Update std libc version to 0.2.169)
 - #134506 (Remove a duplicated check that doesn't do anything anymore.)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Dec 19, 2024
2 parents 3bf62cc + 4f053b1 commit bfa5eb1
Show file tree
Hide file tree
Showing 68 changed files with 531 additions and 488 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2012,9 +2012,9 @@ checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401"

[[package]]
name = "libc"
version = "0.2.168"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"

[[package]]
name = "libdbus-sys"
Expand Down
36 changes: 10 additions & 26 deletions compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion};

use crate::coverageinfo::mapgen::LocalFileId;
use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId};

/// Must match the layout of `LLVMRustCounterKind`.
#[derive(Copy, Clone, Debug)]
Expand Down Expand Up @@ -126,30 +124,16 @@ pub(crate) struct CoverageSpan {
/// Local index into the function's local-to-global file ID table.
/// The value at that index is itself an index into the coverage filename
/// table in the CGU's `__llvm_covmap` section.
file_id: u32,
pub(crate) file_id: u32,

/// 1-based starting line of the source code span.
start_line: u32,
pub(crate) start_line: u32,
/// 1-based starting column of the source code span.
start_col: u32,
pub(crate) start_col: u32,
/// 1-based ending line of the source code span.
end_line: u32,
pub(crate) end_line: u32,
/// 1-based ending column of the source code span. High bit must be unset.
end_col: u32,
}

impl CoverageSpan {
pub(crate) fn from_source_region(
local_file_id: LocalFileId,
code_region: &SourceRegion,
) -> Self {
let file_id = local_file_id.as_u32();
let &SourceRegion { start_line, start_col, end_line, end_col } = code_region;
// Internally, LLVM uses the high bit of `end_col` to distinguish between
// code regions and gap regions, so it can't be used by the column number.
assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}");
Self { file_id, start_line, start_col, end_line, end_col }
}
pub(crate) end_col: u32,
}

/// Holds tables of the various region types in one struct.
Expand Down Expand Up @@ -184,15 +168,15 @@ impl Regions {
#[derive(Clone, Debug)]
#[repr(C)]
pub(crate) struct CodeRegion {
pub(crate) span: CoverageSpan,
pub(crate) cov_span: CoverageSpan,
pub(crate) counter: Counter,
}

/// Must match the layout of `LLVMRustCoverageBranchRegion`.
#[derive(Clone, Debug)]
#[repr(C)]
pub(crate) struct BranchRegion {
pub(crate) span: CoverageSpan,
pub(crate) cov_span: CoverageSpan,
pub(crate) true_counter: Counter,
pub(crate) false_counter: Counter,
}
Expand All @@ -201,7 +185,7 @@ pub(crate) struct BranchRegion {
#[derive(Clone, Debug)]
#[repr(C)]
pub(crate) struct MCDCBranchRegion {
pub(crate) span: CoverageSpan,
pub(crate) cov_span: CoverageSpan,
pub(crate) true_counter: Counter,
pub(crate) false_counter: Counter,
pub(crate) mcdc_branch_params: mcdc::BranchParameters,
Expand All @@ -211,6 +195,6 @@ pub(crate) struct MCDCBranchRegion {
#[derive(Clone, Debug)]
#[repr(C)]
pub(crate) struct MCDCDecisionRegion {
pub(crate) span: CoverageSpan,
pub(crate) cov_span: CoverageSpan,
pub(crate) mcdc_decision_params: mcdc::DecisionParameters,
}
5 changes: 2 additions & 3 deletions compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ pub(crate) fn create_pgo_func_name_var<'ll>(
}
}

pub(crate) fn write_filenames_to_buffer<'a>(
filenames: impl IntoIterator<Item = &'a str>,
) -> Vec<u8> {
pub(crate) fn write_filenames_to_buffer(filenames: &[impl AsRef<str>]) -> Vec<u8> {
let (pointers, lengths) = filenames
.into_iter()
.map(AsRef::as_ref)
.map(|s: &str| (s.as_c_char_ptr(), s.len()))
.unzip::<_, _, Vec<_>, Vec<_>>();

Expand Down
60 changes: 30 additions & 30 deletions compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
use std::iter;
use std::sync::Arc;

use itertools::Itertools;
use rustc_abi::Align;
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::RemapFileNameExt;
use rustc_session::config::RemapPathScopeComponents;
use rustc_span::def_id::DefIdSet;
use rustc_span::{Span, Symbol};
use rustc_span::{SourceFile, StableSourceFileId};
use tracing::debug;

use crate::common::CodegenCx;
Expand All @@ -22,6 +22,7 @@ use crate::coverageinfo::mapgen::covfun::prepare_covfun_record;
use crate::llvm;

mod covfun;
mod spans;

/// Generates and exports the coverage map, which is embedded in special
/// linker sections in the final binary.
Expand Down Expand Up @@ -131,45 +132,51 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
generate_covmap_record(cx, covmap_version, &filenames_buffer);
}

/// Maps "global" (per-CGU) file ID numbers to their underlying filenames.
/// Maps "global" (per-CGU) file ID numbers to their underlying source files.
struct GlobalFileTable {
/// This "raw" table doesn't include the working dir, so a filename's
/// This "raw" table doesn't include the working dir, so a file's
/// global ID is its index in this set **plus one**.
raw_file_table: FxIndexSet<Symbol>,
raw_file_table: FxIndexMap<StableSourceFileId, Arc<SourceFile>>,
}

impl GlobalFileTable {
fn new() -> Self {
Self { raw_file_table: FxIndexSet::default() }
Self { raw_file_table: FxIndexMap::default() }
}

fn global_file_id_for_file_name(&mut self, file_name: Symbol) -> GlobalFileId {
fn global_file_id_for_file(&mut self, file: &Arc<SourceFile>) -> GlobalFileId {
// Ensure the given file has a table entry, and get its index.
let (raw_id, _) = self.raw_file_table.insert_full(file_name);
let entry = self.raw_file_table.entry(file.stable_id);
let raw_id = entry.index();
entry.or_insert_with(|| Arc::clone(file));

// The raw file table doesn't include an entry for the working dir
// (which has ID 0), so add 1 to get the correct ID.
GlobalFileId::from_usize(raw_id + 1)
}

fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec<u8> {
let mut table = Vec::with_capacity(self.raw_file_table.len() + 1);

// LLVM Coverage Mapping Format version 6 (zero-based encoded as 5)
// requires setting the first filename to the compilation directory.
// Since rustc generates coverage maps with relative paths, the
// compilation directory can be combined with the relative paths
// to get absolute paths, if needed.
use rustc_session::RemapFileNameExt;
use rustc_session::config::RemapPathScopeComponents;
let working_dir: &str = &tcx
.sess
.opts
.working_dir
.for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
.to_string_lossy();

// Insert the working dir at index 0, before the other filenames.
let filenames =
iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str));
llvm_cov::write_filenames_to_buffer(filenames)
table.push(
tcx.sess
.opts
.working_dir
.for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
.to_string_lossy(),
);

// Add the regular entries after the base directory.
table.extend(self.raw_file_table.values().map(|file| {
file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy()
}));

llvm_cov::write_filenames_to_buffer(&table)
}
}

Expand All @@ -182,7 +189,7 @@ rustc_index::newtype_index! {
/// An index into a function's list of global file IDs. That underlying list
/// of local-to-global mappings will be embedded in the function's record in
/// the `__llvm_covfun` linker section.
pub(crate) struct LocalFileId {}
struct LocalFileId {}
}

/// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU)
Expand All @@ -208,13 +215,6 @@ impl VirtualFileMapping {
}
}

fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol {
let source_file = tcx.sess.source_map().lookup_source_file(span.lo());
let name =
source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy();
Symbol::intern(&name)
}

/// Generates the contents of the covmap record for this CGU, which mostly
/// consists of a header and a list of filenames. The record is then stored
/// as a global variable in the `__llvm_covmap` section.
Expand Down
49 changes: 31 additions & 18 deletions compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ use rustc_abi::Align;
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
};
use rustc_middle::bug;
use rustc_middle::mir::coverage::{
CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping, MappingKind, Op,
};
use rustc_middle::ty::{Instance, TyCtxt};
use rustc_span::Span;
use rustc_target::spec::HasTargetSpec;
use tracing::debug;

use crate::common::CodegenCx;
use crate::coverageinfo::mapgen::{GlobalFileTable, VirtualFileMapping, span_file_name};
use crate::coverageinfo::mapgen::{GlobalFileTable, VirtualFileMapping, spans};
use crate::coverageinfo::{ffi, llvm_cov};
use crate::llvm;

Expand Down Expand Up @@ -67,12 +67,8 @@ pub(crate) fn prepare_covfun_record<'tcx>(
fill_region_tables(tcx, global_file_table, fn_cov_info, ids_info, &mut covfun);

if covfun.regions.has_no_regions() {
if covfun.is_used {
bug!("a used function should have had coverage mapping data but did not: {covfun:?}");
} else {
debug!(?covfun, "unused function had no coverage mapping data");
return None;
}
debug!(?covfun, "function has no mappings to embed; skipping");
return None;
}

Some(covfun)
Expand Down Expand Up @@ -121,49 +117,66 @@ fn fill_region_tables<'tcx>(
covfun: &mut CovfunRecord<'tcx>,
) {
// Currently a function's mappings must all be in the same file as its body span.
let file_name = span_file_name(tcx, fn_cov_info.body_span);
let source_map = tcx.sess.source_map();
let source_file = source_map.lookup_source_file(fn_cov_info.body_span.lo());

// Look up the global file ID for that filename.
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
// Look up the global file ID for that file.
let global_file_id = global_file_table.global_file_id_for_file(&source_file);

// Associate that global file ID with a local file ID for this function.
let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id);
debug!(" file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'");

let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
&mut covfun.regions;

let make_cov_span = |span: Span| {
spans::make_coverage_span(local_file_id, source_map, fn_cov_info, &source_file, span)
};
let discard_all = tcx.sess.coverage_discard_all_spans_in_codegen();

// 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 { kind, ref source_region } in &fn_cov_info.mappings {
for &Mapping { ref kind, span } in &fn_cov_info.mappings {
// If the mapping refers to counters/expressions that were removed by
// MIR opts, replace those occurrences with zero.
let kind = kind.map_terms(|term| if is_zero_term(term) { CovTerm::Zero } else { term });

let span = ffi::CoverageSpan::from_source_region(local_file_id, source_region);
// Convert the `Span` into coordinates that we can pass to LLVM, or
// discard the span if conversion fails. In rare, cases _all_ of a
// function's spans are discarded, and the rest of coverage codegen
// needs to handle that gracefully to avoid a repeat of #133606.
// We don't have a good test case for triggering that organically, so
// instead we set `-Zcoverage-options=discard-all-spans-in-codegen`
// to force it to occur.
let Some(cov_span) = make_cov_span(span) else { continue };
if discard_all {
continue;
}

match kind {
MappingKind::Code(term) => {
code_regions.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) });
code_regions
.push(ffi::CodeRegion { cov_span, counter: ffi::Counter::from_term(term) });
}
MappingKind::Branch { true_term, false_term } => {
branch_regions.push(ffi::BranchRegion {
span,
cov_span,
true_counter: ffi::Counter::from_term(true_term),
false_counter: ffi::Counter::from_term(false_term),
});
}
MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => {
mcdc_branch_regions.push(ffi::MCDCBranchRegion {
span,
cov_span,
true_counter: ffi::Counter::from_term(true_term),
false_counter: ffi::Counter::from_term(false_term),
mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params),
});
}
MappingKind::MCDCDecision(mcdc_decision_params) => {
mcdc_decision_regions.push(ffi::MCDCDecisionRegion {
span,
cov_span,
mcdc_decision_params: ffi::mcdc::DecisionParameters::from(mcdc_decision_params),
});
}
Expand Down
Loading

0 comments on commit bfa5eb1

Please sign in to comment.