@@ -12,8 +12,10 @@ use rustc_index::IndexVec;
1212use rustc_middle:: mir:: coverage:: MappingKind ;
1313use rustc_middle:: ty:: { self , TyCtxt } ;
1414use rustc_middle:: { bug, mir} ;
15- use rustc_span:: Symbol ;
15+ use rustc_session:: RemapFileNameExt ;
16+ use rustc_session:: config:: RemapPathScopeComponents ;
1617use rustc_span:: def_id:: DefIdSet ;
18+ use rustc_span:: { Span , Symbol } ;
1719use rustc_target:: spec:: HasTargetSpec ;
1820use tracing:: debug;
1921
@@ -70,8 +72,10 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
7072 . map ( |( instance, function_coverage) | ( instance, function_coverage. into_finished ( ) ) )
7173 . collect :: < Vec < _ > > ( ) ;
7274
73- let all_file_names =
74- function_coverage_entries. iter ( ) . flat_map ( |( _, fn_cov) | fn_cov. all_file_names ( ) ) ;
75+ let all_file_names = function_coverage_entries
76+ . iter ( )
77+ . map ( |( _, fn_cov) | fn_cov. function_coverage_info . body_span )
78+ . map ( |span| span_file_name ( tcx, span) ) ;
7579 let global_file_table = GlobalFileTable :: new ( all_file_names) ;
7680
7781 // Encode all filenames referenced by coverage mappings in this CGU.
@@ -96,7 +100,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
96100 let is_used = function_coverage. is_used ( ) ;
97101
98102 let coverage_mapping_buffer =
99- encode_mappings_for_function ( & global_file_table, & function_coverage) ;
103+ encode_mappings_for_function ( tcx , & global_file_table, & function_coverage) ;
100104
101105 if coverage_mapping_buffer. is_empty ( ) {
102106 if function_coverage. is_used ( ) {
@@ -164,13 +168,13 @@ impl GlobalFileTable {
164168 Self { raw_file_table }
165169 }
166170
167- fn global_file_id_for_file_name ( & self , file_name : Symbol ) -> u32 {
171+ fn global_file_id_for_file_name ( & self , file_name : Symbol ) -> GlobalFileId {
168172 let raw_id = self . raw_file_table . get_index_of ( & file_name) . unwrap_or_else ( || {
169173 bug ! ( "file name not found in prepared global file table: {file_name}" ) ;
170174 } ) ;
171175 // The raw file table doesn't include an entry for the working dir
172176 // (which has ID 0), so add 1 to get the correct ID.
173- ( raw_id + 1 ) as u32
177+ GlobalFileId :: from_usize ( raw_id + 1 )
174178 }
175179
176180 fn make_filenames_buffer ( & self , tcx : TyCtxt < ' _ > ) -> Vec < u8 > {
@@ -196,36 +200,54 @@ impl GlobalFileTable {
196200}
197201
198202rustc_index:: newtype_index! {
199- struct LocalFileId { }
203+ /// An index into the CGU's overall list of file paths. The underlying paths
204+ /// will be embedded in the `__llvm_covmap` linker section.
205+ struct GlobalFileId { }
206+ }
207+ rustc_index:: newtype_index! {
208+ /// An index into a function's list of global file IDs. That underlying list
209+ /// of local-to-global mappings will be embedded in the function's record in
210+ /// the `__llvm_covfun` linker section.
211+ pub ( crate ) struct LocalFileId { }
200212}
201213
202214/// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU)
203215/// file IDs.
204216#[ derive( Default ) ]
205217struct VirtualFileMapping {
206- local_to_global : IndexVec < LocalFileId , u32 > ,
207- global_to_local : FxIndexMap < u32 , LocalFileId > ,
218+ local_to_global : IndexVec < LocalFileId , GlobalFileId > ,
219+ global_to_local : FxIndexMap < GlobalFileId , LocalFileId > ,
208220}
209221
210222impl VirtualFileMapping {
211- fn local_id_for_global ( & mut self , global_file_id : u32 ) -> LocalFileId {
223+ fn local_id_for_global ( & mut self , global_file_id : GlobalFileId ) -> LocalFileId {
212224 * self
213225 . global_to_local
214226 . entry ( global_file_id)
215227 . or_insert_with ( || self . local_to_global . push ( global_file_id) )
216228 }
217229
218230 fn into_vec ( self ) -> Vec < u32 > {
219- self . local_to_global . raw
231+ // This conversion should be optimized away to ~zero overhead.
232+ // In any case, it's probably not hot enough to worry about.
233+ self . local_to_global . into_iter ( ) . map ( |global| global. as_u32 ( ) ) . collect ( )
220234 }
221235}
222236
237+ fn span_file_name ( tcx : TyCtxt < ' _ > , span : Span ) -> Symbol {
238+ let source_file = tcx. sess . source_map ( ) . lookup_source_file ( span. lo ( ) ) ;
239+ let name =
240+ source_file. name . for_scope ( tcx. sess , RemapPathScopeComponents :: MACRO ) . to_string_lossy ( ) ;
241+ Symbol :: intern ( & name)
242+ }
243+
223244/// Using the expressions and counter regions collected for a single function,
224245/// generate the variable-sized payload of its corresponding `__llvm_covfun`
225246/// entry. The payload is returned as a vector of bytes.
226247///
227248/// Newly-encountered filenames will be added to the global file table.
228249fn encode_mappings_for_function (
250+ tcx : TyCtxt < ' _ > ,
229251 global_file_table : & GlobalFileTable ,
230252 function_coverage : & FunctionCoverage < ' _ > ,
231253) -> Vec < u8 > {
@@ -242,53 +264,45 @@ fn encode_mappings_for_function(
242264 let mut mcdc_branch_regions = vec ! [ ] ;
243265 let mut mcdc_decision_regions = vec ! [ ] ;
244266
245- // Group mappings into runs with the same filename, preserving the order
246- // yielded by `FunctionCoverage`.
247- // Prepare file IDs for each filename, and prepare the mapping data so that
248- // we can pass it through FFI to LLVM.
249- for ( file_name, counter_regions_for_file) in
250- & counter_regions. group_by ( |( _, region) | region. file_name )
251- {
252- // Look up the global file ID for this filename.
253- let global_file_id = global_file_table. global_file_id_for_file_name ( file_name) ;
254-
255- // Associate that global file ID with a local file ID for this function.
256- let local_file_id = virtual_file_mapping. local_id_for_global ( global_file_id) ;
257- debug ! ( " file id: {local_file_id:?} => global {global_file_id} = '{file_name:?}'" ) ;
258-
259- // For each counter/region pair in this function+file, convert it to a
260- // form suitable for FFI.
261- for ( mapping_kind, region) in counter_regions_for_file {
262- debug ! ( "Adding counter {mapping_kind:?} to map for {region:?}" ) ;
263- let span = ffi:: CoverageSpan :: from_source_region ( local_file_id. as_u32 ( ) , region) ;
264- match mapping_kind {
265- MappingKind :: Code ( term) => {
266- code_regions
267- . push ( ffi:: CodeRegion { span, counter : ffi:: Counter :: from_term ( term) } ) ;
268- }
269- MappingKind :: Branch { true_term, false_term } => {
270- branch_regions. push ( ffi:: BranchRegion {
271- span,
272- true_counter : ffi:: Counter :: from_term ( true_term) ,
273- false_counter : ffi:: Counter :: from_term ( false_term) ,
274- } ) ;
275- }
276- MappingKind :: MCDCBranch { true_term, false_term, mcdc_params } => {
277- mcdc_branch_regions. push ( ffi:: MCDCBranchRegion {
278- span,
279- true_counter : ffi:: Counter :: from_term ( true_term) ,
280- false_counter : ffi:: Counter :: from_term ( false_term) ,
281- mcdc_branch_params : ffi:: mcdc:: BranchParameters :: from ( mcdc_params) ,
282- } ) ;
283- }
284- MappingKind :: MCDCDecision ( mcdc_decision_params) => {
285- mcdc_decision_regions. push ( ffi:: MCDCDecisionRegion {
286- span,
287- mcdc_decision_params : ffi:: mcdc:: DecisionParameters :: from (
288- mcdc_decision_params,
289- ) ,
290- } ) ;
291- }
267+ // Currently a function's mappings must all be in the same file as its body span.
268+ let file_name = span_file_name ( tcx, function_coverage. function_coverage_info . body_span ) ;
269+
270+ // Look up the global file ID for that filename.
271+ let global_file_id = global_file_table. global_file_id_for_file_name ( file_name) ;
272+
273+ // Associate that global file ID with a local file ID for this function.
274+ let local_file_id = virtual_file_mapping. local_id_for_global ( global_file_id) ;
275+ debug ! ( " file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'" ) ;
276+
277+ // For each counter/region pair in this function+file, convert it to a
278+ // form suitable for FFI.
279+ for ( mapping_kind, region) in counter_regions {
280+ debug ! ( "Adding counter {mapping_kind:?} to map for {region:?}" ) ;
281+ let span = ffi:: CoverageSpan :: from_source_region ( local_file_id, region) ;
282+ match mapping_kind {
283+ MappingKind :: Code ( term) => {
284+ code_regions. push ( ffi:: CodeRegion { span, counter : ffi:: Counter :: from_term ( term) } ) ;
285+ }
286+ MappingKind :: Branch { true_term, false_term } => {
287+ branch_regions. push ( ffi:: BranchRegion {
288+ span,
289+ true_counter : ffi:: Counter :: from_term ( true_term) ,
290+ false_counter : ffi:: Counter :: from_term ( false_term) ,
291+ } ) ;
292+ }
293+ MappingKind :: MCDCBranch { true_term, false_term, mcdc_params } => {
294+ mcdc_branch_regions. push ( ffi:: MCDCBranchRegion {
295+ span,
296+ true_counter : ffi:: Counter :: from_term ( true_term) ,
297+ false_counter : ffi:: Counter :: from_term ( false_term) ,
298+ mcdc_branch_params : ffi:: mcdc:: BranchParameters :: from ( mcdc_params) ,
299+ } ) ;
300+ }
301+ MappingKind :: MCDCDecision ( mcdc_decision_params) => {
302+ mcdc_decision_regions. push ( ffi:: MCDCDecisionRegion {
303+ span,
304+ mcdc_decision_params : ffi:: mcdc:: DecisionParameters :: from ( mcdc_decision_params) ,
305+ } ) ;
292306 }
293307 }
294308 }
0 commit comments