about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-06-30 10:28:24 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-07-02 10:45:13 -0700
commit3e26e56a79ae33dfc8f2f4d0123b5080fd0a7853 (patch)
tree597c940aec7675d6a84159ec14fc2ac760184c94
parent83ee47b054deb5939be20d7d6ce03ad33d005424 (diff)
downloadrust-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.rs9
-rw-r--r--src/librustc_trans/trans/cleanup.rs12
-rw-r--r--src/rt/rust_try_msvc_32.ll42
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