diff options
| author | Vadim Chugunov <vadimcn@gmail.com> | 2014-04-10 10:48:38 -0700 |
|---|---|---|
| committer | Vadim Chugunov <vadimcn@gmail.com> | 2014-08-04 18:27:23 -0700 |
| commit | 5a24ee8a9ef1bb3bf250ce39902cf8dfca1a4dea (patch) | |
| tree | 1cbca1cbc7baaa9e1887fefbe2977ce446338c4f /src/rt | |
| parent | a12b23521fd5cc826a787a45cfa6630857a8939e (diff) | |
| download | rust-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.ll | 34 |
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(...) |
