Skip to content

Commit 5f6fcad

Browse files
committed
Auto merge of #75563 - richkadel:llvm-coverage-map-gen-5.4, r=wesleywiser
Moved coverage counter injection from BasicBlock to Statement. As discussed on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Implement.20LLVM-compatible.20source-based.20cod.20compiler-team.23278
2 parents 32c654a + d129ac2 commit 5f6fcad

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+400
-787
lines changed

library/core/src/intrinsics.rs

-64
Original file line numberDiff line numberDiff line change
@@ -1949,70 +1949,6 @@ extern "rust-intrinsic" {
19491949
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
19501950
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
19511951

1952-
/// Internal placeholder for injecting code coverage counters when the "instrument-coverage"
1953-
/// option is enabled. The source code region information is extracted prior to code generation,
1954-
/// and added to the "coverage map", which is injected into the generated code as additional
1955-
/// data. This intrinsic then triggers the generation of LLVM intrinsic call
1956-
/// `instrprof.increment`, using the remaining args (`function_source_hash` and `index`).
1957-
#[cfg(not(bootstrap))]
1958-
#[lang = "count_code_region"]
1959-
pub fn count_code_region(
1960-
function_source_hash: u64,
1961-
index: u32,
1962-
file_name: &'static str,
1963-
start_line: u32,
1964-
start_col: u32,
1965-
end_line: u32,
1966-
end_col: u32,
1967-
);
1968-
1969-
/// Internal marker for code coverage expressions, injected into the MIR when the
1970-
/// "instrument-coverage" option is enabled. This intrinsic is not converted into a
1971-
/// backend intrinsic call, but its arguments are extracted during the production of a
1972-
/// "coverage map", which is injected into the generated code, as additional data.
1973-
/// This marker identifies a code region and two other counters or counter expressions
1974-
/// whose sum is the number of times the code region was executed.
1975-
#[cfg(not(bootstrap))]
1976-
#[lang = "coverage_counter_add"]
1977-
pub fn coverage_counter_add(
1978-
index: u32,
1979-
left_index: u32,
1980-
right_index: u32,
1981-
file_name: &'static str,
1982-
start_line: u32,
1983-
start_col: u32,
1984-
end_line: u32,
1985-
end_col: u32,
1986-
);
1987-
1988-
/// This marker identifies a code region and two other counters or counter expressions
1989-
/// whose difference is the number of times the code region was executed.
1990-
/// (See `coverage_counter_add` for more information.)
1991-
#[cfg(not(bootstrap))]
1992-
#[lang = "coverage_counter_subtract"]
1993-
pub fn coverage_counter_subtract(
1994-
index: u32,
1995-
left_index: u32,
1996-
right_index: u32,
1997-
file_name: &'static str,
1998-
start_line: u32,
1999-
start_col: u32,
2000-
end_line: u32,
2001-
end_col: u32,
2002-
);
2003-
2004-
/// This marker identifies a code region to be added to the "coverage map" to indicate source
2005-
/// code that can never be reached.
2006-
/// (See `coverage_counter_add` for more information.)
2007-
#[cfg(not(bootstrap))]
2008-
pub fn coverage_unreachable(
2009-
file_name: &'static str,
2010-
start_line: u32,
2011-
start_col: u32,
2012-
end_line: u32,
2013-
end_col: u32,
2014-
);
2015-
20161952
/// See documentation of `<*const T>::guaranteed_eq` for details.
20171953
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
20181954
pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;

src/librustc_codegen_llvm/builder.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1117,7 +1117,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11171117
hash: &'ll Value,
11181118
num_counters: &'ll Value,
11191119
index: &'ll Value,
1120-
) -> &'ll Value {
1120+
) {
11211121
debug!(
11221122
"instrprof_increment() with args ({:?}, {:?}, {:?}, {:?})",
11231123
fn_name, hash, num_counters, index
@@ -1128,13 +1128,13 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11281128
let args = self.check_call("call", llfn, args);
11291129

11301130
unsafe {
1131-
llvm::LLVMRustBuildCall(
1131+
let _ = llvm::LLVMRustBuildCall(
11321132
self.llbuilder,
11331133
llfn,
11341134
args.as_ptr() as *const &llvm::Value,
11351135
args.len() as c_uint,
11361136
None,
1137-
)
1137+
);
11381138
}
11391139
}
11401140

src/librustc_codegen_llvm/coverageinfo/mapgen.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ use crate::coverageinfo;
33
use crate::llvm;
44

55
use llvm::coverageinfo::CounterMappingRegion;
6-
use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression, Region};
6+
use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression};
77
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
88
use rustc_data_structures::fx::FxIndexSet;
99
use rustc_llvm::RustString;
10-
use tracing::debug;
10+
use rustc_middle::mir::coverage::CodeRegion;
1111

1212
use std::ffi::CString;
1313

14+
use tracing::debug;
15+
1416
/// Generates and exports the Coverage Map.
1517
///
1618
/// This Coverage Map complies with Coverage Mapping Format version 3 (zero-based encoded as 2),
@@ -91,7 +93,7 @@ impl CoverageMapGenerator {
9193
fn write_coverage_mappings(
9294
&mut self,
9395
expressions: Vec<CounterExpression>,
94-
counter_regions: impl Iterator<Item = (Counter, &'tcx Region<'tcx>)>,
96+
counter_regions: impl Iterator<Item = (Counter, &'a CodeRegion)>,
9597
coverage_mappings_buffer: &RustString,
9698
) {
9799
let mut counter_regions = counter_regions.collect::<Vec<_>>();
@@ -104,22 +106,22 @@ impl CoverageMapGenerator {
104106
let mut current_file_name = None;
105107
let mut current_file_id = 0;
106108

107-
// Convert the list of (Counter, Region) pairs to an array of `CounterMappingRegion`, sorted
109+
// Convert the list of (Counter, CodeRegion) pairs to an array of `CounterMappingRegion`, sorted
108110
// by filename and position. Capture any new files to compute the `CounterMappingRegion`s
109111
// `file_id` (indexing files referenced by the current function), and construct the
110112
// function-specific `virtual_file_mapping` from `file_id` to its index in the module's
111113
// `filenames` array.
112114
counter_regions.sort_unstable_by_key(|(_counter, region)| *region);
113115
for (counter, region) in counter_regions {
114-
let Region { file_name, start_line, start_col, end_line, end_col } = *region;
115-
let same_file = current_file_name.as_ref().map_or(false, |p| p == file_name);
116+
let CodeRegion { file_name, start_line, start_col, end_line, end_col } = *region;
117+
let same_file = current_file_name.as_ref().map_or(false, |p| *p == file_name);
116118
if !same_file {
117119
if current_file_name.is_some() {
118120
current_file_id += 1;
119121
}
120-
current_file_name = Some(file_name.to_string());
121-
let c_filename =
122-
CString::new(file_name).expect("null error converting filename to C string");
122+
current_file_name = Some(file_name);
123+
let c_filename = CString::new(file_name.to_string())
124+
.expect("null error converting filename to C string");
123125
debug!(" file_id: {} = '{:?}'", current_file_id, c_filename);
124126
let (filenames_index, _) = self.filenames.insert_full(c_filename);
125127
virtual_file_mapping.push(filenames_index as u32);

src/librustc_codegen_llvm/coverageinfo/mod.rs

+20-16
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,38 @@ use crate::common::CodegenCx;
55

66
use libc::c_uint;
77
use llvm::coverageinfo::CounterMappingRegion;
8-
use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, ExprKind, FunctionCoverage, Region};
8+
use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, FunctionCoverage};
99
use rustc_codegen_ssa::traits::{
1010
BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, MiscMethods, StaticMethods,
1111
};
1212
use rustc_data_structures::fx::FxHashMap;
1313
use rustc_llvm::RustString;
14+
use rustc_middle::mir::coverage::{
15+
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionIndex, Op,
16+
};
1417
use rustc_middle::ty::Instance;
15-
use tracing::debug;
1618

1719
use std::cell::RefCell;
1820
use std::ffi::CString;
1921

22+
use tracing::debug;
23+
2024
pub mod mapgen;
2125

2226
const COVMAP_VAR_ALIGN_BYTES: usize = 8;
2327

2428
/// A context object for maintaining all state needed by the coverageinfo module.
2529
pub struct CrateCoverageContext<'tcx> {
2630
// Coverage region data for each instrumented function identified by DefId.
27-
pub(crate) function_coverage_map: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>>>,
31+
pub(crate) function_coverage_map: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverage>>,
2832
}
2933

3034
impl<'tcx> CrateCoverageContext<'tcx> {
3135
pub fn new() -> Self {
3236
Self { function_coverage_map: Default::default() }
3337
}
3438

35-
pub fn take_function_coverage_map(&self) -> FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>> {
39+
pub fn take_function_coverage_map(&self) -> FxHashMap<Instance<'tcx>, FunctionCoverage> {
3640
self.function_coverage_map.replace(FxHashMap::default())
3741
}
3842
}
@@ -58,11 +62,11 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
5862
&mut self,
5963
instance: Instance<'tcx>,
6064
function_source_hash: u64,
61-
id: u32,
62-
region: Region<'tcx>,
65+
id: CounterValueReference,
66+
region: CodeRegion,
6367
) {
6468
debug!(
65-
"adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={}, \
69+
"adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={:?}, \
6670
at {:?}",
6771
instance, function_source_hash, id, region,
6872
);
@@ -76,25 +80,25 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
7680
fn add_counter_expression_region(
7781
&mut self,
7882
instance: Instance<'tcx>,
79-
id_descending_from_max: u32,
80-
lhs: u32,
81-
op: ExprKind,
82-
rhs: u32,
83-
region: Region<'tcx>,
83+
id: InjectedExpressionIndex,
84+
lhs: ExpressionOperandId,
85+
op: Op,
86+
rhs: ExpressionOperandId,
87+
region: CodeRegion,
8488
) {
8589
debug!(
86-
"adding counter expression to coverage_regions: instance={:?}, id={}, {} {:?} {}, \
90+
"adding counter expression to coverage_regions: instance={:?}, id={:?}, {:?} {:?} {:?}, \
8791
at {:?}",
88-
instance, id_descending_from_max, lhs, op, rhs, region,
92+
instance, id, lhs, op, rhs, region,
8993
);
9094
let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
9195
coverage_regions
9296
.entry(instance)
9397
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
94-
.add_counter_expression(id_descending_from_max, lhs, op, rhs, region);
98+
.add_counter_expression(id, lhs, op, rhs, region);
9599
}
96100

97-
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: Region<'tcx>) {
101+
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion) {
98102
debug!(
99103
"adding unreachable code to coverage_regions: instance={:?}, at {:?}",
100104
instance, region,

src/librustc_codegen_llvm/intrinsic.rs

-103
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,18 @@ use rustc_ast as ast;
1111
use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
1212
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
1313
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
14-
use rustc_codegen_ssa::coverageinfo;
1514
use rustc_codegen_ssa::glue;
1615
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
1716
use rustc_codegen_ssa::mir::place::PlaceRef;
1817
use rustc_codegen_ssa::traits::*;
1918
use rustc_codegen_ssa::MemFlags;
2019
use rustc_hir as hir;
21-
use rustc_middle::mir::coverage;
22-
use rustc_middle::mir::Operand;
2320
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
2421
use rustc_middle::ty::{self, Ty};
2522
use rustc_middle::{bug, span_bug};
2623
use rustc_span::{sym, symbol::kw, Span, Symbol};
2724
use rustc_target::abi::{self, HasDataLayout, LayoutOf, Primitive};
2825
use rustc_target::spec::PanicStrategy;
29-
use tracing::debug;
3026

3127
use std::cmp::Ordering;
3228
use std::iter;
@@ -83,85 +79,13 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: Symbol) -> Option<&'ll Va
8379
}
8480

8581
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
86-
fn is_codegen_intrinsic(
87-
&mut self,
88-
intrinsic: Symbol,
89-
args: &Vec<Operand<'tcx>>,
90-
caller_instance: ty::Instance<'tcx>,
91-
) -> bool {
92-
let mut is_codegen_intrinsic = true;
93-
// Set `is_codegen_intrinsic` to `false` to bypass `codegen_intrinsic_call()`.
94-
95-
// FIXME(richkadel): Make sure to add coverage analysis tests on a crate with
96-
// external crate dependencies, where:
97-
// 1. Both binary and dependent crates are compiled with `-Zinstrument-coverage`
98-
// 2. Only binary is compiled with `-Zinstrument-coverage`
99-
// 3. Only dependent crates are compiled with `-Zinstrument-coverage`
100-
match intrinsic {
101-
sym::count_code_region => {
102-
use coverage::count_code_region_args::*;
103-
self.add_counter_region(
104-
caller_instance,
105-
op_to_u64(&args[FUNCTION_SOURCE_HASH]),
106-
op_to_u32(&args[COUNTER_ID]),
107-
coverageinfo::Region::new(
108-
op_to_str_slice(&args[FILE_NAME]),
109-
op_to_u32(&args[START_LINE]),
110-
op_to_u32(&args[START_COL]),
111-
op_to_u32(&args[END_LINE]),
112-
op_to_u32(&args[END_COL]),
113-
),
114-
);
115-
}
116-
sym::coverage_counter_add | sym::coverage_counter_subtract => {
117-
is_codegen_intrinsic = false;
118-
use coverage::coverage_counter_expression_args::*;
119-
self.add_counter_expression_region(
120-
caller_instance,
121-
op_to_u32(&args[EXPRESSION_ID]),
122-
op_to_u32(&args[LEFT_ID]),
123-
if intrinsic == sym::coverage_counter_add {
124-
coverageinfo::ExprKind::Add
125-
} else {
126-
coverageinfo::ExprKind::Subtract
127-
},
128-
op_to_u32(&args[RIGHT_ID]),
129-
coverageinfo::Region::new(
130-
op_to_str_slice(&args[FILE_NAME]),
131-
op_to_u32(&args[START_LINE]),
132-
op_to_u32(&args[START_COL]),
133-
op_to_u32(&args[END_LINE]),
134-
op_to_u32(&args[END_COL]),
135-
),
136-
);
137-
}
138-
sym::coverage_unreachable => {
139-
is_codegen_intrinsic = false;
140-
use coverage::coverage_unreachable_args::*;
141-
self.add_unreachable_region(
142-
caller_instance,
143-
coverageinfo::Region::new(
144-
op_to_str_slice(&args[FILE_NAME]),
145-
op_to_u32(&args[START_LINE]),
146-
op_to_u32(&args[START_COL]),
147-
op_to_u32(&args[END_LINE]),
148-
op_to_u32(&args[END_COL]),
149-
),
150-
);
151-
}
152-
_ => {}
153-
}
154-
is_codegen_intrinsic
155-
}
156-
15782
fn codegen_intrinsic_call(
15883
&mut self,
15984
instance: ty::Instance<'tcx>,
16085
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
16186
args: &[OperandRef<'tcx, &'ll Value>],
16287
llresult: &'ll Value,
16388
span: Span,
164-
caller_instance: ty::Instance<'tcx>,
16589
) {
16690
let tcx = self.tcx;
16791
let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
@@ -213,21 +137,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
213137
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
214138
self.call(llfn, &[], None)
215139
}
216-
sym::count_code_region => {
217-
use coverage::count_code_region_args::*;
218-
let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
219-
220-
let fn_name = self.create_pgo_func_name_var(caller_instance);
221-
let hash = args[FUNCTION_SOURCE_HASH].immediate();
222-
let num_counters = self.const_u32(coverageinfo.num_counters);
223-
let index = args[COUNTER_ID].immediate();
224-
debug!(
225-
"translating Rust intrinsic `count_code_region()` to LLVM intrinsic: \
226-
instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
227-
fn_name, hash, num_counters, index,
228-
);
229-
self.instrprof_increment(fn_name, hash, num_counters, index)
230-
}
231140
sym::va_start => self.va_start(args[0].immediate()),
232141
sym::va_end => self.va_end(args[0].immediate()),
233142
sym::va_copy => {
@@ -2238,15 +2147,3 @@ fn float_type_width(ty: Ty<'_>) -> Option<u64> {
22382147
_ => None,
22392148
}
22402149
}
2241-
2242-
fn op_to_str_slice<'tcx>(op: &Operand<'tcx>) -> &'tcx str {
2243-
Operand::value_from_const(op).try_to_str_slice().expect("Value is &str")
2244-
}
2245-
2246-
fn op_to_u32<'tcx>(op: &Operand<'tcx>) -> u32 {
2247-
Operand::scalar_from_const(op).to_u32().expect("Scalar is u32")
2248-
}
2249-
2250-
fn op_to_u64<'tcx>(op: &Operand<'tcx>) -> u64 {
2251-
Operand::scalar_from_const(op).to_u64().expect("Scalar is u64")
2252-
}

src/librustc_codegen_ssa/coverageinfo/ffi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::map::{CounterValueReference, MappedExpressionIndex};
1+
use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
22

33
/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L91)
44
#[derive(Copy, Clone, Debug)]

0 commit comments

Comments
 (0)