Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e3316ae

Browse files
committed
Improve MirPatch documentation and naming.
It's currently lacking comments. This commit adds some, which is useful because there are some methods with non-obvious behaviour. The commit also renames two things: - `patch_map` becomes `term_patch_map`, because it's only about terminators. - `is_patched` becomes `is_term_patched`, for the same reason. (I would guess that originally `MirPatch` only handled terminators, and then over time it expanded to allow other modifications, but these names weren't updated.)
1 parent a1daa34 commit e3316ae

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

compiler/rustc_mir_transform/src/elaborate_drops.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
417417
..
418418
} = data.terminator().kind
419419
{
420-
assert!(!self.patch.is_patched(bb));
420+
assert!(!self.patch.is_term_patched(bb));
421421

422422
let loc = Location { block: tgt, statement_index: 0 };
423423
let path = self.move_data().rev_lookup.find(destination.as_ref());
@@ -462,7 +462,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
462462
// a Goto; see `MirPatch::new`).
463463
}
464464
_ => {
465-
assert!(!self.patch.is_patched(bb));
465+
assert!(!self.patch.is_term_patched(bb));
466466
}
467467
}
468468
}
@@ -486,7 +486,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
486486
..
487487
} = data.terminator().kind
488488
{
489-
assert!(!self.patch.is_patched(bb));
489+
assert!(!self.patch.is_term_patched(bb));
490490

491491
let loc = Location { block: bb, statement_index: data.statements.len() };
492492
let path = self.move_data().rev_lookup.find(destination.as_ref());

compiler/rustc_mir_transform/src/patch.rs

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ use rustc_middle::ty::Ty;
44
use rustc_span::Span;
55
use tracing::debug;
66

7-
/// This struct represents a patch to MIR, which can add
8-
/// new statements and basic blocks and patch over block
9-
/// terminators.
7+
/// This struct lets you "patch" a MIR body, i.e. modify it. You can queue up
8+
/// various changes, such as the addition of new statements and basic blocks
9+
/// and replacement of terminators, and then apply the queued changes all at
10+
/// once with `apply`. This is useful for MIR transformation passes.
1011
pub(crate) struct MirPatch<'tcx> {
11-
patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
12+
term_patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
1213
new_blocks: Vec<BasicBlockData<'tcx>>,
1314
new_statements: Vec<(Location, StatementKind<'tcx>)>,
1415
new_locals: Vec<LocalDecl<'tcx>>,
@@ -24,9 +25,10 @@ pub(crate) struct MirPatch<'tcx> {
2425
}
2526

2627
impl<'tcx> MirPatch<'tcx> {
28+
/// Creates a new, empty patch.
2729
pub(crate) fn new(body: &Body<'tcx>) -> Self {
2830
let mut result = MirPatch {
29-
patch_map: IndexVec::from_elem(None, &body.basic_blocks),
31+
term_patch_map: IndexVec::from_elem(None, &body.basic_blocks),
3032
new_blocks: vec![],
3133
new_statements: vec![],
3234
new_locals: vec![],
@@ -141,10 +143,12 @@ impl<'tcx> MirPatch<'tcx> {
141143
bb
142144
}
143145

144-
pub(crate) fn is_patched(&self, bb: BasicBlock) -> bool {
145-
self.patch_map[bb].is_some()
146+
/// Has a replacement of this block's terminator been queued in this patch?
147+
pub(crate) fn is_term_patched(&self, bb: BasicBlock) -> bool {
148+
self.term_patch_map[bb].is_some()
146149
}
147150

151+
/// Queues the addition of a new temporary with additional local info.
148152
pub(crate) fn new_local_with_info(
149153
&mut self,
150154
ty: Ty<'tcx>,
@@ -159,6 +163,7 @@ impl<'tcx> MirPatch<'tcx> {
159163
Local::new(index)
160164
}
161165

166+
/// Queues the addition of a new temporary.
162167
pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
163168
let index = self.next_local;
164169
self.next_local += 1;
@@ -174,29 +179,46 @@ impl<'tcx> MirPatch<'tcx> {
174179
self.new_locals[new_local_idx].ty
175180
}
176181

182+
/// Queues the addition of a new basic block.
177183
pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
178-
let block = BasicBlock::new(self.patch_map.len());
184+
let block = BasicBlock::new(self.term_patch_map.len());
179185
debug!("MirPatch: new_block: {:?}: {:?}", block, data);
180186
self.new_blocks.push(data);
181-
self.patch_map.push(None);
187+
self.term_patch_map.push(None);
182188
block
183189
}
184190

191+
/// Queues the replacement of a block's terminator.
185192
pub(crate) fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
186-
assert!(self.patch_map[block].is_none());
193+
assert!(self.term_patch_map[block].is_none());
187194
debug!("MirPatch: patch_terminator({:?}, {:?})", block, new);
188-
self.patch_map[block] = Some(new);
195+
self.term_patch_map[block] = Some(new);
189196
}
190197

198+
/// Queues the insertion of a statement at a given location. The statement
199+
/// currently at that location, and all statements that follow, are shifted
200+
/// down. If multiple statements are queued for addition at the same
201+
/// location, the final statement order after calling `apply` will match
202+
/// the queue insertion order.
203+
///
204+
/// E.g. if we have `s0` at location `loc` and do these calls:
205+
///
206+
/// p.add_statement(loc, s1);
207+
/// p.add_statement(loc, s2);
208+
/// p.apply(body);
209+
///
210+
/// then the final order will be `s1, s2, s0`, with `s1` at `loc`.
191211
pub(crate) fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) {
192212
debug!("MirPatch: add_statement({:?}, {:?})", loc, stmt);
193213
self.new_statements.push((loc, stmt));
194214
}
195215

216+
/// Like `add_statement`, but specialized for assignments.
196217
pub(crate) fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) {
197218
self.add_statement(loc, StatementKind::Assign(Box::new((place, rv))));
198219
}
199220

221+
/// Applies the queued changes.
200222
pub(crate) fn apply(self, body: &mut Body<'tcx>) {
201223
debug!(
202224
"MirPatch: {:?} new temps, starting from index {}: {:?}",
@@ -209,21 +231,24 @@ impl<'tcx> MirPatch<'tcx> {
209231
self.new_blocks.len(),
210232
body.basic_blocks.len()
211233
);
212-
let bbs = if self.patch_map.is_empty() && self.new_blocks.is_empty() {
234+
let bbs = if self.term_patch_map.is_empty() && self.new_blocks.is_empty() {
213235
body.basic_blocks.as_mut_preserves_cfg()
214236
} else {
215237
body.basic_blocks.as_mut()
216238
};
217239
bbs.extend(self.new_blocks);
218240
body.local_decls.extend(self.new_locals);
219-
for (src, patch) in self.patch_map.into_iter_enumerated() {
241+
for (src, patch) in self.term_patch_map.into_iter_enumerated() {
220242
if let Some(patch) = patch {
221243
debug!("MirPatch: patching block {:?}", src);
222244
bbs[src].terminator_mut().kind = patch;
223245
}
224246
}
225247

226248
let mut new_statements = self.new_statements;
249+
250+
// This must be a stable sort to provide the ordering described in the
251+
// comment for `add_statement`.
227252
new_statements.sort_by_key(|s| s.0);
228253

229254
let mut delta = 0;

0 commit comments

Comments
 (0)