@@ -100,6 +100,14 @@ impl CoverageCounters {
100
100
BcbCounter :: Counter { id }
101
101
}
102
102
103
+ /// Creates a new physical counter attached a BCB node.
104
+ /// The node must not already have a counter.
105
+ fn make_phys_node_counter ( & mut self , bcb : BasicCoverageBlock ) -> BcbCounter {
106
+ let counter = self . make_counter ( CounterIncrementSite :: Node { bcb } ) ;
107
+ debug ! ( ?bcb, ?counter, "node gets a physical counter" ) ;
108
+ self . set_bcb_counter ( bcb, counter)
109
+ }
110
+
103
111
fn make_expression ( & mut self , lhs : BcbCounter , op : Op , rhs : BcbCounter ) -> BcbCounter {
104
112
let new_expr = BcbExpression { lhs, op, rhs } ;
105
113
* self
@@ -353,28 +361,21 @@ impl<'a> MakeBcbCounters<'a> {
353
361
return counter_kind;
354
362
}
355
363
356
- // A BCB with only one incoming edge gets a simple `Counter` (via `make_counter()`).
357
- // Also, a BCB that loops back to itself gets a simple `Counter`. This may indicate the
358
- // program results in a tight infinite loop, but it should still compile.
359
- let one_path_to_target = !self . basic_coverage_blocks . bcb_has_multiple_in_edges ( bcb) ;
360
- if one_path_to_target || self . bcb_predecessors ( bcb) . contains ( & bcb) {
361
- let counter_kind =
362
- self . coverage_counters . make_counter ( CounterIncrementSite :: Node { bcb } ) ;
363
- if one_path_to_target {
364
- debug ! ( "{bcb:?} gets a new counter: {counter_kind:?}" ) ;
365
- } else {
366
- debug ! (
367
- "{bcb:?} has itself as its own predecessor. It can't be part of its own \
368
- Expression sum, so it will get its own new counter: {counter_kind:?}. \
369
- (Note, the compiled code will generate an infinite loop.)",
370
- ) ;
371
- }
372
- return self . coverage_counters . set_bcb_counter ( bcb, counter_kind) ;
364
+ let predecessors = self . basic_coverage_blocks . predecessors [ bcb] . as_slice ( ) ;
365
+
366
+ // Handle cases where we can't compute a node's count from its in-edges:
367
+ // - START_BCB has no in-edges, so taking the sum would panic (or be wrong).
368
+ // - For nodes with one in-edge, or that directly loop to themselves,
369
+ // trying to get the in-edge counts would require this node's counter,
370
+ // leading to infinite recursion.
371
+ if predecessors. len ( ) <= 1 || predecessors. contains ( & bcb) {
372
+ debug ! ( ?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor" ) ;
373
+ return self . coverage_counters . make_phys_node_counter ( bcb) ;
373
374
}
374
375
375
376
// A BCB with multiple incoming edges can compute its count by ensuring that counters
376
377
// exist for each of those edges, and then adding them up to get a total count.
377
- let in_edge_counters = self . basic_coverage_blocks . predecessors [ bcb ]
378
+ let in_edge_counters = predecessors
378
379
. iter ( )
379
380
. copied ( )
380
381
. map ( |from_bcb| self . get_or_make_edge_counter ( from_bcb, bcb) )
@@ -500,11 +501,6 @@ impl<'a> MakeBcbCounters<'a> {
500
501
None
501
502
}
502
503
503
- #[ inline]
504
- fn bcb_predecessors ( & self , bcb : BasicCoverageBlock ) -> & [ BasicCoverageBlock ] {
505
- & self . basic_coverage_blocks . predecessors [ bcb]
506
- }
507
-
508
504
#[ inline]
509
505
fn bcb_successors ( & self , bcb : BasicCoverageBlock ) -> & [ BasicCoverageBlock ] {
510
506
& self . basic_coverage_blocks . successors [ bcb]
0 commit comments