Skip to content

Commit a1e1398

Browse files
committed
Have a cached unreachable block inside MIR state
It is useful for various cases where direct unreachable cannot be translated and a separate block is necessary.
1 parent 4e86dcd commit a1e1398

File tree

3 files changed

+24
-7
lines changed

3 files changed

+24
-7
lines changed

src/librustc/mir/repr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ pub enum Terminator<'tcx> {
265265
}
266266
}
267267

268-
#[derive(RustcEncodable, RustcDecodable)]
268+
#[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
269269
pub enum CallTargets {
270270
/// The only target that should be entered when function returns normally.
271271
Return(BasicBlock),

src/librustc_trans/trans/mir/block.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
// except according to those terms.
1010

1111
use llvm::BasicBlockRef;
12-
use middle::infer;
13-
use middle::ty;
1412
use rustc::mir::repr as mir;
1513
use trans::adt;
1614
use trans::base;
1715
use trans::build;
16+
use trans::attributes;
1817
use trans::common::{self, Block};
1918
use trans::debuginfo::DebugLoc;
2019
use trans::type_of;
20+
use trans::type_::Type;
2121

2222
use super::MirContext;
2323
use super::operand::OperandValue::{FatPtr, Immediate, Ref};
@@ -56,10 +56,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
5656

5757
// The else branch of the Switch can't be hit, so branch to an unreachable
5858
// instruction so LLVM knows that
59-
// FIXME it might be nice to have just one such block (created lazilly), we could
60-
// store it in the "MIR trans" state.
61-
let unreachable_blk = bcx.fcx.new_temp_block("enum-variant-unreachable");
62-
build::Unreachable(unreachable_blk);
59+
let unreachable_blk = self.unreachable_block();
6360

6461
let switch = build::Switch(bcx, discr, unreachable_blk.llbb, targets.len());
6562
assert_eq!(adt_def.variants.len(), targets.len());
@@ -164,6 +161,18 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
164161
}
165162
}
166163

164+
fn unreachable_block(&mut self) -> Block<'bcx, 'tcx> {
165+
match self.unreachable_block {
166+
Some(b) => b,
167+
None => {
168+
let bl = self.fcx.new_block(false, "unreachable", None);
169+
build::Unreachable(bl);
170+
self.unreachable_block = Some(bl);
171+
bl
172+
}
173+
}
174+
}
175+
167176
fn bcx(&self, bb: mir::BasicBlock) -> Block<'bcx, 'tcx> {
168177
self.blocks[bb.index()]
169178
}

src/librustc_trans/trans/mir/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ use self::operand::OperandRef;
2828
pub struct MirContext<'bcx, 'tcx:'bcx> {
2929
mir: &'bcx mir::Mir<'tcx>,
3030

31+
/// Function context
32+
fcx: &'bcx common::FunctionContext<'bcx, 'tcx>,
33+
3134
/// When unwinding is initiated, we have to store this personality
3235
/// value somewhere so that we can load it and re-use it in the
3336
/// resume instruction. The personality is (afaik) some kind of
@@ -40,6 +43,9 @@ pub struct MirContext<'bcx, 'tcx:'bcx> {
4043
/// A `Block` for each MIR `BasicBlock`
4144
blocks: Vec<Block<'bcx, 'tcx>>,
4245

46+
/// Cached unreachable block
47+
unreachable_block: Option<Block<'bcx, 'tcx>>,
48+
4349
/// An LLVM alloca for each MIR `VarDecl`
4450
vars: Vec<LvalueRef<'tcx>>,
4551

@@ -116,8 +122,10 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
116122

117123
let mut mircx = MirContext {
118124
mir: mir,
125+
fcx: fcx,
119126
llpersonalityslot: None,
120127
blocks: block_bcxs,
128+
unreachable_block: None,
121129
vars: vars,
122130
temps: temps,
123131
args: args,

0 commit comments

Comments
 (0)