]> git.lizzy.rs Git - rust.git/blob - src/librustc_target/spec/abi.rs
Order the Rust and C ABIs first to reduce test churn
[rust.git] / src / librustc_target / spec / abi.rs
1 use std::fmt;
2
3 use rustc_macros::HashStable_Generic;
4
5 #[cfg(test)]
6 mod tests;
7
8 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
9 #[derive(HashStable_Generic)]
10 pub enum Abi {
11     // N.B., this ordering MUST match the AbiDatas array below.
12     // (This is ensured by the test indices_are_correct().)
13
14     // Multiplatform / generic ABIs
15     //
16     // These ABIs come first because every time we add a new ABI, we
17     // have to re-bless all the hashing tests. These are used in many
18     // places, so giving them stable values reduces test churn. The
19     // specific values are meaningless.
20     Rust = 0,
21     C = 1,
22
23     // Single platform ABIs
24     Cdecl,
25     Stdcall,
26     Fastcall,
27     Vectorcall,
28     Thiscall,
29     Aapcs,
30     Win64,
31     SysV64,
32     PtxKernel,
33     Msp430Interrupt,
34     X86Interrupt,
35     AmdGpuKernel,
36     EfiApi,
37
38     // Multiplatform / generic ABIs
39     System,
40     RustIntrinsic,
41     RustCall,
42     PlatformIntrinsic,
43     Unadjusted,
44 }
45
46 #[derive(Copy, Clone)]
47 pub struct AbiData {
48     abi: Abi,
49
50     /// Name of this ABI as we like it called.
51     name: &'static str,
52
53     /// A generic ABI is supported on all platforms.
54     generic: bool,
55 }
56
57 #[allow(non_upper_case_globals)]
58 const AbiDatas: &[AbiData] = &[
59     // Cross-platform ABIs
60     AbiData { abi: Abi::Rust, name: "Rust", generic: true },
61     AbiData { abi: Abi::C, name: "C", generic: true },
62     // Platform-specific ABIs
63     AbiData { abi: Abi::Cdecl, name: "cdecl", generic: false },
64     AbiData { abi: Abi::Stdcall, name: "stdcall", generic: false },
65     AbiData { abi: Abi::Fastcall, name: "fastcall", generic: false },
66     AbiData { abi: Abi::Vectorcall, name: "vectorcall", generic: false },
67     AbiData { abi: Abi::Thiscall, name: "thiscall", generic: false },
68     AbiData { abi: Abi::Aapcs, name: "aapcs", generic: false },
69     AbiData { abi: Abi::Win64, name: "win64", generic: false },
70     AbiData { abi: Abi::SysV64, name: "sysv64", generic: false },
71     AbiData { abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
72     AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt", generic: false },
73     AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false },
74     AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false },
75     AbiData { abi: Abi::EfiApi, name: "efiapi", generic: false },
76     // Cross-platform ABIs
77     AbiData { abi: Abi::System, name: "system", generic: true },
78     AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
79     AbiData { abi: Abi::RustCall, name: "rust-call", generic: true },
80     AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
81     AbiData { abi: Abi::Unadjusted, name: "unadjusted", generic: true },
82 ];
83
84 /// Returns the ABI with the given name (if any).
85 pub fn lookup(name: &str) -> Option<Abi> {
86     AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi)
87 }
88
89 pub fn all_names() -> Vec<&'static str> {
90     AbiDatas.iter().map(|d| d.name).collect()
91 }
92
93 impl Abi {
94     #[inline]
95     pub fn index(self) -> usize {
96         self as usize
97     }
98
99     #[inline]
100     pub fn data(self) -> &'static AbiData {
101         &AbiDatas[self.index()]
102     }
103
104     pub fn name(self) -> &'static str {
105         self.data().name
106     }
107
108     pub fn generic(self) -> bool {
109         self.data().generic
110     }
111 }
112
113 impl fmt::Display for Abi {
114     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115         write!(f, "\"{}\"", self.name())
116     }
117 }