Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable all unwinding on -Z no-landing-pads LTO #10916

Merged
merged 1 commit into from
Dec 13, 2013
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Disable all unwinding on -Z no-landing-pads LTO
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 #10780
alexcrichton committed Dec 11, 2013
commit 667d114f47ae658894c496dbf07a8d29c737c877
6 changes: 6 additions & 0 deletions src/librustc/back/lto.rs
Original file line number Diff line number Diff line change
@@ -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.
//
3 changes: 3 additions & 0 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
@@ -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 {
1 change: 1 addition & 0 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
@@ -1747,6 +1747,7 @@ pub mod llvm {
pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
syms: **c_char,
len: size_t);
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
}
}

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