Skip to content

Commit 529acb6

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

File tree

2 files changed

+104
-85
lines changed

2 files changed

+104
-85
lines changed

compiler/rustc_abi/src/map.rs

Lines changed: 80 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,51 @@ 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 {
229+
efiapi: Some(CanonAbi::C),
230+
x86_interrupt: true,
231+
232+
//FIXME(jubilee): it seems unlikely we want this?
233+
vectorcall: Some(CanonAbi::X86(X86Call::Vectorcall)),
234+
235+
..Default::default()
236+
}
237+
}
238+
"x86_64" => AbiMap {
239+
efiapi: Some(CanonAbi::X86(X86Call::Win64)),
240+
sysv64: Some(CanonAbi::X86(X86Call::SysV64)),
241+
win64: Some(CanonAbi::X86(X86Call::Win64)),
242+
x86_interrupt: true,
243+
244+
//FIXME(jubilee): it seems unlikely we want this?
245+
vectorcall: Some(CanonAbi::X86(X86Call::Vectorcall)),
246+
247+
..Default::default()
248+
},
249+
_ => Default::default(),
250+
}
251+
}
252+
}
253+
207254
// deserialization
208255

209256
type JsonObject = serde_json::Map<String, JsonValue>;
@@ -241,31 +288,19 @@ fn extract_bool_abi(
241288
}
242289

243290
impl AbiMap {
244-
pub fn from_json_object(
291+
pub fn from_arch_and_json(
292+
arch: &str,
245293
mut json: JsonObject,
246-
) -> Result<Self, BTreeMap<String, AbiFromJsonErr>> {
294+
) -> (Self, BTreeMap<String, AbiFromJsonErr>) {
247295
// extract all keys we are interested in
248296
let required_c_abis =
249297
["C", "system", "system-varargs"].map(|abi_str| extract_abi_str(&mut json, abi_str));
250298
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));
299+
let bool_abis =
300+
["aapcs", "cmse-nonsecure-entry"].map(|abi_str| extract_bool_abi(&mut json, abi_str));
301+
// x86ish optional ABIs
302+
let optional_abis = ["stdcall", "fastcall", "thiscall", "vectorcall"]
303+
.map(|abi_str| extract_abi_str(&mut json, abi_str));
269304

270305
// accumulate errors
271306
// create an iterator of invalid types and bad parses
@@ -283,28 +318,22 @@ impl AbiMap {
283318
.chain(errs.cloned())
284319
.collect::<BTreeMap<_, _>>();
285320

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 {
321+
// oh? success? merry giftmas! time to unwrap your presents
322+
// start with the architectural defaults
323+
let arch_map = AbiMap::base_for_arch(arch);
324+
// these have default ABIs to select
325+
let [c_proper, system, system_varargs] =
326+
required_c_abis.map(|result| result.unwrap().unwrap_or(CanonAbi::C));
327+
let rust_cold = rust_cold.unwrap().unwrap_or(CanonAbi::RustCold);
328+
329+
// these stay options, but shell the Result
330+
let [stdcall, fastcall, thiscall, vectorcall] = optional_abis.map(|result| result.unwrap());
331+
332+
// these simplify to booleans
333+
let bool_abis = bool_abis.map(|result| result.unwrap().unwrap_or(false));
334+
let [aapcs, cmse_nonsecure_entry] = bool_abis;
335+
(
336+
AbiMap {
308337
c_proper,
309338
system,
310339
system_varargs,
@@ -314,26 +343,16 @@ impl AbiMap {
314343
aapcs,
315344
cmse_nonsecure_entry,
316345

317-
// ...gpu...
318-
gpu_kernel,
319-
ptx_kernel,
320-
321-
// ...interrupt
322-
avr_interrupt,
323-
msp430_interrupt,
324-
riscv_interrupt,
325-
x86_interrupt,
326-
327346
// x86-ish
328-
efiapi,
329347
stdcall,
330348
fastcall,
331349
thiscall,
332350
vectorcall,
333-
win64,
334-
sysv64,
335-
})
336-
}
351+
352+
..arch_map
353+
},
354+
error_map,
355+
)
337356
}
338357

339358
// 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)