Skip to content

Commit c04e249

Browse files
compiler: add AbiMap
- Add AbiMapping for encoding the nuance of deprecated ABIs
1 parent f57ed46 commit c04e249

File tree

4 files changed

+190
-1
lines changed

4 files changed

+190
-1
lines changed

compiler/rustc_target/src/callconv/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_abi::{
88
};
99
use rustc_macros::HashStable_Generic;
1010

11+
pub use crate::spec::AbiMap;
1112
use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, RustcAbi, WasmCAbi};
1213

1314
mod aarch64;
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
use rustc_abi::{ArmCall, CanonAbi, ExternAbi, InterruptKind, X86Call};
2+
3+
use crate::spec::Target;
4+
5+
/// Mapping for ExternAbi to CanonAbi according to a Target
6+
///
7+
/// A maybe-transitional structure circa 2025 for hosting future experiments in
8+
/// encapsulating arch-specific ABI lowering details to make them more testable.
9+
#[derive(Clone, Debug)]
10+
pub struct AbiMap {
11+
arch: Arch,
12+
os: OsKind,
13+
}
14+
15+
#[derive(Copy, Clone, Debug)]
16+
pub enum AbiMapping {
17+
/// this ABI is exactly mapped for this platform
18+
Direct(CanonAbi),
19+
/// we don't yet warn on this, but we will
20+
Deprecated(CanonAbi),
21+
Invalid,
22+
}
23+
24+
impl AbiMapping {
25+
pub fn into_option(self) -> Option<CanonAbi> {
26+
match self {
27+
Self::Direct(abi) | Self::Deprecated(abi) => Some(abi),
28+
Self::Invalid => None,
29+
}
30+
}
31+
32+
pub fn unwrap(self) -> CanonAbi {
33+
self.into_option().unwrap()
34+
}
35+
36+
pub fn is_mapped(self) -> bool {
37+
self.into_option().is_some()
38+
}
39+
}
40+
41+
impl AbiMap {
42+
pub fn from_target(target: &Target) -> Self {
43+
// the purpose of this little exercise is to force listing what affects these mappings
44+
let arch = match &*target.arch {
45+
"aarch64" => Arch::Aarch64,
46+
"amdgpu" => Arch::Amdgpu,
47+
"arm" if target.llvm_target.starts_with("thumbv8m") => Arch::Arm(ArmVer::ThumbV8M),
48+
"arm" => Arch::Arm(ArmVer::Other),
49+
"avr" => Arch::Avr,
50+
"msp430" => Arch::Msp430,
51+
"nvptx64" => Arch::Nvptx,
52+
"riscv32" | "riscv64" => Arch::Riscv,
53+
"x86" => Arch::X86,
54+
"x86_64" => Arch::X86_64,
55+
_ => Arch::Other,
56+
};
57+
let os = if target.is_like_windows { OsKind::Windows } else { OsKind::Other };
58+
AbiMap { arch, os }
59+
}
60+
61+
pub fn canonize_abi(&self, extern_abi: ExternAbi, has_c_varargs: bool) -> AbiMapping {
62+
let AbiMap { os, arch } = *self;
63+
64+
let canon_abi = match (extern_abi, arch) {
65+
// infallible lowerings
66+
(ExternAbi::C { .. }, _) => CanonAbi::C,
67+
(ExternAbi::Rust | ExternAbi::RustCall, _) => CanonAbi::Rust,
68+
(ExternAbi::Unadjusted, _) => CanonAbi::C,
69+
70+
(ExternAbi::RustCold, _) if self.os == OsKind::Windows => CanonAbi::Rust,
71+
(ExternAbi::RustCold, _) => CanonAbi::RustCold,
72+
73+
(ExternAbi::System { .. }, Arch::X86) if os == OsKind::Windows && !has_c_varargs => {
74+
CanonAbi::X86(X86Call::Stdcall)
75+
}
76+
(ExternAbi::System { .. }, _) => CanonAbi::C,
77+
78+
// fallible lowerings
79+
(ExternAbi::EfiApi, Arch::Arm(..)) => CanonAbi::Arm(ArmCall::Aapcs),
80+
(ExternAbi::EfiApi, Arch::X86_64) => CanonAbi::X86(X86Call::Win64),
81+
(ExternAbi::EfiApi, Arch::Aarch64 | Arch::Riscv | Arch::X86) => CanonAbi::C,
82+
(ExternAbi::EfiApi, _) => return AbiMapping::Invalid,
83+
84+
(ExternAbi::Aapcs { .. }, Arch::Arm(..)) => CanonAbi::Arm(ArmCall::Aapcs),
85+
(ExternAbi::Aapcs { .. }, _) => return AbiMapping::Invalid,
86+
87+
(ExternAbi::CCmseNonSecureCall, Arch::Arm(ArmVer::ThumbV8M)) => {
88+
CanonAbi::Arm(ArmCall::CCmseNonSecureCall)
89+
}
90+
(ExternAbi::CCmseNonSecureEntry, Arch::Arm(ArmVer::ThumbV8M)) => {
91+
CanonAbi::Arm(ArmCall::CCmseNonSecureEntry)
92+
}
93+
(ExternAbi::CCmseNonSecureCall | ExternAbi::CCmseNonSecureEntry, ..) => {
94+
return AbiMapping::Invalid;
95+
}
96+
97+
(ExternAbi::Cdecl { .. }, Arch::X86) => CanonAbi::C,
98+
(ExternAbi::Cdecl { .. }, _) => return AbiMapping::Deprecated(CanonAbi::C),
99+
100+
(ExternAbi::Fastcall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Fastcall),
101+
(ExternAbi::Fastcall { .. }, _) if os == OsKind::Windows => {
102+
return AbiMapping::Deprecated(CanonAbi::C);
103+
}
104+
(ExternAbi::Fastcall { .. }, _) => return AbiMapping::Invalid,
105+
106+
(ExternAbi::Stdcall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Stdcall),
107+
(ExternAbi::Stdcall { .. }, _) if os == OsKind::Windows => {
108+
return AbiMapping::Deprecated(CanonAbi::C);
109+
}
110+
(ExternAbi::Stdcall { .. }, _) => return AbiMapping::Invalid,
111+
112+
(ExternAbi::Thiscall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Thiscall),
113+
(ExternAbi::Thiscall { .. }, _) => return AbiMapping::Invalid,
114+
115+
(ExternAbi::Vectorcall { .. }, Arch::X86 | Arch::X86_64) => {
116+
CanonAbi::X86(X86Call::Vectorcall)
117+
}
118+
(ExternAbi::Vectorcall { .. }, _) if os == OsKind::Windows => {
119+
return AbiMapping::Deprecated(CanonAbi::C);
120+
}
121+
(ExternAbi::Vectorcall { .. }, _) => return AbiMapping::Invalid,
122+
123+
(ExternAbi::SysV64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::SysV64),
124+
(ExternAbi::Win64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::Win64),
125+
(ExternAbi::SysV64 { .. } | ExternAbi::Win64 { .. }, _) => return AbiMapping::Invalid,
126+
127+
(ExternAbi::PtxKernel, Arch::Nvptx) => CanonAbi::GpuKernel,
128+
(ExternAbi::GpuKernel, Arch::Amdgpu | Arch::Nvptx) => CanonAbi::GpuKernel,
129+
(ExternAbi::PtxKernel | ExternAbi::GpuKernel, _) => return AbiMapping::Invalid,
130+
131+
(ExternAbi::AvrInterrupt, Arch::Avr) => CanonAbi::Interrupt(InterruptKind::Avr),
132+
(ExternAbi::AvrNonBlockingInterrupt, Arch::Avr) => {
133+
CanonAbi::Interrupt(InterruptKind::AvrNonBlocking)
134+
}
135+
(ExternAbi::Msp430Interrupt, Arch::Msp430) => {
136+
CanonAbi::Interrupt(InterruptKind::Msp430)
137+
}
138+
(ExternAbi::RiscvInterruptM, Arch::Riscv) => {
139+
CanonAbi::Interrupt(InterruptKind::RiscvMachine)
140+
}
141+
(ExternAbi::RiscvInterruptS, Arch::Riscv) => {
142+
CanonAbi::Interrupt(InterruptKind::RiscvSupervisor)
143+
}
144+
(ExternAbi::X86Interrupt, Arch::X86 | Arch::X86_64) => {
145+
CanonAbi::Interrupt(InterruptKind::X86)
146+
}
147+
(
148+
ExternAbi::AvrInterrupt
149+
| ExternAbi::AvrNonBlockingInterrupt
150+
| ExternAbi::Msp430Interrupt
151+
| ExternAbi::RiscvInterruptM
152+
| ExternAbi::RiscvInterruptS
153+
| ExternAbi::X86Interrupt,
154+
_,
155+
) => return AbiMapping::Invalid,
156+
};
157+
158+
AbiMapping::Direct(canon_abi)
159+
}
160+
}
161+
162+
#[derive(Debug, PartialEq, Copy, Clone)]
163+
enum Arch {
164+
Aarch64,
165+
Amdgpu,
166+
Arm(ArmVer),
167+
Avr,
168+
Msp430,
169+
Nvptx,
170+
Riscv,
171+
X86,
172+
X86_64,
173+
/// Architectures which don't need other considerations for ABI lowering
174+
Other,
175+
}
176+
177+
#[derive(Debug, PartialEq, Copy, Clone)]
178+
enum OsKind {
179+
Windows,
180+
Other,
181+
}
182+
183+
#[derive(Debug, PartialEq, Copy, Clone)]
184+
enum ArmVer {
185+
ThumbV8M,
186+
Other,
187+
}

compiler/rustc_target/src/spec/json.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,6 @@ impl Target {
546546
incorrect_type.push("frame-pointer".into())
547547
}
548548
}
549-
550549
key!(c_int_width = "target-c-int-width");
551550
key!(c_enum_min_bits, Option<u64>); // if None, matches c_int_width
552551
key!(os);

compiler/rustc_target/src/spec/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@ use crate::spec::crt_objects::CrtObjects;
5959

6060
pub mod crt_objects;
6161

62+
mod abi_map;
6263
mod base;
6364
mod json;
6465

66+
pub use abi_map::AbiMap;
6567
pub use base::apple;
6668
pub use base::avr::ef_avr_arch;
6769

0 commit comments

Comments
 (0)