From 667d114f47ae658894c496dbf07a8d29c737c877 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Dec 2013 23:27:15 -0800 Subject: [PATCH] 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 --- src/librustc/back/lto.rs | 6 ++++++ src/librustc/driver/session.rs | 3 +++ src/librustc/lib/llvm.rs | 1 + src/librustc/middle/trans/base.rs | 5 ++--- src/librustc/middle/trans/glue.rs | 4 +--- src/rustllvm/PassWrapper.cpp | 21 +++++++++++++++++++++ 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs index 7c8c6aabd7eab..3efaa387358d0 100644 --- a/src/librustc/back/lto.rs +++ b/src/librustc/back/lto.rs @@ -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. // diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 30d5b7780cf92..79c939f6b7e78 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -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 { diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 7039eced9769f..5b6c0c2b86586 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1747,6 +1747,7 @@ pub mod llvm { pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: **c_char, len: size_t); + pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef); } } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index b95f4affc847e..f3eb51a9f46f0 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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() { diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index b7c518109963b..3c0ffac7b4dbe 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -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, diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 76e24faebd93b..4ac341a12e42a 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -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(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(I)) { + InvokeInst *CI = cast(I); + CI->setDoesNotThrow(); + } + } + } + } +}