@@ -5,7 +5,7 @@ use rustc_abi::Size;
55use rustc_codegen_ssa:: traits:: {
66 BuilderMethods , ConstCodegenMethods , CoverageInfoBuilderMethods , MiscCodegenMethods ,
77} ;
8- use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
8+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
99use rustc_middle:: mir:: coverage:: CoverageKind ;
1010use rustc_middle:: ty:: Instance ;
1111use tracing:: { debug, instrument} ;
@@ -20,9 +20,14 @@ mod mapgen;
2020
2121/// Extra per-CGU context/state needed for coverage instrumentation.
2222pub ( crate ) struct CguCoverageContext < ' ll , ' tcx > {
23- /// Coverage data for each instrumented function identified by DefId.
24- pub ( crate ) instances_used : RefCell < FxIndexSet < Instance < ' tcx > > > ,
25- pub ( crate ) pgo_func_name_var_map : RefCell < FxHashMap < Instance < ' tcx > , & ' ll llvm:: Value > > ,
23+ /// Associates function instances with an LLVM global that holds the
24+ /// function's symbol name, as needed by LLVM coverage intrinsics.
25+ ///
26+ /// Instances in this map are also considered "used" for the purposes of
27+ /// emitting covfun records. Every covfun record holds a hash of its
28+ /// symbol name, and `llvm-cov` will exit fatally if it can't resolve that
29+ /// hash back to an entry in the binary's `__llvm_prf_names` linker section.
30+ pub ( crate ) pgo_func_name_var_map : RefCell < FxIndexMap < Instance < ' tcx > , & ' ll llvm:: Value > > ,
2631 pub ( crate ) mcdc_condition_bitmap_map : RefCell < FxHashMap < Instance < ' tcx > , Vec < & ' ll llvm:: Value > > > ,
2732
2833 covfun_section_name : OnceCell < CString > ,
@@ -31,7 +36,6 @@ pub(crate) struct CguCoverageContext<'ll, 'tcx> {
3136impl < ' ll , ' tcx > CguCoverageContext < ' ll , ' tcx > {
3237 pub ( crate ) fn new ( ) -> Self {
3338 Self {
34- instances_used : RefCell :: < FxIndexSet < _ > > :: default ( ) ,
3539 pgo_func_name_var_map : Default :: default ( ) ,
3640 mcdc_condition_bitmap_map : Default :: default ( ) ,
3741 covfun_section_name : Default :: default ( ) ,
@@ -53,6 +57,14 @@ impl<'ll, 'tcx> CguCoverageContext<'ll, 'tcx> {
5357 . and_then ( |bitmap_map| bitmap_map. get ( decision_depth as usize ) )
5458 . copied ( ) // Dereference Option<&&Value> to Option<&Value>
5559 }
60+
61+ /// Returns the list of instances considered "used" in this CGU, as
62+ /// inferred from the keys of `pgo_func_name_var_map`.
63+ pub ( crate ) fn instances_used ( & self ) -> Vec < Instance < ' tcx > > {
64+ // Collecting into a Vec is way easier than trying to juggle RefCell
65+ // projections, and this should only run once per CGU anyway.
66+ self . pgo_func_name_var_map . borrow ( ) . keys ( ) . copied ( ) . collect :: < Vec < _ > > ( )
67+ }
5668}
5769
5870impl < ' ll , ' tcx > CodegenCx < ' ll , ' tcx > {
@@ -78,7 +90,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
7890 /// string, to hold the function name passed to LLVM intrinsic
7991 /// `instrprof.increment()`. The `Value` is only created once per instance.
8092 /// Multiple invocations with the same instance return the same `Value`.
81- fn get_pgo_func_name_var ( & self , instance : Instance < ' tcx > ) -> & ' ll llvm:: Value {
93+ ///
94+ /// This has the side-effect of causing coverage codegen to consider this
95+ /// function "used", making it eligible to emit an associated covfun record.
96+ fn ensure_pgo_func_name_var ( & self , instance : Instance < ' tcx > ) -> & ' ll llvm:: Value {
8297 debug ! ( "getting pgo_func_name_var for instance={:?}" , instance) ;
8398 let mut pgo_func_name_var_map = self . coverage_cx ( ) . pgo_func_name_var_map . borrow_mut ( ) ;
8499 pgo_func_name_var_map. entry ( instance) . or_insert_with ( || {
@@ -102,7 +117,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
102117 return ;
103118 }
104119
105- let fn_name = self . get_pgo_func_name_var ( instance) ;
120+ let fn_name = self . ensure_pgo_func_name_var ( instance) ;
106121 let hash = self . const_u64 ( function_coverage_info. function_source_hash ) ;
107122 let bitmap_bits = self . const_u32 ( function_coverage_info. mcdc_bitmap_bits as u32 ) ;
108123 self . mcdc_parameters ( fn_name, hash, bitmap_bits) ;
@@ -151,19 +166,14 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
151166 return ;
152167 } ;
153168
154- // Mark the instance as used in this CGU, for coverage purposes.
155- // This includes functions that were not partitioned into this CGU,
156- // but were MIR-inlined into one of this CGU's functions.
157- coverage_cx. instances_used . borrow_mut ( ) . insert ( instance) ;
158-
159169 match * kind {
160170 CoverageKind :: SpanMarker | CoverageKind :: BlockMarker { .. } => unreachable ! (
161171 "marker statement {kind:?} should have been removed by CleanupPostBorrowck"
162172 ) ,
163173 CoverageKind :: VirtualCounter { bcb }
164174 if let Some ( & id) = ids_info. phys_counter_for_node . get ( & bcb) =>
165175 {
166- let fn_name = bx. get_pgo_func_name_var ( instance) ;
176+ let fn_name = bx. ensure_pgo_func_name_var ( instance) ;
167177 let hash = bx. const_u64 ( function_coverage_info. function_source_hash ) ;
168178 let num_counters = bx. const_u32 ( ids_info. num_counters ) ;
169179 let index = bx. const_u32 ( id. as_u32 ( ) ) ;
@@ -193,7 +203,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
193203 "bitmap index of the decision out of range"
194204 ) ;
195205
196- let fn_name = bx. get_pgo_func_name_var ( instance) ;
206+ let fn_name = bx. ensure_pgo_func_name_var ( instance) ;
197207 let hash = bx. const_u64 ( function_coverage_info. function_source_hash ) ;
198208 let bitmap_index = bx. const_u32 ( bitmap_idx) ;
199209 bx. mcdc_tvbitmap_update ( fn_name, hash, bitmap_index, cond_bitmap) ;
0 commit comments