Skip to content

Commit

Permalink
Disable all unwinding on -Z no-landing-pads LTO
Browse files Browse the repository at this point in the history
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 rust-lang#10780
  • Loading branch information
alexcrichton committed Dec 11, 2013
1 parent b8b16ae commit 667d114
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src/librustc/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,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 {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1747,6 +1747,7 @@ pub mod llvm {
pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
syms: **c_char,
len: size_t);
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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() {
Expand Down
4 changes: 1 addition & 3 deletions src/librustc/middle/trans/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
Expand Down
21 changes: 21 additions & 0 deletions src/rustllvm/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
}
}

2 comments on commit 667d114

@alexcrichton
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=pcwalton

@alexcrichton
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors: retry

Please sign in to comment.