]> git.lizzy.rs Git - rust.git/commitdiff
Disable all unwinding on -Z no-landing-pads LTO
authorAlex Crichton <alex@alexcrichton.com>
Wed, 11 Dec 2013 07:27:15 +0000 (23:27 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 11 Dec 2013 17:18:20 +0000 (09:18 -0800)
When performing LTO, the rust compiler has an opportunity to completely strip
all landing pads in all dependent libraries. I've modified the LTO pass to
recognize the -Z no-landing-pads option when also running an LTO pass to flag
everything in LLVM as nothrow. I've verified that this prevents any and all
invoke instructions from being emitted.

I believe that this is one of our best options for moving forward with
accomodating use-cases where unwinding doesn't really make sense. This will
allow libraries to be built with landing pads by default but allow usage of them
in contexts where landing pads aren't necessary.

cc #10780

src/librustc/back/lto.rs
src/librustc/driver/session.rs
src/librustc/lib/llvm.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/glue.rs
src/rustllvm/PassWrapper.cpp

index 7c8c6aabd7eab5cfccee33b9d44df98b2f57d185..3efaa387358d0eb5fb462e3eb6b8c55e1620c28c 100644 (file)
@@ -68,6 +68,12 @@ pub fn run(sess: session::Session, llmod: ModuleRef,
                                          arr.len() as libc::size_t);
     }
 
+    if sess.no_landing_pads() {
+        unsafe {
+            llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
+        }
+    }
+
     // Now we have one massive module inside of llmod. Time to run the
     // LTO-specific optimization passes that LLVM provides.
     //
index 30d5b7780cf92c3b688893fa827193635489eddb..79c939f6b7e7863ed3ca89cdd8592b1bf04b2894 100644 (file)
@@ -348,6 +348,9 @@ pub fn no_integrated_as(&self) -> bool {
     pub fn lto(&self) -> bool {
         self.debugging_opt(lto)
     }
+    pub fn no_landing_pads(&self) -> bool {
+        self.debugging_opt(no_landing_pads)
+    }
 
     // pointless function, now...
     pub fn str_of(&self, id: ast::Ident) -> @str {
index 7039eced9769fbb52411f0c95585a559501ec3fd..5b6c0c2b8658631a6392464ff8145c609f314488 100644 (file)
@@ -1747,6 +1747,7 @@ pub fn LLVMRustLinkInExternalBitcode(M: ModuleRef,
         pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
                                           syms: **c_char,
                                           len: size_t);
+        pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
     }
 }
 
index b95f4affc847e7536147c4ee588504c909757119..f3eb51a9f46f05018cccc1d62d64ca48011fe834 100644 (file)
@@ -915,7 +915,7 @@ pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
 }
 
 pub fn need_invoke(bcx: @mut Block) -> bool {
-    if (bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0) {
+    if bcx.ccx().sess.no_landing_pads() {
         return false;
     }
 
@@ -1254,8 +1254,7 @@ pub fn trans_block_cleanups_(bcx: @mut Block,
     let _icx = push_ctxt("trans_block_cleanups");
     // NB: Don't short-circuit even if this block is unreachable because
     // GC-based cleanup needs to the see that the roots are live.
-    let no_lpads =
-        bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0;
+    let no_lpads = bcx.ccx().sess.no_landing_pads();
     if bcx.unreachable && !no_lpads { return bcx; }
     let mut bcx = bcx;
     for cu in cleanups.rev_iter() {
index b7c518109963bf2ee2112a9cec1eec77e4c96702..3c0ffac7b4dbe35cb2ecad77f082c5860f50da5f 100644 (file)
@@ -15,7 +15,6 @@
 
 use back::abi;
 use back::link::*;
-use driver::session;
 use lib;
 use lib::llvm::{llvm, ValueRef, True};
 use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem};
@@ -274,8 +273,7 @@ pub fn call_tydesc_glue_full(bcx: @mut Block,
     let ccx = bcx.ccx();
     // NB: Don't short-circuit even if this block is unreachable because
     // GC-based cleanup needs to the see that the roots are live.
-    let no_lpads = ccx.sess.opts.debugging_opts & session::no_landing_pads != 0;
-    if bcx.unreachable && !no_lpads { return; }
+    if bcx.unreachable && !ccx.sess.no_landing_pads() { return; }
 
     let static_glue_fn = match static_ti {
       None => None,
index 76e24faebd93b9bdeac3222f3532a02448df76fa..4ac341a12e42a3ac1b03bd7d63a156c1371a4fdc 100644 (file)
@@ -219,3 +219,24 @@ LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) {
     passes.add(llvm::createInternalizePass(ref));
     passes.run(*unwrap(M));
 }
+
+extern "C" void
+LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
+    for (Module::iterator GV = unwrap(M)->begin(),
+         E = unwrap(M)->end(); GV != E; ++GV) {
+        GV->setDoesNotThrow();
+        Function *F = dyn_cast<Function>(GV);
+        if (F == NULL)
+            continue;
+
+        for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
+            for (BasicBlock::iterator I = B->begin(), IE = B->end();
+                 I != IE; ++I) {
+                if (isa<InvokeInst>(I)) {
+                    InvokeInst *CI = cast<InvokeInst>(I);
+                    CI->setDoesNotThrow();
+                }
+            }
+        }
+    }
+}