about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_abi/src/extern_abi.rs141
-rw-r--r--compiler/rustc_abi/src/extern_abi/tests.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/stability.rs9
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs3
4 files changed, 140 insertions, 21 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())
     }
 }
diff --git a/compiler/rustc_abi/src/extern_abi/tests.rs b/compiler/rustc_abi/src/extern_abi/tests.rs
index 72c0f183d50..44ea58d47c2 100644
--- a/compiler/rustc_abi/src/extern_abi/tests.rs
+++ b/compiler/rustc_abi/src/extern_abi/tests.rs
@@ -27,3 +27,11 @@ fn indices_are_correct() {
         assert_eq!(i, abi_data.abi.index());
     }
 }
+
+#[test]
+fn guarantee_lexicographic_ordering() {
+    let abis = ExternAbi::ALL_VARIANTS;
+    let mut sorted_abis = abis.to_vec();
+    sorted_abis.sort_unstable();
+    assert_eq!(abis, sorted_abis);
+}
diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs
index e7c166850a4..14410600fab 100644
--- a/compiler/rustc_ast_lowering/src/stability.rs
+++ b/compiler/rustc_ast_lowering/src/stability.rs
@@ -54,17 +54,12 @@ enum GateReason {
 impl fmt::Display for UnstableAbi {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let Self { abi, .. } = self;
-        let name = abi.to_string();
-        let name = name.trim_matches('"');
         match self.explain {
             GateReason::Experimental => {
-                write!(f, r#"the extern "{name}" ABI is experimental and subject to change"#)
+                write!(f, "the extern {abi} ABI is experimental and subject to change")
             }
             GateReason::ImplDetail => {
-                write!(
-                    f,
-                    r#"the extern "{name}" ABI is an implementation detail and perma-unstable"#
-                )
+                write!(f, "the extern {abi} ABI is an implementation detail and perma-unstable")
             }
         }
     }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 6efd11a8c3c..2bcc33241df 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -747,8 +747,7 @@ fn print_crate_info(
                 }
             }
             CallingConventions => {
-                let mut calling_conventions = rustc_abi::all_names();
-                calling_conventions.sort_unstable();
+                let calling_conventions = rustc_abi::all_names();
                 println_info!("{}", calling_conventions.join("\n"));
             }
             RelocationModels