about summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorVadim Chugunov <vadimcn@gmail.com>2014-04-10 10:48:38 -0700
committerVadim Chugunov <vadimcn@gmail.com>2014-08-04 18:27:23 -0700
commit5a24ee8a9ef1bb3bf250ce39902cf8dfca1a4dea (patch)
tree1cbca1cbc7baaa9e1887fefbe2977ce446338c4f /src/rt
parenta12b23521fd5cc826a787a45cfa6630857a8939e (diff)
downloadrust-5a24ee8a9ef1bb3bf250ce39902cf8dfca1a4dea.tar.gz
rust-5a24ee8a9ef1bb3bf250ce39902cf8dfca1a4dea.zip
Implement unwinding for Win64.
The original trick used to trigger unwinds would not work with GCC's implementation of SEH, so I had to invent a new one: rust_try now consists of two routines: the outer one, whose handler triggers unwinds, and the inner one, that stops unwinds by having a landing pad that swallows exceptions and passes them on to the outer routine via a normal return.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_try.ll34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/rt/rust_try.ll b/src/rt/rust_try.ll
index c912aa789bf..08bf5e3dfac 100644
--- a/src/rt/rust_try.ll
+++ b/src/rt/rust_try.ll
@@ -11,24 +11,40 @@
 ; Rust's try-catch
 ; When f(...) returns normally, the return value is null.
 ; When f(...) throws, the return value is a pointer to the caught exception object.
-; See also: libstd/rt/unwind.rs
+; See also: librustrt/unwind.rs
 
 define i8* @rust_try(void (i8*,i8*)* %f, i8* %fptr, i8* %env) {
 
-	invoke void %f(i8* %fptr, i8* %env)
-		to label %normal
-		unwind label %catch
+    %1 = invoke i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env)
+        to label %normal
+        unwind label %catch
 
 normal:
-	ret i8* null
+    ret i8* %1
 
 catch:
-	%1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality_catch to i8*)
-			catch i8* null ; catch everything
+    landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality_catch to i8*)
+        catch i8* null
+    ; execution will never reach here because rust_try_inner's landing pad does not resume unwinds
+    ret i8* null
+}
+
+define internal i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env) {
+
+    invoke void %f(i8* %fptr, i8* %env)
+        to label %normal
+        unwind label %catch
 
-	; extract and return pointer to the exception object
+normal:
+    ret i8* null
+
+catch:
+    %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality to i8*)
+        catch i8* null
+    ; extract and return pointer to the exception object
     %2 = extractvalue { i8*, i32 } %1, 0
-	ret i8* %2
+    ret i8* %2
 }
 
+declare i32 @rust_eh_personality(...)
 declare i32 @rust_eh_personality_catch(...)