Skip to content

Commit e000aa2

Browse files
committed
coverage: Data structures for recording branch info during MIR building
1 parent 66a0cff commit e000aa2

File tree

5 files changed

+76
-8
lines changed

5 files changed

+76
-8
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
100100

101101
let Coverage { kind } = coverage;
102102
match *kind {
103+
// Block markers have no effect during codegen.
104+
CoverageKind::BlockMarker { .. } => {}
103105
CoverageKind::CounterIncrement { id } => {
104106
func_coverage.mark_counter_id_seen(id);
105107
// We need to explicitly drop the `RefMut` before calling into `instrprof_increment`,

compiler/rustc_middle/src/mir/coverage.rs

+29-2
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,19 @@ impl Debug for CovTerm {
7676

7777
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
7878
pub enum CoverageKind {
79+
BlockMarker {
80+
id: BlockMarkerId,
81+
},
82+
7983
/// Marks the point in MIR control flow represented by a coverage counter.
8084
///
8185
/// This is eventually lowered to `llvm.instrprof.increment` in LLVM IR.
8286
///
8387
/// If this statement does not survive MIR optimizations, any mappings that
8488
/// refer to this counter can have those references simplified to zero.
85-
CounterIncrement { id: CounterId },
89+
CounterIncrement {
90+
id: CounterId,
91+
},
8692

8793
/// Marks the point in MIR control-flow represented by a coverage expression.
8894
///
@@ -92,13 +98,16 @@ pub enum CoverageKind {
9298
/// (This is only inserted for expression IDs that are directly used by
9399
/// mappings. Intermediate expressions with no direct mappings are
94100
/// retained/zeroed based on whether they are transitively used.)
95-
ExpressionUsed { id: ExpressionId },
101+
ExpressionUsed {
102+
id: ExpressionId,
103+
},
96104
}
97105

98106
impl Debug for CoverageKind {
99107
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
100108
use CoverageKind::*;
101109
match self {
110+
BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()),
102111
CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()),
103112
ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()),
104113
}
@@ -187,4 +196,22 @@ pub struct HirInfo {
187196
pub function_source_hash: u64,
188197
pub fn_sig_span: Span,
189198
pub body_span: Span,
199+
200+
pub num_block_markers: usize,
201+
pub branch_spans: Vec<BranchSpan>,
202+
}
203+
204+
rustc_index::newtype_index! {
205+
#[derive(HashStable)]
206+
#[encodable]
207+
#[debug_format = "BlockMarkerId({})"]
208+
pub struct BlockMarkerId {}
209+
}
210+
211+
#[derive(Clone, Debug)]
212+
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
213+
pub struct BranchSpan {
214+
pub span: Span,
215+
pub true_marker: BlockMarkerId,
216+
pub false_marker: BlockMarkerId,
190217
}

compiler/rustc_middle/src/mir/pretty.rs

+20
Original file line numberDiff line numberDiff line change
@@ -493,13 +493,33 @@ pub fn write_mir_intro<'tcx>(
493493
// Add an empty line before the first block is printed.
494494
writeln!(w)?;
495495

496+
if let Some(coverage_hir_info) = &body.coverage_hir_info {
497+
write_coverage_hir_info(coverage_hir_info, w)?;
498+
}
496499
if let Some(function_coverage_info) = &body.function_coverage_info {
497500
write_function_coverage_info(function_coverage_info, w)?;
498501
}
499502

500503
Ok(())
501504
}
502505

506+
fn write_coverage_hir_info(
507+
coverage_hir_info: &coverage::HirInfo,
508+
w: &mut dyn io::Write,
509+
) -> io::Result<()> {
510+
let coverage::HirInfo { branch_spans, .. } = coverage_hir_info;
511+
512+
for coverage::BranchSpan { span, true_marker, false_marker } in branch_spans {
513+
writeln!(
514+
w,
515+
"{INDENT}coverage branch {{ true: {true_marker:?}, false: {false_marker:?} }} => {span:?}",
516+
)?;
517+
}
518+
writeln!(w)?;
519+
520+
Ok(())
521+
}
522+
503523
fn write_function_coverage_info(
504524
function_coverage_info: &coverage::FunctionCoverageInfo,
505525
w: &mut dyn io::Write,

compiler/rustc_middle/src/ty/structural_impls.rs

+1
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ TrivialTypeTraversalImpls! {
397397
::rustc_hir::HirId,
398398
::rustc_hir::MatchSource,
399399
::rustc_target::asm::InlineAsmRegOrRegClass,
400+
crate::mir::coverage::BlockMarkerId,
400401
crate::mir::coverage::CounterId,
401402
crate::mir::coverage::ExpressionId,
402403
crate::mir::Local,

compiler/rustc_mir_build/src/build/coverageinfo.rs

+24-6
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
11
use rustc_middle::hir;
22
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
33
use rustc_middle::mir;
4+
use rustc_middle::mir::coverage::BranchSpan;
45
use rustc_middle::ty::TyCtxt;
56
use rustc_span::def_id::LocalDefId;
67
use rustc_span::{ExpnKind, Span};
78

89
pub(crate) struct HirInfoBuilder {
9-
// Currently there is no extra state tracked here.
10+
pub(crate) branch_coverage_enabled: bool,
11+
pub(crate) num_block_markers: usize,
12+
pub(crate) branch_spans: Vec<BranchSpan>,
1013
}
1114

1215
impl HirInfoBuilder {
1316
pub(crate) fn new_if_enabled_and_eligible(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Self> {
1417
if tcx.sess.instrument_coverage() && is_eligible_for_coverage(tcx, def_id) {
15-
Some(Self {})
18+
Some(Self {
19+
branch_coverage_enabled: tcx.sess.instrument_coverage_branch(),
20+
num_block_markers: 0,
21+
branch_spans: Vec::new(),
22+
})
1623
} else {
1724
None
1825
}
1926
}
2027

2128
pub(crate) fn finish(self, tcx: TyCtxt<'_>, def_id: LocalDefId) -> Box<mir::coverage::HirInfo> {
22-
let Self {} = self;
23-
Box::new(make_coverage_hir_info(tcx, def_id))
29+
Box::new(make_coverage_hir_info(tcx, def_id, self))
2430
}
2531
}
2632

@@ -46,7 +52,11 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
4652
true
4753
}
4854

49-
fn make_coverage_hir_info(tcx: TyCtxt<'_>, def_id: LocalDefId) -> mir::coverage::HirInfo {
55+
fn make_coverage_hir_info(
56+
tcx: TyCtxt<'_>,
57+
def_id: LocalDefId,
58+
builder: HirInfoBuilder,
59+
) -> mir::coverage::HirInfo {
5060
let (maybe_fn_sig, hir_body) = fn_sig_and_body(tcx, def_id);
5161

5262
let function_source_hash = hash_mir_source(tcx, hir_body);
@@ -70,7 +80,15 @@ fn make_coverage_hir_info(tcx: TyCtxt<'_>, def_id: LocalDefId) -> mir::coverage:
7080
body_span.shrink_to_lo()
7181
};
7282

73-
mir::coverage::HirInfo { function_source_hash, fn_sig_span, body_span }
83+
let HirInfoBuilder { branch_coverage_enabled: _, num_block_markers, branch_spans } = builder;
84+
85+
mir::coverage::HirInfo {
86+
function_source_hash,
87+
fn_sig_span,
88+
body_span,
89+
num_block_markers,
90+
branch_spans,
91+
}
7492
}
7593

7694
fn fn_sig_and_body(

0 commit comments

Comments
 (0)