1+ use  std:: cmp:: Ordering ; 
12use  std:: fmt; 
3+ use  std:: hash:: { Hash ,  Hasher } ; 
24
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 } ; 
49
510#[ cfg( test) ]  
611mod  tests; 
712
813use  ExternAbi  as  Abi ; 
914
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 ) ) ]  
1217pub  enum  ExternAbi  { 
1318    // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the 
1419    // hashing tests. These are used in many places, so giving them stable values reduces test 
@@ -68,7 +73,124 @@ pub enum ExternAbi {
6873    RiscvInterruptS , 
6974} 
7075
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  { 
72194    pub  fn  supports_varargs ( self )  -> bool  { 
73195        // * C and Cdecl obviously support varargs. 
74196        // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs. 
@@ -92,144 +214,21 @@ impl Abi {
92214    } 
93215} 
94216
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- 
154217pub  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 ( ) 
156219} 
157220
158- impl  Abi  { 
221+ impl  ExternAbi  { 
159222    /// Default ABI chosen for `extern fn` declarations without an explicit ABI. 
160223pub  const  FALLBACK :  Abi  = Abi :: C  {  unwind :  false  } ; 
161224
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- 
226225    pub  fn  name ( self )  -> & ' static  str  { 
227-         self . data ( ) . name 
226+         self . as_str ( ) 
228227    } 
229228} 
230229
231- impl  fmt:: Display  for  Abi  { 
230+ impl  fmt:: Display  for  ExternAbi  { 
232231    fn  fmt ( & self ,  f :  & mut  fmt:: Formatter < ' _ > )  -> fmt:: Result  { 
233-         write ! ( f,  "\" {}\" " ,  self . name ( ) ) 
232+         write ! ( f,  "\" {}\" " ,  self . as_str ( ) ) 
234233    } 
235234} 
0 commit comments