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.
This commit is contained in:
bors 2013-11-20 11:01:34 -08:00
commit e12bc239b4
5 changed files with 72 additions and 2 deletions

View file

@ -33,6 +33,7 @@ pub enum CallConv {
ColdCallConv = 9,
X86StdcallCallConv = 64,
X86FastcallCallConv = 65,
X86_64_Win64 = 79,
}
pub enum Visibility {

View file

@ -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={})",

View file

@ -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
//

View file

@ -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)
}

View file

@ -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);
}