Skip to content

Commit 667d114

Browse files
committed
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
1 parent b8b16ae commit 667d114

File tree

6 files changed

+34
-6
lines changed

6 files changed

+34
-6
lines changed

src/librustc/back/lto.rs

+6
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ pub fn run(sess: session::Session, llmod: ModuleRef,
6868
arr.len() as libc::size_t);
6969
}
7070

71+
if sess.no_landing_pads() {
72+
unsafe {
73+
llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
74+
}
75+
}
76+
7177
// Now we have one massive module inside of llmod. Time to run the
7278
// LTO-specific optimization passes that LLVM provides.
7379
//

src/librustc/driver/session.rs

+3
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ impl Session_ {
348348
pub fn lto(&self) -> bool {
349349
self.debugging_opt(lto)
350350
}
351+
pub fn no_landing_pads(&self) -> bool {
352+
self.debugging_opt(no_landing_pads)
353+
}
351354

352355
// pointless function, now...
353356
pub fn str_of(&self, id: ast::Ident) -> @str {

src/librustc/lib/llvm.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,7 @@ pub mod llvm {
17471747
pub fn LLVMRustRunRestrictionPass(M: ModuleRef,
17481748
syms: **c_char,
17491749
len: size_t);
1750+
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
17501751
}
17511752
}
17521753

src/librustc/middle/trans/base.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef],
915915
}
916916

917917
pub fn need_invoke(bcx: @mut Block) -> bool {
918-
if (bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0) {
918+
if bcx.ccx().sess.no_landing_pads() {
919919
return false;
920920
}
921921

@@ -1254,8 +1254,7 @@ pub fn trans_block_cleanups_(bcx: @mut Block,
12541254
let _icx = push_ctxt("trans_block_cleanups");
12551255
// NB: Don't short-circuit even if this block is unreachable because
12561256
// GC-based cleanup needs to the see that the roots are live.
1257-
let no_lpads =
1258-
bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0;
1257+
let no_lpads = bcx.ccx().sess.no_landing_pads();
12591258
if bcx.unreachable && !no_lpads { return bcx; }
12601259
let mut bcx = bcx;
12611260
for cu in cleanups.rev_iter() {

src/librustc/middle/trans/glue.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
use back::abi;
1717
use back::link::*;
18-
use driver::session;
1918
use lib;
2019
use lib::llvm::{llvm, ValueRef, True};
2120
use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem};
@@ -274,8 +273,7 @@ pub fn call_tydesc_glue_full(bcx: @mut Block,
274273
let ccx = bcx.ccx();
275274
// NB: Don't short-circuit even if this block is unreachable because
276275
// GC-based cleanup needs to the see that the roots are live.
277-
let no_lpads = ccx.sess.opts.debugging_opts & session::no_landing_pads != 0;
278-
if bcx.unreachable && !no_lpads { return; }
276+
if bcx.unreachable && !ccx.sess.no_landing_pads() { return; }
279277

280278
let static_glue_fn = match static_ti {
281279
None => None,

src/rustllvm/PassWrapper.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,24 @@ LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) {
219219
passes.add(llvm::createInternalizePass(ref));
220220
passes.run(*unwrap(M));
221221
}
222+
223+
extern "C" void
224+
LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
225+
for (Module::iterator GV = unwrap(M)->begin(),
226+
E = unwrap(M)->end(); GV != E; ++GV) {
227+
GV->setDoesNotThrow();
228+
Function *F = dyn_cast<Function>(GV);
229+
if (F == NULL)
230+
continue;
231+
232+
for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
233+
for (BasicBlock::iterator I = B->begin(), IE = B->end();
234+
I != IE; ++I) {
235+
if (isa<InvokeInst>(I)) {
236+
InvokeInst *CI = cast<InvokeInst>(I);
237+
CI->setDoesNotThrow();
238+
}
239+
}
240+
}
241+
}
242+
}

0 commit comments

Comments
 (0)