auto merge of #8488 : klutzy/rust/mingw-w64, r=brson
This patchset enables rustc to cross-build mingw-w64 outputs.
Tested on mingw + mingw-w64 (mingw-builds, win64/seh/win32-threads/gcc-4.8.1).
I also patched llvm to support Win64 stack unwinding.
ebe22bdbce
I cross-built test/run-pass/smallest-hello-world.rs and confirmed it works.
However, I also found something went wrong if I don't have custom `#[start]` routine.
This commit is contained in:
commit
ce27752a69
14 changed files with 497 additions and 40 deletions
|
|
@ -2370,7 +2370,12 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
|
|||
decl_cdecl_fn(ccx.llmod, "amain", llfty)
|
||||
} else {
|
||||
let main_name = match ccx.sess.targ_cfg.os {
|
||||
session::os_win32 => ~"WinMain@16",
|
||||
session::os_win32 => {
|
||||
match ccx.sess.targ_cfg.arch {
|
||||
X86 => ~"WinMain@16",
|
||||
_ => ~"WinMain",
|
||||
}
|
||||
},
|
||||
_ => ~"main",
|
||||
};
|
||||
decl_cdecl_fn(ccx.llmod, main_name, llfty)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ use container::Container;
|
|||
use int;
|
||||
use iterator::Iterator;
|
||||
use libc::consts::os::posix88::*;
|
||||
use libc::{c_int, c_long, c_void, size_t, ssize_t};
|
||||
use libc::{c_int, c_void, size_t};
|
||||
use libc;
|
||||
use num;
|
||||
use ops::Drop;
|
||||
|
|
@ -970,7 +970,7 @@ impl Reader for *libc::FILE {
|
|||
|
||||
unsafe {
|
||||
assert!(libc::fseek(*self,
|
||||
offset as c_long,
|
||||
offset as libc::c_long,
|
||||
convert_whence(whence)) == 0 as c_int);
|
||||
}
|
||||
}
|
||||
|
|
@ -1199,7 +1199,7 @@ impl Writer for *libc::FILE {
|
|||
|
||||
unsafe {
|
||||
assert!(libc::fseek(*self,
|
||||
offset as c_long,
|
||||
offset as libc::c_long,
|
||||
convert_whence(whence)) == 0 as c_int);
|
||||
}
|
||||
}
|
||||
|
|
@ -1240,13 +1240,23 @@ impl Writer for fd_t {
|
|||
fn write(&self, v: &[u8]) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
#[cfg(windows)]
|
||||
type IoSize = libc::c_uint;
|
||||
#[cfg(windows)]
|
||||
type IoRet = c_int;
|
||||
|
||||
#[cfg(unix)]
|
||||
type IoSize = size_t;
|
||||
#[cfg(unix)]
|
||||
type IoRet = libc::ssize_t;
|
||||
|
||||
unsafe {
|
||||
let mut count = 0u;
|
||||
do v.as_imm_buf |vbuf, len| {
|
||||
while count < len {
|
||||
let vb = ptr::offset(vbuf, count as int) as *c_void;
|
||||
let nout = libc::write(*self, vb, len as size_t);
|
||||
if nout < 0 as ssize_t {
|
||||
let nout = libc::write(*self, vb, len as IoSize);
|
||||
if nout < 0 as IoRet {
|
||||
error!("error writing buffer");
|
||||
error!("%s", os::last_os_error());
|
||||
fail!();
|
||||
|
|
|
|||
|
|
@ -764,6 +764,172 @@ pub mod types {
|
|||
pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod arch {
|
||||
pub mod c95 {
|
||||
pub type c_char = i8;
|
||||
pub type c_schar = i8;
|
||||
pub type c_uchar = u8;
|
||||
pub type c_short = i16;
|
||||
pub type c_ushort = u16;
|
||||
pub type c_int = i32;
|
||||
pub type c_uint = u32;
|
||||
pub type c_long = i32;
|
||||
pub type c_ulong = u32;
|
||||
pub type c_float = f32;
|
||||
pub type c_double = f64;
|
||||
pub type size_t = u64;
|
||||
pub type ptrdiff_t = i64;
|
||||
pub type clock_t = i32;
|
||||
pub type time_t = i64;
|
||||
pub type wchar_t = u16;
|
||||
}
|
||||
pub mod c99 {
|
||||
pub type c_longlong = i64;
|
||||
pub type c_ulonglong = u64;
|
||||
pub type intptr_t = int;
|
||||
pub type uintptr_t = uint;
|
||||
}
|
||||
pub mod posix88 {
|
||||
pub type off_t = i32; // XXX unless _FILE_OFFSET_BITS == 64
|
||||
pub type dev_t = u32;
|
||||
pub type ino_t = i16;
|
||||
pub type pid_t = i64;
|
||||
pub type useconds_t = u32;
|
||||
pub type mode_t = u16;
|
||||
pub type ssize_t = i64;
|
||||
}
|
||||
pub mod posix01 {
|
||||
}
|
||||
pub mod posix08 {
|
||||
}
|
||||
pub mod bsd44 {
|
||||
}
|
||||
pub mod extra {
|
||||
use ptr;
|
||||
use libc::types::common::c95::c_void;
|
||||
use libc::types::os::arch::c95::{c_char, c_int, c_uint, size_t};
|
||||
use libc::types::os::arch::c95::{c_ulong};
|
||||
use libc::types::os::arch::c95::{wchar_t};
|
||||
use libc::types::os::arch::c99::{c_ulonglong};
|
||||
|
||||
pub type BOOL = c_int;
|
||||
pub type BYTE = u8;
|
||||
pub type CCHAR = c_char;
|
||||
pub type CHAR = c_char;
|
||||
|
||||
pub type DWORD = c_ulong;
|
||||
pub type DWORDLONG = c_ulonglong;
|
||||
|
||||
pub type HANDLE = LPVOID;
|
||||
pub type HMODULE = c_uint;
|
||||
|
||||
pub type LONG_PTR = i64; // changed
|
||||
|
||||
pub type LPCWSTR = *WCHAR;
|
||||
pub type LPCSTR = *CHAR;
|
||||
pub type LPCTSTR = *CHAR;
|
||||
pub type LPTCH = *CHAR;
|
||||
|
||||
pub type LPWSTR = *mut WCHAR;
|
||||
pub type LPSTR = *mut CHAR;
|
||||
pub type LPTSTR = *mut CHAR;
|
||||
|
||||
// Not really, but opaque to us.
|
||||
pub type LPSECURITY_ATTRIBUTES = LPVOID;
|
||||
|
||||
pub type LPVOID = *mut c_void;
|
||||
pub type LPCVOID = *c_void;
|
||||
pub type LPBYTE = *mut BYTE;
|
||||
pub type LPWORD = *mut WORD;
|
||||
pub type LPDWORD = *mut DWORD;
|
||||
pub type LPHANDLE = *mut HANDLE;
|
||||
|
||||
pub type LRESULT = LONG_PTR;
|
||||
pub type PBOOL = *mut BOOL;
|
||||
pub type WCHAR = wchar_t;
|
||||
pub type WORD = u16;
|
||||
pub type SIZE_T = size_t;
|
||||
|
||||
pub type time64_t = i64;
|
||||
pub type int64 = i64;
|
||||
|
||||
pub struct STARTUPINFO {
|
||||
cb: DWORD,
|
||||
lpReserved: LPTSTR,
|
||||
lpDesktop: LPTSTR,
|
||||
lpTitle: LPTSTR,
|
||||
dwX: DWORD,
|
||||
dwY: DWORD,
|
||||
dwXSize: DWORD,
|
||||
dwYSize: DWORD,
|
||||
dwXCountChars: DWORD,
|
||||
dwYCountCharts: DWORD,
|
||||
dwFillAttribute: DWORD,
|
||||
dwFlags: DWORD,
|
||||
wShowWindow: WORD,
|
||||
cbReserved2: WORD,
|
||||
lpReserved2: LPBYTE,
|
||||
hStdInput: HANDLE,
|
||||
hStdOutput: HANDLE,
|
||||
hStdError: HANDLE
|
||||
}
|
||||
pub type LPSTARTUPINFO = *mut STARTUPINFO;
|
||||
|
||||
pub struct PROCESS_INFORMATION {
|
||||
hProcess: HANDLE,
|
||||
hThread: HANDLE,
|
||||
dwProcessId: DWORD,
|
||||
dwThreadId: DWORD
|
||||
}
|
||||
pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
|
||||
|
||||
pub struct SYSTEM_INFO {
|
||||
wProcessorArchitecture: WORD,
|
||||
wReserved: WORD,
|
||||
dwPageSize: DWORD,
|
||||
lpMinimumApplicationAddress: LPVOID,
|
||||
lpMaximumApplicationAddress: LPVOID,
|
||||
dwActiveProcessorMask: DWORD,
|
||||
dwNumberOfProcessors: DWORD,
|
||||
dwProcessorType: DWORD,
|
||||
dwAllocationGranularity: DWORD,
|
||||
wProcessorLevel: WORD,
|
||||
wProcessorRevision: WORD
|
||||
}
|
||||
pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
|
||||
|
||||
impl SYSTEM_INFO {
|
||||
pub fn new() -> SYSTEM_INFO {
|
||||
SYSTEM_INFO {
|
||||
wProcessorArchitecture: 0,
|
||||
wReserved: 0,
|
||||
dwPageSize: 0,
|
||||
lpMinimumApplicationAddress: ptr::mut_null(),
|
||||
lpMaximumApplicationAddress: ptr::mut_null(),
|
||||
dwActiveProcessorMask: 0,
|
||||
dwNumberOfProcessors: 0,
|
||||
dwProcessorType: 0,
|
||||
dwAllocationGranularity: 0,
|
||||
wProcessorLevel: 0,
|
||||
wProcessorRevision: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MEMORY_BASIC_INFORMATION {
|
||||
BaseAddress: LPVOID,
|
||||
AllocationBase: LPVOID,
|
||||
AllocationProtect: DWORD,
|
||||
RegionSize: SIZE_T,
|
||||
State: DWORD,
|
||||
Protect: DWORD,
|
||||
Type: DWORD
|
||||
}
|
||||
pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
|
@ -3093,6 +3259,7 @@ pub mod funcs {
|
|||
LPSYSTEM_INFO};
|
||||
use libc::types::os::arch::extra::{HANDLE, LPHANDLE};
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[abi = "stdcall"]
|
||||
extern "stdcall" {
|
||||
pub fn GetEnvironmentVariableW(n: LPCWSTR,
|
||||
|
|
@ -3197,6 +3364,111 @@ pub mod funcs {
|
|||
-> LPVOID;
|
||||
pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
extern {
|
||||
pub fn GetEnvironmentVariableW(n: LPCWSTR,
|
||||
v: LPWSTR,
|
||||
nsize: DWORD)
|
||||
-> DWORD;
|
||||
pub fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR)
|
||||
-> BOOL;
|
||||
pub fn GetEnvironmentStringsA() -> LPTCH;
|
||||
pub fn FreeEnvironmentStringsA(env_ptr: LPTCH) -> BOOL;
|
||||
pub fn GetModuleFileNameW(hModule: HMODULE,
|
||||
lpFilename: LPWSTR,
|
||||
nSize: DWORD)
|
||||
-> DWORD;
|
||||
pub fn CreateDirectoryW(lpPathName: LPCWSTR,
|
||||
lpSecurityAttributes:
|
||||
LPSECURITY_ATTRIBUTES)
|
||||
-> BOOL;
|
||||
pub fn CopyFileW(lpExistingFileName: LPCWSTR,
|
||||
lpNewFileName: LPCWSTR,
|
||||
bFailIfExists: BOOL)
|
||||
-> BOOL;
|
||||
pub fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL;
|
||||
pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
|
||||
pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
|
||||
pub fn GetLastError() -> DWORD;
|
||||
pub fn FindFirstFileW(fileName: *u16, findFileData: HANDLE)
|
||||
-> HANDLE;
|
||||
pub fn FindNextFileW(findFile: HANDLE, findFileData: HANDLE)
|
||||
-> BOOL;
|
||||
pub fn FindClose(findFile: HANDLE) -> BOOL;
|
||||
pub fn DuplicateHandle(hSourceProcessHandle: HANDLE,
|
||||
hSourceHandle: HANDLE,
|
||||
hTargetProcessHandle: HANDLE,
|
||||
lpTargetHandle: LPHANDLE,
|
||||
dwDesiredAccess: DWORD,
|
||||
bInheritHandle: BOOL,
|
||||
dwOptions: DWORD)
|
||||
-> BOOL;
|
||||
pub fn CloseHandle(hObject: HANDLE) -> BOOL;
|
||||
pub fn OpenProcess(dwDesiredAccess: DWORD,
|
||||
bInheritHandle: BOOL,
|
||||
dwProcessId: DWORD)
|
||||
-> HANDLE;
|
||||
pub fn GetCurrentProcess() -> HANDLE;
|
||||
pub fn CreateProcessA(lpApplicationName: LPCTSTR,
|
||||
lpCommandLine: LPTSTR,
|
||||
lpProcessAttributes:
|
||||
LPSECURITY_ATTRIBUTES,
|
||||
lpThreadAttributes:
|
||||
LPSECURITY_ATTRIBUTES,
|
||||
bInheritHandles: BOOL,
|
||||
dwCreationFlags: DWORD,
|
||||
lpEnvironment: LPVOID,
|
||||
lpCurrentDirectory: LPCTSTR,
|
||||
lpStartupInfo: LPSTARTUPINFO,
|
||||
lpProcessInformation:
|
||||
LPPROCESS_INFORMATION)
|
||||
-> BOOL;
|
||||
pub fn WaitForSingleObject(hHandle: HANDLE,
|
||||
dwMilliseconds: DWORD)
|
||||
-> DWORD;
|
||||
pub fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint)
|
||||
-> BOOL;
|
||||
pub fn GetExitCodeProcess(hProcess: HANDLE,
|
||||
lpExitCode: LPDWORD)
|
||||
-> BOOL;
|
||||
pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
|
||||
pub fn VirtualAlloc(lpAddress: LPVOID,
|
||||
dwSize: SIZE_T,
|
||||
flAllocationType: DWORD,
|
||||
flProtect: DWORD)
|
||||
-> LPVOID;
|
||||
pub fn VirtualFree(lpAddress: LPVOID,
|
||||
dwSize: SIZE_T,
|
||||
dwFreeType: DWORD)
|
||||
-> BOOL;
|
||||
pub fn VirtualLock(lpAddress: LPVOID, dwSize: SIZE_T) -> BOOL;
|
||||
pub fn VirtualUnlock(lpAddress: LPVOID, dwSize: SIZE_T)
|
||||
-> BOOL;
|
||||
pub fn VirtualProtect(lpAddress: LPVOID,
|
||||
dwSize: SIZE_T,
|
||||
flNewProtect: DWORD,
|
||||
lpflOldProtect: LPDWORD)
|
||||
-> BOOL;
|
||||
pub fn VirtualQuery(lpAddress: LPCVOID,
|
||||
lpBuffer: LPMEMORY_BASIC_INFORMATION,
|
||||
dwLength: SIZE_T)
|
||||
-> SIZE_T;
|
||||
pub fn CreateFileMappingW(hFile: HANDLE,
|
||||
lpAttributes: LPSECURITY_ATTRIBUTES,
|
||||
flProtect: DWORD,
|
||||
dwMaximumSizeHigh: DWORD,
|
||||
dwMaximumSizeLow: DWORD,
|
||||
lpName: LPCTSTR)
|
||||
-> HANDLE;
|
||||
pub fn MapViewOfFile(hFileMappingObject: HANDLE,
|
||||
dwDesiredAccess: DWORD,
|
||||
dwFileOffsetHigh: DWORD,
|
||||
dwFileOffsetLow: DWORD,
|
||||
dwNumberOfBytesToMap: SIZE_T)
|
||||
-> LPVOID;
|
||||
pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod msvcrt {
|
||||
|
|
|
|||
|
|
@ -1042,12 +1042,19 @@ pub fn errno() -> uint {
|
|||
#[fixed_stack_segment]; #[inline(never)];
|
||||
use libc::types::os::arch::extra::DWORD;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[link_name = "kernel32"]
|
||||
#[abi = "stdcall"]
|
||||
extern "stdcall" {
|
||||
fn GetLastError() -> DWORD;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[link_name = "kernel32"]
|
||||
extern {
|
||||
fn GetLastError() -> DWORD;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
GetLastError() as uint
|
||||
}
|
||||
|
|
@ -1113,6 +1120,7 @@ pub fn last_os_error() -> ~str {
|
|||
use libc::types::os::arch::extra::LPSTR;
|
||||
use libc::types::os::arch::extra::LPVOID;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[link_name = "kernel32"]
|
||||
#[abi = "stdcall"]
|
||||
extern "stdcall" {
|
||||
|
|
@ -1126,6 +1134,19 @@ pub fn last_os_error() -> ~str {
|
|||
-> DWORD;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[link_name = "kernel32"]
|
||||
extern {
|
||||
fn FormatMessageA(flags: DWORD,
|
||||
lpSrc: LPVOID,
|
||||
msgId: DWORD,
|
||||
langId: DWORD,
|
||||
buf: LPSTR,
|
||||
nsize: DWORD,
|
||||
args: *c_void)
|
||||
-> DWORD;
|
||||
}
|
||||
|
||||
static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
|
||||
static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
|
||||
|
||||
|
|
@ -1241,7 +1262,7 @@ fn real_args() -> ~[~str] {
|
|||
|
||||
type LPCWSTR = *u16;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[cfg(windows, target_arch = "x86")]
|
||||
#[link_name="kernel32"]
|
||||
#[abi="stdcall"]
|
||||
extern "stdcall" {
|
||||
|
|
@ -1249,13 +1270,26 @@ extern "stdcall" {
|
|||
fn LocalFree(ptr: *c_void);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[cfg(windows, target_arch = "x86_64")]
|
||||
#[link_name="kernel32"]
|
||||
extern {
|
||||
fn GetCommandLineW() -> LPCWSTR;
|
||||
fn LocalFree(ptr: *c_void);
|
||||
}
|
||||
|
||||
#[cfg(windows, target_arch = "x86")]
|
||||
#[link_name="shell32"]
|
||||
#[abi="stdcall"]
|
||||
extern "stdcall" {
|
||||
fn CommandLineToArgvW(lpCmdLine: LPCWSTR, pNumArgs: *mut c_int) -> **u16;
|
||||
}
|
||||
|
||||
#[cfg(windows, target_arch = "x86_64")]
|
||||
#[link_name="shell32"]
|
||||
extern {
|
||||
fn CommandLineToArgvW(lpCmdLine: LPCWSTR, pNumArgs: *mut c_int) -> **u16;
|
||||
}
|
||||
|
||||
struct OverriddenArgs {
|
||||
val: ~[~str]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ impl Context {
|
|||
|
||||
let fp: *c_void = task_start_wrapper as *c_void;
|
||||
let argp: *c_void = unsafe { transmute::<&~fn(), *c_void>(&*start) };
|
||||
let stack_base: *uint = stack.start();
|
||||
let sp: *uint = stack.end();
|
||||
let sp: *mut uint = unsafe { transmute_mut_unsafe(sp) };
|
||||
// Save and then immediately load the current context,
|
||||
|
|
@ -56,7 +57,7 @@ impl Context {
|
|||
swap_registers(transmute_mut_region(&mut *regs), transmute_region(&*regs));
|
||||
};
|
||||
|
||||
initialize_call_frame(&mut *regs, fp, argp, sp);
|
||||
initialize_call_frame(&mut *regs, fp, argp, sp, stack_base);
|
||||
|
||||
return Context {
|
||||
start: Some(start),
|
||||
|
|
@ -107,7 +108,8 @@ fn new_regs() -> ~Registers {
|
|||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
|
||||
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
|
||||
sp: *mut uint, _stack_base: *uint) {
|
||||
|
||||
let sp = align_down(sp);
|
||||
let sp = mut_offset(sp, -4);
|
||||
|
|
@ -123,14 +125,19 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp:
|
|||
regs.ebp = 0;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(windows, target_arch = "x86_64")]
|
||||
type Registers = [uint, ..34];
|
||||
#[cfg(not(windows), target_arch = "x86_64")]
|
||||
type Registers = [uint, ..22];
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(windows, target_arch = "x86_64")]
|
||||
fn new_regs() -> ~Registers { ~([0, .. 34]) }
|
||||
#[cfg(not(windows), target_arch = "x86_64")]
|
||||
fn new_regs() -> ~Registers { ~([0, .. 22]) }
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
|
||||
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
|
||||
sp: *mut uint, stack_base: *uint) {
|
||||
|
||||
// Redefinitions from regs.h
|
||||
static RUSTRT_ARG0: uint = 3;
|
||||
|
|
@ -138,6 +145,21 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp:
|
|||
static RUSTRT_IP: uint = 8;
|
||||
static RUSTRT_RBP: uint = 2;
|
||||
|
||||
#[cfg(windows)]
|
||||
fn initialize_tib(regs: &mut Registers, sp: *mut uint, stack_base: *uint) {
|
||||
// Redefinitions from regs.h
|
||||
static RUSTRT_ST1: uint = 11; // stack bottom
|
||||
static RUSTRT_ST2: uint = 12; // stack top
|
||||
regs[RUSTRT_ST1] = sp as uint;
|
||||
regs[RUSTRT_ST2] = stack_base as uint;
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
fn initialize_tib(_: &mut Registers, _: *mut uint, _: *uint) {
|
||||
}
|
||||
|
||||
// Win64 manages stack range at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
|
||||
initialize_tib(regs, sp, stack_base);
|
||||
|
||||
let sp = align_down(sp);
|
||||
let sp = mut_offset(sp, -1);
|
||||
|
||||
|
|
@ -164,7 +186,8 @@ type Registers = [uint, ..32];
|
|||
fn new_regs() -> ~Registers { ~([0, .. 32]) }
|
||||
|
||||
#[cfg(target_arch = "arm")]
|
||||
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
|
||||
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
|
||||
sp: *mut uint, _stack_base: *uint) {
|
||||
let sp = align_down(sp);
|
||||
// sp of arm eabi is 8-byte aligned
|
||||
let sp = mut_offset(sp, -2);
|
||||
|
|
@ -184,7 +207,8 @@ type Registers = [uint, ..32];
|
|||
fn new_regs() -> ~Registers { ~([0, .. 32]) }
|
||||
|
||||
#[cfg(target_arch = "mips")]
|
||||
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
|
||||
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
|
||||
sp: *mut uint, _stack_base: *uint) {
|
||||
let sp = align_down(sp);
|
||||
// sp of mips o32 is 8-byte aligned
|
||||
let sp = mut_offset(sp, -2);
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ pub unsafe fn get(key: Key) -> *mut c_void {
|
|||
TlsGetValue(key)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[cfg(windows, target_arch = "x86")]
|
||||
#[abi = "stdcall"]
|
||||
extern "stdcall" {
|
||||
fn TlsAlloc() -> DWORD;
|
||||
|
|
@ -94,6 +94,13 @@ extern "stdcall" {
|
|||
fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
|
||||
}
|
||||
|
||||
#[cfg(windows, target_arch = "x86_64")]
|
||||
extern {
|
||||
fn TlsAlloc() -> DWORD;
|
||||
fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL;
|
||||
fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tls_smoke_test() {
|
||||
use cast::transmute;
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ mod dl {
|
|||
FreeLibrary(handle); ()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[link_name = "kernel32"]
|
||||
extern "stdcall" {
|
||||
fn SetLastError(error: u32);
|
||||
|
|
@ -261,4 +262,15 @@ mod dl {
|
|||
fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
|
||||
fn FreeLibrary(handle: *libc::c_void);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[link_name = "kernel32"]
|
||||
extern {
|
||||
fn SetLastError(error: u32);
|
||||
fn LoadLibraryW(name: *u16) -> *libc::c_void;
|
||||
fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
|
||||
handle: **libc::c_void) -> *libc::c_void;
|
||||
fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
|
||||
fn FreeLibrary(handle: *libc::c_void);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ First four arguments:
|
|||
anyhow.
|
||||
*/
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
#if defined(__APPLE__)
|
||||
#define SWAP_REGISTERS _swap_registers
|
||||
#else
|
||||
#define SWAP_REGISTERS swap_registers
|
||||
|
|
@ -86,16 +86,40 @@ SWAP_REGISTERS:
|
|||
mov %r14, (RUSTRT_R14*8)(ARG0)
|
||||
mov %r15, (RUSTRT_R15*8)(ARG0)
|
||||
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
mov %rdi, (RUSTRT_RDI*8)(ARG0)
|
||||
mov %rsi, (RUSTRT_RSI*8)(ARG0)
|
||||
|
||||
// Save stack range
|
||||
mov %gs:0x08, %r8
|
||||
mov %r8, (RUSTRT_ST1*8)(ARG0)
|
||||
mov %gs:0x10, %r9
|
||||
mov %r9, (RUSTRT_ST2*8)(ARG0)
|
||||
#endif
|
||||
|
||||
// Save 0th argument register:
|
||||
mov ARG0, (RUSTRT_ARG0*8)(ARG0)
|
||||
|
||||
// Save non-volatile XMM registers:
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
movapd %xmm6, (RUSTRT_XMM6*8)(ARG0)
|
||||
movapd %xmm7, (RUSTRT_XMM7*8)(ARG0)
|
||||
movapd %xmm8, (RUSTRT_XMM8*8)(ARG0)
|
||||
movapd %xmm9, (RUSTRT_XMM9*8)(ARG0)
|
||||
movapd %xmm10, (RUSTRT_XMM10*8)(ARG0)
|
||||
movapd %xmm11, (RUSTRT_XMM11*8)(ARG0)
|
||||
movapd %xmm12, (RUSTRT_XMM12*8)(ARG0)
|
||||
movapd %xmm13, (RUSTRT_XMM13*8)(ARG0)
|
||||
movapd %xmm14, (RUSTRT_XMM14*8)(ARG0)
|
||||
movapd %xmm15, (RUSTRT_XMM15*8)(ARG0)
|
||||
#else
|
||||
movapd %xmm0, (RUSTRT_XMM0*8)(ARG0)
|
||||
movapd %xmm1, (RUSTRT_XMM1*8)(ARG0)
|
||||
movapd %xmm2, (RUSTRT_XMM2*8)(ARG0)
|
||||
movapd %xmm3, (RUSTRT_XMM3*8)(ARG0)
|
||||
movapd %xmm4, (RUSTRT_XMM4*8)(ARG0)
|
||||
movapd %xmm5, (RUSTRT_XMM5*8)(ARG0)
|
||||
#endif
|
||||
|
||||
// Restore non-volatile integer registers:
|
||||
// (including RSP)
|
||||
|
|
@ -107,16 +131,40 @@ SWAP_REGISTERS:
|
|||
mov (RUSTRT_R14*8)(ARG1), %r14
|
||||
mov (RUSTRT_R15*8)(ARG1), %r15
|
||||
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
mov (RUSTRT_RDI*8)(ARG1), %rdi
|
||||
mov (RUSTRT_RSI*8)(ARG1), %rsi
|
||||
|
||||
// Restore stack range
|
||||
mov (RUSTRT_ST1*8)(ARG1), %r8
|
||||
mov %r8, %gs:0x08
|
||||
mov (RUSTRT_ST2*8)(ARG1), %r9
|
||||
mov %r9, %gs:0x10
|
||||
#endif
|
||||
|
||||
// Restore 0th argument register:
|
||||
mov (RUSTRT_ARG0*8)(ARG1), ARG0
|
||||
|
||||
// Restore non-volatile XMM registers:
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
movapd (RUSTRT_XMM6*8)(ARG1), %xmm6
|
||||
movapd (RUSTRT_XMM7*8)(ARG1), %xmm7
|
||||
movapd (RUSTRT_XMM8*8)(ARG1), %xmm8
|
||||
movapd (RUSTRT_XMM9*8)(ARG1), %xmm9
|
||||
movapd (RUSTRT_XMM10*8)(ARG1), %xmm10
|
||||
movapd (RUSTRT_XMM11*8)(ARG1), %xmm11
|
||||
movapd (RUSTRT_XMM12*8)(ARG1), %xmm12
|
||||
movapd (RUSTRT_XMM13*8)(ARG1), %xmm13
|
||||
movapd (RUSTRT_XMM14*8)(ARG1), %xmm14
|
||||
movapd (RUSTRT_XMM15*8)(ARG1), %xmm15
|
||||
#else
|
||||
movapd (RUSTRT_XMM0*8)(ARG1), %xmm0
|
||||
movapd (RUSTRT_XMM1*8)(ARG1), %xmm1
|
||||
movapd (RUSTRT_XMM2*8)(ARG1), %xmm2
|
||||
movapd (RUSTRT_XMM3*8)(ARG1), %xmm3
|
||||
movapd (RUSTRT_XMM4*8)(ARG1), %xmm4
|
||||
movapd (RUSTRT_XMM5*8)(ARG1), %xmm5
|
||||
#endif
|
||||
|
||||
// Jump to the instruction pointer
|
||||
// found in regs:
|
||||
|
|
|
|||
|
|
@ -18,10 +18,13 @@
|
|||
|
||||
.text
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
#if defined(__APPLE__)
|
||||
.globl ___morestack
|
||||
.private_extern MORESTACK
|
||||
___morestack:
|
||||
#elif defined(_WIN32)
|
||||
.globl __morestack
|
||||
__morestack:
|
||||
#else
|
||||
.globl __morestack
|
||||
.hidden __morestack
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
.text
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
#if defined(__APPLE__)
|
||||
#define UPCALL_NEW_STACK _upcall_new_stack
|
||||
#define UPCALL_DEL_STACK _upcall_del_stack
|
||||
#define MORESTACK ___morestack
|
||||
|
|
|
|||
|
|
@ -18,15 +18,33 @@
|
|||
#define RUSTRT_R14 6
|
||||
#define RUSTRT_R15 7
|
||||
#define RUSTRT_IP 8
|
||||
// Not used, just padding
|
||||
#define RUSTRT_XXX 9
|
||||
#define RUSTRT_XMM0 10
|
||||
#define RUSTRT_XMM1 12
|
||||
#define RUSTRT_XMM2 14
|
||||
#define RUSTRT_XMM3 16
|
||||
#define RUSTRT_XMM4 18
|
||||
#define RUSTRT_XMM5 20
|
||||
#define RUSTRT_MAX 22
|
||||
#if defined(__MINGW32__) || defined(_WINDOWS)
|
||||
#define RUSTRT_RDI 9
|
||||
#define RUSTRT_RSI 10
|
||||
#define RUSTRT_ST1 11
|
||||
#define RUSTRT_ST2 12
|
||||
#define RUSTRT_XMM6 14
|
||||
#define RUSTRT_XMM7 16
|
||||
#define RUSTRT_XMM8 18
|
||||
#define RUSTRT_XMM9 20
|
||||
#define RUSTRT_XMM10 22
|
||||
#define RUSTRT_XMM11 24
|
||||
#define RUSTRT_XMM12 26
|
||||
#define RUSTRT_XMM13 28
|
||||
#define RUSTRT_XMM14 30
|
||||
#define RUSTRT_XMM15 32
|
||||
#define RUSTRT_MAX 34
|
||||
#else
|
||||
// Not used, just padding
|
||||
#define RUSTRT_XXX 9
|
||||
#define RUSTRT_XMM0 10
|
||||
#define RUSTRT_XMM1 12
|
||||
#define RUSTRT_XMM2 14
|
||||
#define RUSTRT_XMM3 16
|
||||
#define RUSTRT_XMM4 18
|
||||
#define RUSTRT_XMM5 20
|
||||
#define RUSTRT_MAX 22
|
||||
#endif
|
||||
|
||||
// ARG0 is the register in which the first argument goes.
|
||||
// Naturally this depends on your operating system.
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ extern "C" CDECL ALWAYS_INLINE uintptr_t get_sp_limit() {
|
|||
asm volatile (
|
||||
"movq %%fs:24, %0"
|
||||
: "=r"(limit));
|
||||
#elif defined(_WIN64)
|
||||
asm volatile (
|
||||
"movq %%gs:0x28, %0"
|
||||
: "=r"(limit));
|
||||
#endif
|
||||
|
||||
return limit;
|
||||
|
|
@ -65,6 +69,10 @@ extern "C" CDECL ALWAYS_INLINE void record_sp_limit(void *limit) {
|
|||
asm volatile (
|
||||
"movq %0, %%fs:24"
|
||||
:: "r"(limit));
|
||||
#elif defined(_WIN64)
|
||||
asm volatile (
|
||||
"movq %0, %%gs:0x28"
|
||||
:: "r"(limit));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,8 +54,18 @@ upcall_call_shim_on_rust_stack(void *args, void *fn_ptr) {
|
|||
|
||||
/**********************************************************************/
|
||||
|
||||
#ifdef __SEH__
|
||||
# define PERSONALITY_FUNC __gxx_personality_seh0
|
||||
#else
|
||||
# ifdef __USING_SJLJ_EXCEPTIONS__
|
||||
# define PERSONALITY_FUNC __gxx_personality_sjlj
|
||||
# else
|
||||
# define PERSONALITY_FUNC __gxx_personality_v0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern "C" _Unwind_Reason_Code
|
||||
__gxx_personality_v0(int version,
|
||||
PERSONALITY_FUNC(int version,
|
||||
_Unwind_Action actions,
|
||||
uint64_t exception_class,
|
||||
_Unwind_Exception *ue_header,
|
||||
|
|
@ -72,11 +82,11 @@ struct s_rust_personality_args {
|
|||
|
||||
extern "C" void
|
||||
upcall_s_rust_personality(s_rust_personality_args *args) {
|
||||
args->retval = __gxx_personality_v0(args->version,
|
||||
args->actions,
|
||||
args->exception_class,
|
||||
args->ue_header,
|
||||
args->context);
|
||||
args->retval = PERSONALITY_FUNC(args->version,
|
||||
args->actions,
|
||||
args->exception_class,
|
||||
args->ue_header,
|
||||
args->context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@
|
|||
#undef PLAT_x86_darwin
|
||||
#undef PLAT_amd64_darwin
|
||||
#undef PLAT_x86_win32
|
||||
#undef PLAT_amd64_win64
|
||||
#undef PLAT_x86_linux
|
||||
#undef PLAT_amd64_linux
|
||||
#undef PLAT_ppc32_linux
|
||||
|
|
@ -125,7 +126,11 @@
|
|||
# define PLAT_amd64_darwin 1
|
||||
#elif defined(__MINGW32__) || defined(__CYGWIN32__) \
|
||||
|| (defined(_WIN32) && defined(_M_IX86))
|
||||
# define PLAT_x86_win32 1
|
||||
# if defined(__x86_64__)
|
||||
# define PLAT_amd64_win64 1
|
||||
# elif defined(__i386__)
|
||||
# define PLAT_x86_win32 1
|
||||
# endif
|
||||
#elif defined(__linux__) && defined(__i386__)
|
||||
# define PLAT_x86_linux 1
|
||||
#elif defined(__linux__) && defined(__x86_64__)
|
||||
|
|
@ -349,7 +354,8 @@ valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
|
|||
|
||||
/* ------------------------ amd64-{linux,darwin} --------------- */
|
||||
|
||||
#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
|
||||
#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
|
||||
|| defined(PLAT_amd64_win64)
|
||||
|
||||
typedef
|
||||
struct {
|
||||
|
|
@ -3716,14 +3722,14 @@ VALGRIND_PRINTF(const char *format, ...)
|
|||
#if defined(NVALGRIND)
|
||||
return 0;
|
||||
#else /* NVALGRIND */
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) || defined(PLAT_amd64_win64)
|
||||
uintptr_t _qzz_res;
|
||||
#else
|
||||
unsigned long _qzz_res;
|
||||
#endif
|
||||
va_list vargs;
|
||||
va_start(vargs, format);
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) || defined(PLAT_amd64_win64)
|
||||
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
|
||||
VG_USERREQ__PRINTF_VALIST_BY_REF,
|
||||
(uintptr_t)format,
|
||||
|
|
@ -3754,14 +3760,14 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
|
|||
#if defined(NVALGRIND)
|
||||
return 0;
|
||||
#else /* NVALGRIND */
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) || defined(PLAT_amd64_win64)
|
||||
uintptr_t _qzz_res;
|
||||
#else
|
||||
unsigned long _qzz_res;
|
||||
#endif
|
||||
va_list vargs;
|
||||
va_start(vargs, format);
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) || defined(PLAT_amd64_win64)
|
||||
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
|
||||
VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
|
||||
(uintptr_t)format,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue