From 50fb4be1cce008ef8c0b4b40e70460c1be1d795a Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Sat, 16 Nov 2013 18:25:56 -0500 Subject: [PATCH 1/3] Add Win64 calling convention. --- src/librustc/lib/llvm.rs | 1 + src/librustc/middle/trans/foreign.rs | 3 ++- src/libsyntax/abi.rs | 3 +++ .../auxiliary/extern_calling_convention.rs | 27 +++++++++++++++++++ .../extern-calling-convention-test.rs | 20 ++++++++++++++ 5 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/test/auxiliary/extern_calling_convention.rs create mode 100644 src/test/run-pass/extern-calling-convention-test.rs diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 14af20f0cb9ee..160bc5111688a 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -33,6 +33,7 @@ pub enum CallConv { ColdCallConv = 9, X86StdcallCallConv = 64, X86FastcallCallConv = 65, + X86_64_Win64 = 79, } pub enum Visibility { diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 7da80507df07d..161c4ee0d14ad 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -33,7 +33,7 @@ use syntax::{ast}; use syntax::{attr, ast_map}; use syntax::parse::token::special_idents; use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, System, - Cdecl, Aapcs, C, AbiSet}; + Cdecl, Aapcs, C, AbiSet, Win64}; use util::ppaux::{Repr, UserString}; use middle::trans::type_::Type; @@ -96,6 +96,7 @@ pub fn llvm_calling_convention(ccx: &mut CrateContext, Stdcall => lib::llvm::X86StdcallCallConv, Fastcall => lib::llvm::X86FastcallCallConv, C => lib::llvm::CCallConv, + Win64 => lib::llvm::X86_64_Win64, // NOTE These API constants ought to be more specific Cdecl => lib::llvm::CCallConv, diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 972d2f43e73f5..4e9ba5532f37e 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -23,6 +23,7 @@ pub enum Abi { Stdcall, Fastcall, Aapcs, + Win64, // Multiplatform ABIs second Rust, @@ -73,6 +74,8 @@ static AbiDatas: &'static [AbiData] = &[ AbiData {abi: Stdcall, name: "stdcall", abi_arch: Archs(IntelBits)}, AbiData {abi: Fastcall, name:"fastcall", abi_arch: Archs(IntelBits)}, AbiData {abi: Aapcs, name: "aapcs", abi_arch: Archs(ArmBits)}, + AbiData {abi: Win64, name: "win64", + abi_arch: Archs(1 << (X86_64 as uint))}, // Cross-platform ABIs // diff --git a/src/test/auxiliary/extern_calling_convention.rs b/src/test/auxiliary/extern_calling_convention.rs new file mode 100644 index 0000000000000..30579f0fc777b --- /dev/null +++ b/src/test/auxiliary/extern_calling_convention.rs @@ -0,0 +1,27 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Make sure Rust generates the correct calling convention for extern +// functions. + +#[inline(never)] +pub extern "win64" fn foo(a: int, b: int, c: int, d: int) { + assert!(a == 1); + assert!(b == 2); + assert!(c == 3); + assert!(d == 4); + + println!("a: {:?}, b: {:?}, c: {:?}, d: {:?}", + a, b, c, d) +} + +fn main() { + foo(1, 2, 3, 4) +} diff --git a/src/test/run-pass/extern-calling-convention-test.rs b/src/test/run-pass/extern-calling-convention-test.rs new file mode 100644 index 0000000000000..e8609a8b60b1a --- /dev/null +++ b/src/test/run-pass/extern-calling-convention-test.rs @@ -0,0 +1,20 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-fast: aux-build not compatible with fast +// aux-build:extern_calling_convention.rs + +extern mod extern_calling_convention; + +use extern_calling_convention::foo; + +fn main() { + foo(1, 2, 3, 4); +} From 5b534e4a22d914e284c650f4504789c2678961bd Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Sat, 16 Nov 2013 19:59:08 -0500 Subject: [PATCH 2/3] Use the correct calling convention for extern rust functions. --- src/librustc/middle/trans/foreign.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 161c4ee0d14ad..716ea049b66ed 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -399,11 +399,19 @@ pub fn register_rust_fn_with_foreign_abi(ccx: @mut CrateContext, let tys = foreign_types_for_id(ccx, node_id); let llfn_ty = lltype_for_fn_from_foreign_types(&tys); + let t = ty::node_id_to_type(ccx.tcx, node_id); + let cconv = match ty::get(t).sty { + ty::ty_bare_fn(ref fn_ty) => { + let c = llvm_calling_convention(ccx, fn_ty.abis); + c.unwrap_or(lib::llvm::CCallConv) + } + _ => lib::llvm::CCallConv + }; let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, - lib::llvm::CCallConv, + cconv, llfn_ty); add_argument_attributes(&tys, llfn); debug!("register_rust_fn_with_foreign_abi(node_id={:?}, llfn_ty={}, llfn={})", From 02e565a187adc0b5a7348852de664be26eb1701c Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 19 Nov 2013 12:46:28 -0500 Subject: [PATCH 3/3] Don't use win64 calling convention on 32-bit machines. --- src/test/auxiliary/extern_calling_convention.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/test/auxiliary/extern_calling_convention.rs b/src/test/auxiliary/extern_calling_convention.rs index 30579f0fc777b..41c57831da64f 100644 --- a/src/test/auxiliary/extern_calling_convention.rs +++ b/src/test/auxiliary/extern_calling_convention.rs @@ -12,16 +12,26 @@ // functions. #[inline(never)] +#[cfg(target_arch = "x86_64")] pub extern "win64" fn foo(a: int, b: int, c: int, d: int) { assert!(a == 1); assert!(b == 2); assert!(c == 3); assert!(d == 4); - + println!("a: {:?}, b: {:?}, c: {:?}, d: {:?}", a, b, c, d) } -fn main() { - foo(1, 2, 3, 4) +#[inline(never)] +#[cfg(target_arch = "x86")] +#[cfg(target_arch = "arm")] +pub extern fn foo(a: int, b: int, c: int, d: int) { + assert!(a == 1); + assert!(b == 2); + assert!(c == 3); + assert!(d == 4); + + println!("a: {:?}, b: {:?}, c: {:?}, d: {:?}", + a, b, c, d) }