@@ -90,64 +90,69 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
90
90
args : & Vec < Operand < ' tcx > > ,
91
91
caller_instance : ty:: Instance < ' tcx > ,
92
92
) -> bool {
93
+ let mut is_codegen_intrinsic = true ;
94
+ // Set `is_codegen_intrinsic` to `false` to bypass `codegen_intrinsic_call()`.
95
+
93
96
if self . tcx . sess . opts . debugging_opts . instrument_coverage {
94
- // Add the coverage information from the MIR to the Codegen context. Some coverage
95
- // intrinsics are used only to pass along the coverage information (returns `false`
96
- // for `is_codegen_intrinsic()`), but `count_code_region` is also converted into an
97
- // LLVM intrinsic to increment a coverage counter.
98
- match intrinsic {
99
- sym:: count_code_region => {
100
- use coverage:: count_code_region_args:: * ;
101
- self . add_counter_region (
102
- caller_instance,
103
- op_to_u64 ( & args[ FUNCTION_SOURCE_HASH ] ) ,
104
- op_to_u32 ( & args[ COUNTER_ID ] ) ,
105
- op_to_u32 ( & args[ START_BYTE_POS ] ) ,
106
- op_to_u32 ( & args[ END_BYTE_POS ] ) ,
107
- ) ;
108
- return true ; // Also inject the counter increment in the backend
109
- }
110
- sym:: coverage_counter_add | sym:: coverage_counter_subtract => {
111
- use coverage:: coverage_counter_expression_args:: * ;
112
- self . add_counter_expression_region (
113
- caller_instance,
114
- op_to_u32 ( & args[ EXPRESSION_ID ] ) ,
115
- op_to_u32 ( & args[ LEFT_ID ] ) ,
116
- if intrinsic == sym:: coverage_counter_add {
117
- ExprKind :: Add
118
- } else {
119
- ExprKind :: Subtract
120
- } ,
121
- op_to_u32 ( & args[ RIGHT_ID ] ) ,
122
- op_to_u32 ( & args[ START_BYTE_POS ] ) ,
123
- op_to_u32 ( & args[ END_BYTE_POS ] ) ,
124
- ) ;
125
- return false ; // Does not inject backend code
97
+ // If the intrinsic is from the local MIR, add the coverage information to the Codegen
98
+ // context, to be encoded into the local crate's coverage map.
99
+ if caller_instance. def_id ( ) . is_local ( ) {
100
+ // FIXME(richkadel): Make sure to add coverage analysis tests on a crate with
101
+ // external crate dependencies, where:
102
+ // 1. Both binary and dependent crates are compiled with `-Zinstrument-coverage`
103
+ // 2. Only binary is compiled with `-Zinstrument-coverage`
104
+ // 3. Only dependent crates are compiled with `-Zinstrument-coverage`
105
+ match intrinsic {
106
+ sym:: count_code_region => {
107
+ use coverage:: count_code_region_args:: * ;
108
+ self . add_counter_region (
109
+ caller_instance,
110
+ op_to_u64 ( & args[ FUNCTION_SOURCE_HASH ] ) ,
111
+ op_to_u32 ( & args[ COUNTER_ID ] ) ,
112
+ op_to_u32 ( & args[ START_BYTE_POS ] ) ,
113
+ op_to_u32 ( & args[ END_BYTE_POS ] ) ,
114
+ ) ;
115
+ }
116
+ sym:: coverage_counter_add | sym:: coverage_counter_subtract => {
117
+ use coverage:: coverage_counter_expression_args:: * ;
118
+ self . add_counter_expression_region (
119
+ caller_instance,
120
+ op_to_u32 ( & args[ EXPRESSION_ID ] ) ,
121
+ op_to_u32 ( & args[ LEFT_ID ] ) ,
122
+ if intrinsic == sym:: coverage_counter_add {
123
+ ExprKind :: Add
124
+ } else {
125
+ ExprKind :: Subtract
126
+ } ,
127
+ op_to_u32 ( & args[ RIGHT_ID ] ) ,
128
+ op_to_u32 ( & args[ START_BYTE_POS ] ) ,
129
+ op_to_u32 ( & args[ END_BYTE_POS ] ) ,
130
+ ) ;
131
+ }
132
+ sym:: coverage_unreachable => {
133
+ use coverage:: coverage_unreachable_args:: * ;
134
+ self . add_unreachable_region (
135
+ caller_instance,
136
+ op_to_u32 ( & args[ START_BYTE_POS ] ) ,
137
+ op_to_u32 ( & args[ END_BYTE_POS ] ) ,
138
+ ) ;
139
+ }
140
+ _ => { }
126
141
}
127
- sym:: coverage_unreachable => {
128
- use coverage:: coverage_unreachable_args:: * ;
129
- self . add_unreachable_region (
130
- caller_instance,
131
- op_to_u32 ( & args[ START_BYTE_POS ] ) ,
132
- op_to_u32 ( & args[ END_BYTE_POS ] ) ,
133
- ) ;
134
- return false ; // Does not inject backend code
142
+ }
143
+
144
+ // Only the `count_code_region` coverage intrinsic is translated into an actual LLVM
145
+ // intrinsic call (local or not); otherwise, set `is_codegen_intrinsic` to `false`.
146
+ match intrinsic {
147
+ sym:: coverage_counter_add
148
+ | sym:: coverage_counter_subtract
149
+ | sym:: coverage_unreachable => {
150
+ is_codegen_intrinsic = false ;
135
151
}
136
152
_ => { }
137
153
}
138
- } else {
139
- // NOT self.tcx.sess.opts.debugging_opts.instrument_coverage
140
- if intrinsic == sym:: count_code_region {
141
- // An external crate may have been pre-compiled with coverage instrumentation, and
142
- // some references from the current crate to the external crate might carry along
143
- // the call terminators to coverage intrinsics, like `count_code_region` (for
144
- // example, when instantiating a generic function). If the current crate has
145
- // `instrument_coverage` disabled, the `count_code_region` call terminators should
146
- // be ignored.
147
- return false ; // Do not inject coverage counters inlined from external crates
148
- }
149
154
}
150
- true // Unhandled intrinsics should be passed to `codegen_intrinsic_call()`
155
+ is_codegen_intrinsic
151
156
}
152
157
153
158
fn codegen_intrinsic_call (
0 commit comments