mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
Make native "c-stack-stdcall" ABI work
The symbol name is based on the number of arguments, so we have to declare it correctly. For some reason GetLastError doesn't work now.
This commit is contained in:
parent
ae2ce09267
commit
4a4d31cf0e
@ -3840,6 +3840,7 @@ fn trans_c_stack_native_call(bcx: @block_ctxt, f: @ast::expr,
|
||||
let ccx = bcx_ccx(bcx);
|
||||
let f_res = trans_callee(bcx, f);
|
||||
let llfn = f_res.val, bcx = f_res.bcx;
|
||||
let llfn = BitCast(bcx, llfn, T_ptr(T_fn([], bcx_ccx(bcx).int_type)));
|
||||
|
||||
// Translate the callee.
|
||||
let { params: _, ty: fn_ty } = ty::expr_ty_params_and_ty(bcx_tcx(bcx), f);
|
||||
@ -5651,8 +5652,22 @@ fn register_native_fn(ccx: @crate_ctxt, sp: span, path: [str], name: str,
|
||||
ret;
|
||||
}
|
||||
ast::native_abi_c_stack_stdcall. {
|
||||
// The name of stdcall functions depend on their argument count
|
||||
// so we have to declare them correctly
|
||||
let fn_args_tys = ty::ty_fn_args(ccx.tcx, fn_type);
|
||||
let fn_ret_ty = ty::ty_fn_ret(ccx.tcx, fn_type);
|
||||
let ll_args_tys = [];
|
||||
for arg in fn_args_tys {
|
||||
let arg_ty = arg.ty;
|
||||
check type_has_static_size(ccx, arg_ty);
|
||||
ll_args_tys += [type_of(ccx, sp, arg_ty)];
|
||||
}
|
||||
check type_has_static_size(ccx, fn_ret_ty);
|
||||
let ll_ret_ty = type_of(ccx, sp, fn_ret_ty);
|
||||
let native_fn_ty = T_fn(ll_args_tys, ll_ret_ty);
|
||||
|
||||
let llfn = decl_fn(ccx.llmod, name, lib::llvm::LLVMX86StdcallCallConv,
|
||||
T_fn([], ccx.int_type));
|
||||
native_fn_ty);
|
||||
ccx.item_ids.insert(id, llfn);
|
||||
ccx.item_symbols.insert(id, name);
|
||||
ret;
|
||||
|
@ -1,14 +1,19 @@
|
||||
// GetLastError doesn't seem to work with stack switching
|
||||
// xfail-test
|
||||
|
||||
#[cfg(target_os = "win32")]
|
||||
native "x86stdcall" mod kernel32 {
|
||||
native "c-stack-stdcall" mod kernel32 {
|
||||
fn SetLastError(err: uint);
|
||||
fn GetLastError() -> uint;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(target_os = "win32")]
|
||||
fn main() {
|
||||
let expected = 10u;
|
||||
let expected = 1234u;
|
||||
kernel32::SetLastError(expected);
|
||||
let actual = kernel32::GetLastError();
|
||||
log_err actual;
|
||||
assert (expected == actual);
|
||||
}
|
||||
|
||||
|
26
src/test/run-pass/x86stdcall2.rs
Normal file
26
src/test/run-pass/x86stdcall2.rs
Normal file
@ -0,0 +1,26 @@
|
||||
type HANDLE = u32;
|
||||
type DWORD = u32;
|
||||
type SIZE_T = u32;
|
||||
type LPVOID = uint;
|
||||
type BOOL = u8;
|
||||
|
||||
#[cfg(target_os = "win32")]
|
||||
native "c-stack-stdcall" mod kernel32 {
|
||||
fn GetProcessHeap() -> HANDLE;
|
||||
fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
|
||||
fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(target_os = "win32")]
|
||||
fn main() {
|
||||
let heap = kernel32::GetProcessHeap();
|
||||
let mem = kernel32::HeapAlloc(heap, 0u32, 100u32);
|
||||
assert mem != 0u;
|
||||
let res = kernel32::HeapFree(heap, 0u32, mem);
|
||||
assert res != 0u8;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn main() { }
|
Loading…
Reference in New Issue
Block a user