@@ -35,6 +35,11 @@ const ID_SEPARATOR: &str = ",";
35
35
36
36
const RUSTC_COVERAGE_DEBUG_OPTIONS : & str = "RUSTC_COVERAGE_DEBUG_OPTIONS" ;
37
37
38
+ /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
39
+ /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
40
+ /// to construct the coverage map.
41
+ pub struct InstrumentCoverage ;
42
+
38
43
#[ derive( Debug , Clone ) ]
39
44
struct DebugOptions {
40
45
allow_unused_expressions : bool ,
@@ -138,10 +143,119 @@ impl Default for ExpressionFormat {
138
143
}
139
144
}
140
145
141
- /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
142
- /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
143
- /// to construct the coverage map.
144
- pub struct InstrumentCoverage ;
146
+ #[ derive( Debug ) ]
147
+ struct DebugCounter {
148
+ counter_kind : CoverageKind ,
149
+ some_block_label : Option < String > ,
150
+ }
151
+
152
+ impl DebugCounter {
153
+ fn new ( counter_kind : CoverageKind , some_block_label : Option < String > ) -> Self {
154
+ Self {
155
+ counter_kind,
156
+ some_block_label,
157
+ }
158
+ }
159
+ }
160
+
161
+ struct DebugCounters {
162
+ some_counters : Option < FxHashMap < ExpressionOperandId , DebugCounter > > ,
163
+ }
164
+
165
+ impl DebugCounters {
166
+ pub fn new ( ) -> Self {
167
+ Self {
168
+ some_counters : None ,
169
+ }
170
+ }
171
+
172
+ pub fn enable ( & mut self ) {
173
+ self . some_counters . replace ( FxHashMap :: default ( ) ) ;
174
+ }
175
+
176
+ pub fn is_enabled ( & mut self ) -> bool {
177
+ self . some_counters . is_some ( )
178
+ }
179
+
180
+ pub fn add_counter ( & mut self , counter_kind : & CoverageKind , some_block_label : Option < String > ) {
181
+ if let Some ( counters) = & mut self . some_counters {
182
+ let id: ExpressionOperandId = match * counter_kind {
183
+ CoverageKind :: Counter { id, .. } => id. into ( ) ,
184
+ | CoverageKind :: Expression { id, .. } => id. into ( ) ,
185
+ _ => bug ! ( "the given `CoverageKind` is not an counter or expression: {:?}" , counter_kind) ,
186
+ } ;
187
+ counters. insert ( id. into ( ) , DebugCounter :: new ( counter_kind. clone ( ) , some_block_label) ) . expect_none ( "attempt to add the same counter_kind to DebugCounters more than once" ) ;
188
+ }
189
+ }
190
+
191
+ pub fn some_block_label ( & self , operand : ExpressionOperandId ) -> Option < & String > {
192
+ self . some_counters . as_ref ( ) . map_or ( None , |counters| counters. get ( & operand) . map_or ( None , |debug_counter| debug_counter. some_block_label . as_ref ( ) ) )
193
+ }
194
+
195
+ pub fn format_counter ( & self , counter_kind : & CoverageKind ) -> String {
196
+ match * counter_kind {
197
+ CoverageKind :: Counter { .. } => format ! ( "Counter({})" , self . format_counter_kind( counter_kind) ) ,
198
+ CoverageKind :: Expression { .. } => format ! ( "Expression({})" , self . format_counter_kind( counter_kind) ) ,
199
+ CoverageKind :: Unreachable { .. } => "Unreachable" . to_owned ( ) ,
200
+ }
201
+ }
202
+
203
+ fn format_counter_kind ( & self , counter_kind : & CoverageKind ) -> String {
204
+ let counter_format = & debug_options ( ) . counter_format ;
205
+ if let CoverageKind :: Expression { id, lhs, op, rhs } = * counter_kind {
206
+ if counter_format. operation {
207
+ return format ! (
208
+ "{}{} {} {}" ,
209
+ if counter_format. id || self . some_counters. is_none( ) {
210
+ format!( "#{} = " , id. index( ) )
211
+ } else {
212
+ String :: new( )
213
+ } ,
214
+ self . format_operand( lhs) ,
215
+ if op == Op :: Add { "+" } else { "-" } ,
216
+ self . format_operand( rhs) ,
217
+ ) ;
218
+ }
219
+ }
220
+
221
+ let id: ExpressionOperandId = match * counter_kind {
222
+ CoverageKind :: Counter { id, .. } => id. into ( ) ,
223
+ | CoverageKind :: Expression { id, .. } => id. into ( ) ,
224
+ _ => bug ! ( "the given `CoverageKind` is not an counter or expression: {:?}" , counter_kind) ,
225
+ } ;
226
+ if self . some_counters . is_some ( ) && ( counter_format. block || !counter_format. id ) {
227
+ let counters = self . some_counters . as_ref ( ) . unwrap ( ) ;
228
+ if let Some ( DebugCounter { some_block_label : Some ( block_label) , .. } ) = counters. get ( & id. into ( ) ) {
229
+ return if counter_format. id {
230
+ format ! ( "{}#{}" , block_label, id. index( ) )
231
+ } else {
232
+ format ! ( "{}" , block_label)
233
+ }
234
+ }
235
+ }
236
+ format ! ( "#{}" , id. index( ) )
237
+ }
238
+
239
+ fn format_operand ( & self , operand : ExpressionOperandId ) -> String {
240
+ if operand. index ( ) == 0 {
241
+ return String :: from ( "0" ) ;
242
+ }
243
+ if let Some ( counters) = & self . some_counters {
244
+ if let Some ( DebugCounter { counter_kind, some_block_label } ) = counters. get ( & operand) {
245
+ if let CoverageKind :: Expression { .. } = counter_kind {
246
+ if let Some ( block_label) = some_block_label {
247
+ if debug_options ( ) . counter_format . block {
248
+ return format ! ( "{}:({})" , block_label, self . format_counter_kind( counter_kind) ) ;
249
+ }
250
+ }
251
+ return format ! ( "({})" , self . format_counter_kind( counter_kind) ) ;
252
+ }
253
+ return format ! ( "{}" , self . format_counter_kind( counter_kind) ) ;
254
+ }
255
+ }
256
+ format ! ( "#{}" , operand. index( ) . to_string( ) )
257
+ }
258
+ }
145
259
146
260
/// The `query` provider for `CoverageInfo`, requested by `codegen_coverage()` (to inject each
147
261
/// counter) and `FunctionCoverage::new()` (to extract the coverage map metadata from the MIR).
@@ -923,120 +1037,6 @@ struct TraversalContext {
923
1037
worklist : Vec < BasicCoverageBlock > ,
924
1038
}
925
1039
926
- #[ derive( Debug ) ]
927
- struct DebugCounter {
928
- counter_kind : CoverageKind ,
929
- some_block_label : Option < String > ,
930
- }
931
-
932
- impl DebugCounter {
933
- fn new ( counter_kind : CoverageKind , some_block_label : Option < String > ) -> Self {
934
- Self {
935
- counter_kind,
936
- some_block_label,
937
- }
938
- }
939
- }
940
-
941
- struct DebugCounters {
942
- some_counters : Option < FxHashMap < ExpressionOperandId , DebugCounter > > ,
943
- }
944
-
945
- impl DebugCounters {
946
- pub fn new ( ) -> Self {
947
- Self {
948
- some_counters : None ,
949
- }
950
- }
951
-
952
- pub fn enable ( & mut self ) {
953
- self . some_counters . replace ( FxHashMap :: default ( ) ) ;
954
- }
955
-
956
- pub fn is_enabled ( & mut self ) -> bool {
957
- self . some_counters . is_some ( )
958
- }
959
-
960
- pub fn add_counter ( & mut self , counter_kind : & CoverageKind , some_block_label : Option < String > ) {
961
- if let Some ( counters) = & mut self . some_counters {
962
- let id: ExpressionOperandId = match * counter_kind {
963
- CoverageKind :: Counter { id, .. } => id. into ( ) ,
964
- | CoverageKind :: Expression { id, .. } => id. into ( ) ,
965
- _ => bug ! ( "the given `CoverageKind` is not an counter or expression: {:?}" , counter_kind) ,
966
- } ;
967
- counters. insert ( id. into ( ) , DebugCounter :: new ( counter_kind. clone ( ) , some_block_label) ) . expect_none ( "attempt to add the same counter_kind to DebugCounters more than once" ) ;
968
- }
969
- }
970
-
971
- pub fn some_block_label ( & self , operand : ExpressionOperandId ) -> Option < & String > {
972
- self . some_counters . as_ref ( ) . map_or ( None , |counters| counters. get ( & operand) . map_or ( None , |debug_counter| debug_counter. some_block_label . as_ref ( ) ) )
973
- }
974
-
975
- pub fn format_counter ( & self , counter_kind : & CoverageKind ) -> String {
976
- match * counter_kind {
977
- CoverageKind :: Counter { .. } => format ! ( "Counter({})" , self . format_counter_kind( counter_kind) ) ,
978
- CoverageKind :: Expression { .. } => format ! ( "Expression({})" , self . format_counter_kind( counter_kind) ) ,
979
- CoverageKind :: Unreachable { .. } => "Unreachable" . to_owned ( ) ,
980
- }
981
- }
982
-
983
- fn format_counter_kind ( & self , counter_kind : & CoverageKind ) -> String {
984
- let counter_format = & debug_options ( ) . counter_format ;
985
- if let CoverageKind :: Expression { id, lhs, op, rhs } = * counter_kind {
986
- if counter_format. operation {
987
- return format ! (
988
- "{}{} {} {}" ,
989
- if counter_format. id || self . some_counters. is_none( ) {
990
- format!( "#{} = " , id. index( ) )
991
- } else {
992
- String :: new( )
993
- } ,
994
- self . format_operand( lhs) ,
995
- if op == Op :: Add { "+" } else { "-" } ,
996
- self . format_operand( rhs) ,
997
- ) ;
998
- }
999
- }
1000
-
1001
- let id: ExpressionOperandId = match * counter_kind {
1002
- CoverageKind :: Counter { id, .. } => id. into ( ) ,
1003
- | CoverageKind :: Expression { id, .. } => id. into ( ) ,
1004
- _ => bug ! ( "the given `CoverageKind` is not an counter or expression: {:?}" , counter_kind) ,
1005
- } ;
1006
- if self . some_counters . is_some ( ) && ( counter_format. block || !counter_format. id ) {
1007
- let counters = self . some_counters . as_ref ( ) . unwrap ( ) ;
1008
- if let Some ( DebugCounter { some_block_label : Some ( block_label) , .. } ) = counters. get ( & id. into ( ) ) {
1009
- return if counter_format. id {
1010
- format ! ( "{}#{}" , block_label, id. index( ) )
1011
- } else {
1012
- format ! ( "{}" , block_label)
1013
- }
1014
- }
1015
- }
1016
- format ! ( "#{}" , id. index( ) )
1017
- }
1018
-
1019
- fn format_operand ( & self , operand : ExpressionOperandId ) -> String {
1020
- if operand. index ( ) == 0 {
1021
- return String :: from ( "0" ) ;
1022
- }
1023
- if let Some ( counters) = & self . some_counters {
1024
- if let Some ( DebugCounter { counter_kind, some_block_label } ) = counters. get ( & operand) {
1025
- if let CoverageKind :: Expression { .. } = counter_kind {
1026
- if let Some ( block_label) = some_block_label {
1027
- if debug_options ( ) . counter_format . block {
1028
- return format ! ( "{}:({})" , block_label, self . format_counter_kind( counter_kind) ) ;
1029
- }
1030
- }
1031
- return format ! ( "({})" , self . format_counter_kind( counter_kind) ) ;
1032
- }
1033
- return format ! ( "{}" , self . format_counter_kind( counter_kind) ) ;
1034
- }
1035
- }
1036
- format ! ( "#{}" , operand. index( ) . to_string( ) )
1037
- }
1038
- }
1039
-
1040
1040
struct Instrumentor < ' a , ' tcx > {
1041
1041
pass_name : & ' a str ,
1042
1042
tcx : TyCtxt < ' tcx > ,
@@ -1130,13 +1130,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
1130
1130
if level_enabled ! ( tracing:: Level :: DEBUG ) || dump_graphviz {
1131
1131
debug_used_expression_operands = Some ( FxHashMap :: default ( ) ) ;
1132
1132
debug_unused_expressions = Some ( Vec :: new ( ) ) ;
1133
- // TODO(richkadel): remove me:
1134
- // const SIMPLIFY_EXPRESSIONS: bool = false;
1135
- // if SIMPLIFY_EXPRESSIONS {
1136
1133
if debug_options ( ) . simplify_expressions {
1137
1134
self . debug_expressions_cache . replace ( FxHashMap :: default ( ) ) ;
1138
1135
}
1139
- // CAUTION! The `SIMPLIFY_EXPRESSIONS ` option is only helpful for some debugging
1136
+ // CAUTION! The `simplify_expressions ` option is only helpful for some debugging
1140
1137
// situations and it can change the generated MIR `Coverage` statements (resulting in
1141
1138
// differences in behavior when enabled, under `DEBUG`, compared to normal operation and
1142
1139
// testing).
@@ -1165,10 +1162,14 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
1165
1162
debug_edge_to_counter = Some ( FxHashMap :: default ( ) ) ;
1166
1163
}
1167
1164
1165
+ let mut bcbs_with_coverage = BitSet :: new_empty ( self . basic_coverage_blocks . num_nodes ( ) ) ;
1166
+ for covspan in & coverage_spans {
1167
+ bcbs_with_coverage. insert ( covspan. bcb ) ;
1168
+ }
1169
+
1168
1170
// Analyze the coverage graph (aka, BCB control flow graph), and inject expression-optimized
1169
1171
// counters.
1170
-
1171
- self . make_bcb_counters ( & mut collect_intermediate_expressions) ;
1172
+ self . make_bcb_counters ( bcbs_with_coverage, & mut collect_intermediate_expressions) ;
1172
1173
1173
1174
// If debugging, add any intermediate expressions (which are not associated with any BCB) to
1174
1175
// the `debug_used_expression_operands` map.
@@ -1438,14 +1439,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
1438
1439
// FIXME(richkadel): Determine if unused expressions can and should be prevented, and
1439
1440
// if so, it would be a `bug!` if encountered in the future. At the present time,
1440
1441
// however we do sometimes encounter unused expressions (in only a subset of test cases)
1441
- // even when `SIMPLIFY_EXPRESSIONS ` is disabled. It's not yet clear what causes this, or
1442
+ // even when `simplify_expressions ` is disabled. It's not yet clear what causes this, or
1442
1443
// if it should be allowed in the long term, but as long as the coverage capability
1443
1444
// still works, generate warning messages only, for now.
1444
- // TODO(richkadel): remove:
1445
- // const ALLOW_UNUSED_EXPRESSIONS: bool = true;
1446
- // if self.debug_expressions_cache.is_some() || ALLOW_UNUSED_EXPRESSIONS {
1447
1445
if self . debug_expressions_cache . is_some ( ) || debug_options ( ) . allow_unused_expressions {
1448
- // Note, the debugging const `SIMPLIFY_EXPRESSIONS `, which initializes the
1446
+ // Note, the debugging option `simplify_expressions `, which initializes the
1449
1447
// `debug_expressions_cache` can cause some counters to become unused, and
1450
1448
// is not a bug.
1451
1449
//
@@ -1518,7 +1516,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
1518
1516
///
1519
1517
/// Returns non-code-span expressions created to represent intermediate values (if required),
1520
1518
/// such as to add two counters so the result can be subtracted from another counter.
1521
- fn make_bcb_counters ( & mut self , collect_intermediate_expressions : & mut Vec < CoverageKind > ) {
1519
+ fn make_bcb_counters (
1520
+ & mut self ,
1521
+ bcbs_with_coverage : BitSet < BasicCoverageBlock > ,
1522
+ collect_intermediate_expressions : & mut Vec < CoverageKind > ,
1523
+ ) {
1522
1524
debug ! ( "make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock" ) ;
1523
1525
let num_bcbs = self . basic_coverage_blocks . num_nodes ( ) ;
1524
1526
let mut backedges = IndexVec :: from_elem_n (
@@ -1608,6 +1610,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
1608
1610
}
1609
1611
}
1610
1612
1613
+ if !bcbs_with_coverage. contains ( bcb) {
1614
+ continue ;
1615
+ }
1616
+
1611
1617
let bcb_counter_operand = self . get_or_make_counter_operand ( bcb, collect_intermediate_expressions) ;
1612
1618
1613
1619
let needs_branch_counters = {
0 commit comments