1
+ use std:: cmp:: Ordering ;
1
2
use std:: fmt;
3
+ use std:: hash:: { Hash , Hasher } ;
2
4
3
- use rustc_macros:: { Decodable , Encodable , HashStable_Generic } ;
5
+ #[ cfg( feature = "nightly" ) ]
6
+ use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher , StableOrd } ;
7
+ #[ cfg( feature = "nightly" ) ]
8
+ use rustc_macros:: { Decodable , Encodable } ;
4
9
5
10
#[ cfg( test) ]
6
11
mod tests;
7
12
8
13
use ExternAbi as Abi ;
9
14
10
- #[ derive( PartialEq , Eq , PartialOrd , Ord , Hash , Clone , Copy , Debug ) ]
11
- #[ derive ( HashStable_Generic , Encodable , Decodable ) ]
15
+ #[ derive( Clone , Copy , Debug ) ]
16
+ #[ cfg_attr ( feature = "nightly" , derive ( Encodable , Decodable ) ) ]
12
17
pub enum ExternAbi {
13
18
// Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the
14
19
// hashing tests. These are used in many places, so giving them stable values reduces test
@@ -68,7 +73,124 @@ pub enum ExternAbi {
68
73
RiscvInterruptS ,
69
74
}
70
75
71
- impl Abi {
76
+ macro_rules! abi_impls {
77
+ ( $e_name: ident = {
78
+ $( $variant: ident $( { unwind: $uw: literal } ) ? =><= $tok: literal, ) *
79
+ } ) => {
80
+ impl $e_name {
81
+ pub const ALL_VARIANTS : & [ Self ] = & [
82
+ $( $e_name:: $variant $( { unwind: $uw } ) * , ) *
83
+ ] ;
84
+ pub const fn as_str( & self ) -> & ' static str {
85
+ match self {
86
+ $( $e_name:: $variant $( { unwind: $uw } ) * => $tok, ) *
87
+ }
88
+ }
89
+ }
90
+
91
+ impl :: core:: str :: FromStr for $e_name {
92
+ type Err = AbiFromStrErr ;
93
+ fn from_str( s: & str ) -> Result <$e_name, Self :: Err > {
94
+ match s {
95
+ $( $tok => Ok ( $e_name:: $variant $( { unwind: $uw } ) * ) , ) *
96
+ _ => Err ( AbiFromStrErr :: Unknown ) ,
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ #[ derive( Debug ) ]
104
+ pub enum AbiFromStrErr {
105
+ Unknown ,
106
+ }
107
+
108
+ abi_impls ! {
109
+ ExternAbi = {
110
+ C { unwind: false } =><= "C" ,
111
+ CCmseNonSecureCall =><= "C-cmse-nonsecure-call" ,
112
+ CCmseNonSecureEntry =><= "C-cmse-nonsecure-entry" ,
113
+ C { unwind: true } =><= "C-unwind" ,
114
+ Rust =><= "Rust" ,
115
+ Aapcs { unwind: false } =><= "aapcs" ,
116
+ Aapcs { unwind: true } =><= "aapcs-unwind" ,
117
+ AvrInterrupt =><= "avr-interrupt" ,
118
+ AvrNonBlockingInterrupt =><= "avr-non-blocking-interrupt" ,
119
+ Cdecl { unwind: false } =><= "cdecl" ,
120
+ Cdecl { unwind: true } =><= "cdecl-unwind" ,
121
+ EfiApi =><= "efiapi" ,
122
+ Fastcall { unwind: false } =><= "fastcall" ,
123
+ Fastcall { unwind: true } =><= "fastcall-unwind" ,
124
+ GpuKernel =><= "gpu-kernel" ,
125
+ Msp430Interrupt =><= "msp430-interrupt" ,
126
+ PtxKernel =><= "ptx-kernel" ,
127
+ RiscvInterruptM =><= "riscv-interrupt-m" ,
128
+ RiscvInterruptS =><= "riscv-interrupt-s" ,
129
+ RustCall =><= "rust-call" ,
130
+ RustCold =><= "rust-cold" ,
131
+ RustIntrinsic =><= "rust-intrinsic" ,
132
+ Stdcall { unwind: false } =><= "stdcall" ,
133
+ Stdcall { unwind: true } =><= "stdcall-unwind" ,
134
+ System { unwind: false } =><= "system" ,
135
+ System { unwind: true } =><= "system-unwind" ,
136
+ SysV64 { unwind: false } =><= "sysv64" ,
137
+ SysV64 { unwind: true } =><= "sysv64-unwind" ,
138
+ Thiscall { unwind: false } =><= "thiscall" ,
139
+ Thiscall { unwind: true } =><= "thiscall-unwind" ,
140
+ Unadjusted =><= "unadjusted" ,
141
+ Vectorcall { unwind: false } =><= "vectorcall" ,
142
+ Vectorcall { unwind: true } =><= "vectorcall-unwind" ,
143
+ Win64 { unwind: false } =><= "win64" ,
144
+ Win64 { unwind: true } =><= "win64-unwind" ,
145
+ X86Interrupt =><= "x86-interrupt" ,
146
+ }
147
+ }
148
+
149
+ impl Ord for ExternAbi {
150
+ fn cmp ( & self , rhs : & Self ) -> Ordering {
151
+ self . as_str ( ) . cmp ( rhs. as_str ( ) )
152
+ }
153
+ }
154
+
155
+ impl PartialOrd for ExternAbi {
156
+ fn partial_cmp ( & self , rhs : & Self ) -> Option < Ordering > {
157
+ Some ( self . cmp ( rhs) )
158
+ }
159
+ }
160
+
161
+ impl PartialEq for ExternAbi {
162
+ fn eq ( & self , rhs : & Self ) -> bool {
163
+ self . cmp ( rhs) == Ordering :: Equal
164
+ }
165
+ }
166
+
167
+ impl Eq for ExternAbi { }
168
+
169
+ impl Hash for ExternAbi {
170
+ fn hash < H : Hasher > ( & self , state : & mut H ) {
171
+ self . as_str ( ) . hash ( state) ;
172
+ // double-assurance of a prefix breaker
173
+ u32:: from_be_bytes ( * b"ABI\0 " ) . hash ( state) ;
174
+ }
175
+ }
176
+
177
+ #[ cfg( feature = "nightly" ) ]
178
+ impl < C > HashStable < C > for ExternAbi {
179
+ #[ inline]
180
+ fn hash_stable ( & self , _: & mut C , hasher : & mut StableHasher ) {
181
+ Hash :: hash ( self , hasher) ;
182
+ }
183
+ }
184
+
185
+ #[ cfg( feature = "nightly" ) ]
186
+ impl StableOrd for ExternAbi {
187
+ const CAN_USE_UNSTABLE_SORT : bool = true ;
188
+
189
+ // because each ABI is hashed like a string, there is no possible instability
190
+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
191
+ }
192
+
193
+ impl ExternAbi {
72
194
pub fn supports_varargs ( self ) -> bool {
73
195
// * C and Cdecl obviously support varargs.
74
196
// * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
@@ -92,144 +214,21 @@ impl Abi {
92
214
}
93
215
}
94
216
95
- #[ derive( Copy , Clone ) ]
96
- pub struct AbiData {
97
- pub abi : Abi ,
98
-
99
- /// Name of this ABI as we like it called.
100
- pub name : & ' static str ,
101
- }
102
-
103
- #[ allow( non_upper_case_globals) ]
104
- pub const AbiDatas : & [ AbiData ] = & [
105
- AbiData { abi : Abi :: Rust , name : "Rust" } ,
106
- AbiData { abi : Abi :: C { unwind : false } , name : "C" } ,
107
- AbiData { abi : Abi :: C { unwind : true } , name : "C-unwind" } ,
108
- AbiData { abi : Abi :: Cdecl { unwind : false } , name : "cdecl" } ,
109
- AbiData { abi : Abi :: Cdecl { unwind : true } , name : "cdecl-unwind" } ,
110
- AbiData { abi : Abi :: Stdcall { unwind : false } , name : "stdcall" } ,
111
- AbiData { abi : Abi :: Stdcall { unwind : true } , name : "stdcall-unwind" } ,
112
- AbiData { abi : Abi :: Fastcall { unwind : false } , name : "fastcall" } ,
113
- AbiData { abi : Abi :: Fastcall { unwind : true } , name : "fastcall-unwind" } ,
114
- AbiData { abi : Abi :: Vectorcall { unwind : false } , name : "vectorcall" } ,
115
- AbiData { abi : Abi :: Vectorcall { unwind : true } , name : "vectorcall-unwind" } ,
116
- AbiData { abi : Abi :: Thiscall { unwind : false } , name : "thiscall" } ,
117
- AbiData { abi : Abi :: Thiscall { unwind : true } , name : "thiscall-unwind" } ,
118
- AbiData { abi : Abi :: Aapcs { unwind : false } , name : "aapcs" } ,
119
- AbiData { abi : Abi :: Aapcs { unwind : true } , name : "aapcs-unwind" } ,
120
- AbiData { abi : Abi :: Win64 { unwind : false } , name : "win64" } ,
121
- AbiData { abi : Abi :: Win64 { unwind : true } , name : "win64-unwind" } ,
122
- AbiData { abi : Abi :: SysV64 { unwind : false } , name : "sysv64" } ,
123
- AbiData { abi : Abi :: SysV64 { unwind : true } , name : "sysv64-unwind" } ,
124
- AbiData { abi : Abi :: PtxKernel , name : "ptx-kernel" } ,
125
- AbiData { abi : Abi :: Msp430Interrupt , name : "msp430-interrupt" } ,
126
- AbiData { abi : Abi :: X86Interrupt , name : "x86-interrupt" } ,
127
- AbiData { abi : Abi :: GpuKernel , name : "gpu-kernel" } ,
128
- AbiData { abi : Abi :: EfiApi , name : "efiapi" } ,
129
- AbiData { abi : Abi :: AvrInterrupt , name : "avr-interrupt" } ,
130
- AbiData { abi : Abi :: AvrNonBlockingInterrupt , name : "avr-non-blocking-interrupt" } ,
131
- AbiData { abi : Abi :: CCmseNonSecureCall , name : "C-cmse-nonsecure-call" } ,
132
- AbiData { abi : Abi :: CCmseNonSecureEntry , name : "C-cmse-nonsecure-entry" } ,
133
- AbiData { abi : Abi :: System { unwind : false } , name : "system" } ,
134
- AbiData { abi : Abi :: System { unwind : true } , name : "system-unwind" } ,
135
- AbiData { abi : Abi :: RustIntrinsic , name : "rust-intrinsic" } ,
136
- AbiData { abi : Abi :: RustCall , name : "rust-call" } ,
137
- AbiData { abi : Abi :: Unadjusted , name : "unadjusted" } ,
138
- AbiData { abi : Abi :: RustCold , name : "rust-cold" } ,
139
- AbiData { abi : Abi :: RiscvInterruptM , name : "riscv-interrupt-m" } ,
140
- AbiData { abi : Abi :: RiscvInterruptS , name : "riscv-interrupt-s" } ,
141
- ] ;
142
-
143
- #[ derive( Copy , Clone , Debug ) ]
144
- pub struct AbiUnsupported { }
145
- /// Returns the ABI with the given name (if any).
146
- pub fn lookup ( name : & str ) -> Result < Abi , AbiUnsupported > {
147
- AbiDatas
148
- . iter ( )
149
- . find ( |abi_data| name == abi_data. name )
150
- . map ( |& x| x. abi )
151
- . ok_or_else ( || AbiUnsupported { } )
152
- }
153
-
154
217
pub fn all_names ( ) -> Vec < & ' static str > {
155
- AbiDatas . iter ( ) . map ( |d| d . name ) . collect ( )
218
+ ExternAbi :: ALL_VARIANTS . iter ( ) . map ( |abi| abi . as_str ( ) ) . collect ( )
156
219
}
157
220
158
- impl Abi {
221
+ impl ExternAbi {
159
222
/// Default ABI chosen for `extern fn` declarations without an explicit ABI.
160
223
pub const FALLBACK : Abi = Abi :: C { unwind : false } ;
161
224
162
- #[ inline]
163
- pub fn index ( self ) -> usize {
164
- // N.B., this ordering MUST match the AbiDatas array above.
165
- // (This is ensured by the test indices_are_correct().)
166
- use Abi :: * ;
167
- let i = match self {
168
- // Cross-platform ABIs
169
- Rust => 0 ,
170
- C { unwind : false } => 1 ,
171
- C { unwind : true } => 2 ,
172
- // Platform-specific ABIs
173
- Cdecl { unwind : false } => 3 ,
174
- Cdecl { unwind : true } => 4 ,
175
- Stdcall { unwind : false } => 5 ,
176
- Stdcall { unwind : true } => 6 ,
177
- Fastcall { unwind : false } => 7 ,
178
- Fastcall { unwind : true } => 8 ,
179
- Vectorcall { unwind : false } => 9 ,
180
- Vectorcall { unwind : true } => 10 ,
181
- Thiscall { unwind : false } => 11 ,
182
- Thiscall { unwind : true } => 12 ,
183
- Aapcs { unwind : false } => 13 ,
184
- Aapcs { unwind : true } => 14 ,
185
- Win64 { unwind : false } => 15 ,
186
- Win64 { unwind : true } => 16 ,
187
- SysV64 { unwind : false } => 17 ,
188
- SysV64 { unwind : true } => 18 ,
189
- PtxKernel => 19 ,
190
- Msp430Interrupt => 20 ,
191
- X86Interrupt => 21 ,
192
- GpuKernel => 22 ,
193
- EfiApi => 23 ,
194
- AvrInterrupt => 24 ,
195
- AvrNonBlockingInterrupt => 25 ,
196
- CCmseNonSecureCall => 26 ,
197
- CCmseNonSecureEntry => 27 ,
198
- // Cross-platform ABIs
199
- System { unwind : false } => 28 ,
200
- System { unwind : true } => 29 ,
201
- RustIntrinsic => 30 ,
202
- RustCall => 31 ,
203
- Unadjusted => 32 ,
204
- RustCold => 33 ,
205
- RiscvInterruptM => 34 ,
206
- RiscvInterruptS => 35 ,
207
- } ;
208
- debug_assert ! (
209
- AbiDatas
210
- . iter( )
211
- . enumerate( )
212
- . find( |( _, AbiData { abi, .. } ) | * abi == self )
213
- . map( |( index, _) | index)
214
- . expect( "abi variant has associated data" )
215
- == i,
216
- "Abi index did not match `AbiDatas` ordering"
217
- ) ;
218
- i
219
- }
220
-
221
- #[ inline]
222
- pub fn data ( self ) -> & ' static AbiData {
223
- & AbiDatas [ self . index ( ) ]
224
- }
225
-
226
225
pub fn name ( self ) -> & ' static str {
227
- self . data ( ) . name
226
+ self . as_str ( )
228
227
}
229
228
}
230
229
231
- impl fmt:: Display for Abi {
230
+ impl fmt:: Display for ExternAbi {
232
231
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
233
- write ! ( f, "\" {}\" " , self . name ( ) )
232
+ write ! ( f, "\" {}\" " , self . as_str ( ) )
234
233
}
235
234
}
0 commit comments