Fix bug in mark_code_coverage_dead_code_cgus.

The comment says "Find the smallest CGU that has exported symbols and
put the dead function stubs in that CGU". But the code sorts the CGUs by
size (smallest first) and then searches them in reverse order, which
means it will find the *largest* CGU that has exported symbols.

The erroneous code was introduced in #92142.

This commit changes it to use a simpler search, avoiding the sort, and
fixes the bug in the process.
This commit is contained in:
Nicholas Nethercote 2023-06-15 09:50:48 +10:00
parent 9d7295f0be
commit 57a7c8f577

View File

@ -529,20 +529,15 @@ fn mark_code_coverage_dead_code_cgu<'tcx>(codegen_units: &mut [CodegenUnit<'tcx>
// the object file (CGU) containing the dead function stubs is included
// in the final binary. This will probably require forcing these
// function symbols to be included via `-u` or `/include` linker args.
let mut cgus: Vec<&mut CodegenUnit<'tcx>> = codegen_units.iter_mut().collect();
cgus.sort_by_key(|cgu| cgu.size_estimate());
let dead_code_cgu = codegen_units
.iter_mut()
.filter(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External))
.min_by_key(|cgu| cgu.size_estimate());
// If there are no CGUs that have externally linked items, then we just
// pick the first CGU as a fallback.
let dead_code_cgu = if let Some(cgu) = dead_code_cgu { cgu } else { &mut codegen_units[0] };
let dead_code_cgu = if let Some(cgu) = cgus
.into_iter()
.rev()
.find(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External))
{
cgu
} else {
// If there are no CGUs that have externally linked items,
// then we just pick the first CGU as a fallback.
&mut codegen_units[0]
};
dead_code_cgu.make_code_coverage_dead_code_cgu();
}