提交 c40d6265 编写于 作者: B Brian Anderson

Support x86 stdcall convention

This allows rust to call the Win32 API
上级 68287592
......@@ -1314,6 +1314,15 @@ fn FastCall(ValueRef Fn, &ValueRef[] Args) -> ValueRef {
ret v;
}
fn CallWithConv(ValueRef Fn, &ValueRef[] Args,
uint Conv) -> ValueRef {
assert !(*terminated);
auto v = llvm::LLVMBuildCall(B, Fn, ivec::to_ptr(Args),
ivec::len(Args), str::buf(""));
llvm::LLVMSetInstructionCallConv(v, Conv);
ret v;
}
fn Select(ValueRef If, ValueRef Then, ValueRef Else) -> ValueRef {
assert (!*terminated);
ret llvm::LLVMBuildSelect(B, If, Then, Else, str::buf(""));
......
......@@ -221,6 +221,7 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
case ('i') { abi = ast::native_abi_rust_intrinsic; }
case ('c') { abi = ast::native_abi_cdecl; }
case ('l') { abi = ast::native_abi_llvm; }
case ('s') { abi = ast::native_abi_x86stdcall; }
}
auto func = parse_ty_fn(st, sd);
ret ty::mk_native_fn(st.tcx, abi, func._0, func._1);
......
......@@ -155,6 +155,7 @@ fn enc_sty(&ioivec::writer w, &@ctxt cx, &ty::sty st) {
}
case (native_abi_cdecl) { w.write_char('c'); }
case (native_abi_llvm) { w.write_char('l'); }
case (native_abi_x86stdcall) { w.write_char('s'); }
}
enc_ty_fn(w, cx, args, out, return, ~[]);
}
......
......@@ -751,7 +751,8 @@ fn trans_native_call(&builder b, @glue_fns glues, ValueRef lltaskptr,
ModuleRef llmod, &str name, bool pass_task,
&ValueRef[] args) -> ValueRef {
let int n = std::ivec::len[ValueRef](args) as int;
let ValueRef llnative = get_simple_extern_fn(externs, llmod, name, n);
let ValueRef llnative = get_simple_extern_fn(externs, llmod,
name, n);
let ValueRef[] call_args = ~[];
for (ValueRef a in args) { call_args += ~[b.ZExtOrBitCast(a, T_int())]; }
ret b.Call(llnative, call_args);
......@@ -8142,6 +8143,11 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx, &span sp, &str[] path, str name,
uses_retptr = false;
cast_to_i32 = false;
}
case (ast::native_abi_x86stdcall) {
pass_task = false;
uses_retptr = false;
cast_to_i32 = true;
}
}
auto lltaskptr;
......@@ -8185,7 +8191,7 @@ fn convert_arg_to_i32(&@block_ctxt cx, ValueRef v, ty::t t, ty::mode mode)
fn trans_simple_native_abi(&@block_ctxt bcx, str name,
&mutable ValueRef[] call_args,
ty::t fn_type, uint first_arg_n,
bool uses_retptr) ->
bool uses_retptr, uint cc) ->
tup(ValueRef, ValueRef) {
let TypeRef[] call_arg_tys = ~[];
for (ValueRef arg in call_args) { call_arg_tys += ~[val_ty(arg)]; }
......@@ -8202,8 +8208,12 @@ fn trans_simple_native_abi(&@block_ctxt bcx, str name,
auto llnativefn =
get_extern_fn(bcx.fcx.lcx.ccx.externs, bcx.fcx.lcx.ccx.llmod,
name, lib::llvm::LLVMCCallConv, llnativefnty);
auto r = bcx.build.Call(llnativefn, call_args);
name, cc, llnativefnty);
auto r = if (cc == lib::llvm::LLVMCCallConv) {
bcx.build.Call(llnativefn, call_args)
} else {
bcx.build.CallWithConv(llnativefn, call_args, cc)
};
auto rptr = bcx.fcx.llretptr;
ret tup(r, rptr);
}
......@@ -8231,7 +8241,8 @@ fn trans_simple_native_abi(&@block_ctxt bcx, str name,
case (ast::native_abi_llvm) {
auto result =
trans_simple_native_abi(bcx, name, call_args, fn_type, arg_n,
uses_retptr);
uses_retptr,
lib::llvm::LLVMCCallConv);
r = result._0;
rptr = result._1;
}
......@@ -8239,7 +8250,16 @@ fn trans_simple_native_abi(&@block_ctxt bcx, str name,
auto external_name = "rust_intrinsic_" + name;
auto result =
trans_simple_native_abi(bcx, external_name, call_args,
fn_type, arg_n, uses_retptr);
fn_type, arg_n, uses_retptr,
lib::llvm::LLVMCCallConv);
r = result._0;
rptr = result._1;
}
case (ast::native_abi_x86stdcall) {
auto result =
trans_simple_native_abi(bcx, name, call_args, fn_type, arg_n,
uses_retptr,
lib::llvm::LLVMX86StdcallCallConv);
r = result._0;
rptr = result._1;
}
......
......@@ -526,6 +526,7 @@ fn ty_mach_to_str(ty_mach tm) -> str {
native_abi_cdecl;
native_abi_llvm;
native_abi_rust_intrinsic;
native_abi_x86stdcall;
}
type native_mod =
......
......@@ -2004,6 +2004,8 @@ fn parse_item_native_mod(&parser p, &ast::attribute[] attrs) -> @ast::item {
abi = ast::native_abi_llvm;
} else if (str::eq(t, "rust-intrinsic")) {
abi = ast::native_abi_rust_intrinsic;
} else if (str::eq(t, "x86stdcall")) {
abi = ast::native_abi_x86stdcall;
} else { p.fatal("unsupported abi: " + t); fail; }
}
expect_word(p, "mod");
......
// xfail-stage0
#[cfg(target_os = "win32")]
mod m {
native "x86stdcall" mod kernel32 {
fn SetLastError(uint err);
fn GetLastError() -> uint;
}
fn main() {
auto expected = 10u;
kernel32::SetLastError(expected);
auto actual = kernel32::GetLastError();
assert expected == actual;
}
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
fn main() {
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册