Skip to content

Commit d52dbdb

Browse files
compiler: use arch-dependent AbiMap construction
Use module privacy to make it harder to construct incorrect AbiMaps.
1 parent 47c2870 commit d52dbdb

14 files changed

+180
-205
lines changed

compiler/rustc_abi/src/map.rs

Lines changed: 83 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
22

33
use 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)]
88
pub 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

162196
type JsonObject = serde_json::Map<String, JsonValue>;
@@ -194,31 +228,19 @@ fn extract_bool_abi(
194228
}
195229

196230
impl 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

Comments
 (0)