rust/src/libsyntax/abi.rs
mr.Shu ee3fa68fed Fixed error starting with uppercase
Error messages cleaned in librustc/middle

Error messages cleaned in libsyntax

Error messages cleaned in libsyntax more agressively

Error messages cleaned in librustc more aggressively

Fixed affected tests

Fixed other failing tests

Last failing tests fixed
2014-02-08 20:59:38 +01:00

445 lines
11 KiB
Rust

// Copyright 2012-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.
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.
// (This is ensured by the test indices_are_correct().)
// Single platform ABIs come first (`for_arch()` relies on this)
Cdecl,
Stdcall,
Fastcall,
Aapcs,
Win64,
// Multiplatform ABIs second
Rust,
C,
System,
RustIntrinsic,
}
#[allow(non_camel_case_types)]
#[deriving(Eq)]
pub enum Architecture {
// NB. You cannot change the ordering of these
// constants without adjusting IntelBits below.
// (This is ensured by the test indices_are_correct().)
X86,
X86_64,
Arm,
Mips
}
static IntelBits: u32 = (1 << (X86 as uint)) | (1 << (X86_64 as uint));
static ArmBits: u32 = (1 << (Arm as uint));
struct AbiData {
abi: Abi,
// Name of this ABI as we like it called.
name: &'static str,
// Is it specific to a platform? If so, which one? Also, what is
// the name that LLVM gives it (in case we disagree)
abi_arch: AbiArchitecture
}
enum AbiArchitecture {
RustArch, // Not a real ABI (e.g., intrinsic)
AllArch, // An ABI that specifies cross-platform defaults (e.g., "C")
Archs(u32) // Multiple architectures (bitset)
}
#[deriving(Clone, Eq, Encodable, Decodable)]
pub struct AbiSet {
priv bits: u32 // each bit represents one of the abis below
}
static AbiDatas: &'static [AbiData] = &[
// Platform-specific ABIs
AbiData {abi: Cdecl, name: "cdecl", abi_arch: Archs(IntelBits)},
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
//
// NB: Do not adjust this ordering without
// 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},
];
fn each_abi(op: |abi: Abi| -> bool) -> bool {
/*!
*
* Iterates through each of the defined ABIs.
*/
AbiDatas.iter().advance(|abi_data| op(abi_data.abi))
}
pub fn lookup(name: &str) -> Option<Abi> {
/*!
*
* Returns the ABI with the given name (if any).
*/
let mut res = None;
each_abi(|abi| {
if name == abi.data().name {
res = Some(abi);
false
} else {
true
}
});
res
}
pub fn all_names() -> ~[&'static str] {
AbiDatas.map(|d| d.name)
}
impl Abi {
#[inline]
pub fn index(&self) -> uint {
*self as uint
}
#[inline]
pub fn data(&self) -> &'static AbiData {
&AbiDatas[self.index()]
}
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 {
fn bit(&self) -> u32 {
1 << (*self as u32)
}
}
impl AbiSet {
pub fn from(abi: Abi) -> AbiSet {
AbiSet { bits: (1 << abi.index()) }
}
#[inline]
pub fn Rust() -> AbiSet {
AbiSet::from(Rust)
}
#[inline]
pub fn C() -> AbiSet {
AbiSet::from(C)
}
#[inline]
pub fn Intrinsic() -> AbiSet {
AbiSet::from(RustIntrinsic)
}
pub fn default() -> AbiSet {
AbiSet::C()
}
pub fn empty() -> AbiSet {
AbiSet { bits: 0 }
}
#[inline]
pub fn is_rust(&self) -> bool {
self.bits == 1 << Rust.index()
}
#[inline]
pub fn is_c(&self) -> bool {
self.bits == 1 << C.index()
}
#[inline]
pub fn is_intrinsic(&self) -> bool {
self.bits == 1 << RustIntrinsic.index()
}
pub fn contains(&self, abi: Abi) -> bool {
(self.bits & (1 << abi.index())) != 0
}
pub fn subset_of(&self, other_abi_set: AbiSet) -> bool {
(self.bits & other_abi_set.bits) == self.bits
}
pub fn add(&mut self, abi: Abi) {
self.bits |= (1 << abi.index());
}
pub fn each(&self, op: |abi: Abi| -> bool) -> bool {
each_abi(|abi| !self.contains(abi) || op(abi))
}
pub fn is_empty(&self) -> bool {
self.bits == 0
}
pub fn for_target(&self, os: Os, arch: Architecture) -> Option<Abi> {
// NB---Single platform ABIs come first
let mut res = None;
self.each(|abi| {
let data = abi.data();
match data.abi_arch {
Archs(a) if (a & arch.bit()) != 0 => { res = Some(abi); false }
Archs(_) => { true }
RustArch | AllArch => { res = Some(abi); false }
}
});
res.map(|r| r.for_target(os, arch))
}
pub fn check_valid(&self) -> Option<(Abi, Abi)> {
let mut abis = ~[];
self.each(|abi| { abis.push(abi); true });
for (i, abi) in abis.iter().enumerate() {
let data = abi.data();
for other_abi in abis.slice(0, i).iter() {
let other_data = other_abi.data();
debug!("abis=({:?},{:?}) datas=({:?},{:?})",
abi, data.abi_arch,
other_abi, other_data.abi_arch);
match (&data.abi_arch, &other_data.abi_arch) {
(&AllArch, &AllArch) => {
// Two cross-architecture ABIs
return Some((*abi, *other_abi));
}
(_, &RustArch) |
(&RustArch, _) => {
// Cannot combine Rust or Rust-Intrinsic with
// anything else.
return Some((*abi, *other_abi));
}
(&Archs(is), &Archs(js)) if (is & js) != 0 => {
// Two ABIs for same architecture
return Some((*abi, *other_abi));
}
_ => {}
}
}
}
return None;
}
}
impl to_bytes::IterBytes for Abi {
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
self.index().iter_bytes(lsb0, f)
}
}
impl to_bytes::IterBytes for AbiSet {
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
self.bits.iter_bytes(lsb0, f)
}
}
impl ToStr for Abi {
fn to_str(&self) -> ~str {
self.data().name.to_str()
}
}
impl ToStr for AbiSet {
fn to_str(&self) -> ~str {
let mut strs = ~[];
self.each(|abi| {
strs.push(abi.data().name);
true
});
format!("\"{}\"", strs.connect(" "))
}
}
#[test]
fn lookup_Rust() {
let abi = lookup("Rust");
assert!(abi.is_some() && abi.unwrap().data().name == "Rust");
}
#[test]
fn lookup_cdecl() {
let abi = lookup("cdecl");
assert!(abi.is_some() && abi.unwrap().data().name == "cdecl");
}
#[test]
fn lookup_baz() {
let abi = lookup("baz");
assert!(abi.is_none());
}
#[cfg(test)]
fn cannot_combine(n: Abi, m: Abi) {
let mut set = AbiSet::empty();
set.add(n);
set.add(m);
match set.check_valid() {
Some((a, b)) => {
assert!((n == a && m == b) ||
(m == a && n == b));
}
None => {
fail!("invalid match not detected");
}
}
}
#[cfg(test)]
fn can_combine(n: Abi, m: Abi) {
let mut set = AbiSet::empty();
set.add(n);
set.add(m);
match set.check_valid() {
Some((_, _)) => {
fail!("valid match declared invalid");
}
None => {}
}
}
#[test]
fn cannot_combine_cdecl_and_stdcall() {
cannot_combine(Cdecl, Stdcall);
}
#[test]
fn cannot_combine_c_and_rust() {
cannot_combine(C, Rust);
}
#[test]
fn cannot_combine_rust_and_cdecl() {
cannot_combine(Rust, Cdecl);
}
#[test]
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);
}
#[test]
fn can_combine_aapcs_and_stdcall() {
can_combine(Aapcs, Stdcall);
}
#[test]
fn abi_to_str_stdcall_aaps() {
let mut set = AbiSet::empty();
set.add(Aapcs);
set.add(Stdcall);
assert!(set.to_str() == ~"\"stdcall aapcs\"");
}
#[test]
fn abi_to_str_c_aaps() {
let mut set = AbiSet::empty();
set.add(Aapcs);
set.add(C);
debug!("set = {}", set.to_str());
assert!(set.to_str() == ~"\"aapcs C\"");
}
#[test]
fn abi_to_str_rust() {
let mut set = AbiSet::empty();
set.add(Rust);
debug!("set = {}", set.to_str());
assert!(set.to_str() == ~"\"Rust\"");
}
#[test]
fn indices_are_correct() {
for (i, abi_data) in AbiDatas.iter().enumerate() {
assert_eq!(i, abi_data.abi.index());
}
let bits = 1 << (X86 as u32);
let bits = bits | 1 << (X86_64 as u32);
assert_eq!(IntelBits, bits);
let bits = 1 << (Arm as u32);
assert_eq!(ArmBits, bits);
}
#[cfg(test)]
fn get_arch(abis: &[Abi], os: Os, arch: Architecture) -> Option<Abi> {
let mut set = AbiSet::empty();
for &abi in abis.iter() {
set.add(abi);
}
set.for_target(os, arch)
}
#[test]
fn pick_multiplatform() {
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() {
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));
}