Skip to content

Commit 3a0adb8

Browse files
committed
---
yaml --- r: 126415 b: refs/heads/master c: 5a24ee8 h: refs/heads/master i: 126413: 475c659 126411: c8b5b6a 126407: c3e368d 126399: f7a958b v: v3
1 parent 5806a56 commit 3a0adb8

File tree

4 files changed

+147
-36
lines changed

4 files changed

+147
-36
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: a12b23521fd5cc826a787a45cfa6630857a8939e
2+
refs/heads/master: 5a24ee8a9ef1bb3bf250ce39902cf8dfca1a4dea
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 9fc8394d3bce22ab483f98842434c84c396212ae
55
refs/heads/try: cd2003ffd8dd976342f9e8fc1429ae93d6780e81

trunk/src/librustrt/libunwind.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub type _Unwind_Word = libc::uintptr_t;
6060
pub static unwinder_private_data_size: uint = 5;
6161

6262
#[cfg(target_arch = "x86_64")]
63-
pub static unwinder_private_data_size: uint = 2;
63+
pub static unwinder_private_data_size: uint = 6;
6464

6565
#[cfg(target_arch = "arm", not(target_os = "ios"))]
6666
pub static unwinder_private_data_size: uint = 20;

trunk/src/librustrt/unwind.rs

Lines changed: 120 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
227227
// This is achieved by overriding the return value in search phase to always
228228
// say "catch!".
229229

230-
#[cfg(not(target_arch = "arm"), not(test))]
230+
#[cfg(not(target_arch = "arm"), not(windows, target_arch = "x86_64"), not(test))]
231231
#[doc(hidden)]
232232
#[allow(visible_private_types)]
233233
pub mod eabi {
@@ -244,7 +244,8 @@ pub mod eabi {
244244
}
245245

246246
#[lang="eh_personality"]
247-
extern fn eh_personality(
247+
#[no_mangle] // referenced from rust_try.ll
248+
extern fn rust_eh_personality(
248249
version: c_int,
249250
actions: uw::_Unwind_Action,
250251
exception_class: uw::_Unwind_Exception_Class,
@@ -260,21 +261,19 @@ pub mod eabi {
260261

261262
#[no_mangle] // referenced from rust_try.ll
262263
pub extern "C" fn rust_eh_personality_catch(
263-
version: c_int,
264+
_version: c_int,
264265
actions: uw::_Unwind_Action,
265-
exception_class: uw::_Unwind_Exception_Class,
266-
ue_header: *mut uw::_Unwind_Exception,
267-
context: *mut uw::_Unwind_Context
266+
_exception_class: uw::_Unwind_Exception_Class,
267+
_ue_header: *mut uw::_Unwind_Exception,
268+
_context: *mut uw::_Unwind_Context
268269
) -> uw::_Unwind_Reason_Code
269270
{
271+
270272
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
271273
uw::_URC_HANDLER_FOUND // catch!
272274
}
273275
else { // cleanup phase
274-
unsafe {
275-
__gcc_personality_v0(version, actions, exception_class, ue_header,
276-
context)
277-
}
276+
uw::_URC_INSTALL_CONTEXT
278277
}
279278
}
280279
}
@@ -299,7 +298,7 @@ pub mod eabi {
299298
}
300299

301300
#[lang="eh_personality"]
302-
#[no_mangle] // so we can reference it by name from middle/trans/base.rs
301+
#[no_mangle] // referenced from rust_try.ll
303302
pub extern "C" fn rust_eh_personality(
304303
version: c_int,
305304
actions: uw::_Unwind_Action,
@@ -316,29 +315,26 @@ pub mod eabi {
316315

317316
#[no_mangle] // referenced from rust_try.ll
318317
pub extern "C" fn rust_eh_personality_catch(
319-
version: c_int,
318+
_version: c_int,
320319
actions: uw::_Unwind_Action,
321-
exception_class: uw::_Unwind_Exception_Class,
322-
ue_header: *mut uw::_Unwind_Exception,
323-
context: *mut uw::_Unwind_Context
320+
_exception_class: uw::_Unwind_Exception_Class,
321+
_ue_header: *mut uw::_Unwind_Exception,
322+
_context: *mut uw::_Unwind_Context
324323
) -> uw::_Unwind_Reason_Code
325324
{
326325
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
327326
uw::_URC_HANDLER_FOUND // catch!
328327
}
329328
else { // cleanup phase
330-
unsafe {
331-
__gcc_personality_sj0(version, actions, exception_class, ue_header,
332-
context)
333-
}
329+
uw::_URC_INSTALL_CONTEXT
334330
}
335331
}
336332
}
337333

338334

339335
// ARM EHABI uses a slightly different personality routine signature,
340336
// but otherwise works the same.
341-
#[cfg(target_arch = "arm", not(test), not(target_os = "ios"))]
337+
#[cfg(target_arch = "arm", not(target_os = "ios", not(test)))]
342338
#[allow(visible_private_types)]
343339
pub mod eabi {
344340
use uw = libunwind;
@@ -352,7 +348,8 @@ pub mod eabi {
352348
}
353349

354350
#[lang="eh_personality"]
355-
extern "C" fn eh_personality(
351+
#[no_mangle] // referenced from rust_try.ll
352+
extern "C" fn rust_eh_personality(
356353
state: uw::_Unwind_State,
357354
ue_header: *mut uw::_Unwind_Exception,
358355
context: *mut uw::_Unwind_Context
@@ -366,19 +363,117 @@ pub mod eabi {
366363
#[no_mangle] // referenced from rust_try.ll
367364
pub extern "C" fn rust_eh_personality_catch(
368365
state: uw::_Unwind_State,
369-
ue_header: *mut uw::_Unwind_Exception,
370-
context: *mut uw::_Unwind_Context
366+
_ue_header: *mut uw::_Unwind_Exception,
367+
_context: *mut uw::_Unwind_Context
371368
) -> uw::_Unwind_Reason_Code
372369
{
373370
if (state as c_int & uw::_US_ACTION_MASK as c_int)
374371
== uw::_US_VIRTUAL_UNWIND_FRAME as c_int { // search phase
375372
uw::_URC_HANDLER_FOUND // catch!
376373
}
377374
else { // cleanup phase
378-
unsafe {
379-
__gcc_personality_v0(state, ue_header, context)
375+
uw::_URC_INSTALL_CONTEXT
376+
}
377+
}
378+
}
379+
380+
// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx)
381+
//
382+
// This looks a bit convoluted because rather than implementing a native SEH handler,
383+
// GCC reuses the same personality routine as for the other architectures by wrapping it
384+
// with an "API translator" layer (_GCC_specific_handler).
385+
386+
#[cfg(windows, target_arch = "x86_64", not(test))]
387+
#[allow(visible_private_types)]
388+
#[allow(non_camel_case_types)]
389+
#[allow(unused_variable)]
390+
#[allow(uppercase_variables)]
391+
pub mod eabi {
392+
use uw = libunwind;
393+
use libc::{c_void, c_int};
394+
395+
struct EXCEPTION_RECORD;
396+
struct CONTEXT;
397+
struct DISPATCHER_CONTEXT;
398+
399+
#[repr(C)]
400+
enum EXCEPTION_DISPOSITION {
401+
ExceptionContinueExecution,
402+
ExceptionContinueSearch,
403+
ExceptionNestedException,
404+
ExceptionCollidedUnwind
405+
}
406+
407+
type _Unwind_Personality_Fn =
408+
extern "C" fn(
409+
version: c_int,
410+
actions: uw::_Unwind_Action,
411+
exception_class: uw::_Unwind_Exception_Class,
412+
ue_header: *mut uw::_Unwind_Exception,
413+
context: *mut uw::_Unwind_Context
414+
) -> uw::_Unwind_Reason_Code;
415+
416+
extern "C" {
417+
fn __gcc_personality_seh0(
418+
exceptionRecord: *mut EXCEPTION_RECORD,
419+
establisherFrame: *mut c_void,
420+
contextRecord: *mut CONTEXT,
421+
dispatcherContext: *mut DISPATCHER_CONTEXT
422+
) -> EXCEPTION_DISPOSITION;
423+
424+
fn _GCC_specific_handler(
425+
exceptionRecord: *mut EXCEPTION_RECORD,
426+
establisherFrame: *mut c_void,
427+
contextRecord: *mut CONTEXT,
428+
dispatcherContext: *mut DISPATCHER_CONTEXT,
429+
personality: _Unwind_Personality_Fn
430+
) -> EXCEPTION_DISPOSITION;
431+
}
432+
433+
#[lang="eh_personality"]
434+
#[no_mangle] // referenced from rust_try.ll
435+
extern "C" fn rust_eh_personality(
436+
exceptionRecord: *mut EXCEPTION_RECORD,
437+
establisherFrame: *mut c_void,
438+
contextRecord: *mut CONTEXT,
439+
dispatcherContext: *mut DISPATCHER_CONTEXT
440+
) -> EXCEPTION_DISPOSITION
441+
{
442+
unsafe {
443+
__gcc_personality_seh0(exceptionRecord, establisherFrame,
444+
contextRecord, dispatcherContext)
445+
}
446+
}
447+
448+
#[no_mangle] // referenced from rust_try.ll
449+
pub extern "C" fn rust_eh_personality_catch(
450+
exceptionRecord: *mut EXCEPTION_RECORD,
451+
establisherFrame: *mut c_void,
452+
contextRecord: *mut CONTEXT,
453+
dispatcherContext: *mut DISPATCHER_CONTEXT
454+
) -> EXCEPTION_DISPOSITION
455+
{
456+
extern "C" fn inner(
457+
_version: c_int,
458+
actions: uw::_Unwind_Action,
459+
_exception_class: uw::_Unwind_Exception_Class,
460+
_ue_header: *mut uw::_Unwind_Exception,
461+
_context: *mut uw::_Unwind_Context
462+
) -> uw::_Unwind_Reason_Code
463+
{
464+
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
465+
uw::_URC_HANDLER_FOUND // catch!
466+
}
467+
else { // cleanup phase
468+
uw::_URC_INSTALL_CONTEXT
380469
}
381470
}
471+
472+
unsafe {
473+
_GCC_specific_handler(exceptionRecord, establisherFrame,
474+
contextRecord, dispatcherContext,
475+
inner)
476+
}
382477
}
383478
}
384479

trunk/src/rt/rust_try.ll

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,40 @@
1111
; Rust's try-catch
1212
; When f(...) returns normally, the return value is null.
1313
; When f(...) throws, the return value is a pointer to the caught exception object.
14-
; See also: libstd/rt/unwind.rs
14+
; See also: librustrt/unwind.rs
1515

1616
define i8* @rust_try(void (i8*,i8*)* %f, i8* %fptr, i8* %env) {
1717

18-
invoke void %f(i8* %fptr, i8* %env)
19-
to label %normal
20-
unwind label %catch
18+
%1 = invoke i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env)
19+
to label %normal
20+
unwind label %catch
2121

2222
normal:
23-
ret i8* null
23+
ret i8* %1
2424

2525
catch:
26-
%1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality_catch to i8*)
27-
catch i8* null ; catch everything
26+
landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality_catch to i8*)
27+
catch i8* null
28+
; execution will never reach here because rust_try_inner's landing pad does not resume unwinds
29+
ret i8* null
30+
}
31+
32+
define internal i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env) {
33+
34+
invoke void %f(i8* %fptr, i8* %env)
35+
to label %normal
36+
unwind label %catch
2837

29-
; extract and return pointer to the exception object
38+
normal:
39+
ret i8* null
40+
41+
catch:
42+
%1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @rust_eh_personality to i8*)
43+
catch i8* null
44+
; extract and return pointer to the exception object
3045
%2 = extractvalue { i8*, i32 } %1, 0
31-
ret i8* %2
46+
ret i8* %2
3247
}
3348

49+
declare i32 @rust_eh_personality(...)
3450
declare i32 @rust_eh_personality_catch(...)

0 commit comments

Comments
 (0)