]> git.lizzy.rs Git - rust.git/commitdiff
Create personality slot when translating Resume
authorSimonas Kazlauskas <git@kazlauskas.me>
Fri, 1 Jan 2016 22:45:21 +0000 (00:45 +0200)
committerSimonas Kazlauskas <git@kazlauskas.me>
Wed, 6 Jan 2016 11:57:52 +0000 (13:57 +0200)
This considerably simplifies code around calling functions and translation of Resume itself. This
removes requirement that a block containing Resume terminator is always translated after something
which creates a landing pad, thus allowing us to actually translate some valid MIRs we could not
translate before.

However, an assumption is added that translator is correct (in regards to landing pad generation)
and code will never reach the Resume terminator without going through a landing pad first. Breaking
these assumptions would pass an `undef` value into the personality functions.

src/librustc_trans/trans/mir/block.rs
src/librustc_trans/trans/mir/mod.rs

index 969b9cd19d1a15598d5828cb9f3f06ef0488d3c3..aa0b3a25ebb0cabc8f3603255922c8c2bdd484f1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::BasicBlockRef;
+use llvm::{BasicBlockRef, ValueRef};
 use rustc::mir::repr as mir;
 use trans::adt;
 use trans::base;
@@ -80,13 +80,10 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
             }
 
             mir::Terminator::Resume => {
-                if let Some(personalityslot) = self.llpersonalityslot {
-                    let lp = build::Load(bcx, personalityslot);
-                    base::call_lifetime_end(bcx, personalityslot);
-                    build::Resume(bcx, lp);
-                } else {
-                    panic!("resume terminator without personality slot set")
-                }
+                let ps = self.get_personality_slot(bcx);
+                let lp = build::Load(bcx, ps);
+                base::call_lifetime_end(bcx, ps);
+                base::trans_unwind_resume(bcx, lp);
             }
 
             mir::Terminator::Return => {
@@ -187,29 +184,17 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                             build::Br(target, postinvoketarget.llbb, debugloc);
                         }
                     },
-                    // Everything else uses the regular `Call`, but we have to be careful to
-                    // generate landing pads for later, even if we do not use it.
-                    // FIXME: maybe just change Resume to not panic in that case?
-                    (_, k@&mir::CallKind::DivergingCleanup(_)) |
-                    (_, k@&mir::CallKind::Diverging) => {
-                        if let mir::CallKind::DivergingCleanup(_) = *k {
-                            // make a landing pad regardless, so it sets the personality slot.
-                            let block = self.unreachable_block();
-                            self.make_landing_pad(block);
-                        }
+                    (_, &mir::CallKind::DivergingCleanup(_)) |
+                    (_, &mir::CallKind::Diverging) => {
                         build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
                         build::Unreachable(bcx);
                     }
                     (_, k@&mir::CallKind::ConvergingCleanup { .. }) |
                     (_, k@&mir::CallKind::Converging { .. }) => {
-                        let ret = match *k {
+                        // Bug #20046
+                        let target = match *k {
+                            mir::CallKind::ConvergingCleanup { targets, .. } => targets.0,
                             mir::CallKind::Converging { target, .. } => target,
-                            mir::CallKind::ConvergingCleanup { targets, .. } => {
-                                // make a landing pad regardless (so it sets the personality slot.
-                                let block = self.unreachable_block();
-                                self.make_landing_pad(block);
-                                targets.0
-                            },
                             _ => unreachable!()
                         };
                         let llret = build::Call(bcx,
@@ -222,13 +207,26 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                                 .expect("return destination and type not set");
                             base::store_ty(bcx, llret, ret_dest.llval, ret_ty);
                         }
-                        build::Br(bcx, self.llblock(ret), debugloc)
+                        build::Br(bcx, self.llblock(target), debugloc);
                     }
                 }
             }
         }
     }
 
+    fn get_personality_slot(&mut self, bcx: Block<'bcx, 'tcx>) -> ValueRef {
+        let ccx = bcx.ccx();
+        if let Some(slot) = self.llpersonalityslot {
+            slot
+        } else {
+            let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
+            let slot = base::alloca(bcx, llretty, "personalityslot");
+            self.llpersonalityslot = Some(slot);
+            base::call_lifetime_start(bcx, slot);
+            slot
+        }
+    }
+
     fn make_landing_pad(&mut self, cleanup: Block<'bcx, 'tcx>) -> Block<'bcx, 'tcx> {
         let bcx = cleanup.fcx.new_block(true, "cleanup", None);
         let ccx = bcx.ccx();
@@ -236,15 +234,8 @@ fn make_landing_pad(&mut self, cleanup: Block<'bcx, 'tcx>) -> Block<'bcx, 'tcx>
         let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
         let llretval = build::LandingPad(bcx, llretty, llpersonality, 1);
         build::SetCleanup(bcx, llretval);
-        match self.llpersonalityslot {
-            Some(slot) => build::Store(bcx, llretval, slot),
-            None => {
-                let personalityslot = base::alloca(bcx, llretty, "personalityslot");
-                self.llpersonalityslot = Some(personalityslot);
-                base::call_lifetime_start(bcx, personalityslot);
-                build::Store(bcx, llretval, personalityslot)
-            }
-        };
+        let slot = self.get_personality_slot(bcx);
+        build::Store(bcx, llretval, slot);
         build::Br(bcx, cleanup.llbb, DebugLoc::None);
         bcx
     }
index 1aceb67dd12100191b7a21cda23cb41ba8fbb17a..75ce33da2c9b9da66eb84a77ad40fbdabb3f1eaf 100644 (file)
@@ -136,9 +136,6 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
 
     // Translate the body of each block
     for &bb in &mir_blocks {
-        // NB that we do not handle the Resume terminator specially, because a block containing
-        // that terminator will have a higher block number than a function call which should take
-        // care of filling in that information.
         mircx.trans_block(bb);
     }
 }