@@ -3,30 +3,33 @@ use crate::llvm;
3
3
use crate::abi::Abi;
4
4
use crate::builder::Builder;
5
5
use crate::common::CodegenCx;
6
+ use crate::coverageinfo::map_data::{CounterExpression, FunctionCoverage};
6
7
7
8
use libc::c_uint;
8
9
use llvm::coverageinfo::CounterMappingRegion;
9
- use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, FunctionCoverage};
10
10
use rustc_codegen_ssa::traits::{
11
- BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, CoverageInfoMethods ,
12
- MiscMethods, StaticMethods,
11
+ BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods ,
12
+ StaticMethods,
13
13
};
14
14
use rustc_data_structures::fx::FxHashMap;
15
15
use rustc_hir as hir;
16
16
use rustc_hir::def_id::DefId;
17
17
use rustc_llvm::RustString;
18
18
use rustc_middle::bug;
19
19
use rustc_middle::mir::coverage::{
20
- CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
20
+ CodeRegion, CounterValueReference, CoverageKind, ExpressionOperandId, InjectedExpressionId, Op,
21
21
};
22
+ use rustc_middle::mir::Coverage;
22
23
use rustc_middle::ty;
23
- use rustc_middle::ty::layout::FnAbiOf;
24
+ use rustc_middle::ty::layout::{ FnAbiOf, HasTyCtxt} ;
24
25
use rustc_middle::ty::subst::InternalSubsts;
25
26
use rustc_middle::ty::Instance;
26
27
27
28
use std::cell::RefCell;
28
29
use std::ffi::CString;
29
30
31
+ mod ffi;
32
+ pub(crate) mod map_data;
30
33
pub mod mapgen;
31
34
32
35
const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START;
@@ -53,11 +56,17 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> {
53
56
}
54
57
}
55
58
56
- impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
57
- fn coverageinfo_finalize(&self) {
59
+ // These methods used to be part of trait `CoverageInfoMethods`, which no longer
60
+ // exists after most coverage code was moved out of SSA.
61
+ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
62
+ pub(crate) fn coverageinfo_finalize(&self) {
58
63
mapgen::finalize(self)
59
64
}
60
65
66
+ /// For LLVM codegen, returns a function-specific `Value` for a global
67
+ /// string, to hold the function name passed to LLVM intrinsic
68
+ /// `instrprof.increment()`. The `Value` is only created once per instance.
69
+ /// Multiple invocations with the same instance return the same `Value`.
61
70
fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value {
62
71
if let Some(coverage_context) = self.coverage_context() {
63
72
debug!("getting pgo_func_name_var for instance={:?}", instance);
@@ -94,6 +103,54 @@ impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
94
103
}
95
104
96
105
impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
106
+ fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) {
107
+ let bx = self;
108
+
109
+ let Coverage { kind, code_region } = coverage.clone();
110
+ match kind {
111
+ CoverageKind::Counter { function_source_hash, id } => {
112
+ if bx.set_function_source_hash(instance, function_source_hash) {
113
+ // If `set_function_source_hash()` returned true, the coverage map is enabled,
114
+ // so continue adding the counter.
115
+ if let Some(code_region) = code_region {
116
+ // Note: Some counters do not have code regions, but may still be referenced
117
+ // from expressions. In that case, don't add the counter to the coverage map,
118
+ // but do inject the counter intrinsic.
119
+ bx.add_coverage_counter(instance, id, code_region);
120
+ }
121
+
122
+ let coverageinfo = bx.tcx().coverageinfo(instance.def);
123
+
124
+ let fn_name = bx.get_pgo_func_name_var(instance);
125
+ let hash = bx.const_u64(function_source_hash);
126
+ let num_counters = bx.const_u32(coverageinfo.num_counters);
127
+ let index = bx.const_u32(id.zero_based_index());
128
+ debug!(
129
+ "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
130
+ fn_name, hash, num_counters, index,
131
+ );
132
+ bx.instrprof_increment(fn_name, hash, num_counters, index);
133
+ }
134
+ }
135
+ CoverageKind::Expression { id, lhs, op, rhs } => {
136
+ bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
137
+ }
138
+ CoverageKind::Unreachable => {
139
+ bx.add_coverage_unreachable(
140
+ instance,
141
+ code_region.expect("unreachable regions always have code regions"),
142
+ );
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ // These methods used to be part of trait `CoverageInfoBuilderMethods`, but
149
+ // after moving most coverage code out of SSA they are now just ordinary methods.
150
+ impl<'tcx> Builder<'_, '_, 'tcx> {
151
+ /// Returns true if the function source hash was added to the coverage map (even if it had
152
+ /// already been added, for this instance). Returns false *only* if `-C instrument-coverage` is
153
+ /// not enabled (a coverage map is not being generated).
97
154
fn set_function_source_hash(
98
155
&mut self,
99
156
instance: Instance<'tcx>,
@@ -115,6 +172,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
115
172
}
116
173
}
117
174
175
+ /// Returns true if the counter was added to the coverage map; false if `-C instrument-coverage`
176
+ /// is not enabled (a coverage map is not being generated).
118
177
fn add_coverage_counter(
119
178
&mut self,
120
179
instance: Instance<'tcx>,
@@ -137,6 +196,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
137
196
}
138
197
}
139
198
199
+ /// Returns true if the expression was added to the coverage map; false if
200
+ /// `-C instrument-coverage` is not enabled (a coverage map is not being generated).
140
201
fn add_coverage_counter_expression(
141
202
&mut self,
142
203
instance: Instance<'tcx>,
@@ -163,6 +224,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
163
224
}
164
225
}
165
226
227
+ /// Returns true if the region was added to the coverage map; false if `-C instrument-coverage`
228
+ /// is not enabled (a coverage map is not being generated).
166
229
fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool {
167
230
if let Some(coverage_context) = self.coverage_context() {
168
231
debug!(
0 commit comments