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.
This commit is contained in:
bors 2013-12-13 12:56:36 -08:00
commit 378897a09c
6 changed files with 34 additions and 6 deletions

View 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.
//

View File

@ -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 {

View File

@ -1747,6 +1747,7 @@ pub mod llvm {
pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
syms: **c_char,
len: size_t);
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
}
}

View 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() {

View 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,

View 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();
}
}
}
}
}