From f9de964ccf767498ed7b1b4a879aaca1777a9d3d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 29 Jun 2015 16:07:45 -0700 Subject: [PATCH] msvc: Enable landing pads by default This commit turns on landing pads for MSVC by default, which means that we'll now be running cleanups for values on the stack when an exception is thrown. This commit "fixes" the previously seen LLVM abort by attaching the `noinline` attribute to all generated drop glue to prevent landing pads from being inlined into other landing pads. The performance of MSVC is highly likely to decrease from this commit, but there are various routes we can taken in the future if this ends up staying for quite a while, such as generating a shim function only called from landing pads which calls the actual drop glue, and this shim is marked noinline. For now, however, this patch enables MSVC to successfully bootstrap itself! --- src/librustc_trans/trans/base.rs | 7 +------ src/librustc_trans/trans/glue.rs | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 0cd6bbad03aa..b829a9c6ec44 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -751,12 +751,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } pub fn need_invoke(bcx: Block) -> bool { - // FIXME(#25869) currently unwinding is not implemented for MSVC and our - // normal unwinding infrastructure ends up just causing linker - // errors with the current LLVM implementation, so landing - // pads are disabled entirely for MSVC targets - if bcx.sess().no_landing_pads() || - bcx.sess().target.target.options.is_like_msvc { + if bcx.sess().no_landing_pads() { return false; } diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 3bcdcd89c47f..be8510c8e968 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -22,8 +22,9 @@ use middle::lang_items::ExchangeFreeFnLangItem; use middle::subst; use middle::subst::{Subst, Substs}; use middle::ty::{self, Ty}; -use trans::adt; use trans::adt::GetDtorType; // for tcx.dtor_type() +use trans::adt; +use trans::attributes; use trans::base::*; use trans::build::*; use trans::callee; @@ -43,6 +44,7 @@ use trans::type_::Type; use arena::TypedArena; use libc::c_uint; use syntax::ast; +use syntax::attr::InlineAttr; pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, @@ -250,6 +252,25 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, update_linkage(ccx, llfn, None, OriginalTranslation); + // FIXME: Currently LLVM has a bug where if an SSA value is created in one + // landing pad and then used in another it will abort during + // compilation. The compiler never actually generates nested landing + // pads, but this often arises when destructors are inlined into + // other functions. To prevent this inlining from happening (and thus + // preventing the LLVM abort) we mark all drop glue as inline(never) + // on MSVC. + // + // For more information about the bug, see: + // + // https://llvm.org/bugs/show_bug.cgi?id=23884 + // + // This is clearly not the ideal solution to the problem (due to the + // perf hits), so this should be removed once the upstream bug is + // fixed. + if ccx.sess().target.target.options.is_like_msvc { + attributes::inline(llfn, InlineAttr::Never); + } + ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1); // All glue functions take values passed *by alias*; this is a // requirement since in many contexts glue is invoked indirectly and