New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for 64-bit Windows builds #16261
Changes from 10 commits
862ba43
bf420e5
bf76e00
ad2f67f
9bdaf0b
081991e
a12b235
5a24ee8
cb55279
cd2003f
881bfb1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,7 +125,7 @@ extern fn stack_exhausted() { | |
} | ||
|
||
#[inline(always)] | ||
pub unsafe fn record_stack_bounds(stack_lo: uint, stack_hi: uint) { | ||
pub unsafe fn record_stack_bounds_green(stack_lo: uint, stack_hi: uint) { | ||
// When the old runtime had segmented stacks, it used a calculation that was | ||
// "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic | ||
// symbol resolution, llvm function calls, etc. In theory this red zone | ||
|
@@ -154,6 +154,11 @@ pub unsafe fn record_stack_bounds(stack_lo: uint, stack_hi: uint) { | |
} | ||
} | ||
|
||
#[inline(always)] | ||
pub unsafe fn record_stack_bounds(stack_lo: uint, _stack_hi: uint) { | ||
record_sp_limit(stack_lo + RED_ZONE); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why was this introduced? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is to allow setting morestack stack limit from libnative without touching Windows's stack bounds TIB fields (gs:0x08 and gs:0x10). Since libnative relies on os-managed stacks, it should not mess with these. Currently it doesn't even do it correctly, because gs:0x10 is supposed to be the commit limit, not the reserve limit, as @klutzy had explained here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If that's the case, this function needs to have some comments to justify its existence and explain what it's doing. Also, if the other function is wrong, why not just delete it? Surely it must be doing something? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The original function is still needed for libgreen, because it creates stacks from scratch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thinking about this, could you just update libnative to call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean Maybe call libnative variant There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, that sounds good to me. I think that the green/native naming is a bit of a misnomer, but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you also add a comment to the function explaining how its different from the others? |
||
|
||
/// Records the current limit of the stack as specified by `end`. | ||
/// | ||
/// This is stored in an OS-dependent location, likely inside of the thread | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -220,14 +220,21 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class { | |
// | ||
// This is pretty close to Rust's exception handling approach, except that Rust | ||
// does have a single "catch-all" handler at the bottom of each task's stack. | ||
// So we have two versions: | ||
// So we have two versions of the personality routine: | ||
// - rust_eh_personality, used by all cleanup landing pads, which never catches, | ||
// so the behavior of __gcc_personality_v0 is perfectly adequate there, and | ||
// - rust_eh_personality_catch, used only by rust_try(), which always catches. | ||
// This is achieved by overriding the return value in search phase to always | ||
// say "catch!". | ||
// | ||
// Note, however, that for implementation simplicity, rust_eh_personality_catch | ||
// lacks code to install a landing pad, so in order to obtain exception object | ||
// pointer (which it needs to return upstream), rust_try() employs another trick: | ||
// it calls into the nested rust_try_inner(), whose landing pad does not resume | ||
// unwinds. Instead, it extracts the exception pointer and performs a "normal" | ||
// return. | ||
// | ||
// See also: rt/rust_try.ll | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I'll just have to trust you on this one! |
||
|
||
#[cfg(not(target_arch = "arm"), not(test))] | ||
#[cfg(not(target_arch = "arm"), not(windows, target_arch = "x86_64"), not(test))] | ||
#[doc(hidden)] | ||
#[allow(visible_private_types)] | ||
pub mod eabi { | ||
|
@@ -244,7 +251,8 @@ pub mod eabi { | |
} | ||
|
||
#[lang="eh_personality"] | ||
extern fn eh_personality( | ||
#[no_mangle] // referenced from rust_try.ll | ||
extern fn rust_eh_personality( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may have been a rebase gone awry There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, that's intentional. |
||
version: c_int, | ||
actions: uw::_Unwind_Action, | ||
exception_class: uw::_Unwind_Exception_Class, | ||
|
@@ -260,21 +268,19 @@ pub mod eabi { | |
|
||
#[no_mangle] // referenced from rust_try.ll | ||
pub extern "C" fn rust_eh_personality_catch( | ||
version: c_int, | ||
_version: c_int, | ||
actions: uw::_Unwind_Action, | ||
exception_class: uw::_Unwind_Exception_Class, | ||
ue_header: *mut uw::_Unwind_Exception, | ||
context: *mut uw::_Unwind_Context | ||
_exception_class: uw::_Unwind_Exception_Class, | ||
_ue_header: *mut uw::_Unwind_Exception, | ||
_context: *mut 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) | ||
} | ||
uw::_URC_INSTALL_CONTEXT | ||
} | ||
} | ||
} | ||
|
@@ -299,7 +305,7 @@ pub mod eabi { | |
} | ||
|
||
#[lang="eh_personality"] | ||
#[no_mangle] // so we can reference it by name from middle/trans/base.rs | ||
#[no_mangle] // referenced from rust_try.ll | ||
pub extern "C" fn rust_eh_personality( | ||
version: c_int, | ||
actions: uw::_Unwind_Action, | ||
|
@@ -316,29 +322,27 @@ pub mod eabi { | |
|
||
#[no_mangle] // referenced from rust_try.ll | ||
pub extern "C" fn rust_eh_personality_catch( | ||
version: c_int, | ||
_version: c_int, | ||
actions: uw::_Unwind_Action, | ||
exception_class: uw::_Unwind_Exception_Class, | ||
ue_header: *mut uw::_Unwind_Exception, | ||
context: *mut uw::_Unwind_Context | ||
_exception_class: uw::_Unwind_Exception_Class, | ||
_ue_header: *mut uw::_Unwind_Exception, | ||
_context: *mut 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_sj0(version, actions, exception_class, ue_header, | ||
context) | ||
} | ||
uw::_URC_INSTALL_CONTEXT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this intentional? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. |
||
} | ||
} | ||
} | ||
|
||
|
||
// ARM EHABI uses a slightly different personality routine signature, | ||
// but otherwise works the same. | ||
#[cfg(target_arch = "arm", not(test), not(target_os = "ios"))] | ||
#[cfg(target_arch = "arm", not(target_os = "ios"), not(test))] | ||
#[doc(hidden)] | ||
#[allow(visible_private_types)] | ||
pub mod eabi { | ||
use uw = libunwind; | ||
|
@@ -352,7 +356,8 @@ pub mod eabi { | |
} | ||
|
||
#[lang="eh_personality"] | ||
extern "C" fn eh_personality( | ||
#[no_mangle] // referenced from rust_try.ll | ||
extern "C" fn rust_eh_personality( | ||
state: uw::_Unwind_State, | ||
ue_header: *mut uw::_Unwind_Exception, | ||
context: *mut uw::_Unwind_Context | ||
|
@@ -366,19 +371,116 @@ pub mod eabi { | |
#[no_mangle] // referenced from rust_try.ll | ||
pub extern "C" fn rust_eh_personality_catch( | ||
state: uw::_Unwind_State, | ||
ue_header: *mut uw::_Unwind_Exception, | ||
context: *mut uw::_Unwind_Context | ||
_ue_header: *mut uw::_Unwind_Exception, | ||
_context: *mut 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) | ||
uw::_URC_INSTALL_CONTEXT | ||
} | ||
} | ||
} | ||
|
||
// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx) | ||
// | ||
// This looks a bit convoluted because rather than implementing a native SEH handler, | ||
// GCC reuses the same personality routine as for the other architectures by wrapping it | ||
// with an "API translator" layer (_GCC_specific_handler). | ||
|
||
#[cfg(windows, target_arch = "x86_64", not(test))] | ||
#[doc(hidden)] | ||
#[allow(visible_private_types)] | ||
#[allow(non_camel_case_types)] | ||
pub mod eabi { | ||
use uw = libunwind; | ||
use libc::{c_void, c_int}; | ||
|
||
struct EXCEPTION_RECORD; | ||
struct CONTEXT; | ||
struct DISPATCHER_CONTEXT; | ||
|
||
#[repr(C)] | ||
enum EXCEPTION_DISPOSITION { | ||
ExceptionContinueExecution, | ||
ExceptionContinueSearch, | ||
ExceptionNestedException, | ||
ExceptionCollidedUnwind | ||
} | ||
|
||
type _Unwind_Personality_Fn = | ||
extern "C" fn( | ||
version: c_int, | ||
actions: uw::_Unwind_Action, | ||
exception_class: uw::_Unwind_Exception_Class, | ||
ue_header: *mut uw::_Unwind_Exception, | ||
context: *mut uw::_Unwind_Context | ||
) -> uw::_Unwind_Reason_Code; | ||
|
||
extern "C" { | ||
fn __gcc_personality_seh0( | ||
exceptionRecord: *mut EXCEPTION_RECORD, | ||
establisherFrame: *mut c_void, | ||
contextRecord: *mut CONTEXT, | ||
dispatcherContext: *mut DISPATCHER_CONTEXT | ||
) -> EXCEPTION_DISPOSITION; | ||
|
||
fn _GCC_specific_handler( | ||
exceptionRecord: *mut EXCEPTION_RECORD, | ||
establisherFrame: *mut c_void, | ||
contextRecord: *mut CONTEXT, | ||
dispatcherContext: *mut DISPATCHER_CONTEXT, | ||
personality: _Unwind_Personality_Fn | ||
) -> EXCEPTION_DISPOSITION; | ||
} | ||
|
||
#[lang="eh_personality"] | ||
#[no_mangle] // referenced from rust_try.ll | ||
extern "C" fn rust_eh_personality( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
exceptionRecord: *mut EXCEPTION_RECORD, | ||
establisherFrame: *mut c_void, | ||
contextRecord: *mut CONTEXT, | ||
dispatcherContext: *mut DISPATCHER_CONTEXT | ||
) -> EXCEPTION_DISPOSITION | ||
{ | ||
unsafe { | ||
__gcc_personality_seh0(exceptionRecord, establisherFrame, | ||
contextRecord, dispatcherContext) | ||
} | ||
} | ||
|
||
#[no_mangle] // referenced from rust_try.ll | ||
pub extern "C" fn rust_eh_personality_catch( | ||
exceptionRecord: *mut EXCEPTION_RECORD, | ||
establisherFrame: *mut c_void, | ||
contextRecord: *mut CONTEXT, | ||
dispatcherContext: *mut DISPATCHER_CONTEXT | ||
) -> EXCEPTION_DISPOSITION | ||
{ | ||
extern "C" fn inner( | ||
_version: c_int, | ||
actions: uw::_Unwind_Action, | ||
_exception_class: uw::_Unwind_Exception_Class, | ||
_ue_header: *mut uw::_Unwind_Exception, | ||
_context: *mut 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 | ||
uw::_URC_INSTALL_CONTEXT | ||
} | ||
} | ||
|
||
unsafe { | ||
_GCC_specific_handler(exceptionRecord, establisherFrame, | ||
contextRecord, dispatcherContext, | ||
inner) | ||
} | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is changed by the line? (was this causing problem on some environments?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Purely cosmetic. Since we are now on mingw64, I thought we should use its' triple for consistency.