about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2015-12-19 16:47:52 +0200
committerSimonas Kazlauskas <git@kazlauskas.me>2016-01-06 13:57:51 +0200
commita1e13983f7d3890c3fb984179925ed8ad2dee31c (patch)
tree0b30bab00523430827ada0717e6822f2b83e42e9
parent4e86dcdb7295e88d3ccc28b508ba69a24fefa371 (diff)
downloadrust-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.rs2
-rw-r--r--src/librustc_trans/trans/mir/block.rs21
-rw-r--r--src/librustc_trans/trans/mir/mod.rs8
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,