diff options
| author | Kyle Huey <khuey@kylehuey.com> | 2024-08-03 21:23:35 -0700 |
|---|---|---|
| committer | Kyle Huey <khuey@kylehuey.com> | 2024-08-03 21:23:35 -0700 |
| commit | 709406fc6c792bd5dd0d07fbc59c4437b3d47f95 (patch) | |
| tree | d3fb71f143025348749b9eef0c62c4baf05e8951 | |
| parent | a6043039ad3aef48e08d72a3e32545accdee427a (diff) | |
| download | rust-709406fc6c792bd5dd0d07fbc59c4437b3d47f95.tar.gz rust-709406fc6c792bd5dd0d07fbc59c4437b3d47f95.zip | |
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.
| -rw-r--r-- | compiler/rustc_mir_transform/src/simplify.rs | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 5bbe3bb747f..4fe8cf6213f 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -31,6 +31,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_span::DUMMY_SP; use smallvec::SmallVec; pub enum SimplifyCfg { @@ -318,6 +319,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) { let mut orig_index = 0; let mut used_index = 0; let mut kept_unreachable = None; + let mut deduplicated_unreachable = false; basic_blocks.raw.retain(|bbdata| { let orig_bb = BasicBlock::new(orig_index); 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); if kept_unreachable != used_bb { replacements[orig_index] = kept_unreachable; + deduplicated_unreachable = true; orig_index += 1; return false; } @@ -341,6 +344,14 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) { 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 target in block.terminator_mut().successors_mut() { *target = replacements[target.index()]; |
