Skip to content

Commit da48646

Browse files
Rollup merge of #78300 - richkadel:coverage-cx, r=wesleywiser
Make codegen coverage_context optional, and check Addresses Issue #78286 Libraries compiled with coverage and linked with out enabling coverage would fail when attempting to add the library's coverage statements to the codegen coverage context (None). Now, if coverage statements are encountered while compiling / linking with `-Z instrument-coverage` disabled, codegen will *not* attempt to add code regions to a coverage map, and it will not inject the LLVM instrprof_increment intrinsic calls.
2 parents a07fc3d + f75a236 commit da48646

File tree

5 files changed

+74
-50
lines changed

5 files changed

+74
-50
lines changed

compiler/rustc_codegen_llvm/src/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
324324
}
325325

326326
#[inline]
327-
pub fn coverage_context(&'a self) -> &'a coverageinfo::CrateCoverageContext<'tcx> {
328-
self.coverage_cx.as_ref().unwrap()
327+
pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'tcx>> {
328+
self.coverage_cx.as_ref()
329329
}
330330
}
331331

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ use tracing::debug;
2626
/// undocumented details in Clang's implementation (that may or may not be important) were also
2727
/// replicated for Rust's Coverage Map.
2828
pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
29-
let function_coverage_map = cx.coverage_context().take_function_coverage_map();
29+
let function_coverage_map = match cx.coverage_context() {
30+
Some(ctx) => ctx.take_function_coverage_map(),
31+
None => return,
32+
};
3033
if function_coverage_map.is_empty() {
3134
// This module has no functions with coverage instrumentation
3235
return;

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+47-32
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,22 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
6464
function_source_hash: u64,
6565
id: CounterValueReference,
6666
region: CodeRegion,
67-
) {
68-
debug!(
69-
"adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={:?}, \
70-
at {:?}",
71-
instance, function_source_hash, id, region,
72-
);
73-
let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
74-
coverage_regions
75-
.entry(instance)
76-
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
77-
.add_counter(function_source_hash, id, region);
67+
) -> bool {
68+
if let Some(coverage_context) = self.coverage_context() {
69+
debug!(
70+
"adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={:?}, \
71+
at {:?}",
72+
instance, function_source_hash, id, region,
73+
);
74+
let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut();
75+
coverage_regions
76+
.entry(instance)
77+
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
78+
.add_counter(function_source_hash, id, region);
79+
true
80+
} else {
81+
false
82+
}
7883
}
7984

8085
fn add_counter_expression_region(
@@ -85,29 +90,39 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
8590
op: Op,
8691
rhs: ExpressionOperandId,
8792
region: CodeRegion,
88-
) {
89-
debug!(
90-
"adding counter expression to coverage_regions: instance={:?}, id={:?}, {:?} {:?} {:?}, \
91-
at {:?}",
92-
instance, id, lhs, op, rhs, region,
93-
);
94-
let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
95-
coverage_regions
96-
.entry(instance)
97-
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
98-
.add_counter_expression(id, lhs, op, rhs, region);
93+
) -> bool {
94+
if let Some(coverage_context) = self.coverage_context() {
95+
debug!(
96+
"adding counter expression to coverage_regions: instance={:?}, id={:?}, {:?} {:?} {:?}, \
97+
at {:?}",
98+
instance, id, lhs, op, rhs, region,
99+
);
100+
let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut();
101+
coverage_regions
102+
.entry(instance)
103+
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
104+
.add_counter_expression(id, lhs, op, rhs, region);
105+
true
106+
} else {
107+
false
108+
}
99109
}
100110

101-
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion) {
102-
debug!(
103-
"adding unreachable code to coverage_regions: instance={:?}, at {:?}",
104-
instance, region,
105-
);
106-
let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
107-
coverage_regions
108-
.entry(instance)
109-
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
110-
.add_unreachable_region(region);
111+
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool {
112+
if let Some(coverage_context) = self.coverage_context() {
113+
debug!(
114+
"adding unreachable code to coverage_regions: instance={:?}, at {:?}",
115+
instance, region,
116+
);
117+
let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut();
118+
coverage_regions
119+
.entry(instance)
120+
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
121+
.add_unreachable_region(region);
122+
true
123+
} else {
124+
false
125+
}
111126
}
112127
}
113128

compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1010
let Coverage { kind, code_region } = coverage;
1111
match kind {
1212
CoverageKind::Counter { function_source_hash, id } => {
13-
bx.add_counter_region(self.instance, function_source_hash, id, code_region);
13+
if bx.add_counter_region(self.instance, function_source_hash, id, code_region) {
14+
let coverageinfo = bx.tcx().coverageinfo(self.instance.def_id());
1415

15-
let coverageinfo = bx.tcx().coverageinfo(self.instance.def_id());
16-
17-
let fn_name = bx.create_pgo_func_name_var(self.instance);
18-
let hash = bx.const_u64(function_source_hash);
19-
let num_counters = bx.const_u32(coverageinfo.num_counters);
20-
let id = bx.const_u32(u32::from(id));
21-
debug!(
22-
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
23-
fn_name, hash, num_counters, id,
24-
);
25-
bx.instrprof_increment(fn_name, hash, num_counters, id);
16+
let fn_name = bx.create_pgo_func_name_var(self.instance);
17+
let hash = bx.const_u64(function_source_hash);
18+
let num_counters = bx.const_u32(coverageinfo.num_counters);
19+
let id = bx.const_u32(u32::from(id));
20+
debug!(
21+
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
22+
fn_name, hash, num_counters, id,
23+
);
24+
bx.instrprof_increment(fn_name, hash, num_counters, id);
25+
}
2626
}
2727
CoverageKind::Expression { id, lhs, op, rhs } => {
2828
bx.add_counter_expression_region(self.instance, id, lhs, op, rhs, code_region);

compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ pub trait CoverageInfoMethods: BackendTypes {
99
pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
1010
fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value;
1111

12+
/// Returns true if the counter was added to the coverage map; false if `-Z instrument-coverage`
13+
/// is not enabled (a coverage map is not being generated).
1214
fn add_counter_region(
1315
&mut self,
1416
instance: Instance<'tcx>,
1517
function_source_hash: u64,
1618
id: CounterValueReference,
1719
region: CodeRegion,
18-
);
20+
) -> bool;
1921

22+
/// Returns true if the expression was added to the coverage map; false if
23+
/// `-Z instrument-coverage` is not enabled (a coverage map is not being generated).
2024
fn add_counter_expression_region(
2125
&mut self,
2226
instance: Instance<'tcx>,
@@ -25,7 +29,9 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
2529
op: Op,
2630
rhs: ExpressionOperandId,
2731
region: CodeRegion,
28-
);
32+
) -> bool;
2933

30-
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion);
34+
/// Returns true if the region was added to the coverage map; false if `-Z instrument-coverage`
35+
/// is not enabled (a coverage map is not being generated).
36+
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool;
3137
}

0 commit comments

Comments
 (0)