Skip to content
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

Merged
merged 11 commits into from Aug 6, 2014
4 changes: 2 additions & 2 deletions mk/platform.mk
Expand Up @@ -377,7 +377,7 @@ RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabi :=
# mipsel-linux configuration
CC_mipsel-linux=mipsel-linux-gcc
CXX_mipsel-linux=mipsel-linux-g++
CPP_mipsel-linux=mipsel-linux-gcc
CPP_mipsel-linux=mipsel-linux-gcc
AR_mipsel-linux=mipsel-linux-ar
CFG_LIB_NAME_mipsel-linux=lib$(1).so
CFG_STATIC_LIB_NAME_mipsel-linux=lib$(1).a
Expand Down Expand Up @@ -641,7 +641,7 @@ define CFG_MAKE_TOOLCHAIN
CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1))
CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1))
AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1))
RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CXX_$(1))) \
RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CC_$(1))) \
-C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1))

RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1))
Expand Down
2 changes: 1 addition & 1 deletion src/etc/get-snapshot.py
Expand Up @@ -53,7 +53,7 @@ def unpack_snapshot(triple, dl_path):
dl_path = sys.argv[2]
else:
# There are no 64-bit Windows snapshots yet, so we'll use 32-bit ones instead, for now
snap_triple = triple if triple != "x86_64-w64-mingw32" else "i686-pc-mingw32"
snap_triple = triple if triple != "x86_64-w64-mingw32" else "i686-w64-mingw32"
Copy link
Contributor

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?)

Copy link
Contributor Author

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.

snap = determine_curr_snapshot(snap_triple)
dl = os.path.join(download_dir_base, snap)
url = download_url_base + "/" + snap
Expand Down
44 changes: 31 additions & 13 deletions src/libgreen/context.rs
Expand Up @@ -13,6 +13,8 @@ use std::uint;
use std::mem::transmute;
use std::rt::stack;
use std::raw;
#[cfg(target_arch = "x86_64")]
use std::simd;

// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing
// SSE regs. It would be marginally better not to do this. In C++ we
Expand Down Expand Up @@ -103,11 +105,11 @@ impl Context {
// invalid for the current task. Lucky for us `rust_swap_registers`
// is a C function so we don't have to worry about that!
match in_context.stack_bounds {
Some((lo, hi)) => stack::record_stack_bounds(lo, hi),
Some((lo, hi)) => stack::record_stack_bounds_green(lo, hi),
// If we're going back to one of the original contexts or
// something that's possibly not a "normal task", then reset
// the stack limit to 0 to make morestack never fail
None => stack::record_stack_bounds(0, uint::MAX),
None => stack::record_stack_bounds_green(0, uint::MAX),
}
rust_swap_registers(out_regs, in_regs)
}
Expand Down Expand Up @@ -186,14 +188,30 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
// windows requires saving more registers (both general and XMM), so the windows
// register context must be larger.
#[cfg(windows, target_arch = "x86_64")]
type Registers = [uint, ..34];
struct Registers {
gpr:[uint, ..14],
_xmm:[simd::u32x4, ..10]
}
#[cfg(not(windows), target_arch = "x86_64")]
type Registers = [uint, ..22];
struct Registers {
gpr:[uint, ..10],
_xmm:[simd::u32x4, ..6]
}

#[cfg(windows, target_arch = "x86_64")]
fn new_regs() -> Box<Registers> { box() ([0, .. 34]) }
fn new_regs() -> Box<Registers> {
box() Registers {
gpr:[0,..14],
_xmm:[simd::u32x4(0,0,0,0),..10]
}
}
#[cfg(not(windows), target_arch = "x86_64")]
fn new_regs() -> Box<Registers> { box() ([0, .. 22]) }
fn new_regs() -> Box<Registers> {
box() Registers {
gpr:[0,..10],
_xmm:[simd::u32x4(0,0,0,0),..6]
}
}

#[cfg(target_arch = "x86_64")]
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
Expand Down Expand Up @@ -222,20 +240,20 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,

// These registers are frobbed by rust_bootstrap_green_task into the right
// location so we can invoke the "real init function", `fptr`.
regs[RUSTRT_R12] = arg as uint;
regs[RUSTRT_R13] = procedure.code as uint;
regs[RUSTRT_R14] = procedure.env as uint;
regs[RUSTRT_R15] = fptr as uint;
regs.gpr[RUSTRT_R12] = arg as uint;
regs.gpr[RUSTRT_R13] = procedure.code as uint;
regs.gpr[RUSTRT_R14] = procedure.env as uint;
regs.gpr[RUSTRT_R15] = fptr as uint;

// These registers are picked up by the regular context switch paths. These
// will put us in "mostly the right context" except for frobbing all the
// arguments to the right place. We have the small trampoline code inside of
// rust_bootstrap_green_task to do that.
regs[RUSTRT_RSP] = sp as uint;
regs[RUSTRT_IP] = rust_bootstrap_green_task as uint;
regs.gpr[RUSTRT_RSP] = sp as uint;
regs.gpr[RUSTRT_IP] = rust_bootstrap_green_task as uint;

// Last base pointer on the stack should be 0
regs[RUSTRT_RBP] = 0;
regs.gpr[RUSTRT_RBP] = 0;
}

#[cfg(target_arch = "arm")]
Expand Down
2 changes: 1 addition & 1 deletion src/librustrt/libunwind.rs
Expand Up @@ -60,7 +60,7 @@ pub type _Unwind_Word = libc::uintptr_t;
pub static unwinder_private_data_size: uint = 5;

#[cfg(target_arch = "x86_64")]
pub static unwinder_private_data_size: uint = 2;
pub static unwinder_private_data_size: uint = 6;

#[cfg(target_arch = "arm", not(target_os = "ios"))]
pub static unwinder_private_data_size: uint = 20;
Expand Down
7 changes: 6 additions & 1 deletion src/librustrt/stack.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this introduced?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.
I know, having two of them is not optimal, but couldn't think of anything better. I am open to suggestions...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this, could you just update libnative to call record_stack_limit as opposed to record_stack_bounds. You can move the RED_ZONE addition into record_stack_limit as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean record_sp_limit? There's a number of uses which add a value other than RED_ZONE:
https://github.com/rust-lang/rust/blob/master/src/librustrt/stack.rs#L71
https://github.com/rust-lang/rust/blob/master/src/libstd/rand/os.rs#L213
https://github.com/rust-lang/rust/blob/master/src/libstd/rand/os.rs#L217
I think it's better left alone.

Maybe call libnative variant record_os_managed_stack_bounds?

Copy link
Member

Choose a reason for hiding this comment

The 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 record_os_managed_stack_bounds seems good.

Copy link
Member

Choose a reason for hiding this comment

The 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
Expand Down
145 changes: 120 additions & 25 deletions src/librustrt/unwind.rs
Expand Up @@ -227,7 +227,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
// This is achieved by overriding the return value in search phase to always
// say "catch!".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment is outdated with respect to there being two personality functions now used by the "try function"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No there's still two. We just no longer use rust_eh_personality_catch in the unwind phase.
Ok, I'll think about how to clarify this in comment.


#[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 {
Expand All @@ -244,7 +244,8 @@ pub mod eabi {
}

#[lang="eh_personality"]
extern fn eh_personality(
#[no_mangle] // referenced from rust_try.ll
extern fn rust_eh_personality(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may have been a rebase gone awry

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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,
Expand All @@ -260,21 +261,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
}
}
}
Expand All @@ -299,7 +298,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,
Expand All @@ -316,29 +315,26 @@ 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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)))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does nested not work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think so. It's a typo. :(

#[allow(visible_private_types)]
pub mod eabi {
use uw = libunwind;
Expand All @@ -352,7 +348,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
Expand All @@ -366,19 +363,117 @@ 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))]
#[allow(visible_private_types)]
#[allow(non_camel_case_types)]
#[allow(unused_variable)]
#[allow(uppercase_variables)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These could probably just be combined to #[allow(warnings)]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, is you prefer it that way.

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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The #[no_mangle] shouldn't be necessary (nor the rust_ prefix)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rust_eh_personality is now referenced from rust_try.ll, so it should be public and un-mangled.

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)
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/libstd/rand/os.rs
Expand Up @@ -136,10 +136,11 @@ mod imp {
use rand::Rng;
use result::{Ok, Err};
use rt::stack;
use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
use self::libc::types::os::arch::extra::{LONG_PTR};
use slice::MutableVector;

type HCRYPTPROV = c_ulong;
type HCRYPTPROV = LONG_PTR;

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
Expand Down
2 changes: 1 addition & 1 deletion src/llvm
Submodule llvm updated 896 files