Skip to content

Commit 6c65616

Browse files
committed
Major refactoring
1 parent 3a769a2 commit 6c65616

19 files changed

Lines changed: 943 additions & 847 deletions

src/abi.rs

Lines changed: 129 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -1,225 +1,139 @@
1-
use core::{
2-
fmt::{self, Debug, Display},
3-
str::FromStr,
4-
};
5-
6-
/// The ABI or calling convention of a function pointer.
7-
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
8-
// from https://github.com/rust-lang/rust/blob/4fa80a5e733e2202d7ca4c203c2fdfda41cfe7dc/compiler/rustc_abi/src/extern_abi.rs#L21
9-
pub enum Abi {
10-
/* universal */
11-
/// This is the same as `extern fn foo()`; whatever the default your C compiler supports.
12-
C {
13-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
14-
unwind: bool,
15-
},
16-
/// Usually the same as [`extern "C"`](Abi::C), except on Win32, in which case it's
17-
/// [`"stdcall"`](Abi::Stdcall), or what you should use to link to the Windows API itself.
18-
System {
19-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
20-
unwind: bool,
21-
},
22-
23-
/// The default ABI when you write a normal `fn foo()` in any Rust code.
24-
Rust,
25-
26-
/* arm */
27-
/// The default for ARM.
28-
Aapcs {
29-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
30-
unwind: bool,
31-
},
32-
33-
/* x86 */
34-
/// The default for `x86_32` C code.
35-
Cdecl {
36-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
37-
unwind: bool,
38-
},
39-
/// The default for the Win32 API on `x86_32`.
40-
Stdcall {
41-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
42-
unwind: bool,
43-
},
44-
/// The `fastcall` ABI.
45-
Fastcall {
46-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
47-
unwind: bool,
48-
},
49-
/// The Windows C++ ABI.
50-
Thiscall {
51-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
52-
unwind: bool,
53-
},
54-
/// The `vectorcall` ABI.
55-
Vectorcall {
56-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
57-
unwind: bool,
58-
},
59-
60-
/* x86_64 */
61-
/// The default for C code on non-Windows `x86_64`.
62-
SysV64 {
63-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
64-
unwind: bool,
65-
},
66-
/// The default for C code on `x86_64` Windows.
67-
Win64 {
68-
/// Whether unwinding across this ABI boundary is allowed (`*-unwind`).
69-
unwind: bool,
70-
},
1+
use crate::AbiValue;
2+
3+
/// Type-level marker trait for function ABI.
4+
///
5+
/// Types implementing this trait represent a specific `extern "..."` ABI.
6+
///
7+
/// See [`Abi`] for the runtime representation.
8+
pub trait Abi {
9+
/// The exact ABI string used in `extern "..."`.
10+
const STR: &'static str;
11+
12+
/// The runtime [`Abi`] that represent this marker type.
13+
const VALUE: AbiValue;
14+
15+
/// The runtime [`Abi`] that represent this marker type.
16+
const ALLOWS_UNWIND: bool = Self::VALUE.allows_unwind();
7117
}
7218

73-
impl Abi {
74-
/// Returns whether unwinding after a panic is allowed inside the called function.
75-
#[must_use]
76-
pub const fn allows_unwind(&self) -> bool {
77-
match *self {
78-
Abi::Rust => true,
79-
Abi::C { unwind }
80-
| Abi::System { unwind }
81-
| Abi::Aapcs { unwind }
82-
| Abi::Cdecl { unwind }
83-
| Abi::Stdcall { unwind }
84-
| Abi::Fastcall { unwind }
85-
| Abi::Thiscall { unwind }
86-
| Abi::Vectorcall { unwind }
87-
| Abi::SysV64 { unwind }
88-
| Abi::Win64 { unwind } => unwind,
19+
/// Helper macro to implement [`Abi`].
20+
macro_rules! define_abi_marker {
21+
($name:ident, $lit:literal) => {
22+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23+
#[doc = "Type-level marker for the `"]
24+
#[doc = $lit]
25+
#[doc = "` ABI."]
26+
pub struct $name;
27+
28+
impl Abi for $name {
29+
const STR: &'static str = $lit;
30+
const VALUE: AbiValue = AbiValue::from_str_const($lit).unwrap();
8931
}
90-
}
91-
92-
/// Canonicalize this ABI for the current target.
93-
///
94-
/// Maps aliases (e.g. `system`, `cdecl`) to the concrete ABI actually used on
95-
/// the current OS/architecture, following Rust compiler rules.
96-
///
97-
/// Returns [`None`] if this ABI is not supported on the current target.
98-
#[must_use]
99-
pub fn canonize(self, has_c_varargs: bool) -> Option<Abi> {
100-
// from https://github.com/rust-lang/rust/blob/4fa80a5e733e2202d7ca4c203c2fdfda41cfe7dc/compiler/rustc_target/src/spec/abi_map.rs#L79
101-
let os_windows = cfg!(target_os = "windows");
102-
let os_vexos = cfg!(target_os = "vexos");
103-
104-
let arch_x86 = cfg!(target_arch = "x86");
105-
let arch_x86_64 = cfg!(target_arch = "x86_64");
106-
let arch_arm = cfg!(target_arch = "arm");
107-
let arch_aarch64 = cfg!(target_arch = "aarch64");
108-
let arch_arm_any = arch_arm || arch_aarch64;
109-
110-
#[allow(clippy::match_same_arms)]
111-
let out = match self {
112-
Abi::C { unwind } => Abi::C { unwind },
113-
Abi::Rust => Abi::Rust,
114-
Abi::System { unwind } if arch_x86 && os_windows && !has_c_varargs => {
115-
Abi::Stdcall { unwind }
116-
}
117-
Abi::System { unwind } if arch_arm && os_vexos => Abi::Aapcs { unwind },
118-
Abi::System { unwind } => Abi::C { unwind },
119-
120-
// arm
121-
Abi::Aapcs { unwind } if arch_arm_any => Abi::Aapcs { unwind },
122-
Abi::Aapcs { .. } => return None,
123-
124-
// x86
125-
Abi::Cdecl { unwind } if arch_x86 => Abi::C { unwind },
126-
Abi::Cdecl { unwind } => Abi::C { unwind },
127-
128-
Abi::Fastcall { unwind } if arch_x86 => Abi::Fastcall { unwind },
129-
Abi::Fastcall { unwind } if os_windows => Abi::C { unwind },
130-
Abi::Fastcall { .. } => return None,
131-
132-
Abi::Stdcall { unwind } if arch_x86 => Abi::Stdcall { unwind },
133-
Abi::Stdcall { unwind } if os_windows => Abi::C { unwind },
134-
Abi::Stdcall { .. } => return None,
135-
136-
Abi::Thiscall { unwind } if arch_x86 => Abi::Thiscall { unwind },
137-
Abi::Thiscall { .. } => return None,
138-
139-
Abi::Vectorcall { unwind } if arch_x86 || arch_x86_64 => Abi::Vectorcall { unwind },
140-
Abi::Vectorcall { .. } => return None,
141-
142-
Abi::SysV64 { unwind } if arch_x86_64 => Abi::SysV64 { unwind },
143-
Abi::Win64 { unwind } if arch_x86_64 => Abi::Win64 { unwind },
144-
Abi::SysV64 { .. } | Abi::Win64 { .. } => return None,
145-
};
146-
147-
Some(out)
148-
}
149-
}
150-
151-
impl Display for Abi {
152-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153-
write!(f, "{}", self.to_str())
154-
}
32+
};
15533
}
15634

157-
macro_rules! abi_kind_impl {
158-
(
159-
$t:ty => {
160-
$(
161-
$variant:ident $( { unwind: $uw:literal } )? => $tok:literal,
162-
)*
163-
}
164-
) => {
165-
impl $t {
166-
/// Returns the string representation of this ABI.
167-
#[must_use]
168-
pub const fn to_str(&self) -> &'static str {
169-
match self {
170-
$( Self::$variant $( { unwind: $uw } )? => $tok, )*
171-
}
172-
}
35+
// Universal
36+
define_abi_marker!(C, "C");
37+
define_abi_marker!(CUnwind, "C-unwind");
38+
define_abi_marker!(System, "system");
39+
define_abi_marker!(SystemUnwind, "system-unwind");
40+
41+
// Rust
42+
define_abi_marker!(Rust, "Rust");
43+
44+
// ARM
45+
define_abi_marker!(Aapcs, "aapcs");
46+
define_abi_marker!(AapcsUnwind, "aapcs-unwind");
47+
48+
// x86
49+
define_abi_marker!(Cdecl, "cdecl");
50+
define_abi_marker!(CdeclUnwind, "cdecl-unwind");
51+
define_abi_marker!(Stdcall, "stdcall");
52+
define_abi_marker!(StdcallUnwind, "stdcall-unwind");
53+
define_abi_marker!(Fastcall, "fastcall");
54+
define_abi_marker!(FastcallUnwind, "fastcall-unwind");
55+
define_abi_marker!(Thiscall, "thiscall");
56+
define_abi_marker!(ThiscallUnwind, "thiscall-unwind");
57+
define_abi_marker!(Vectorcall, "vectorcall");
58+
define_abi_marker!(VectorcallUnwind, "vectorcall-unwind");
59+
60+
// x86_64
61+
define_abi_marker!(SysV64, "sysv64");
62+
define_abi_marker!(SysV64Unwind, "sysv64-unwind");
63+
define_abi_marker!(Win64, "win64");
64+
define_abi_marker!(Win64Unwind, "win64-unwind");
65+
66+
/// Macro to convert an ABI string to the corrsponding [`Abi`] marker type.
67+
#[macro_export]
68+
macro_rules! abi {
69+
// Common
70+
("Rust") => {
71+
$crate::abi::Rust
72+
};
73+
("C") => {
74+
$crate::abi::C
75+
};
76+
("C-unwind") => {
77+
$crate::abi::CUnwind
78+
};
79+
("system") => {
80+
$crate::abi::System
81+
};
82+
("system-unwind") => {
83+
$crate::abi::SystemUnwind
84+
};
17385

174-
/// The same as the [`FromStr`] implementation, but (only!) for use in `const` contexts.
175-
#[must_use]
176-
pub const fn from_str_const(conv: &'static str) -> Option<Self> {
177-
$(
178-
if konst::eq_str(conv, $tok) {
179-
return Some(Self::$variant $( { unwind: $uw } )?);
180-
}
181-
)*
182-
None
183-
}
184-
}
86+
// ARM
87+
("aapcs") => {
88+
$crate::abi::Aapcs
89+
};
90+
("aapcs-unwind") => {
91+
$crate::abi::AapcsUnwind
92+
};
18593

186-
impl FromStr for $t {
187-
type Err = ();
94+
// x86
95+
("cdecl") => {
96+
$crate::abi::Cdecl
97+
};
98+
("cdecl-unwind") => {
99+
$crate::abi::CdeclUnwind
100+
};
101+
("stdcall") => {
102+
$crate::abi::Stdcall
103+
};
104+
("stdcall-unwind") => {
105+
$crate::abi::StdcallUnwind
106+
};
107+
("fastcall") => {
108+
$crate::abi::Fastcall
109+
};
110+
("fastcall-unwind") => {
111+
$crate::abi::FastcallUnwind
112+
};
113+
("thiscall") => {
114+
$crate::abi::Thiscall
115+
};
116+
("thiscall-unwind") => {
117+
$crate::abi::ThiscallUnwind
118+
};
119+
("vectorcall") => {
120+
$crate::abi::Vectorcall
121+
};
122+
("vectorcall-unwind") => {
123+
$crate::abi::VectorcallUnwind
124+
};
188125

189-
fn from_str(s: &str) -> Result<Self, Self::Err> {
190-
match s {
191-
$( $tok => Ok(Self::$variant $( { unwind: $uw } )?), )*
192-
_ => Err(()),
193-
}
194-
}
195-
}
126+
// x86_64
127+
("sysv64") => {
128+
$crate::abi::SysV64
129+
};
130+
("sysv64-unwind") => {
131+
$crate::abi::SysV64Unwind
132+
};
133+
("win64") => {
134+
$crate::abi::Win64
135+
};
136+
("win64-unwind") => {
137+
$crate::abi::Win64Unwind
196138
};
197139
}
198-
199-
abi_kind_impl!(Abi => {
200-
Rust => "Rust",
201-
202-
C { unwind: false } => "C",
203-
C { unwind: true } => "C-unwind",
204-
System { unwind: false } => "system",
205-
System { unwind: true } => "system-unwind",
206-
207-
Aapcs { unwind: false } => "aapcs",
208-
Aapcs { unwind: true } => "aapcs-unwind",
209-
210-
Cdecl { unwind: false } => "cdecl",
211-
Cdecl { unwind: true } => "cdecl-unwind",
212-
Stdcall { unwind: false } => "stdcall",
213-
Stdcall { unwind: true } => "stdcall-unwind",
214-
Fastcall { unwind: false } => "fastcall",
215-
Fastcall { unwind: true } => "fastcall-unwind",
216-
Thiscall { unwind: false } => "thiscall",
217-
Thiscall { unwind: true } => "thiscall-unwind",
218-
Vectorcall { unwind: false } => "vectorcall",
219-
Vectorcall { unwind: true } => "vectorcall-unwind",
220-
221-
SysV64 { unwind: false } => "sysv64",
222-
SysV64 { unwind: true } => "sysv64-unwind",
223-
Win64 { unwind: false } => "win64",
224-
Win64 { unwind: true } => "win64-unwind",
225-
});

0 commit comments

Comments
 (0)