Skip to content

Commit

Permalink
rustc_trans: Disable landing pads on 32-bit MSVC
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
alexcrichton committed Jul 2, 2015
1 parent 83ee47b commit 3e26e56
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 6 deletions.
9 changes: 8 additions & 1 deletion src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 7 additions & 5 deletions src/librustc_trans/trans/cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand All @@ -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,
Expand Down
42 changes: 42 additions & 0 deletions src/rt/rust_try_msvc_32.ll
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 3e26e56

Please sign in to comment.