From 2fcc70ec9d2f73b61285283aeb4abce4a4e84901 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 8 Nov 2013 11:06:57 -0800 Subject: Add a "system" ABI This adds an other ABI option which allows a custom selection over the target architecture and OS. The only current candidate for this change is that kernel32 on win32 uses stdcall, but on win64 it uses the cdecl calling convention. Otherwise everywhere else this is defined as using the Cdecl calling convention. cc #10049 Closes #8774 --- src/libsyntax/abi.rs | 49 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index ed20b160eb4..972d2f43e73 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -10,6 +10,9 @@ use std::to_bytes; +#[deriving(Eq)] +pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, } + #[deriving(Eq)] pub enum Abi { // NB: This ordering MUST match the AbiDatas array below. @@ -24,6 +27,7 @@ pub enum Abi { // Multiplatform ABIs second Rust, C, + System, RustIntrinsic, } @@ -76,6 +80,7 @@ static AbiDatas: &'static [AbiData] = &[ // adjusting the indices below. AbiData {abi: Rust, name: "Rust", abi_arch: RustArch}, AbiData {abi: C, name: "C", abi_arch: AllArch}, + AbiData {abi: System, name: "system", abi_arch: AllArch}, AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch}, ]; @@ -125,6 +130,14 @@ impl Abi { pub fn name(&self) -> &'static str { self.data().name } + + pub fn for_target(&self, os: Os, arch: Architecture) -> Abi { + match (*self, os, arch) { + (System, OsWin32, X86) => Stdcall, + (System, _, _) => C, + (me, _, _) => me, + } + } } impl Architecture { @@ -196,7 +209,7 @@ impl AbiSet { self.bits == 0 } - pub fn for_arch(&self, arch: Architecture) -> Option { + pub fn for_target(&self, os: Os, arch: Architecture) -> Option { // NB---Single platform ABIs come first let mut res = None; @@ -210,7 +223,7 @@ impl AbiSet { } }; - res + res.map(|r| r.for_target(os, arch)) } pub fn check_valid(&self) -> Option<(Abi, Abi)> { @@ -344,6 +357,11 @@ fn cannot_combine_rust_intrinsic_and_cdecl() { cannot_combine(RustIntrinsic, Cdecl); } +#[test] +fn can_combine_system_and_cdecl() { + can_combine(System, Cdecl); +} + #[test] fn can_combine_c_and_stdcall() { can_combine(C, Stdcall); @@ -382,36 +400,41 @@ fn abi_to_str_rust() { #[test] fn indices_are_correct() { for (i, abi_data) in AbiDatas.iter().enumerate() { - assert!(i == abi_data.abi.index()); + assert_eq!(i, abi_data.abi.index()); } let bits = 1 << (X86 as u32); let bits = bits | 1 << (X86_64 as u32); - assert!(IntelBits == bits); + assert_eq!(IntelBits, bits); let bits = 1 << (Arm as u32); - assert!(ArmBits == bits); + assert_eq!(ArmBits, bits); } #[cfg(test)] -fn check_arch(abis: &[Abi], arch: Architecture, expect: Option) { +fn get_arch(abis: &[Abi], os: Os, arch: Architecture) -> Option { let mut set = AbiSet::empty(); for &abi in abis.iter() { set.add(abi); } - let r = set.for_arch(arch); - assert!(r == expect); + set.for_target(os, arch) } #[test] fn pick_multiplatform() { - check_arch([C, Cdecl], X86, Some(Cdecl)); - check_arch([C, Cdecl], X86_64, Some(Cdecl)); - check_arch([C, Cdecl], Arm, Some(C)); + assert_eq!(get_arch([C, Cdecl], OsLinux, X86), Some(Cdecl)); + assert_eq!(get_arch([C, Cdecl], OsLinux, X86_64), Some(Cdecl)); + assert_eq!(get_arch([C, Cdecl], OsLinux, Arm), Some(C)); } #[test] fn pick_uniplatform() { - check_arch([Stdcall], X86, Some(Stdcall)); - check_arch([Stdcall], Arm, None); + assert_eq!(get_arch([Stdcall], OsLinux, X86), Some(Stdcall)); + assert_eq!(get_arch([Stdcall], OsLinux, Arm), None); + assert_eq!(get_arch([System], OsLinux, X86), Some(C)); + assert_eq!(get_arch([System], OsWin32, X86), Some(Stdcall)); + assert_eq!(get_arch([System], OsWin32, X86_64), Some(C)); + assert_eq!(get_arch([System], OsWin32, Arm), Some(C)); + assert_eq!(get_arch([Stdcall], OsWin32, X86), Some(Stdcall)); + assert_eq!(get_arch([Stdcall], OsWin32, X86_64), Some(Stdcall)); } -- cgit 1.4.1-3-g733a5