Skip to content

Commit 609ea4e

Browse files
committed
Resolved most of the feedback in the PR
Added `TODO` comments for a few things left to check. I'll either resolve them or conver them to FIXME's with issue numbers before uploading the changes.
1 parent 469160a commit 609ea4e

File tree

327 files changed

+24029
-5932
lines changed

Some content is hidden

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

327 files changed

+24029
-5932
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+30-8
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,36 @@ impl CoverageMapGenerator {
141141
virtual_file_mapping.push(filenames_index as u32);
142142
}
143143
debug!("Adding counter {:?} to map for {:?}", counter, region);
144-
mapping_regions.push(CounterMappingRegion::code_region(
145-
counter,
146-
current_file_id,
147-
start_line,
148-
start_col,
149-
end_line,
150-
end_col,
151-
));
144+
match counter.kind {
145+
rustc_codegen_ssa::coverageinfo::map::CounterKind::Zero => {
146+
// Assume `Zero` counters are either from `Unreachable` code regions, or they
147+
// should at least be handled similarly, the `gap_region` signifies a code span
148+
// that should be marked as known, but uncovered (counted as zero executions)
149+
// _except_ where other code regions overlap. For example, a closure that is
150+
// defined but never used will probably not get codegenned, and therefore would
151+
// not have any coverage, but the MIR in which the closure is defined can at
152+
// least inject the span for the closure as a `gap_region`, ensuring the code
153+
// region is at least known about, and can be flagged as uncovered if necessary.
154+
mapping_regions.push(CounterMappingRegion::gap_region(
155+
counter,
156+
current_file_id,
157+
start_line,
158+
start_col,
159+
end_line,
160+
end_col,
161+
));
162+
}
163+
_ => {
164+
mapping_regions.push(CounterMappingRegion::code_region(
165+
counter,
166+
current_file_id,
167+
start_line,
168+
start_col,
169+
end_line,
170+
end_col,
171+
));
172+
}
173+
}
152174
}
153175

154176
// Encode and append the current function's coverage mapping data

compiler/rustc_middle/src/hir/map/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
4747
}
4848
}
4949

50-
fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> {
50+
pub fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> {
5151
match &node {
5252
Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
5353
| Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })

compiler/rustc_mir/src/transform/coverage/counters.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,9 @@ impl<'a> BcbCounters<'a> {
148148

149149
let mut bcbs_with_coverage = BitSet::new_empty(num_bcbs);
150150
for covspan in coverage_spans {
151-
bcbs_with_coverage.insert(covspan.bcb);
151+
if let Some(bcb) = covspan.bcb {
152+
bcbs_with_coverage.insert(bcb);
153+
}
152154
}
153155

154156
// Walk the `CoverageGraph`. For each `BasicCoverageBlock` node with an associated

compiler/rustc_mir/src/transform/coverage/debug.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -657,10 +657,19 @@ fn span_viewables(
657657
for coverage_span in coverage_spans {
658658
let tooltip = coverage_span.format_coverage_statements(tcx, mir_body);
659659
let CoverageSpan { span, bcb, .. } = coverage_span;
660-
let bcb_data = &basic_coverage_blocks[*bcb];
661-
let id = bcb_data.id();
662-
let leader_bb = bcb_data.leader_bb();
663-
span_viewables.push(SpanViewable { bb: leader_bb, span: *span, id, tooltip });
660+
if let Some(bcb) = *bcb {
661+
let bcb_data = &basic_coverage_blocks[bcb];
662+
let id = bcb_data.id();
663+
let leader_bb = bcb_data.leader_bb();
664+
span_viewables.push(SpanViewable { bb: leader_bb, span: *span, id, tooltip });
665+
} else {
666+
span_viewables.push(SpanViewable {
667+
bb: mir::START_BLOCK,
668+
span: *span,
669+
id: String::from("Unreachable"),
670+
tooltip,
671+
});
672+
}
664673
}
665674
span_viewables
666675
}

compiler/rustc_mir/src/transform/coverage/graph.rs

+1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ rustc_index::newtype_index! {
278278
/// A node in the [control-flow graph][CFG] of CoverageGraph.
279279
pub(super) struct BasicCoverageBlock {
280280
DEBUG_FORMAT = "bcb{}",
281+
const START_BCB = 0,
281282
}
282283
}
283284

compiler/rustc_mir/src/transform/coverage/mod.rs

+59-22
Original file line numberDiff line numberDiff line change
@@ -88,21 +88,27 @@ struct Instrumentor<'a, 'tcx> {
8888
pass_name: &'a str,
8989
tcx: TyCtxt<'tcx>,
9090
mir_body: &'a mut mir::Body<'tcx>,
91+
fn_sig_span: Span,
9192
body_span: Span,
9293
basic_coverage_blocks: CoverageGraph,
9394
coverage_counters: CoverageCounters,
9495
}
9596

9697
impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
9798
fn new(pass_name: &'a str, tcx: TyCtxt<'tcx>, mir_body: &'a mut mir::Body<'tcx>) -> Self {
98-
let hir_body = hir_body(tcx, mir_body.source.def_id());
99+
let (some_fn_sig, hir_body) = fn_sig_and_body(tcx, mir_body.source.def_id());
99100
let body_span = hir_body.value.span;
101+
let fn_sig_span = match some_fn_sig {
102+
Some(fn_sig) => fn_sig.span.with_hi(body_span.lo()),
103+
None => body_span.shrink_to_lo(),
104+
};
100105
let function_source_hash = hash_mir_source(tcx, hir_body);
101106
let basic_coverage_blocks = CoverageGraph::from_mir(mir_body);
102107
Self {
103108
pass_name,
104109
tcx,
105110
mir_body,
111+
fn_sig_span,
106112
body_span,
107113
basic_coverage_blocks,
108114
coverage_counters: CoverageCounters::new(function_source_hash),
@@ -114,9 +120,15 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
114120
let source_map = tcx.sess.source_map();
115121
let mir_source = self.mir_body.source;
116122
let def_id = mir_source.def_id();
123+
let fn_sig_span = self.fn_sig_span;
117124
let body_span = self.body_span;
118125

119-
debug!("instrumenting {:?}, span: {}", def_id, source_map.span_to_string(body_span));
126+
debug!(
127+
"instrumenting {:?}, fn sig span: {}, body span: {}",
128+
def_id,
129+
source_map.span_to_string(fn_sig_span),
130+
source_map.span_to_string(body_span)
131+
);
120132

121133
let mut graphviz_data = debug::GraphvizData::new();
122134
let mut debug_used_expressions = debug::UsedExpressions::new();
@@ -138,6 +150,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
138150
// Compute `CoverageSpan`s from the `CoverageGraph`.
139151
let coverage_spans = CoverageSpans::generate_coverage_spans(
140152
&self.mir_body,
153+
fn_sig_span,
141154
body_span,
142155
&self.basic_coverage_blocks,
143156
);
@@ -260,26 +273,47 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
260273

261274
let mut bcb_counters = IndexVec::from_elem_n(None, self.basic_coverage_blocks.num_nodes());
262275
for covspan in coverage_spans {
263-
let bcb = covspan.bcb;
264276
let span = covspan.span;
265-
let counter_kind = if let Some(&counter_operand) = bcb_counters[bcb].as_ref() {
266-
self.coverage_counters.make_identity_counter(counter_operand)
267-
} else if let Some(counter_kind) = self.bcb_data_mut(bcb).take_counter() {
268-
bcb_counters[bcb] = Some(counter_kind.as_operand_id());
269-
debug_used_expressions.add_expression_operands(&counter_kind);
270-
counter_kind
271-
} else {
272-
bug!("Every BasicCoverageBlock should have a Counter or Expression");
273-
};
274-
graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind);
275-
// FIXME(#78542): Can spans for `TerminatorKind::Goto` be improved to avoid special
276-
// cases?
277-
let some_code_region = if self.is_code_region_redundant(bcb, span, body_span) {
278-
None
277+
if let Some(bcb) = covspan.bcb {
278+
let counter_kind = if let Some(&counter_operand) = bcb_counters[bcb].as_ref() {
279+
self.coverage_counters.make_identity_counter(counter_operand)
280+
} else if let Some(counter_kind) = self.bcb_data_mut(bcb).take_counter() {
281+
bcb_counters[bcb] = Some(counter_kind.as_operand_id());
282+
debug_used_expressions.add_expression_operands(&counter_kind);
283+
counter_kind
284+
} else {
285+
bug!("Every BasicCoverageBlock should have a Counter or Expression");
286+
};
287+
graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind);
288+
// FIXME(#78542): Can spans for `TerminatorKind::Goto` be improved to avoid special
289+
// cases?
290+
let some_code_region = if self.is_code_region_redundant(bcb, span, body_span) {
291+
None
292+
} else {
293+
Some(make_code_region(file_name, &source_file, span, body_span))
294+
};
295+
inject_statement(
296+
self.mir_body,
297+
counter_kind,
298+
self.bcb_last_bb(bcb),
299+
some_code_region,
300+
);
279301
} else {
280-
Some(make_code_region(file_name, &source_file, span, body_span))
281-
};
282-
inject_statement(self.mir_body, counter_kind, self.bcb_last_bb(bcb), some_code_region);
302+
// A closure body has its own, separate MIR, but the code span for the closure body
303+
// is known to the enclosing function's MIR. Since it is possible for a closure to
304+
// be "unused", that closure's MIR would not get codegenned and would not have any
305+
// known coverage. Adding an `Unreachable` code region for the closure ensures the
306+
// closure's region is known to coverage and can be marked "uncovered" if needed.
307+
// Note, the `Unreachable` region will generate a `Zero` counter, which is
308+
// subsequently turned into a `gap_region` in the Coverage Map. The `gap_region`
309+
// ensures code is only marked uncovered if there is no other defined coverage.
310+
inject_statement(
311+
self.mir_body,
312+
CoverageKind::Unreachable,
313+
mir::START_BLOCK,
314+
Some(make_code_region(file_name, &source_file, span, body_span)),
315+
);
316+
}
283317
}
284318
}
285319

@@ -521,10 +555,13 @@ fn make_code_region(
521555
}
522556
}
523557

524-
fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx rustc_hir::Body<'tcx> {
558+
fn fn_sig_and_body<'tcx>(
559+
tcx: TyCtxt<'tcx>,
560+
def_id: DefId,
561+
) -> (Option<&'tcx rustc_hir::FnSig<'tcx>>, &'tcx rustc_hir::Body<'tcx>) {
525562
let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
526563
let fn_body_id = hir::map::associated_body(hir_node).expect("HIR node is a function with body");
527-
tcx.hir().body(fn_body_id)
564+
(hir::map::fn_sig(hir_node), tcx.hir().body(fn_body_id))
528565
}
529566

530567
fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 {

0 commit comments

Comments
 (0)