about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-12-13 12:56:36 -0800
committerbors <bors@rust-lang.org>2013-12-13 12:56:36 -0800
commit378897a09c4c72595d450f74f2ffbb1ab44958a2 (patch)
tree029b82798846a0addae26001a7fa831e5f40aa54
parentae3078ca257fe39a7fdc84bdfb81778b2542c520 (diff)
parent667d114f47ae658894c496dbf07a8d29c737c877 (diff)
downloadrust-378897a09c4c72595d450f74f2ffbb1ab44958a2.tar.gz
rust-378897a09c4c72595d450f74f2ffbb1ab44958a2.zip
auto merge of #10916 : alexcrichton/rust/nounwind, r=pcwalton
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.
-rw-r--r--src/librustc/back/lto.rs6
-rw-r--r--src/librustc/driver/session.rs3
-rw-r--r--src/librustc/lib/llvm.rs1
-rw-r--r--src/librustc/middle/trans/base.rs5
-rw-r--r--src/librustc/middle/trans/glue.rs4
-rw-r--r--src/rustllvm/PassWrapper.cpp21
6 files changed, 34 insertions, 6 deletions
diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs
index 7c8c6aabd7e..3efaa387358 100644
--- a/src/librustc/back/lto.rs
+++ b/src/librustc/back/lto.rs
@@ -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.
     //
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index c6a6f7b5e90..00f39138f58 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -347,6 +347,9 @@ impl Session_ {
     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 {
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 7039eced976..5b6c0c2b865 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -1747,6 +1747,7 @@ pub mod llvm {
         pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
                                           syms: **c_char,
                                           len: size_t);
+        pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
     }
 }
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index d6fc48b52ea..045330835dc 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -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() {
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 3e3ba06538b..2a27a7cee3c 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -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,
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 76e24faebd9..4ac341a12e4 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -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();
+                }
+            }
+        }
+    }
+}