When deduplicating unreachable blocks, erase the source information.
After deduplication the block conceptually belongs to multiple locations in the source. Although these blocks are unreachable, in #123341 we did come across a real side effect, an unreachable block that survives into the compiled code can cause a debugger to set a breakpoint on the wrong instruction. Erasing the source information ensures that a debugger will never be misled into thinking that the unreachable block is worth setting a breakpoint on, especially after #128627. Technically we don't need to erase the source information if all the deduplicated blocks have identical source information, but tracking that seems like more effort than it's worth.
This commit is contained in:
parent
a6043039ad
commit
709406fc6c
@ -31,6 +31,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec};
|
|||||||
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
use rustc_span::DUMMY_SP;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
pub enum SimplifyCfg {
|
pub enum SimplifyCfg {
|
||||||
@ -318,6 +319,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
|
|||||||
let mut orig_index = 0;
|
let mut orig_index = 0;
|
||||||
let mut used_index = 0;
|
let mut used_index = 0;
|
||||||
let mut kept_unreachable = None;
|
let mut kept_unreachable = None;
|
||||||
|
let mut deduplicated_unreachable = false;
|
||||||
basic_blocks.raw.retain(|bbdata| {
|
basic_blocks.raw.retain(|bbdata| {
|
||||||
let orig_bb = BasicBlock::new(orig_index);
|
let orig_bb = BasicBlock::new(orig_index);
|
||||||
if !reachable.contains(orig_bb) {
|
if !reachable.contains(orig_bb) {
|
||||||
@ -330,6 +332,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
|
|||||||
let kept_unreachable = *kept_unreachable.get_or_insert(used_bb);
|
let kept_unreachable = *kept_unreachable.get_or_insert(used_bb);
|
||||||
if kept_unreachable != used_bb {
|
if kept_unreachable != used_bb {
|
||||||
replacements[orig_index] = kept_unreachable;
|
replacements[orig_index] = kept_unreachable;
|
||||||
|
deduplicated_unreachable = true;
|
||||||
orig_index += 1;
|
orig_index += 1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -341,6 +344,14 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
|
|||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If we deduplicated unreachable blocks we erase their source_info as we
|
||||||
|
// can no longer attribute their code to a particular location in the
|
||||||
|
// source.
|
||||||
|
if deduplicated_unreachable {
|
||||||
|
basic_blocks[kept_unreachable.unwrap()].terminator_mut().source_info =
|
||||||
|
SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE };
|
||||||
|
}
|
||||||
|
|
||||||
for block in basic_blocks {
|
for block in basic_blocks {
|
||||||
for target in block.terminator_mut().successors_mut() {
|
for target in block.terminator_mut().successors_mut() {
|
||||||
*target = replacements[target.index()];
|
*target = replacements[target.index()];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user