Skip to content

Commit 1356572

Browse files
committed
MIR: Do not require END_BLOCK to always exist
Once upon a time, along with START_BLOCK and END_BLOCK in the castle of important blocks also lived a RESUME_BLOCK (or was it UNWIND_BLOCK? Either works, I don’t remember anymore). This trinity of important blocks were required to always exist from the birth to death of the MIR-land they belonged to. Some time later, it was discovered that RESUME_BLOCK was just a lazy goon enjoying comfortable life in the light of fame of the other two. Needless to say, once found out, the RESUME_BLOCK was quickly slain and disposed of. Now, the all-seeing eye of ours discovers that END_BLOCK is actually the more evil and better disguised twin of the slain RESUME_BLOCK. Thus END_BLOCK gets slain and quickly disposed of. Glory to the START_BLOCK, one and only lord of the important blocks’ castle! --- Basically, all this does, is removing restriction for END_BLOCK to exist past the first invocation of RemoveDeadBlocks pass. This way for functions whose CFG does not reach the `END_BLOCK` end up not containing the block. As far as the implementation goes, I’m not entirely satisfied with the `BasicBlock::end_block`, I had hoped to make `new` a `const fn` and then just have a `const END_BLOCK` private to mir::build, but it turns out that constant functions don’t yet support conditionals nor a way to assert.
1 parent 073a09f commit 1356572

File tree

6 files changed

+16
-15
lines changed

6 files changed

+16
-15
lines changed

src/librustc/mir/repr.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ pub struct Mir<'tcx> {
5959
/// where execution begins
6060
pub const START_BLOCK: BasicBlock = BasicBlock(0);
6161

62-
/// where execution ends, on normal return
63-
pub const END_BLOCK: BasicBlock = BasicBlock(1);
64-
6562
impl<'tcx> Mir<'tcx> {
6663
pub fn all_basic_blocks(&self) -> Vec<BasicBlock> {
6764
(0..self.basic_blocks.len())
@@ -216,6 +213,13 @@ impl BasicBlock {
216213
BasicBlock(index as u32)
217214
}
218215

216+
/// Returns a BasicBlock with index 1. This is actual end block (containing
217+
/// the Return terminator) only during the building of MIR and should not be
218+
/// used outside that.
219+
pub const fn end_block() -> BasicBlock {
220+
BasicBlock(1)
221+
}
222+
219223
/// Extract the index.
220224
pub fn index(self) -> usize {
221225
self.0 as usize
@@ -305,8 +309,7 @@ pub enum TerminatorKind<'tcx> {
305309
Resume,
306310

307311
/// Indicates a normal return. The ReturnPointer lvalue should
308-
/// have been filled in by now. This should only occur in the
309-
/// `END_BLOCK`.
312+
/// have been filled in by now. This should occur at most once.
310313
Return,
311314

312315
/// Drop the Lvalue

src/librustc_mir/build/expr/into.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
262262
}
263263
};
264264
let extent = this.extent_of_return_scope();
265-
this.exit_scope(expr_span, extent, block, END_BLOCK);
265+
this.exit_scope(expr_span, extent, block, BasicBlock::end_block());
266266
this.cfg.start_new_block().unit()
267267
}
268268
ExprKind::Call { ty, fun, args } => {

src/librustc_mir/build/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
183183
};
184184

185185
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
186-
assert_eq!(builder.cfg.start_new_block(), END_BLOCK);
186+
let end_block = builder.cfg.start_new_block();
187+
assert_eq!(end_block, BasicBlock::end_block());
187188

188189

189190
let mut arg_decls = None; // assigned to `Some` in closures below
@@ -205,11 +206,10 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
205206
}));
206207

207208
builder.cfg.terminate(block, call_site_scope_id, span,
208-
TerminatorKind::Goto { target: END_BLOCK });
209-
builder.cfg.terminate(END_BLOCK, call_site_scope_id, span,
209+
TerminatorKind::Goto { target: end_block });
210+
builder.cfg.terminate(end_block, call_site_scope_id, span,
210211
TerminatorKind::Return);
211-
212-
END_BLOCK.unit()
212+
end_block.unit()
213213
});
214214

215215
assert!(

src/librustc_mir/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
2121
#![unstable(feature = "rustc_private", issue = "27812")]
2222

2323
#![feature(box_patterns)]
24+
#![feature(const_fn)]
2425
#![feature(rustc_private)]
2526
#![feature(staged_api)]
2627
#![feature(question_mark)]

src/librustc_mir/transform/remove_dead_blocks.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ pub struct RemoveDeadBlocks;
4343
impl<'tcx> MirPass<'tcx> for RemoveDeadBlocks {
4444
fn run_pass(&mut self, _: &TyCtxt<'tcx>, _: NodeId, mir: &mut Mir<'tcx>) {
4545
let mut seen = BitVector::new(mir.basic_blocks.len());
46-
// These blocks are always required.
46+
// This block is always required.
4747
seen.insert(START_BLOCK.index());
48-
seen.insert(END_BLOCK.index());
4948

5049
let mut worklist = Vec::with_capacity(4);
5150
worklist.push(START_BLOCK);

src/librustc_trans/mir/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,6 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
164164
.map(|&bb|{
165165
if bb == mir::START_BLOCK {
166166
fcx.new_block("start", None)
167-
} else if bb == mir::END_BLOCK {
168-
fcx.new_block("end", None)
169167
} else {
170168
fcx.new_block(&format!("{:?}", bb), None)
171169
}

0 commit comments

Comments
 (0)