mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
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:
commit
378897a09c
@ -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.
|
||||
//
|
||||
|
@ -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 {
|
||||
|
@ -1747,6 +1747,7 @@ pub mod llvm {
|
||||
pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
|
||||
syms: **c_char,
|
||||
len: size_t);
|
||||
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user