diff options
| author | bors <bors@rust-lang.org> | 2013-12-13 12:56:36 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-12-13 12:56:36 -0800 |
| commit | 378897a09c4c72595d450f74f2ffbb1ab44958a2 (patch) | |
| tree | 029b82798846a0addae26001a7fa831e5f40aa54 | |
| parent | ae3078ca257fe39a7fdc84bdfb81778b2542c520 (diff) | |
| parent | 667d114f47ae658894c496dbf07a8d29c737c877 (diff) | |
| download | rust-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.rs | 6 | ||||
| -rw-r--r-- | src/librustc/driver/session.rs | 3 | ||||
| -rw-r--r-- | src/librustc/lib/llvm.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/trans/base.rs | 5 | ||||
| -rw-r--r-- | src/librustc/middle/trans/glue.rs | 4 | ||||
| -rw-r--r-- | src/rustllvm/PassWrapper.cpp | 21 |
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(); + } + } + } + } +} |
