]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_target/src/spec/abi.rs
Auto merge of #97800 - pnkfelix:issue-97463-fix-aarch64-call-abi-does-not-zeroext...
[rust.git] / compiler / rustc_target / src / 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, Clone, Copy, Debug)]
9 #[derive(HashStable_Generic, Encodable, Decodable)]
10 pub enum Abi {
11     // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the
12     // hashing tests. These are used in many places, so giving them stable values reduces test
13     // churn. The specific values are meaningless.
14     Rust,
15     C { unwind: bool },
16     Cdecl { unwind: bool },
17     Stdcall { unwind: bool },
18     Fastcall { unwind: bool },
19     Vectorcall { unwind: bool },
20     Thiscall { unwind: bool },
21     Aapcs { unwind: bool },
22     Win64 { unwind: bool },
23     SysV64 { unwind: bool },
24     PtxKernel,
25     Msp430Interrupt,
26     X86Interrupt,
27     AmdGpuKernel,
28     EfiApi,
29     AvrInterrupt,
30     AvrNonBlockingInterrupt,
31     CCmseNonSecureCall,
32     Wasm,
33     System { unwind: bool },
34     RustIntrinsic,
35     RustCall,
36     PlatformIntrinsic,
37     Unadjusted,
38     RustCold,
39 }
40
41 #[derive(Copy, Clone)]
42 pub struct AbiData {
43     abi: Abi,
44
45     /// Name of this ABI as we like it called.
46     name: &'static str,
47 }
48
49 #[allow(non_upper_case_globals)]
50 const AbiDatas: &[AbiData] = &[
51     AbiData { abi: Abi::Rust, name: "Rust" },
52     AbiData { abi: Abi::C { unwind: false }, name: "C" },
53     AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" },
54     AbiData { abi: Abi::Cdecl { unwind: false }, name: "cdecl" },
55     AbiData { abi: Abi::Cdecl { unwind: true }, name: "cdecl-unwind" },
56     AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" },
57     AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" },
58     AbiData { abi: Abi::Fastcall { unwind: false }, name: "fastcall" },
59     AbiData { abi: Abi::Fastcall { unwind: true }, name: "fastcall-unwind" },
60     AbiData { abi: Abi::Vectorcall { unwind: false }, name: "vectorcall" },
61     AbiData { abi: Abi::Vectorcall { unwind: true }, name: "vectorcall-unwind" },
62     AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" },
63     AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" },
64     AbiData { abi: Abi::Aapcs { unwind: false }, name: "aapcs" },
65     AbiData { abi: Abi::Aapcs { unwind: true }, name: "aapcs-unwind" },
66     AbiData { abi: Abi::Win64 { unwind: false }, name: "win64" },
67     AbiData { abi: Abi::Win64 { unwind: true }, name: "win64-unwind" },
68     AbiData { abi: Abi::SysV64 { unwind: false }, name: "sysv64" },
69     AbiData { abi: Abi::SysV64 { unwind: true }, name: "sysv64-unwind" },
70     AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" },
71     AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" },
72     AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" },
73     AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel" },
74     AbiData { abi: Abi::EfiApi, name: "efiapi" },
75     AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" },
76     AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" },
77     AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" },
78     AbiData { abi: Abi::Wasm, name: "wasm" },
79     AbiData { abi: Abi::System { unwind: false }, name: "system" },
80     AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" },
81     AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" },
82     AbiData { abi: Abi::RustCall, name: "rust-call" },
83     AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" },
84     AbiData { abi: Abi::Unadjusted, name: "unadjusted" },
85     AbiData { abi: Abi::RustCold, name: "rust-cold" },
86 ];
87
88 /// Returns the ABI with the given name (if any).
89 pub fn lookup(name: &str) -> Option<Abi> {
90     AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi)
91 }
92
93 pub fn all_names() -> Vec<&'static str> {
94     AbiDatas.iter().map(|d| d.name).collect()
95 }
96
97 impl Abi {
98     /// Default ABI chosen for `extern fn` declarations without an explicit ABI.
99     pub const FALLBACK: Abi = Abi::C { unwind: false };
100
101     #[inline]
102     pub fn index(self) -> usize {
103         // N.B., this ordering MUST match the AbiDatas array above.
104         // (This is ensured by the test indices_are_correct().)
105         use Abi::*;
106         let i = match self {
107             // Cross-platform ABIs
108             Rust => 0,
109             C { unwind: false } => 1,
110             C { unwind: true } => 2,
111             // Platform-specific ABIs
112             Cdecl { unwind: false } => 3,
113             Cdecl { unwind: true } => 4,
114             Stdcall { unwind: false } => 5,
115             Stdcall { unwind: true } => 6,
116             Fastcall { unwind: false } => 7,
117             Fastcall { unwind: true } => 8,
118             Vectorcall { unwind: false } => 9,
119             Vectorcall { unwind: true } => 10,
120             Thiscall { unwind: false } => 11,
121             Thiscall { unwind: true } => 12,
122             Aapcs { unwind: false } => 13,
123             Aapcs { unwind: true } => 14,
124             Win64 { unwind: false } => 15,
125             Win64 { unwind: true } => 16,
126             SysV64 { unwind: false } => 17,
127             SysV64 { unwind: true } => 18,
128             PtxKernel => 19,
129             Msp430Interrupt => 20,
130             X86Interrupt => 21,
131             AmdGpuKernel => 22,
132             EfiApi => 23,
133             AvrInterrupt => 24,
134             AvrNonBlockingInterrupt => 25,
135             CCmseNonSecureCall => 26,
136             Wasm => 27,
137             // Cross-platform ABIs
138             System { unwind: false } => 28,
139             System { unwind: true } => 29,
140             RustIntrinsic => 30,
141             RustCall => 31,
142             PlatformIntrinsic => 32,
143             Unadjusted => 33,
144             RustCold => 34,
145         };
146         debug_assert!(
147             AbiDatas
148                 .iter()
149                 .enumerate()
150                 .find(|(_, AbiData { abi, .. })| *abi == self)
151                 .map(|(index, _)| index)
152                 .expect("abi variant has associated data")
153                 == i,
154             "Abi index did not match `AbiDatas` ordering"
155         );
156         i
157     }
158
159     #[inline]
160     pub fn data(self) -> &'static AbiData {
161         &AbiDatas[self.index()]
162     }
163
164     pub fn name(self) -> &'static str {
165         self.data().name
166     }
167 }
168
169 impl fmt::Display for Abi {
170     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171         match self {
172             abi => write!(f, "\"{}\"", abi.name()),
173         }
174     }
175 }