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:
bors 2013-08-26 11:46:13 -07:00
commit ce27752a69
14 changed files with 497 additions and 40 deletions

View file

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

View file

@ -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!();

View file

@ -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 {

View file

@ -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]
}

View file

@ -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);

View file

@ -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;

View file

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

View file

@ -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:

View file

@ -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

View file

@ -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

View file

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

View file

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

View file

@ -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);
}
/**

View file

@ -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,