diff options
| author | bors <bors@rust-lang.org> | 2013-11-20 11:01:34 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-11-20 11:01:34 -0800 |
| commit | e12bc239b4e85d0dedc5ba6e9f7ffa0b91ade634 (patch) | |
| tree | 3f5752af4483fea874d47504a3b0cffd52ef2989 /src | |
| parent | 6a25ba374b2bfe32d4411cab3547d76d47769d6c (diff) | |
| parent | 02e565a187adc0b5a7348852de664be26eb1701c (diff) | |
| download | rust-e12bc239b4e85d0dedc5ba6e9f7ffa0b91ade634.tar.gz rust-e12bc239b4e85d0dedc5ba6e9f7ffa0b91ade634.zip | |
auto merge of #10527 : eholk/rust/win64, r=alexcrichton
This was needed to access UEFI boot services in my new Boot2Rust experiment. I also realized that Rust functions declared as extern always use the C calling convention regardless of how they were declared, so this pull request fixes that as well.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/lib/llvm.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/trans/foreign.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/abi.rs | 3 | ||||
| -rw-r--r-- | src/test/auxiliary/extern_calling_convention.rs | 37 | ||||
| -rw-r--r-- | src/test/run-pass/extern-calling-convention-test.rs | 20 |
5 files changed, 72 insertions, 2 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 14af20f0cb9..160bc511168 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 33036aab65b..d73345b8474 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, @@ -398,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={})", diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index c2283bf1227..60d49b4c9ed 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 00000000000..41c57831da6 --- /dev/null +++ b/src/test/auxiliary/extern_calling_convention.rs @@ -0,0 +1,37 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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)] +#[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) +} + +#[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) +} 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 00000000000..e8609a8b60b --- /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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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); +} |
