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.
This commit is contained in:
parent
4e86dcdb72
commit
a1e13983f7
@ -265,7 +265,7 @@ pub enum Terminator<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
|
||||
pub enum CallTargets {
|
||||
/// The only target that should be entered when function returns normally.
|
||||
Return(BasicBlock),
|
||||
|
@ -9,15 +9,15 @@
|
||||
// except according to those terms.
|
||||
|
||||
use llvm::BasicBlockRef;
|
||||
use middle::infer;
|
||||
use middle::ty;
|
||||
use rustc::mir::repr as mir;
|
||||
use trans::adt;
|
||||
use trans::base;
|
||||
use trans::build;
|
||||
use trans::attributes;
|
||||
use trans::common::{self, Block};
|
||||
use trans::debuginfo::DebugLoc;
|
||||
use trans::type_of;
|
||||
use trans::type_::Type;
|
||||
|
||||
use super::MirContext;
|
||||
use super::operand::OperandValue::{FatPtr, Immediate, Ref};
|
||||
@ -56,10 +56,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
|
||||
// The else branch of the Switch can't be hit, so branch to an unreachable
|
||||
// instruction so LLVM knows that
|
||||
// FIXME it might be nice to have just one such block (created lazilly), we could
|
||||
// store it in the "MIR trans" state.
|
||||
let unreachable_blk = bcx.fcx.new_temp_block("enum-variant-unreachable");
|
||||
build::Unreachable(unreachable_blk);
|
||||
let unreachable_blk = self.unreachable_block();
|
||||
|
||||
let switch = build::Switch(bcx, discr, unreachable_blk.llbb, targets.len());
|
||||
assert_eq!(adt_def.variants.len(), targets.len());
|
||||
@ -164,6 +161,18 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn unreachable_block(&mut self) -> Block<'bcx, 'tcx> {
|
||||
match self.unreachable_block {
|
||||
Some(b) => b,
|
||||
None => {
|
||||
let bl = self.fcx.new_block(false, "unreachable", None);
|
||||
build::Unreachable(bl);
|
||||
self.unreachable_block = Some(bl);
|
||||
bl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bcx(&self, bb: mir::BasicBlock) -> Block<'bcx, 'tcx> {
|
||||
self.blocks[bb.index()]
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ use self::operand::OperandRef;
|
||||
pub struct MirContext<'bcx, 'tcx:'bcx> {
|
||||
mir: &'bcx mir::Mir<'tcx>,
|
||||
|
||||
/// Function context
|
||||
fcx: &'bcx common::FunctionContext<'bcx, 'tcx>,
|
||||
|
||||
/// When unwinding is initiated, we have to store this personality
|
||||
/// value somewhere so that we can load it and re-use it in the
|
||||
/// resume instruction. The personality is (afaik) some kind of
|
||||
@ -40,6 +43,9 @@ pub struct MirContext<'bcx, 'tcx:'bcx> {
|
||||
/// A `Block` for each MIR `BasicBlock`
|
||||
blocks: Vec<Block<'bcx, 'tcx>>,
|
||||
|
||||
/// Cached unreachable block
|
||||
unreachable_block: Option<Block<'bcx, 'tcx>>,
|
||||
|
||||
/// An LLVM alloca for each MIR `VarDecl`
|
||||
vars: Vec<LvalueRef<'tcx>>,
|
||||
|
||||
@ -116,8 +122,10 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
|
||||
|
||||
let mut mircx = MirContext {
|
||||
mir: mir,
|
||||
fcx: fcx,
|
||||
llpersonalityslot: None,
|
||||
blocks: block_bcxs,
|
||||
unreachable_block: None,
|
||||
vars: vars,
|
||||
temps: temps,
|
||||
args: args,
|
||||
|
Loading…
x
Reference in New Issue
Block a user