diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-06-30 10:28:24 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-07-02 10:45:13 -0700 |
| commit | 3e26e56a79ae33dfc8f2f4d0123b5080fd0a7853 (patch) | |
| tree | 597c940aec7675d6a84159ec14fc2ac760184c94 | |
| parent | 83ee47b054deb5939be20d7d6ce03ad33d005424 (diff) | |
| download | rust-3e26e56a79ae33dfc8f2f4d0123b5080fd0a7853.tar.gz rust-3e26e56a79ae33dfc8f2f4d0123b5080fd0a7853.zip | |
rustc_trans: Disable landing pads on 32-bit MSVC
This is currently quite buggy in LLVM from what I can tell, so just disable it entirely. This commit also adds preliminary support, however, to actually target 32-bit MSVC by making sure the `rust_try_msvc_32.ll` file exists and wiring up exceptions to `_except_handler3` instead of `__C_specific_handler` (which doesn't exist on 32-bit).
| -rw-r--r-- | src/librustc_trans/trans/base.rs | 9 | ||||
| -rw-r--r-- | src/librustc_trans/trans/cleanup.rs | 12 | ||||
| -rw-r--r-- | src/rt/rust_try_msvc_32.ll | 42 |
3 files changed, 57 insertions, 6 deletions
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index b829a9c6ec4..079cd9c3757 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -752,7 +752,14 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pub fn need_invoke(bcx: Block) -> bool { if bcx.sess().no_landing_pads() { - return false; + return false + } + + // Currently 32-bit MSVC unwinding is not super well implemented in LLVM, so + // we avoid it entirely. + if bcx.sess().target.target.options.is_like_msvc && + bcx.sess().target.target.arch == "x86" { + return false } // Avoid using invoke if we are already inside a landing pad. diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index 588e4cea504..1891320313a 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -851,8 +851,8 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx // an "exception", but for MSVC we want to force SEH. This means that we // can't actually have the personality function be our standard // `rust_eh_personality` function, but rather we wired it up to the - // CRT's custom `__C_specific_handler` personality funciton, which - // forces LLVM to consider landing pads as "landing pads for SEH". + // CRT's custom personality function, which forces LLVM to consider + // landing pads as "landing pads for SEH". let target = &self.ccx.sess().target.target; let llpersonality = match pad_bcx.tcx().lang_items.eh_personality() { Some(def_id) if !target.options.is_like_msvc => { @@ -864,10 +864,12 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx match *personality { Some(llpersonality) => llpersonality, None => { - let name = if target.options.is_like_msvc { - "__C_specific_handler" - } else { + let name = if !target.options.is_like_msvc { "rust_eh_personality" + } else if target.arch == "x86" { + "_except_handler3" + } else { + "__C_specific_handler" }; let fty = Type::variadic_func(&[], &Type::i32(self.ccx)); let f = declare::declare_cfn(self.ccx, name, fty, diff --git a/src/rt/rust_try_msvc_32.ll b/src/rt/rust_try_msvc_32.ll new file mode 100644 index 00000000000..bdee53b136e --- /dev/null +++ b/src/rt/rust_try_msvc_32.ll @@ -0,0 +1,42 @@ +; Copyright 2015 The Rust Project Developers. See the COPYRIGHT +; file at the top-level directory of this distribution and at +; http://rust-lang.org/COPYRIGHT. +; +; Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +; http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +; <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +; option. This file may not be copied, modified, or distributed +; except according to those terms. + +; For more comments about what's going on here see rust_try_msvc_64.ll. The only +; difference between that and this file is the personality function used as it's +; different for 32-bit MSVC than it is for 64-bit. + +define i8* @rust_try(void (i8*)* %f, i8* %env) + personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) +{ + invoke void %f(i8* %env) + to label %normal + unwind label %catch + +normal: + ret i8* null +catch: + %vals = landingpad { i8*, i32 } + catch i8* bitcast (i32 (i8*, i8*)* @__rust_try_filter to i8*) + %ehptr = extractvalue { i8*, i32 } %vals, 0 + %sel = extractvalue { i8*, i32 } %vals, 1 + %filter_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @__rust_try_filter to i8*)) + %is_filter = icmp eq i32 %sel, %filter_sel + br i1 %is_filter, label %catch-return, label %catch-resume + +catch-return: + ret i8* %ehptr + +catch-resume: + resume { i8*, i32 } %vals +} + +declare i32 @_except_handler3(...) +declare i32 @__rust_try_filter(i8*, i8*) +declare i32 @llvm.eh.typeid.for(i8*) readnone nounwind |
