about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-26 11:46:13 -0700
committerbors <bors@rust-lang.org>2013-08-26 11:46:13 -0700
commitce27752a69df6093ec0d104a7ecce755983a0f78 (patch)
tree9f81660a9117b57830d18b659d1dbfe1b3dc6fb7 /src/libstd
parent36b511558595a49b8c091937915d7616c2d62f14 (diff)
parent442f4a5f2ca6f7f4082c09968e0fd83601a50d2a (diff)
downloadrust-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.rs20
-rw-r--r--src/libstd/libc.rs272
-rw-r--r--src/libstd/os.rs38
-rw-r--r--src/libstd/rt/context.rs38
-rw-r--r--src/libstd/rt/thread_local_storage.rs9
-rw-r--r--src/libstd/unstable/dynamic_lib.rs12
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);
+    }
 }