1
1
use std:: iter;
2
2
3
- use itertools:: Itertools as _ ;
3
+ use itertools:: Itertools ;
4
4
use rustc_abi:: Align ;
5
5
use rustc_codegen_ssa:: traits:: {
6
6
BaseTypeCodegenMethods , ConstCodegenMethods , StaticCodegenMethods ,
7
7
} ;
8
8
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
9
9
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
10
10
use rustc_index:: IndexVec ;
11
+ use rustc_middle:: mir;
11
12
use rustc_middle:: ty:: { self , TyCtxt } ;
12
- use rustc_middle:: { bug, mir} ;
13
13
use rustc_session:: RemapFileNameExt ;
14
14
use rustc_session:: config:: RemapPathScopeComponents ;
15
15
use rustc_span:: def_id:: DefIdSet ;
@@ -67,25 +67,21 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
67
67
return ;
68
68
}
69
69
70
- let all_file_names = function_coverage_map
71
- . iter ( )
72
- . map ( |( _, fn_cov) | fn_cov. function_coverage_info . body_span )
73
- . map ( |span| span_file_name ( tcx, span) ) ;
74
- let global_file_table = GlobalFileTable :: new ( all_file_names) ;
75
-
76
- // Encode all filenames referenced by coverage mappings in this CGU.
77
- let filenames_buffer = global_file_table. make_filenames_buffer ( tcx) ;
78
- // The `llvm-cov` tool uses this hash to associate each covfun record with
79
- // its corresponding filenames table, since the final binary will typically
80
- // contain multiple covmap records from different compilation units.
81
- let filenames_hash = llvm_cov:: hash_bytes ( & filenames_buffer) ;
82
-
83
- let mut unused_function_names = Vec :: new ( ) ;
70
+ // The order of entries in this global file table needs to be deterministic,
71
+ // and ideally should also be independent of the details of stable-hashing,
72
+ // because coverage tests snapshots (`.cov-map`) can observe the order and
73
+ // would need to be re-blessed if it changes. As long as those requirements
74
+ // are satisfied, the order can be arbitrary.
75
+ let mut global_file_table = GlobalFileTable :: new ( ) ;
84
76
85
77
let covfun_records = function_coverage_map
86
78
. into_iter ( )
79
+ // Sort by symbol name, so that the global file table is built in an
80
+ // order that doesn't depend on the stable-hash-based order in which
81
+ // instances were visited during codegen.
82
+ . sorted_by_cached_key ( |& ( instance, _) | tcx. symbol_name ( instance) . name )
87
83
. filter_map ( |( instance, function_coverage) | {
88
- prepare_covfun_record ( tcx, & global_file_table, instance, & function_coverage)
84
+ prepare_covfun_record ( tcx, & mut global_file_table, instance, & function_coverage)
89
85
} )
90
86
. collect :: < Vec < _ > > ( ) ;
91
87
@@ -98,6 +94,15 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
98
94
return ;
99
95
}
100
96
97
+ // Encode all filenames referenced by coverage mappings in this CGU.
98
+ let filenames_buffer = global_file_table. make_filenames_buffer ( tcx) ;
99
+ // The `llvm-cov` tool uses this hash to associate each covfun record with
100
+ // its corresponding filenames table, since the final binary will typically
101
+ // contain multiple covmap records from different compilation units.
102
+ let filenames_hash = llvm_cov:: hash_bytes ( & filenames_buffer) ;
103
+
104
+ let mut unused_function_names = vec ! [ ] ;
105
+
101
106
for covfun in & covfun_records {
102
107
unused_function_names. extend ( covfun. mangled_function_name_if_unused ( ) ) ;
103
108
@@ -137,22 +142,13 @@ struct GlobalFileTable {
137
142
}
138
143
139
144
impl GlobalFileTable {
140
- fn new ( all_file_names : impl IntoIterator < Item = Symbol > ) -> Self {
141
- // Collect all of the filenames into a set. Filenames usually come in
142
- // contiguous runs, so we can dedup adjacent ones to save work.
143
- let mut raw_file_table = all_file_names. into_iter ( ) . dedup ( ) . collect :: < FxIndexSet < Symbol > > ( ) ;
144
-
145
- // Sort the file table by its actual string values, not the arbitrary
146
- // ordering of its symbols.
147
- raw_file_table. sort_unstable_by ( |a, b| a. as_str ( ) . cmp ( b. as_str ( ) ) ) ;
148
-
149
- Self { raw_file_table }
145
+ fn new ( ) -> Self {
146
+ Self { raw_file_table : FxIndexSet :: default ( ) }
150
147
}
151
148
152
- fn global_file_id_for_file_name ( & self , file_name : Symbol ) -> GlobalFileId {
153
- let raw_id = self . raw_file_table . get_index_of ( & file_name) . unwrap_or_else ( || {
154
- bug ! ( "file name not found in prepared global file table: {file_name}" ) ;
155
- } ) ;
149
+ fn global_file_id_for_file_name ( & mut self , file_name : Symbol ) -> GlobalFileId {
150
+ // Ensure the given file has a table entry, and get its index.
151
+ let ( raw_id, _) = self . raw_file_table . insert_full ( file_name) ;
156
152
// The raw file table doesn't include an entry for the working dir
157
153
// (which has ID 0), so add 1 to get the correct ID.
158
154
GlobalFileId :: from_usize ( raw_id + 1 )
0 commit comments