Skip to content

Commit 77bf818

Browse files
committed
!! (WIP) Use the existing filename groupings in mapgen
1 parent f3b149c commit 77bf818

File tree

2 files changed

+37
-43
lines changed

2 files changed

+37
-43
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -222,36 +222,20 @@ impl<'tcx> FunctionCoverage<'tcx> {
222222
self.source_hash
223223
}
224224

225-
/// Generate an array of CounterExpressions, and an iterator over all `Counter`s and their
226-
/// associated `Regions` (from which the LLVM-specific `CoverageMapGenerator` will create
227-
/// `CounterMappingRegion`s.
228-
pub fn get_expressions_and_counter_regions(
229-
&self,
230-
) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &CodeRegion)>) {
225+
#[track_caller]
226+
fn assert_source_hash_is_set(&self) {
231227
assert!(
232228
self.source_hash != 0 || !self.is_used,
233229
"No counters provided the source_hash for used function: {:?}",
234230
self.instance
235231
);
236-
237-
let counter_expressions = self.counter_expressions();
238-
// Expression IDs are indices into `self.expressions`, and on the LLVM
239-
// side they will be treated as indices into `counter_expressions`, so
240-
// the two vectors should correspond 1:1.
241-
assert_eq!(self.expressions.len(), counter_expressions.len());
242-
243-
let all_mappings = self.mappings_per_file.values().flatten();
244-
let counter_regions = all_mappings.map(|(mapping_kind, code_region)| {
245-
let counter = Counter::from_term(*mapping_kind);
246-
(counter, code_region)
247-
});
248-
249-
(counter_expressions, counter_regions)
250232
}
251233

252234
/// Convert this function's coverage expression data into a form that can be
253235
/// passed through FFI to LLVM.
254-
fn counter_expressions(&self) -> Vec<CounterExpression> {
236+
pub(crate) fn counter_expressions(&self) -> Vec<CounterExpression> {
237+
self.assert_source_hash_is_set();
238+
255239
// We know that LLVM will optimize out any unused expressions before
256240
// producing the final coverage map, so there's no need to do the same
257241
// thing on the Rust side unless we're confident we can do much better.
@@ -278,4 +262,18 @@ impl<'tcx> FunctionCoverage<'tcx> {
278262
})
279263
.collect::<Vec<_>>()
280264
}
265+
266+
pub(crate) fn has_mappings(&self) -> bool {
267+
self.mappings_per_file.values().any(|vec| !vec.is_empty())
268+
}
269+
270+
pub(crate) fn all_mappings_by_filename(
271+
&self,
272+
) -> impl Iterator<Item = (Symbol, &[(CovTerm, CodeRegion)])> {
273+
self.assert_source_hash_is_set();
274+
self.mappings_per_file
275+
.iter()
276+
.map(|(file_name, mappings)| (*file_name, mappings.as_slice()))
277+
.filter(|(_, mappings)| !mappings.is_empty())
278+
}
281279
}

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::common::CodegenCx;
22
use crate::coverageinfo;
3-
use crate::coverageinfo::ffi::CounterMappingRegion;
3+
use crate::coverageinfo::ffi::{Counter, CounterMappingRegion};
44
use crate::coverageinfo::map_data::FunctionCoverage;
55
use crate::llvm;
66

@@ -159,49 +159,45 @@ fn encode_mappings_for_function(
159159
global_file_table: &mut GlobalFileTable,
160160
function_coverage: &FunctionCoverage<'_>,
161161
) -> Vec<u8> {
162-
let (expressions, counter_regions) = function_coverage.get_expressions_and_counter_regions();
163-
164-
let mut counter_regions = counter_regions.collect::<Vec<_>>();
165-
if counter_regions.is_empty() {
162+
if !function_coverage.has_mappings() {
166163
return Vec::new();
167164
}
168165

166+
let expressions = function_coverage.counter_expressions();
167+
169168
let mut virtual_file_mapping = Vec::new();
170-
let mut mapping_regions = Vec::with_capacity(counter_regions.len());
171-
172-
// Convert the list of (Counter, CodeRegion) pairs to an array of `CounterMappingRegion`, sorted
173-
// by filename and position. Capture any new files to compute the `CounterMappingRegion`s
174-
// `file_id` (indexing files referenced by the current function), and construct the
175-
// function-specific `virtual_file_mapping` from `file_id` to its index in the module's
176-
// `filenames` array.
177-
counter_regions.sort_by_key(|(_counter, region)| region.file_name);
178-
for (local_file_id, counter_regions_for_file) in
179-
(0u32..).zip(counter_regions.group_by(|(_, a), (_, b)| a.file_name == b.file_name))
169+
let mut mapping_regions = Vec::new();
170+
171+
for (local_file_id, (file_name, mappings_for_file)) in
172+
(0u32..).zip(function_coverage.all_mappings_by_filename())
180173
{
174+
assert!(!mappings_for_file.is_empty(), "{mappings_for_file:?}");
181175
// Look up (or allocate) the global file ID for this file name.
182-
let file_name = counter_regions_for_file[0].1.file_name;
183176
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
184177

185178
// Associate that global file ID with a local file ID for this function.
186179
assert_eq!(local_file_id as usize, virtual_file_mapping.len());
187180
virtual_file_mapping.push(global_file_id);
188181
debug!(" file_id: local {local_file_id} => global {global_file_id} = '{file_name:?}'");
189182

190-
// For each counter/region pair in this function+file, convert it
191-
// to a form suitable for FFI.
192-
for &(counter, region) in counter_regions_for_file {
183+
mapping_regions.extend(mappings_for_file.iter().map(|(mapping_kind, region)| {
184+
let counter = Counter::from_term(*mapping_kind);
193185
let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = *region;
194186

195187
debug!("Adding counter {counter:?} to map for {region:?}");
196-
mapping_regions.push(CounterMappingRegion::code_region(
188+
CounterMappingRegion::code_region(
197189
counter,
198190
local_file_id,
199191
start_line,
200192
start_col,
201193
end_line,
202194
end_col,
203-
));
204-
}
195+
)
196+
}));
197+
}
198+
199+
if mapping_regions.is_empty() {
200+
bug!("no mappings generated for function: {function_coverage:?}");
205201
}
206202

207203
// Encode the function's coverage mappings into a buffer.

0 commit comments

Comments
 (0)