diff options
| author | bors <bors@rust-lang.org> | 2013-08-26 11:46:13 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-08-26 11:46:13 -0700 |
| commit | ce27752a69df6093ec0d104a7ecce755983a0f78 (patch) | |
| tree | 9f81660a9117b57830d18b659d1dbfe1b3dc6fb7 /src/libstd | |
| parent | 36b511558595a49b8c091937915d7616c2d62f14 (diff) | |
| parent | 442f4a5f2ca6f7f4082c09968e0fd83601a50d2a (diff) | |
| download | rust-ce27752a69df6093ec0d104a7ecce755983a0f78.tar.gz rust-ce27752a69df6093ec0d104a7ecce755983a0f78.zip | |
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. https://github.com/klutzy/llvm/commit/ebe22bdbcebc4f8342c4c7c50e3b61fa6c68c1ad 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.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io.rs | 20 | ||||
| -rw-r--r-- | src/libstd/libc.rs | 272 | ||||
| -rw-r--r-- | src/libstd/os.rs | 38 | ||||
| -rw-r--r-- | src/libstd/rt/context.rs | 38 | ||||
| -rw-r--r-- | src/libstd/rt/thread_local_storage.rs | 9 | ||||
| -rw-r--r-- | src/libstd/unstable/dynamic_lib.rs | 12 |
6 files changed, 374 insertions, 15 deletions
diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 2412ce9daf3..e3f88033bd0 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 26b4f15f3e9..790dc886c04 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 0b5f53dbf19..e7caf3f23ab 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 5aaddc68383..476554bf7f7 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 a9cd29c18c9..b2c2c670b55 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 6dbe68200b3..90cf49cad1c 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); + } } |
