(index<- ) ./libsyntax/abi.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Wed Apr 9 17:27:03 2014
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::fmt;
12
13 #[deriving(Eq)]
14 pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, }
15
16 #[deriving(Eq, TotalEq, Hash, Encodable, Decodable, Clone)]
17 pub enum Abi {
18 // NB: This ordering MUST match the AbiDatas array below.
19 // (This is ensured by the test indices_are_correct().)
20
21 // Single platform ABIs come first (`for_arch()` relies on this)
22 Cdecl,
23 Stdcall,
24 Fastcall,
25 Aapcs,
26 Win64,
27
28 // Multiplatform ABIs second
29 Rust,
30 C,
31 System,
32 RustIntrinsic,
33 }
34
35 #[allow(non_camel_case_types)]
36 #[deriving(Eq)]
37 pub enum Architecture {
38 // NB. You cannot change the ordering of these
39 // constants without adjusting IntelBits below.
40 // (This is ensured by the test indices_are_correct().)
41 X86,
42 X86_64,
43 Arm,
44 Mips
45 }
46
47 static IntelBits: u32 = (1 << (X86 as uint)) | (1 << (X86_64 as uint));
48 static ArmBits: u32 = (1 << (Arm as uint));
49
50 pub struct AbiData {
51 abi: Abi,
52
53 // Name of this ABI as we like it called.
54 name: &'static str,
55
56 // Is it specific to a platform? If so, which one? Also, what is
57 // the name that LLVM gives it (in case we disagree)
58 abi_arch: AbiArchitecture
59 }
60
61 pub enum AbiArchitecture {
62 RustArch, // Not a real ABI (e.g., intrinsic)
63 AllArch, // An ABI that specifies cross-platform defaults (e.g., "C")
64 Archs(u32) // Multiple architectures (bitset)
65 }
66
67 static AbiDatas: &'static [AbiData] = &[
68 // Platform-specific ABIs
69 AbiData {abi: Cdecl, name: "cdecl", abi_arch: Archs(IntelBits)},
70 AbiData {abi: Stdcall, name: "stdcall", abi_arch: Archs(IntelBits)},
71 AbiData {abi: Fastcall, name:"fastcall", abi_arch: Archs(IntelBits)},
72 AbiData {abi: Aapcs, name: "aapcs", abi_arch: Archs(ArmBits)},
73 AbiData {abi: Win64, name: "win64",
74 abi_arch: Archs(1 << (X86_64 as uint))},
75
76 // Cross-platform ABIs
77 //
78 // NB: Do not adjust this ordering without
79 // adjusting the indices below.
80 AbiData {abi: Rust, name: "Rust", abi_arch: RustArch},
81 AbiData {abi: C, name: "C", abi_arch: AllArch},
82 AbiData {abi: System, name: "system", abi_arch: AllArch},
83 AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch},
84 ];
85
86 fn each_abi(op: |abi: Abi| -> bool) -> bool {
87 /*!
88 *
89 * Iterates through each of the defined ABIs.
90 */
91
92 AbiDatas.iter().advance(|abi_data| op(abi_data.abi))
93 }
94
95 pub fn lookup(name: &str) -> Option<Abi> {
96 /*!
97 *
98 * Returns the ABI with the given name (if any).
99 */
100
101 let mut res = None;
102
103 each_abi(|abi| {
104 if name == abi.data().name {
105 res = Some(abi);
106 false
107 } else {
108 true
109 }
110 });
111 res
112 }
113
114 pub fn all_names() -> Vec<&'static str> {
115 AbiDatas.iter().map(|d| d.name).collect()
116 }
117
118 impl Abi {
119 #[inline]
120 pub fn index(&self) -> uint {
121 *self as uint
122 }
123
124 #[inline]
125 pub fn data(&self) -> &'static AbiData {
126 &AbiDatas[self.index()]
127 }
128
129 pub fn name(&self) -> &'static str {
130 self.data().name
131 }
132
133 pub fn for_target(&self, os: Os, arch: Architecture) -> Option<Abi> {
134 // If this ABI isn't actually for the specified architecture, then we
135 // short circuit early
136 match self.data().abi_arch {
137 Archs(a) if a & arch.bit() == 0 => return None,
138 Archs(_) | RustArch | AllArch => {}
139 }
140 // Transform this ABI as appropriate for the requested os/arch
141 // combination.
142 Some(match (*self, os, arch) {
143 (System, OsWin32, X86) => Stdcall,
144 (System, _, _) => C,
145 (me, _, _) => me,
146 })
147 }
148 }
149
150 impl Architecture {
151 fn bit(&self) -> u32 {
152 1 << (*self as u32)
153 }
154 }
155
156 impl fmt::Show for Abi {
157 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158 write!(f.buf, "\"{}\"", self.name())
159 }
160 }
161
162 #[test]
163 fn lookup_Rust() {
164 let abi = lookup("Rust");
165 assert!(abi.is_some() && abi.unwrap().data().name == "Rust");
166 }
167
168 #[test]
169 fn lookup_cdecl() {
170 let abi = lookup("cdecl");
171 assert!(abi.is_some() && abi.unwrap().data().name == "cdecl");
172 }
173
174 #[test]
175 fn lookup_baz() {
176 let abi = lookup("baz");
177 assert!(abi.is_none());
178 }
179
180 #[test]
181 fn indices_are_correct() {
182 for (i, abi_data) in AbiDatas.iter().enumerate() {
183 assert_eq!(i, abi_data.abi.index());
184 }
185
186 let bits = 1 << (X86 as u32);
187 let bits = bits | 1 << (X86_64 as u32);
188 assert_eq!(IntelBits, bits);
189
190 let bits = 1 << (Arm as u32);
191 assert_eq!(ArmBits, bits);
192 }
193
194 #[test]
195 fn pick_uniplatform() {
196 assert_eq!(Stdcall.for_target(OsLinux, X86), Some(Stdcall));
197 assert_eq!(Stdcall.for_target(OsLinux, Arm), None);
198 assert_eq!(System.for_target(OsLinux, X86), Some(C));
199 assert_eq!(System.for_target(OsWin32, X86), Some(Stdcall));
200 assert_eq!(System.for_target(OsWin32, X86_64), Some(C));
201 assert_eq!(System.for_target(OsWin32, Arm), Some(C));
202 assert_eq!(Stdcall.for_target(OsWin32, X86), Some(Stdcall));
203 assert_eq!(Stdcall.for_target(OsWin32, X86_64), Some(Stdcall));
204 }
libsyntax/abi.rs:16:60-16:60 -enum- definition:
pub enum Abi {
// NB: This ordering MUST match the AbiDatas array below.
// (This is ensured by the test indices_are_correct().)
references:- 30libsyntax/ast.rs:
libsyntax/ast_map.rs:
libsyntax/visit.rs:
libsyntax/parse/parser.rs:
libsyntax/print/pprust.rs:
libsyntax/abi.rs:
libsyntax/abi.rs:36:16-36:16 -enum- definition:
pub enum Architecture {
// NB. You cannot change the ordering of these
// constants without adjusting IntelBits below.
references:- 5133: pub fn for_target(&self, os: Os, arch: Architecture) -> Option<Abi> {
134: // If this ABI isn't actually for the specified architecture, then we
--
150: impl Architecture {
151: fn bit(&self) -> u32 {
libsyntax/abi.rs:13:16-13:16 -enum- definition:
pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, }
pub enum Abi {
// NB: This ordering MUST match the AbiDatas array below.
references:- 414: pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, }
--
133: pub fn for_target(&self, os: Os, arch: Architecture) -> Option<Abi> {
134: // If this ABI isn't actually for the specified architecture, then we
libsyntax/abi.rs:49:1-49:1 -struct- definition:
pub struct AbiData {
abi: Abi,
// Name of this ABI as we like it called.
references:- 1179: // adjusting the indices below.
80: AbiData {abi: Rust, name: "Rust", abi_arch: RustArch},
81: AbiData {abi: C, name: "C", abi_arch: AllArch},
82: AbiData {abi: System, name: "system", abi_arch: AllArch},
83: AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch},
84: ];
--
124: #[inline]
125: pub fn data(&self) -> &'static AbiData {
126: &AbiDatas[self.index()]