]> git.lizzy.rs Git - rust.git/commitdiff
Don’t generate landing-pads if -Z no-landing-pads
authorSimonas Kazlauskas <git@kazlauskas.me>
Sun, 20 Dec 2015 13:30:09 +0000 (15:30 +0200)
committerSimonas Kazlauskas <git@kazlauskas.me>
Wed, 6 Jan 2016 11:57:52 +0000 (13:57 +0200)
src/librustc/mir/repr.rs
src/librustc_mir/build/scope.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/mir/block.rs
src/librustc_trans/trans/mir/mod.rs

index f59cdb74b625de397a67a611681a57254fd18115..fa3573b383b685909ff89585f5cef3a74f3b2021 100644 (file)
@@ -192,6 +192,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 pub struct BasicBlockData<'tcx> {
     pub statements: Vec<Statement<'tcx>>,
     pub terminator: Option<Terminator<'tcx>>,
+    pub is_cleanup: bool,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -341,6 +342,7 @@ pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> {
         BasicBlockData {
             statements: vec![],
             terminator: terminator,
+            is_cleanup: false,
         }
     }
 
index 758c5781efc423c6bad062da3e562552ab567281..080b979c1ecc23c1781a82bd5b95796b1e0dd143 100644 (file)
@@ -251,6 +251,7 @@ pub fn diverge_cleanup(&mut self) -> Option<BasicBlock> {
                 continue;
             } else {
                 let new_block = self.cfg.start_new_block();
+                self.cfg.block_data_mut(new_block).is_cleanup = true;
                 self.cfg.terminate(new_block, terminator);
                 terminator = Terminator::Goto { target: new_block };
                 for &(kind, span, ref lvalue) in scope.drops.iter().rev() {
index 4197f80cb5ea31282c959e17d89b09727b68b5be..a6e6d3042205093ab7ce9769e1ed3b80bb272d48 100644 (file)
@@ -958,22 +958,28 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
     sess.target.target.options.is_like_msvc && sess.target.target.arch == "x86"
 }
 
-pub fn need_invoke(bcx: Block) -> bool {
+pub fn avoid_invoke(bcx: Block) -> bool {
     // FIXME(#25869) currently SEH-based unwinding is pretty buggy in LLVM and
     //               is being overhauled as this is being written. Until that
     //               time such that upstream LLVM's implementation is more solid
     //               and we start binding it we need to skip invokes for any
     //               target which wants SEH-based unwinding.
     if bcx.sess().no_landing_pads() || wants_msvc_seh(bcx.sess()) {
-        return false;
+        true
+    } else if bcx.is_lpad {
+        // Avoid using invoke if we are already inside a landing pad.
+        true
+    } else {
+        false
     }
+}
 
-    // Avoid using invoke if we are already inside a landing pad.
-    if bcx.is_lpad {
-        return false;
+pub fn need_invoke(bcx: Block) -> bool {
+    if avoid_invoke(bcx) {
+        false
+    } else {
+        bcx.fcx.needs_invoke()
     }
-
-    bcx.fcx.needs_invoke()
 }
 
 pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, t: Ty<'tcx>) -> ValueRef {
index d41c4dec2b28bd906de902c91d12398f89ac6c76..55117a6db39578e99c05a0cf8f199dfe5c3f759e 100644 (file)
@@ -128,19 +128,9 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
 
                 let debugloc = DebugLoc::None;
                 let attrs = attributes::from_fn_type(bcx.ccx(), callee.ty);
-                match *targets {
-                    mir::CallTargets::Return(ret) => {
-                        let llret = build::Call(bcx,
-                                                callee.immediate(),
-                                                &llargs[..],
-                                                Some(attrs),
-                                                debugloc);
-                        if !return_outptr && !common::type_is_zero_size(bcx.ccx(), ret_ty) {
-                            base::store_ty(bcx, llret, call_dest.llval, ret_ty);
-                        }
-                        build::Br(bcx, self.llblock(ret), debugloc)
-                    }
-                    mir::CallTargets::WithCleanup((ret, cleanup)) => {
+                match (*targets, base::avoid_invoke(bcx)) {
+                    (mir::CallTargets::WithCleanup((ret, cleanup)), false) => {
+                        let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
                         build::Invoke(bcx,
                                       callee.immediate(),
@@ -153,6 +143,26 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                             // FIXME: What do we do here?
                             unimplemented!()
                         }
+                    },
+                    (t, _) => {
+                        let ret = match t {
+                            mir::CallTargets::Return(ret) => ret,
+                            mir::CallTargets::WithCleanup((ret, _)) => {
+                                // make a landing pad regardless (so it sets the personality slot.
+                                let block = self.unreachable_block();
+                                self.make_landing_pad(block);
+                                ret
+                            }
+                        };
+                        let llret = build::Call(bcx,
+                                                callee.immediate(),
+                                                &llargs[..],
+                                                Some(attrs),
+                                                debugloc);
+                        if !return_outptr && !common::type_is_zero_size(bcx.ccx(), ret_ty) {
+                            base::store_ty(bcx, llret, call_dest.llval, ret_ty);
+                        }
+                        build::Br(bcx, self.llblock(ret), debugloc)
                     }
                 }
             },
@@ -171,12 +181,9 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                 }
                 let debugloc = DebugLoc::None;
                 let attrs = attributes::from_fn_type(bcx.ccx(), callee.ty);
-                match *cleanup {
-                    None => {
-                        build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
-                        build::Unreachable(bcx);
-                    }
-                    Some(cleanup) => {
+                match (*cleanup, base::avoid_invoke(bcx)) {
+                    (Some(cleanup), false) => {
+                        let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
                         let unreachable = self.unreachable_block();
                         build::Invoke(bcx,
@@ -187,13 +194,22 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                                       Some(attrs),
                                       debugloc);
                     }
+                    (t, _) => {
+                        if t.is_some() {
+                            // make a landing pad regardless, so it sets the personality slot.
+                            let block = self.unreachable_block();
+                            self.make_landing_pad(block);
+                        }
+                        build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
+                        build::Unreachable(bcx);
+                    }
                 }
             }
         }
     }
 
-    fn make_landing_pad(&mut self, cleanup: mir::BasicBlock) -> Block<'bcx, 'tcx> {
-        let bcx = self.bcx(cleanup).fcx.new_block(true, "cleanup", None);
+    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();
         let llpersonality = bcx.fcx.eh_personality();
         let llretty = Type::struct_(ccx, &[Type::i8p(ccx), Type::i32(ccx)], false);
@@ -208,7 +224,7 @@ fn make_landing_pad(&mut self, cleanup: mir::BasicBlock) -> Block<'bcx, 'tcx> {
                 build::Store(bcx, llretval, personalityslot)
             }
         };
-        build::Br(bcx, self.llblock(cleanup), DebugLoc::None);
+        build::Br(bcx, cleanup.llbb, DebugLoc::None);
         bcx
     }
 
index 8eb06731ea3ae3c68e821d5968363795dd9c043f..1aceb67dd12100191b7a21cda23cb41ba8fbb17a 100644 (file)
@@ -113,7 +113,10 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
     // Allocate a `Block` for every basic block
     let block_bcxs: Vec<Block<'bcx,'tcx>> =
         mir_blocks.iter()
-                  .map(|&bb| fcx.new_block(false, &format!("{:?}", bb), None))
+                  .map(|&bb|{
+                      let is_cleanup = mir.basic_block_data(bb).is_cleanup;
+                      fcx.new_block(is_cleanup, &format!("{:?}", bb), None)
+                  })
                   .collect();
 
     // Branch to the START block