@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
22
33use serde_json:: Value as JsonValue ;
44
5- use crate :: { AbiFromJsonErr , ArmCall , CanonAbi , ExternAbi , InterruptKind } ;
5+ use crate :: { AbiFromJsonErr , ArmCall , CanonAbi , ExternAbi , InterruptKind , X86Call } ;
66
77#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
88pub struct AbiMap {
@@ -15,27 +15,28 @@ pub struct AbiMap {
1515 /// ABI used for `extern "rust-cold"`
1616 pub rust_cold : CanonAbi ,
1717
18- // optional abstract ABIs
19- pub efiapi : Option < CanonAbi > ,
18+ // optional architecture-specific ABIs, should always answer a certain way per-arch
19+ efiapi : Option < CanonAbi > ,
20+ win64 : Option < CanonAbi > ,
21+ sysv64 : Option < CanonAbi > ,
22+
23+ // optional abstract ABIs, these can be very weird
2024 pub stdcall : Option < CanonAbi > ,
2125 pub fastcall : Option < CanonAbi > ,
2226 pub thiscall : Option < CanonAbi > ,
2327 pub vectorcall : Option < CanonAbi > ,
24- pub win64 : Option < CanonAbi > ,
25- pub sysv64 : Option < CanonAbi > ,
2628
2729 // optional concrete ABIs
2830 // arm
2931 pub aapcs : bool ,
3032 pub cmse_nonsecure_entry : bool ,
31- // gpu
32- pub gpu_kernel : bool ,
33- pub ptx_kernel : bool ,
34- // interrupt
35- pub avr_interrupt : bool ,
36- pub msp430_interrupt : bool ,
37- pub riscv_interrupt : bool ,
38- pub x86_interrupt : bool ,
33+
34+ gpu_kernel : bool ,
35+ ptx_kernel : bool ,
36+ avr_interrupt : bool ,
37+ msp430_interrupt : bool ,
38+ riscv_interrupt : bool ,
39+ x86_interrupt : bool ,
3940}
4041
4142// usually the reasonable default, but pay attention to system
@@ -157,6 +158,39 @@ impl AbiMap {
157158 }
158159}
159160
161+ // construction
162+
163+ impl AbiMap {
164+ pub fn base_for_arch ( arch : & str ) -> AbiMap {
165+ match arch {
166+ "aarch64" => AbiMap { efiapi : Some ( CanonAbi :: C ) , ..Default :: default ( ) } ,
167+ "amdgpu" => AbiMap { gpu_kernel : true , ..Default :: default ( ) } ,
168+ "arm" => AbiMap {
169+ aapcs : true ,
170+ efiapi : Some ( CanonAbi :: Arm ( ArmCall :: Aapcs ) ) ,
171+ ..Default :: default ( )
172+ } ,
173+ "avr" => AbiMap { avr_interrupt : true , ..Default :: default ( ) } ,
174+ "msp430" => AbiMap { msp430_interrupt : true , ..Default :: default ( ) } ,
175+ "nvptx64" => AbiMap { ptx_kernel : true , gpu_kernel : true , ..Default :: default ( ) } ,
176+ "riscv32" | "riscv64" => {
177+ AbiMap { efiapi : Some ( CanonAbi :: C ) , riscv_interrupt : true , ..Default :: default ( ) }
178+ }
179+ "x86" => {
180+ AbiMap { efiapi : Some ( CanonAbi :: C ) , x86_interrupt : true , ..Default :: default ( ) }
181+ }
182+ "x86_64" => AbiMap {
183+ efiapi : Some ( CanonAbi :: X86 ( X86Call :: Win64 ) ) ,
184+ sysv64 : Some ( CanonAbi :: X86 ( X86Call :: SysV64 ) ) ,
185+ win64 : Some ( CanonAbi :: X86 ( X86Call :: Win64 ) ) ,
186+ x86_interrupt : true ,
187+ ..Default :: default ( )
188+ } ,
189+ _ => Default :: default ( ) ,
190+ }
191+ }
192+ }
193+
160194// deserialization
161195
162196type JsonObject = serde_json:: Map < String , JsonValue > ;
@@ -194,31 +228,19 @@ fn extract_bool_abi(
194228}
195229
196230impl AbiMap {
197- pub fn from_json_object (
231+ pub fn from_arch_and_json (
232+ arch : & str ,
198233 mut json : JsonObject ,
199- ) -> Result < Self , BTreeMap < String , AbiFromJsonErr > > {
234+ ) -> ( Self , BTreeMap < String , AbiFromJsonErr > ) {
200235 // extract all keys we are interested in
201236 let required_c_abis =
202237 [ "C" , "system" , "system-varargs" ] . map ( |abi_str| extract_abi_str ( & mut json, abi_str) ) ;
203238 let rust_cold = extract_abi_str ( & mut json, "rust-cold" ) ;
204- let bool_abis = [
205- // arm...
206- "aapcs" ,
207- "cmse-nonsecure-entry" ,
208- // ...gpu...
209- "gpu-kernel" ,
210- "ptx-kernel" ,
211- // ...interrupt
212- "avr-interrupt" ,
213- "msp430-interrupt" ,
214- "riscv-interrupt" ,
215- "x86-interrupt" ,
216- ]
217- . map ( |abi_str| extract_bool_abi ( & mut json, abi_str) ) ;
218- // x86ish
219- let optional_abis =
220- [ "efiapi" , "stdcall" , "fastcall" , "thiscall" , "vectorcall" , "win64" , "sysv64" ]
221- . map ( |abi_str| extract_abi_str ( & mut json, abi_str) ) ;
239+ let bool_abis =
240+ [ "aapcs" , "cmse-nonsecure-entry" ] . map ( |abi_str| extract_bool_abi ( & mut json, abi_str) ) ;
241+ // x86ish optional ABIs
242+ let optional_abis = [ "stdcall" , "fastcall" , "thiscall" , "vectorcall" ]
243+ . map ( |abi_str| extract_abi_str ( & mut json, abi_str) ) ;
222244
223245 // accumulate errors
224246 // create an iterator of invalid types and bad parses
@@ -236,28 +258,28 @@ impl AbiMap {
236258 . chain ( errs. cloned ( ) )
237259 . collect :: < BTreeMap < _ , _ > > ( ) ;
238260
239- if error_map . len ( ) > 0 {
240- Err ( error_map )
241- } else {
242- // oh? success? merry giftmas! time to unwrap your presents
243- // these have default ABIs to select
244- let [ c_proper , system , system_varargs ] =
245- required_c_abis . map ( |result| result . unwrap ( ) . unwrap_or ( CanonAbi :: C ) ) ;
246- let rust_cold = rust_cold . unwrap ( ) . unwrap_or ( CanonAbi :: RustCold ) ;
247-
248- // these stay options, but shell the Result
249- let [ efiapi , stdcall , fastcall , thiscall , vectorcall , win64 , sysv64 ] =
250- optional_abis . map ( |result| result . unwrap ( ) ) ;
251-
252- // these simplify to booleans
253- let bool_abis = bool_abis . map ( |result| result . unwrap ( ) . unwrap_or ( false ) ) ;
254- // repeat the mantra: arm...
255- let [ aapcs , cmse_nonsecure_entry , bool_abis @ .. ] = bool_abis ;
256- // ...gpu...
257- let [ gpu_kernel , ptx_kernel , bool_abis @ .. ] = bool_abis ;
258- // ...interrupt
259- let [ avr_interrupt , msp430_interrupt , riscv_interrupt , x86_interrupt ] = bool_abis ;
260- Ok ( AbiMap {
261+ // oh? success? merry giftmas! time to unwrap your presents
262+ // start with the architectural defaults
263+ let arch_map = AbiMap :: base_for_arch ( arch ) ;
264+ // these have default ABIs to select
265+ let [ c_proper , system , system_varargs ] =
266+ required_c_abis . map ( |result| result . unwrap ( ) . unwrap_or ( CanonAbi :: C ) ) ;
267+ let rust_cold = rust_cold . unwrap ( ) . unwrap_or ( CanonAbi :: RustCold ) ;
268+
269+ let [ stdcall , fastcall , thiscall , vectorcall ] = optional_abis . map ( |result| result . unwrap ( ) ) ;
270+ let bool_abis = bool_abis . map ( |result| result . unwrap ( ) . unwrap_or ( false ) ) ;
271+ let [ aapcs , cmse_nonsecure_entry ] = bool_abis ;
272+
273+ // OR the arch defaults with the parsed values
274+ let stdcall = stdcall . or ( arch_map . stdcall ) ;
275+ let fastcall = fastcall . or ( arch_map . fastcall ) ;
276+ let thiscall = thiscall . or ( arch_map . thiscall ) ;
277+ let vectorcall = vectorcall . or ( arch_map . vectorcall ) ;
278+
279+ let aapcs = aapcs | arch_map . aapcs ;
280+ let cmse_nonsecure_entry = cmse_nonsecure_entry | arch_map . cmse_nonsecure_entry ;
281+ (
282+ AbiMap {
261283 c_proper,
262284 system,
263285 system_varargs,
@@ -267,38 +289,26 @@ impl AbiMap {
267289 aapcs,
268290 cmse_nonsecure_entry,
269291
270- // ...gpu...
271- gpu_kernel,
272- ptx_kernel,
273-
274- // ...interrupt
275- avr_interrupt,
276- msp430_interrupt,
277- riscv_interrupt,
278- x86_interrupt,
279-
280292 // x86-ish
281- efiapi,
282293 stdcall,
283294 fastcall,
284295 thiscall,
285296 vectorcall,
286- win64,
287- sysv64,
288- } )
289- }
297+
298+ ..arch_map
299+ } ,
300+ error_map,
301+ )
290302 }
291303
292304 // serialization
293305 pub fn to_json_object ( & self ) -> JsonObject {
294306 let mut json_obj = JsonObject :: new ( ) ;
307+ json_obj. insert ( "C" . to_owned ( ) , self . c_proper . as_str ( ) . to_owned ( ) . into ( ) ) ;
295308 json_obj. insert ( "system" . to_owned ( ) , self . system . as_str ( ) . to_owned ( ) . into ( ) ) ;
296309 json_obj
297310 . insert ( "system-varargs" . to_owned ( ) , self . system_varargs . as_str ( ) . to_owned ( ) . into ( ) ) ;
298311 json_obj. insert ( "rust-cold" . to_owned ( ) , self . rust_cold . as_str ( ) . to_owned ( ) . into ( ) ) ;
299- if let Some ( abi) = self . efiapi {
300- json_obj. insert ( "efiapi" . to_owned ( ) , abi. as_str ( ) . to_owned ( ) . into ( ) ) ;
301- }
302312 if let Some ( abi) = self . stdcall {
303313 json_obj. insert ( "stdcall" . to_owned ( ) , abi. as_str ( ) . to_owned ( ) . into ( ) ) ;
304314 }
@@ -311,36 +321,12 @@ impl AbiMap {
311321 if let Some ( abi) = self . vectorcall {
312322 json_obj. insert ( "vectorcall" . to_owned ( ) , abi. as_str ( ) . to_owned ( ) . into ( ) ) ;
313323 }
314- if let Some ( abi) = self . win64 {
315- json_obj. insert ( "win64" . to_owned ( ) , abi. as_str ( ) . to_owned ( ) . into ( ) ) ;
316- }
317- if let Some ( abi) = self . sysv64 {
318- json_obj. insert ( "sysv64" . to_owned ( ) , abi. as_str ( ) . to_owned ( ) . into ( ) ) ;
319- }
320324 if self . cmse_nonsecure_entry {
321325 json_obj. insert ( "cmse-nonsecure-entry" . to_owned ( ) , JsonValue :: Bool ( true ) ) ;
322326 }
323327 if self . aapcs {
324328 json_obj. insert ( "aapcs" . to_owned ( ) , JsonValue :: Bool ( true ) ) ;
325329 }
326- if self . gpu_kernel {
327- json_obj. insert ( "gpu-kernel" . to_owned ( ) , JsonValue :: Bool ( true ) ) ;
328- }
329- if self . ptx_kernel {
330- json_obj. insert ( "ptx-kernel" . to_owned ( ) , JsonValue :: Bool ( true ) ) ;
331- }
332- if self . avr_interrupt {
333- json_obj. insert ( "avr-interrupt" . to_owned ( ) , JsonValue :: Bool ( true ) ) ;
334- }
335- if self . msp430_interrupt {
336- json_obj. insert ( "msp430-interrupt" . to_owned ( ) , JsonValue :: Bool ( true ) ) ;
337- }
338- if self . riscv_interrupt {
339- json_obj. insert ( "riscv-interrupt" . to_owned ( ) , JsonValue :: Bool ( true ) ) ;
340- }
341- if self . x86_interrupt {
342- json_obj. insert ( "x86-interrupt" . to_owned ( ) , JsonValue :: Bool ( true ) ) ;
343- }
344330
345331 json_obj
346332 }
0 commit comments