about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Chugunov <vadimcn@gmail.com>2014-01-03 23:34:15 -0800
committerVadim Chugunov <vadimcn@gmail.com>2014-01-03 23:34:15 -0800
commitcefb2c7e45140e1492b3cb45601a538478f40577 (patch)
tree32ed257df40eb903ac0b24456caf09e4b2af8388
parent8bfd2a84cfe83b3a0ff8f3a828303b378a8d94b9 (diff)
downloadrust-cefb2c7e45140e1492b3cb45601a538478f40577.tar.gz
rust-cefb2c7e45140e1492b3cb45601a538478f40577.zip
Fix ARM unwinding.
-rw-r--r--mk/platform.mk14
-rw-r--r--mk/rt.mk2
-rw-r--r--src/libstd/rt/unwind.rs159
3 files changed, 128 insertions, 47 deletions
diff --git a/mk/platform.mk b/mk/platform.mk
index 4070ccaf270..10c597e61d1 100644
--- a/mk/platform.mk
+++ b/mk/platform.mk
@@ -157,6 +157,7 @@ CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-l
 CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-whole-archive
 CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_x86_64-unknown-linux-gnu := .linux.def
+CFG_LLC_FLAGS_x86_64-unknown-linux-gnu :=
 CFG_INSTALL_NAME_x86_64-unknown-linux-gnu =
 CFG_LIBUV_LINK_FLAGS_x86_64-unknown-linux-gnu =
 CFG_LLVM_BUILD_ENV_x86_64-unknown-linux-gnu="CXXFLAGS=-fno-omit-frame-pointer"
@@ -184,6 +185,7 @@ CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-lis
 CFG_GCCISH_PRE_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-whole-archive
 CFG_GCCISH_POST_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_i686-unknown-linux-gnu := .linux.def
+CFG_LLC_FLAGS_i686-unknown-linux-gnu :=
 CFG_INSTALL_NAME_i686-unknown-linux-gnu =
 CFG_LIBUV_LINK_FLAGS_i686-unknown-linux-gnu =
 CFG_LLVM_BUILD_ENV_i686-unknown-linux-gnu="CXXFLAGS=-fno-omit-frame-pointer"
@@ -213,6 +215,7 @@ CFG_GCCISH_DEF_FLAG_arm-apple-darwin := -Wl,-exported_symbols_list,
 CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-darwin :=
 CFG_GCCISH_POST_LIB_FLAGS_arm-apple-darwin :=
 CFG_DEF_SUFFIX_arm-apple-darwin := .darwin.def
+CFG_LLC_FLAGS_arm-apple-darwin := -arm-enable-ehabi -arm-enable-ehabi-descriptors
 CFG_INSTALL_NAME_arm-apple-darwin = -Wl,-install_name,@rpath/$(1)
 CFG_LIBUV_LINK_FLAGS_arm-apple-darwin =
 CFG_EXE_SUFFIX_arm-apple-darwin :=
@@ -240,6 +243,7 @@ CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
 CFG_GCCISH_PRE_LIB_FLAGS_x86_64-apple-darwin :=
 CFG_GCCISH_POST_LIB_FLAGS_x86_64-apple-darwin :=
 CFG_DEF_SUFFIX_x86_64-apple-darwin := .darwin.def
+CFG_LLC_FLAGS_x86_64-apple-darwin :=
 CFG_INSTALL_NAME_x86_64-apple-darwin = -Wl,-install_name,@rpath/$(1)
 CFG_LIBUV_LINK_FLAGS_x86_64-apple-darwin =
 CFG_EXE_SUFFIX_x86_64-apple-darwin :=
@@ -266,6 +270,7 @@ CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
 CFG_GCCISH_PRE_LIB_FLAGS_i686-apple-darwin :=
 CFG_GCCISH_POST_LIB_FLAGS_i686-apple-darwin :=
 CFG_DEF_SUFFIX_i686-apple-darwin := .darwin.def
+CFG_LLC_FLAGS_i686-apple-darwin :=
 CFG_INSTALL_NAME_i686-apple-darwin = -Wl,-install_name,@rpath/$(1)
 CFG_LIBUV_LINK_FLAGS_i686-apple-darwin =
 CFG_EXE_SUFFIX_i686-apple-darwin :=
@@ -292,6 +297,7 @@ CFG_GCCISH_DEF_FLAG_arm-linux-androideabi := -Wl,--export-dynamic,--dynamic-list
 CFG_GCCISH_PRE_LIB_FLAGS_arm-linux-androideabi := -Wl,-whole-archive
 CFG_GCCISH_POST_LIB_FLAGS_arm-linux-androideabi := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_arm-linux-androideabi := .android.def
+CFG_LLC_FLAGS_arm-linux-androideabi := -arm-enable-ehabi -arm-enable-ehabi-descriptors
 CFG_INSTALL_NAME_arm-linux-androideabi =
 CFG_LIBUV_LINK_FLAGS_arm-linux-androideabi =
 CFG_EXE_SUFFIX_arm-linux-androideabi :=
@@ -321,6 +327,7 @@ CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynami
 CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-whole-archive
 CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_arm-unknown-linux-gnueabihf := .linux.def
+CFG_LLC_FLAGS_arm-unknown-linux-gnueabihf := -arm-enable-ehabi -arm-enable-ehabi-descriptors
 CFG_INSTALL_NAME_ar,-unknown-linux-gnueabihf =
 CFG_LIBUV_LINK_FLAGS_arm-unknown-linux-gnueabihf =
 CFG_EXE_SUFFIX_arm-unknown-linux-gnueabihf :=
@@ -350,6 +357,7 @@ CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabi := -Wl,--export-dynamic,--dynamic-
 CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-whole-archive
 CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_arm-unknown-linux-gnueabi := .linux.def
+CFG_LLC_FLAGS_arm-unknown-linux-gnueabi := -arm-enable-ehabi -arm-enable-ehabi-descriptors
 CFG_INSTALL_NAME_arm-unknown-linux-gnueabi =
 CFG_LIBUV_LINK_FLAGS_arm-unknown-linux-gnueabi =
 CFG_EXE_SUFFIX_arm-unknown-linux-gnueabi :=
@@ -378,6 +386,7 @@ CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-lis
 CFG_GCCISH_PRE_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-whole-archive
 CFG_GCCISH_POST_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_mips-unknown-linux-gnu := .linux.def
+CFG_LLC_FLAGS_mips-unknown-linux-gnu :=
 CFG_INSTALL_NAME_mips-unknown-linux-gnu =
 CFG_LIBUV_LINK_FLAGS_mips-unknown-linux-gnu =
 CFG_EXE_SUFFIX_mips-unknown-linux-gnu :=
@@ -405,6 +414,7 @@ CFG_GCCISH_DEF_FLAG_i686-pc-mingw32 :=
 CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-mingw32 :=
 CFG_GCCISH_POST_LIB_FLAGS_i686-pc-mingw32 :=
 CFG_DEF_SUFFIX_i686-pc-mingw32 := .mingw32.def
+CFG_LLC_FLAGS_i686-pc-mingw32 :=
 CFG_INSTALL_NAME_i686-pc-mingw32 =
 CFG_LIBUV_LINK_FLAGS_i686-pc-mingw32 := -lws2_32 -lpsapi -liphlpapi
 CFG_LLVM_BUILD_ENV_i686-pc-mingw32 := CPATH=$(CFG_SRC_DIR)src/etc/mingw-fix-include
@@ -432,6 +442,7 @@ CFG_GCCISH_DEF_FLAG_i586-mingw32msvc :=
 CFG_GCCISH_PRE_LIB_FLAGS_i586-mingw32msvc :=
 CFG_GCCISH_POST_LIB_FLAGS_i586-mingw32msvc :=
 CFG_DEF_SUFFIX_i586-mingw32msvc := .mingw32.def
+CFG_LLC_FLAGS_i586-mingw32msvc :=
 CFG_INSTALL_NAME_i586-mingw32msvc =
 CFG_LIBUV_LINK_FLAGS_i586-mingw32msvc := -L$(CFG_MINGW32_CROSS_PATH)/i586-mingw32msvc/lib -lws2_32 -lpsapi -liphlpapi
 CFG_EXE_SUFFIX_i586-mingw32msvc := .exe
@@ -461,6 +472,7 @@ CFG_GCCISH_DEF_FLAG_i686-w64-mingw32 :=
 CFG_GCCISH_PRE_LIB_FLAGS_i686-w64-mingw32 :=
 CFG_GCCISH_POST_LIB_FLAGS_i686-w64-mingw32 :=
 CFG_DEF_SUFFIX_i686-w64-mingw32 := .mingw32.def
+CFG_LLC_FLAGS_i686-w64-mingw32 :=
 CFG_INSTALL_NAME_i686-w64-mingw32 =
 CFG_LIBUV_LINK_FLAGS_i686-w64-mingw32 := -lws2_32 -lpsapi -liphlpapi
 CFG_EXE_SUFFIX_i686-w64-mingw32 := .exe
@@ -489,6 +501,7 @@ CFG_GCCISH_DEF_FLAG_x86_64-w64-mingw32 :=
 CFG_GCCISH_PRE_LIB_FLAGS_x86_64-w64-mingw32 :=
 CFG_GCCISH_POST_LIB_FLAGS_x86_64-w64-mingw32 :=
 CFG_DEF_SUFFIX_x86_64-w64-mingw32 := .mingw32.def
+CFG_LLC_FLAGS_x86_64-w64-mingw32 :=
 CFG_INSTALL_NAME_x86_64-w64-mingw32 =
 CFG_LIBUV_LINK_FLAGS_x86_64-w64-mingw32 := -lws2_32 -lpsapi -liphlpapi
 CFG_EXE_SUFFIX_x86_64-w64-mingw32 := .exe
@@ -515,6 +528,7 @@ CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-lis
 CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-whole-archive
 CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-no-whole-archive
 CFG_DEF_SUFFIX_x86_64-unknown-freebsd := .bsd.def
+CFG_LLC_FLAGS_x86_64-unknown-freebsd :=
 CFG_INSTALL_NAME_x86_64-unknown-freebsd =
 CFG_LIBUV_LINK_FLAGS_x86_64-unknown-freebsd := -pthread  -lkvm
 CFG_EXE_SUFFIX_x86_64-unknown-freebsd :=
diff --git a/mk/rt.mk b/mk/rt.mk
index ddffcb3ffb9..38cc233b933 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -116,7 +116,7 @@ $$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.S  $$(MKFILE_DEPS) \
 $$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.ll  $$(MKFILE_DEPS) \
                      $$(LLVM_CONFIG_$$(CFG_BUILD))
 	@$$(call E, compile: $$@)
-	$$(Q)$(LLC_$(CFG_BUILD)) -filetype=obj -mtriple=$(1) -relocation-model=pic -o $$@ $$<
+	$$(Q)$(LLC_$(CFG_BUILD)) $$(CFG_LLC_FLAGS_$(1)) -filetype=obj -mtriple=$(1) -relocation-model=pic -o $$@ $$<
 
 $$(RT_BUILD_DIR_$(1)_$(2))/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJS_$(1)_$(2))
 	@$$(call E, link: $$@)
diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs
index 358df7260f4..3904be179c2 100644
--- a/src/libstd/rt/unwind.rs
+++ b/src/libstd/rt/unwind.rs
@@ -59,8 +59,7 @@ use any::{Any, AnyRefExt};
 use c_str::CString;
 use cast;
 use kinds::Send;
-use libc::{c_char, size_t};
-use libc::{c_void, c_int};
+use libc::{c_void, c_char, size_t};
 use option::{Some, None, Option};
 use result::{Err, Ok};
 use rt::local::Local;
@@ -78,6 +77,7 @@ mod libunwind {
 
     use libc::{uintptr_t, uint64_t};
 
+    #[cfg(not(target_os = "android"))]
     #[repr(C)]
     pub enum _Unwind_Action
     {
@@ -88,6 +88,18 @@ mod libunwind {
         _UA_END_OF_STACK = 16,
     }
 
+    #[cfg(target_os = "android")]
+    #[repr(C)]
+    pub enum _Unwind_State
+    {
+      _US_VIRTUAL_UNWIND_FRAME = 0,
+      _US_UNWIND_FRAME_STARTING = 1,
+      _US_UNWIND_FRAME_RESUME = 2,
+      _US_ACTION_MASK = 3,
+      _US_FORCE_UNWIND = 8,
+      _US_END_OF_STACK = 16
+    }
+
     #[repr(C)]
     pub enum _Unwind_Reason_Code {
         _URC_NO_REASON = 0,
@@ -99,6 +111,7 @@ mod libunwind {
         _URC_HANDLER_FOUND = 6,
         _URC_INSTALL_CONTEXT = 7,
         _URC_CONTINUE_UNWIND = 8,
+        _URC_FAILURE = 9, // used only by ARM EABI
     }
 
     pub type _Unwind_Exception_Class = uint64_t;
@@ -108,8 +121,7 @@ mod libunwind {
     pub struct _Unwind_Exception {
         exception_class: _Unwind_Exception_Class,
         exception_cleanup: _Unwind_Exception_Cleanup_Fn,
-        private_1: _Unwind_Word,
-        private_2: _Unwind_Word,
+        private: [_Unwind_Word, ..20],
     }
 
     pub enum _Unwind_Context {}
@@ -148,7 +160,7 @@ impl Unwinder {
             let ep = rust_try(try_fn, closure.code as *c_void,
                               closure.env as *c_void);
             if !ep.is_null() {
-                rtdebug!("Caught {}", (*ep).exception_class);
+                rtdebug!("caught {}", (*ep).exception_class);
                 uw::_Unwind_DeleteException(ep);
             }
         }
@@ -190,8 +202,7 @@ impl Unwinder {
                 let exception = ~uw::_Unwind_Exception {
                     exception_class: rust_exception_class(),
                     exception_cleanup: exception_cleanup,
-                    private_1: 0,
-                    private_2: 0
+                    private: [0, ..20],
                 };
                 let error = uw::_Unwind_RaiseException(cast::transmute(exception));
                 rtabort!("Could not unwind stack, error = {}", error as int)
@@ -242,51 +253,107 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
 //   This is achieved by overriding the return value in search phase to always
 //   say "catch!".
 
-extern "C" {
-    fn __gcc_personality_v0(version: c_int,
-                            actions: uw::_Unwind_Action,
-                            exception_class: uw::_Unwind_Exception_Class,
-                            ue_header: *uw::_Unwind_Exception,
-                            context: *uw::_Unwind_Context)
-        -> uw::_Unwind_Reason_Code;
-}
+#[cfg(not(target_os = "android"))]
+pub mod eabi {
+    use uw = super::libunwind;
+    use libc::c_int;
 
-#[lang="eh_personality"]
-#[no_mangle] // so we can reference it by name from middle/trans/base.rs
-#[doc(hidden)]
-#[cfg(not(test))]
-pub extern "C" fn rust_eh_personality(
-    version: c_int,
-    actions: uw::_Unwind_Action,
-    exception_class: uw::_Unwind_Exception_Class,
-    ue_header: *uw::_Unwind_Exception,
-    context: *uw::_Unwind_Context
-) -> uw::_Unwind_Reason_Code
-{
-    unsafe {
-        __gcc_personality_v0(version, actions, exception_class, ue_header,
-                             context)
+    extern "C" {
+        fn __gcc_personality_v0(version: c_int,
+                                actions: uw::_Unwind_Action,
+                                exception_class: uw::_Unwind_Exception_Class,
+                                ue_header: *uw::_Unwind_Exception,
+                                context: *uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
+    }
+
+    #[lang="eh_personality"]
+    #[no_mangle] // so we can reference it by name from middle/trans/base.rs
+    #[doc(hidden)]
+    #[cfg(not(test))]
+    pub extern "C" fn rust_eh_personality(
+        version: c_int,
+        actions: uw::_Unwind_Action,
+        exception_class: uw::_Unwind_Exception_Class,
+        ue_header: *uw::_Unwind_Exception,
+        context: *uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        unsafe {
+            __gcc_personality_v0(version, actions, exception_class, ue_header,
+                                 context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    #[doc(hidden)]
+    #[cfg(not(test))]
+    pub extern "C" fn rust_eh_personality_catch(
+        version: c_int,
+        actions: uw::_Unwind_Action,
+        exception_class: uw::_Unwind_Exception_Class,
+        ue_header: *uw::_Unwind_Exception,
+        context: *uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            unsafe {
+                 __gcc_personality_v0(version, actions, exception_class, ue_header,
+                                      context)
+            }
+        }
     }
 }
 
-#[no_mangle] // referenced from rust_try.ll
-#[doc(hidden)]
-#[cfg(not(test))]
-pub extern "C" fn rust_eh_personality_catch(
-    version: c_int,
-    actions: uw::_Unwind_Action,
-    exception_class: uw::_Unwind_Exception_Class,
-    ue_header: *uw::_Unwind_Exception,
-    context: *uw::_Unwind_Context
-) -> uw::_Unwind_Reason_Code
-{
-    if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
-        uw::_URC_HANDLER_FOUND // catch!
+// ARM EHABI uses a slightly different personality routine signature,
+// but otherwise works the same.
+#[cfg(target_os = "android")]
+pub mod eabi {
+    use uw = super::libunwind;
+    use libc::c_int;
+
+    extern "C" {
+        fn __gcc_personality_v0(state: uw::_Unwind_State,
+                                ue_header: *uw::_Unwind_Exception,
+                                context: *uw::_Unwind_Context)
+            -> uw::_Unwind_Reason_Code;
     }
-    else { // cleanup phase
+
+    #[lang="eh_personality"]
+    #[no_mangle] // so we can reference it by name from middle/trans/base.rs
+    #[doc(hidden)]
+    #[cfg(not(test))]
+    pub extern "C" fn rust_eh_personality(
+        state: uw::_Unwind_State,
+        ue_header: *uw::_Unwind_Exception,
+        context: *uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
         unsafe {
-             __gcc_personality_v0(version, actions, exception_class, ue_header,
-                                  context)
+            __gcc_personality_v0(state, ue_header, context)
+        }
+    }
+
+    #[no_mangle] // referenced from rust_try.ll
+    #[doc(hidden)]
+    #[cfg(not(test))]
+    pub extern "C" fn rust_eh_personality_catch(
+        state: uw::_Unwind_State,
+        ue_header: *uw::_Unwind_Exception,
+        context: *uw::_Unwind_Context
+    ) -> uw::_Unwind_Reason_Code
+    {
+        if (state as c_int & uw::_US_ACTION_MASK as c_int)
+                           == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { // search phase
+            uw::_URC_HANDLER_FOUND // catch!
+        }
+        else { // cleanup phase
+            unsafe {
+                 __gcc_personality_v0(state, ue_header, context)
+            }
         }
     }
 }