diff options
| author | Simonas Kazlauskas <git@kazlauskas.me> | 2015-12-19 16:47:52 +0200 |
|---|---|---|
| committer | Simonas Kazlauskas <git@kazlauskas.me> | 2016-01-06 13:57:51 +0200 |
| commit | a1e13983f7d3890c3fb984179925ed8ad2dee31c (patch) | |
| tree | 0b30bab00523430827ada0717e6822f2b83e42e9 | |
| parent | 4e86dcdb7295e88d3ccc28b508ba69a24fefa371 (diff) | |
| download | rust-a1e13983f7d3890c3fb984179925ed8ad2dee31c.tar.gz rust-a1e13983f7d3890c3fb984179925ed8ad2dee31c.zip | |
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.
| -rw-r--r-- | src/librustc/mir/repr.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/mir/block.rs | 21 | ||||
| -rw-r--r-- | src/librustc_trans/trans/mir/mod.rs | 8 |
3 files changed, 24 insertions, 7 deletions
diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 2878b3d5e4e..f59cdb74b62 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -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), diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs index c2645d9882b..72d5709e022 100644 --- a/src/librustc_trans/trans/mir/block.rs +++ b/src/librustc_trans/trans/mir/block.rs @@ -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()] } diff --git a/src/librustc_trans/trans/mir/mod.rs b/src/librustc_trans/trans/mir/mod.rs index 5403b53596c..8eb06731ea3 100644 --- a/src/librustc_trans/trans/mir/mod.rs +++ b/src/librustc_trans/trans/mir/mod.rs @@ -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, |
