diff options
| author | Jubilee Young <workingjubilee@gmail.com> | 2025-02-10 03:57:32 -0800 |
|---|---|---|
| committer | Jubilee Young <workingjubilee@gmail.com> | 2025-02-11 20:18:01 -0800 |
| commit | 8abff35b41b8de89da35ab851f931d6a582f7670 (patch) | |
| tree | 9fc31fe88da020be50493a9402cd87796cf35b33 /compiler/rustc_abi/src/extern_abi.rs | |
| parent | 038c183d5f94b5ca3bed351374b01be4b1c90176 (diff) | |
| download | rust-8abff35b41b8de89da35ab851f931d6a582f7670.tar.gz rust-8abff35b41b8de89da35ab851f931d6a582f7670.zip | |
compiler: compare and hash ExternAbi like its string
Directly map each ExternAbi variant to its string and back again. This has a few advantages: - By making the ABIs compare equal to their strings, we can easily lexicographically sort them and use that sorted slice at runtime. - We no longer need a workaround to make sure the hashes remain stable, as they already naturally are (by being the hashes of unique strings). - The compiler can carry around less &str wide pointers
Diffstat (limited to 'compiler/rustc_abi/src/extern_abi.rs')
| -rw-r--r-- | compiler/rustc_abi/src/extern_abi.rs | 141 |
1 files changed, 129 insertions, 12 deletions
diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index a4dc87247a0..2355c64cfc9 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -1,15 +1,20 @@ +use std::cmp::Ordering; use std::fmt; +use std::hash::{Hash, Hasher}; +use std::str::FromStr; #[cfg(feature = "nightly")] -use rustc_macros::{Decodable, Encodable, HashStable_Generic}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd}; +#[cfg(feature = "nightly")] +use rustc_macros::{Decodable, Encodable}; #[cfg(test)] mod tests; use ExternAbi as Abi; -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)] -#[cfg_attr(feature = "nightly", derive(HashStable_Generic, Encodable, Decodable))] +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))] pub enum ExternAbi { // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the // hashing tests. These are used in many places, so giving them stable values reduces test @@ -69,7 +74,123 @@ pub enum ExternAbi { RiscvInterruptS, } -impl Abi { +macro_rules! abi_impls { + ($e_name:ident = { + $($variant:ident $({ unwind: $uw:literal })? =><= $tok:literal,)* + }) => { + impl $e_name { + pub const ALL_VARIANTS: &[Self] = &[ + $($e_name::$variant $({ unwind: $uw })*,)* + ]; + pub const fn as_str(&self) -> &'static str { + match self { + $($e_name::$variant $( { unwind: $uw } )* => $tok,)* + } + } + } + + impl ::core::str::FromStr for $e_name { + type Err = AbiFromStrErr; + fn from_str(s: &str) -> Result<$e_name, Self::Err> { + match s { + $($tok => Ok($e_name::$variant $({ unwind: $uw })*),)* + _ => Err(AbiFromStrErr::Unknown), + } + } + } + } +} + +pub enum AbiFromStrErr { + Unknown, +} + +abi_impls! { + ExternAbi = { + C { unwind: false } =><= "C", + CCmseNonSecureCall =><= "C-cmse-nonsecure-call", + CCmseNonSecureEntry =><= "C-cmse-nonsecure-entry", + C { unwind: true } =><= "C-unwind", + Rust =><= "Rust", + Aapcs { unwind: false } =><= "aapcs", + Aapcs { unwind: true } =><= "aapcs-unwind", + AvrInterrupt =><= "avr-interrupt", + AvrNonBlockingInterrupt =><= "avr-non-blocking-interrupt", + Cdecl { unwind: false } =><= "cdecl", + Cdecl { unwind: true } =><= "cdecl-unwind", + EfiApi =><= "efiapi", + Fastcall { unwind: false } =><= "fastcall", + Fastcall { unwind: true } =><= "fastcall-unwind", + GpuKernel =><= "gpu-kernel", + Msp430Interrupt =><= "msp430-interrupt", + PtxKernel =><= "ptx-kernel", + RiscvInterruptM =><= "riscv-interrupt-m", + RiscvInterruptS =><= "riscv-interrupt-s", + RustCall =><= "rust-call", + RustCold =><= "rust-cold", + RustIntrinsic =><= "rust-intrinsic", + Stdcall { unwind: false } =><= "stdcall", + Stdcall { unwind: true } =><= "stdcall-unwind", + System { unwind: false } =><= "system", + System { unwind: true } =><= "system-unwind", + SysV64 { unwind: false } =><= "sysv64", + SysV64 { unwind: true } =><= "sysv64-unwind", + Thiscall { unwind: false } =><= "thiscall", + Thiscall { unwind: true } =><= "thiscall-unwind", + Unadjusted =><= "unadjusted", + Vectorcall { unwind: false } =><= "vectorcall", + Vectorcall { unwind: true } =><= "vectorcall-unwind", + Win64 { unwind: false } =><= "win64", + Win64 { unwind: true } =><= "win64-unwind", + X86Interrupt =><= "x86-interrupt", + } +} + +impl Ord for ExternAbi { + fn cmp(&self, rhs: &Self) -> Ordering { + self.as_str().cmp(rhs.as_str()) + } +} + +impl PartialOrd for ExternAbi { + fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { + Some(self.cmp(rhs)) + } +} + +impl PartialEq for ExternAbi { + fn eq(&self, rhs: &Self) -> bool { + self.cmp(rhs) == Ordering::Equal + } +} + +impl Eq for ExternAbi {} + +impl Hash for ExternAbi { + fn hash<H: Hasher>(&self, state: &mut H) { + self.as_str().hash(state); + // double-assurance of a prefix breaker + u32::from_be_bytes(*b"ABI\0").hash(state); + } +} + +#[cfg(feature = "nightly")] +impl<C> HashStable<C> for ExternAbi { + #[inline] + fn hash_stable(&self, _: &mut C, hasher: &mut StableHasher) { + Hash::hash(self, hasher); + } +} + +#[cfg(feature = "nightly")] +impl StableOrd for ExternAbi { + const CAN_USE_UNSTABLE_SORT: bool = true; + + // because each ABI is hashed like a string, there is no possible instability + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); +} + +impl ExternAbi { pub fn supports_varargs(self) -> bool { // * C and Cdecl obviously support varargs. // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs. @@ -145,15 +266,11 @@ pub const AbiDatas: &[AbiData] = &[ pub struct AbiUnsupported {} /// Returns the ABI with the given name (if any). pub fn lookup(name: &str) -> Result<Abi, AbiUnsupported> { - AbiDatas - .iter() - .find(|abi_data| name == abi_data.name) - .map(|&x| x.abi) - .ok_or_else(|| AbiUnsupported {}) + ExternAbi::from_str(name).map_err(|_| AbiUnsupported {}) } pub fn all_names() -> Vec<&'static str> { - AbiDatas.iter().map(|d| d.name).collect() + ExternAbi::ALL_VARIANTS.iter().map(|abi| abi.as_str()).collect() } impl Abi { @@ -229,8 +346,8 @@ impl Abi { } } -impl fmt::Display for Abi { +impl fmt::Display for ExternAbi { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "\"{}\"", self.name()) + write!(f, "\"{}\"", self.as_str()) } } |
