Skip to content

Commit df7e311

Browse files
compiler: use arch-dependent AbiMap construction
1 parent a843822 commit df7e311

File tree

2 files changed

+92
-85
lines changed

2 files changed

+92
-85
lines changed

compiler/rustc_abi/src/map.rs

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::{BTreeMap, BTreeSet};
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,14 +15,16 @@ pub struct AbiMap {
1515
/// ABI used for `extern "rust-cold"`
1616
pub rust_cold: CanonAbi,
1717

18-
// optional abstract ABIs
18+
// optional architecture-specific ABIs, should always answer a certain way per-arch
1919
pub efiapi: Option<CanonAbi>,
20+
pub win64: Option<CanonAbi>,
21+
pub 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
@@ -204,6 +206,39 @@ impl AbiMap {
204206
}
205207
}
206208

209+
// construction
210+
211+
impl AbiMap {
212+
pub fn base_for_arch(arch: &str) -> AbiMap {
213+
match arch {
214+
"aarch64" => AbiMap { efiapi: Some(CanonAbi::C), ..Default::default() },
215+
"amdgpu" => AbiMap { gpu_kernel: true, ..Default::default() },
216+
"arm" => AbiMap {
217+
aapcs: true,
218+
efiapi: Some(CanonAbi::Arm(ArmCall::Aapcs)),
219+
..Default::default()
220+
},
221+
"avr" => AbiMap { avr_interrupt: true, ..Default::default() },
222+
"msp430" => AbiMap { msp430_interrupt: true, ..Default::default() },
223+
"nvptx64" => AbiMap { ptx_kernel: true, gpu_kernel: true, ..Default::default() },
224+
"riscv32" | "riscv64" => {
225+
AbiMap { efiapi: Some(CanonAbi::C), riscv_interrupt: true, ..Default::default() }
226+
}
227+
"x86" => {
228+
AbiMap { efiapi: Some(CanonAbi::C), x86_interrupt: true, ..Default::default() }
229+
}
230+
"x86_64" => AbiMap {
231+
efiapi: Some(CanonAbi::X86(X86Call::Win64)),
232+
sysv64: Some(CanonAbi::X86(X86Call::SysV64)),
233+
win64: Some(CanonAbi::X86(X86Call::Win64)),
234+
x86_interrupt: true,
235+
..Default::default()
236+
},
237+
_ => Default::default(),
238+
}
239+
}
240+
}
241+
207242
// deserialization
208243

209244
type JsonObject = serde_json::Map<String, JsonValue>;
@@ -241,31 +276,19 @@ fn extract_bool_abi(
241276
}
242277

243278
impl AbiMap {
244-
pub fn from_json_object(
279+
pub fn from_arch_and_json(
280+
arch: &str,
245281
mut json: JsonObject,
246-
) -> Result<Self, BTreeMap<String, AbiFromJsonErr>> {
282+
) -> (Self, BTreeMap<String, AbiFromJsonErr>) {
247283
// extract all keys we are interested in
248284
let required_c_abis =
249285
["C", "system", "system-varargs"].map(|abi_str| extract_abi_str(&mut json, abi_str));
250286
let rust_cold = extract_abi_str(&mut json, "rust-cold");
251-
let bool_abis = [
252-
// arm...
253-
"aapcs",
254-
"cmse-nonsecure-entry",
255-
// ...gpu...
256-
"gpu-kernel",
257-
"ptx-kernel",
258-
// ...interrupt
259-
"avr-interrupt",
260-
"msp430-interrupt",
261-
"riscv-interrupt",
262-
"x86-interrupt",
263-
]
264-
.map(|abi_str| extract_bool_abi(&mut json, abi_str));
265-
// x86ish
266-
let optional_abis =
267-
["efiapi", "stdcall", "fastcall", "thiscall", "vectorcall", "win64", "sysv64"]
268-
.map(|abi_str| extract_abi_str(&mut json, abi_str));
287+
let bool_abis =
288+
["aapcs", "cmse-nonsecure-entry"].map(|abi_str| extract_bool_abi(&mut json, abi_str));
289+
// x86ish optional ABIs
290+
let optional_abis = ["stdcall", "fastcall", "thiscall", "vectorcall"]
291+
.map(|abi_str| extract_abi_str(&mut json, abi_str));
269292

270293
// accumulate errors
271294
// create an iterator of invalid types and bad parses
@@ -283,28 +306,22 @@ impl AbiMap {
283306
.chain(errs.cloned())
284307
.collect::<BTreeMap<_, _>>();
285308

286-
if error_map.len() > 0 {
287-
Err(error_map)
288-
} else {
289-
// oh? success? merry giftmas! time to unwrap your presents
290-
// these have default ABIs to select
291-
let [c_proper, system, system_varargs] =
292-
required_c_abis.map(|result| result.unwrap().unwrap_or(CanonAbi::C));
293-
let rust_cold = rust_cold.unwrap().unwrap_or(CanonAbi::RustCold);
294-
295-
// these stay options, but shell the Result
296-
let [efiapi, stdcall, fastcall, thiscall, vectorcall, win64, sysv64] =
297-
optional_abis.map(|result| result.unwrap());
298-
299-
// these simplify to booleans
300-
let bool_abis = bool_abis.map(|result| result.unwrap().unwrap_or(false));
301-
// repeat the mantra: arm...
302-
let [aapcs, cmse_nonsecure_entry, bool_abis @ ..] = bool_abis;
303-
// ...gpu...
304-
let [gpu_kernel, ptx_kernel, bool_abis @ ..] = bool_abis;
305-
// ...interrupt
306-
let [avr_interrupt, msp430_interrupt, riscv_interrupt, x86_interrupt] = bool_abis;
307-
Ok(AbiMap {
309+
// oh? success? merry giftmas! time to unwrap your presents
310+
// start with the architectural defaults
311+
let arch_map = AbiMap::base_for_arch(arch);
312+
// these have default ABIs to select
313+
let [c_proper, system, system_varargs] =
314+
required_c_abis.map(|result| result.unwrap().unwrap_or(CanonAbi::C));
315+
let rust_cold = rust_cold.unwrap().unwrap_or(CanonAbi::RustCold);
316+
317+
// these stay options, but shell the Result
318+
let [stdcall, fastcall, thiscall, vectorcall] = optional_abis.map(|result| result.unwrap());
319+
320+
// these simplify to booleans
321+
let bool_abis = bool_abis.map(|result| result.unwrap().unwrap_or(false));
322+
let [aapcs, cmse_nonsecure_entry] = bool_abis;
323+
(
324+
AbiMap {
308325
c_proper,
309326
system,
310327
system_varargs,
@@ -314,26 +331,16 @@ impl AbiMap {
314331
aapcs,
315332
cmse_nonsecure_entry,
316333

317-
// ...gpu...
318-
gpu_kernel,
319-
ptx_kernel,
320-
321-
// ...interrupt
322-
avr_interrupt,
323-
msp430_interrupt,
324-
riscv_interrupt,
325-
x86_interrupt,
326-
327334
// x86-ish
328-
efiapi,
329335
stdcall,
330336
fastcall,
331337
thiscall,
332338
vectorcall,
333-
win64,
334-
sysv64,
335-
})
336-
}
339+
340+
..arch_map
341+
},
342+
error_map,
343+
)
337344
}
338345

339346
// serialization

compiler/rustc_target/src/spec/json.rs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::Cow;
22
use std::collections::BTreeMap;
33
use std::str::FromStr;
44

5-
use rustc_abi::{AbiFromJsonErr, AbiFromStrErr};
5+
use rustc_abi::{AbiFromJsonErr, AbiFromStrErr, AbiMap};
66
use serde_json::Value;
77

88
use super::{Target, TargetKind, TargetOptions, TargetWarnings};
@@ -60,33 +60,33 @@ impl Target {
6060
let mut unused_fields = vec![];
6161
let mut bad_kv = vec![];
6262

63+
base.options.abi_map = AbiMap::base_for_arch(&base.arch);
6364
match obj.remove("abi-map") {
64-
Some(Json::Object(object)) => match rustc_abi::AbiMap::from_json_object(object) {
65-
Ok(abi_map) => base.options.abi_map = abi_map,
66-
Err(error_map) => {
67-
for (key, error) in error_map {
68-
match error {
69-
AbiFromJsonErr::InvalidType => {
70-
incorrect_type.push(["abi-map", &key].join("."))
71-
}
72-
AbiFromJsonErr::UnusedKey => {
73-
unused_fields.push(["abi-map", &key].join("."))
74-
}
75-
AbiFromJsonErr::Parse { kind, value } => bad_kv.push((
76-
["abi-map", &key].join("."),
77-
match kind {
78-
AbiFromStrErr::Unknown => {
79-
format!("{value} is not a valid CanonAbi")
80-
}
81-
AbiFromStrErr::NoUnwind => {
82-
format!("{value} must not be -unwind")
83-
}
84-
},
85-
)),
65+
Some(Json::Object(object)) => {
66+
let (abi_map, error_map) = AbiMap::from_arch_and_json(&base.arch, object);
67+
base.options.abi_map = abi_map;
68+
for (key, error) in error_map {
69+
match error {
70+
AbiFromJsonErr::InvalidType => {
71+
incorrect_type.push(["abi-map", &key].join("."))
72+
}
73+
AbiFromJsonErr::UnusedKey => {
74+
unused_fields.push(["abi-map", &key].join("."))
8675
}
76+
AbiFromJsonErr::Parse { kind, value } => bad_kv.push((
77+
["abi-map", &key].join("."),
78+
match kind {
79+
AbiFromStrErr::Unknown => {
80+
format!("{value} is not a valid CanonAbi")
81+
}
82+
AbiFromStrErr::NoUnwind => {
83+
format!("{value} must not be -unwind")
84+
}
85+
},
86+
)),
8787
}
8888
}
89-
},
89+
}
9090
Some(_) => incorrect_type.push("abi-map".to_owned()),
9191
None => (),
9292
};

0 commit comments

Comments
 (0)