@@ -3,30 +3,33 @@ use crate::llvm;
33use crate :: abi:: Abi ;
44use crate :: builder:: Builder ;
55use crate :: common:: CodegenCx ;
6+ use crate :: coverageinfo:: map_data:: { CounterExpression , FunctionCoverage } ;
67
78use libc:: c_uint;
89use llvm:: coverageinfo:: CounterMappingRegion ;
9- use rustc_codegen_ssa:: coverageinfo:: map:: { CounterExpression , FunctionCoverage } ;
1010use rustc_codegen_ssa:: traits:: {
11- BaseTypeMethods , BuilderMethods , ConstMethods , CoverageInfoBuilderMethods , CoverageInfoMethods ,
12- MiscMethods , StaticMethods ,
11+ BaseTypeMethods , BuilderMethods , ConstMethods , CoverageInfoBuilderMethods , MiscMethods ,
12+ StaticMethods ,
1313} ;
1414use rustc_data_structures:: fx:: FxHashMap ;
1515use rustc_hir as hir;
1616use rustc_hir:: def_id:: DefId ;
1717use rustc_llvm:: RustString ;
1818use rustc_middle:: bug;
1919use rustc_middle:: mir:: coverage:: {
20- CodeRegion , CounterValueReference , ExpressionOperandId , InjectedExpressionId , Op ,
20+ CodeRegion , CounterValueReference , CoverageKind , ExpressionOperandId , InjectedExpressionId , Op ,
2121} ;
22+ use rustc_middle:: mir:: Coverage ;
2223use rustc_middle:: ty;
23- use rustc_middle:: ty:: layout:: FnAbiOf ;
24+ use rustc_middle:: ty:: layout:: { FnAbiOf , HasTyCtxt } ;
2425use rustc_middle:: ty:: subst:: InternalSubsts ;
2526use rustc_middle:: ty:: Instance ;
2627
2728use std:: cell:: RefCell ;
2829use std:: ffi:: CString ;
2930
31+ mod ffi;
32+ pub ( crate ) mod map_data;
3033pub mod mapgen;
3134
3235const UNUSED_FUNCTION_COUNTER_ID : CounterValueReference = CounterValueReference :: START ;
@@ -53,11 +56,17 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> {
5356 }
5457}
5558
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 ) {
5863 mapgen:: finalize ( self )
5964 }
6065
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`.
6170 fn get_pgo_func_name_var ( & self , instance : Instance < ' tcx > ) -> & ' ll llvm:: Value {
6271 if let Some ( coverage_context) = self . coverage_context ( ) {
6372 debug ! ( "getting pgo_func_name_var for instance={:?}" , instance) ;
@@ -94,6 +103,54 @@ impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
94103}
95104
96105impl < ' 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).
97154 fn set_function_source_hash (
98155 & mut self ,
99156 instance : Instance < ' tcx > ,
@@ -115,6 +172,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
115172 }
116173 }
117174
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).
118177 fn add_coverage_counter (
119178 & mut self ,
120179 instance : Instance < ' tcx > ,
@@ -137,6 +196,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
137196 }
138197 }
139198
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).
140201 fn add_coverage_counter_expression (
141202 & mut self ,
142203 instance : Instance < ' tcx > ,
@@ -163,6 +224,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
163224 }
164225 }
165226
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).
166229 fn add_coverage_unreachable ( & mut self , instance : Instance < ' tcx > , region : CodeRegion ) -> bool {
167230 if let Some ( coverage_context) = self . coverage_context ( ) {
168231 debug ! (
0 commit comments