diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 634e339e03de0..1fc682912b35f 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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) diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 2412ce9daf3c1..e3f88033bd06b 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -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!(); diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index 26b4f15f3e99f..790dc886c0497 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -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 { diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 0b5f53dbf19e4..e7caf3f23abae 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -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] } diff --git a/src/libstd/rt/context.rs b/src/libstd/rt/context.rs index 5aaddc68383f1..476554bf7f7be 100644 --- a/src/libstd/rt/context.rs +++ b/src/libstd/rt/context.rs @@ -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); diff --git a/src/libstd/rt/thread_local_storage.rs b/src/libstd/rt/thread_local_storage.rs index a9cd29c18c965..b2c2c670b5558 100644 --- a/src/libstd/rt/thread_local_storage.rs +++ b/src/libstd/rt/thread_local_storage.rs @@ -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; diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 6dbe68200b3b7..90cf49cad1ccf 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -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); + } } diff --git a/src/rt/arch/x86_64/_context.S b/src/rt/arch/x86_64/_context.S index f718cac963470..857fe91c9141b 100644 --- a/src/rt/arch/x86_64/_context.S +++ b/src/rt/arch/x86_64/_context.S @@ -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: diff --git a/src/rt/arch/x86_64/ccall.S b/src/rt/arch/x86_64/ccall.S index d4bc37fee957d..dbee5bcdc90a3 100644 --- a/src/rt/arch/x86_64/ccall.S +++ b/src/rt/arch/x86_64/ccall.S @@ -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 diff --git a/src/rt/arch/x86_64/morestack.S b/src/rt/arch/x86_64/morestack.S index 9d16afc0a1b35..b718c9121c57b 100644 --- a/src/rt/arch/x86_64/morestack.S +++ b/src/rt/arch/x86_64/morestack.S @@ -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 diff --git a/src/rt/arch/x86_64/regs.h b/src/rt/arch/x86_64/regs.h index 1aca452df108b..cff47ac378af0 100644 --- a/src/rt/arch/x86_64/regs.h +++ b/src/rt/arch/x86_64/regs.h @@ -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. diff --git a/src/rt/arch/x86_64/sp.h b/src/rt/arch/x86_64/sp.h index bf011f4d01976..764927759fe68 100644 --- a/src/rt/arch/x86_64/sp.h +++ b/src/rt/arch/x86_64/sp.h @@ -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 } diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 21c0d21924261..7ccb06a3296f4 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -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); } /** diff --git a/src/rt/vg/valgrind.h b/src/rt/vg/valgrind.h index 222a58e156323..c9aa0fd032835 100644 --- a/src/rt/vg/valgrind.h +++ b/src/rt/vg/valgrind.h @@ -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,