diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index 2f0abed3d27f8f5b4e02acae9fad74f0541f9534..bb7dd4f26213ccf69ed92f17d46324dcf6fc3590 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -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("")); diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs index b4d96d17a3e963d15e019e8731278cf057c75af6..2804c53024052dae8cb8f4c6757e2537bfd995c9 100644 --- a/src/comp/metadata/tydecode.rs +++ b/src/comp/metadata/tydecode.rs @@ -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); diff --git a/src/comp/metadata/tyencode.rs b/src/comp/metadata/tyencode.rs index 4d7e1b8ac187bc66675c1ebde05426fd6a150560..3b3ce6b3866af0341d3e6cef89257a08a211d2b7 100644 --- a/src/comp/metadata/tyencode.rs +++ b/src/comp/metadata/tyencode.rs @@ -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, ~[]); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2493569567da3049af4364eeaf7e392ddf8211a6..68a5823a7615be485f530e2e9141549b3c06c568 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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; } diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index fd5a308cbb8f07707815f7f48ff0eddb5435da02..745aa4e1fcdeab94136a976dd149874ae629f0e9 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -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 = diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 183c9ce0c47b73f6e3cb05dd55d0c1afd091a0d5..59dbf72f7c501470f62954d1b952d205506a3691 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -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"); diff --git a/src/test/run-pass/x86stdcall.rs b/src/test/run-pass/x86stdcall.rs new file mode 100644 index 0000000000000000000000000000000000000000..0b61ddaff288aa241c393e8f0c3afa2725f6709b --- /dev/null +++ b/src/test/run-pass/x86stdcall.rs @@ -0,0 +1,21 @@ +// 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