about summary refs log tree commit diff
path: root/compiler/rustc_target/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_target/src')
-rw-r--r--compiler/rustc_target/src/callconv/arm.rs6
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs109
-rw-r--r--compiler/rustc_target/src/json.rs38
-rw-r--r--compiler/rustc_target/src/spec/abi_map.rs187
-rw-r--r--compiler/rustc_target/src/spec/json.rs30
-rw-r--r--compiler/rustc_target/src/spec/mod.rs122
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs5
-rw-r--r--compiler/rustc_target/src/target_features.rs26
8 files changed, 245 insertions, 278 deletions
diff --git a/compiler/rustc_target/src/callconv/arm.rs b/compiler/rustc_target/src/callconv/arm.rs
index 0a5dcc66347..70830fa07b6 100644
--- a/compiler/rustc_target/src/callconv/arm.rs
+++ b/compiler/rustc_target/src/callconv/arm.rs
@@ -1,6 +1,6 @@
-use rustc_abi::{HasDataLayout, TyAbiInterface};
+use rustc_abi::{ArmCall, CanonAbi, HasDataLayout, TyAbiInterface};
 
-use crate::callconv::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform};
+use crate::callconv::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
 use crate::spec::HasTargetSpec;
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
@@ -90,7 +90,7 @@ where
     // If this is a target with a hard-float ABI, and the function is not explicitly
     // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
     let vfp = cx.target_spec().llvm_target.ends_with("hf")
-        && fn_abi.conv != Conv::ArmAapcs
+        && fn_abi.conv != CanonAbi::Arm(ArmCall::Aapcs)
         && !fn_abi.c_variadic;
 
     if !fn_abi.ret.is_ignore() {
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 907614520a2..d2e49cea647 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -1,13 +1,12 @@
-use std::fmt::Display;
-use std::str::FromStr;
 use std::{fmt, iter};
 
 use rustc_abi::{
-    AddressSpace, Align, BackendRepr, ExternAbi, HasDataLayout, Primitive, Reg, RegKind, Scalar,
-    Size, TyAbiInterface, TyAndLayout,
+    AddressSpace, Align, BackendRepr, CanonAbi, ExternAbi, HasDataLayout, Primitive, Reg, RegKind,
+    Scalar, Size, TyAbiInterface, TyAndLayout,
 };
 use rustc_macros::HashStable_Generic;
 
+pub use crate::spec::AbiMap;
 use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, RustcAbi, WasmCAbi};
 
 mod aarch64;
@@ -530,41 +529,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum Conv {
-    // General language calling conventions, for which every target
-    // should have its own backend (e.g. LLVM) support.
-    C,
-    Rust,
-
-    Cold,
-    PreserveMost,
-    PreserveAll,
-
-    // Target-specific calling conventions.
-    ArmAapcs,
-    CCmseNonSecureCall,
-    CCmseNonSecureEntry,
-
-    Msp430Intr,
-
-    GpuKernel,
-
-    X86Fastcall,
-    X86Intr,
-    X86Stdcall,
-    X86ThisCall,
-    X86VectorCall,
-
-    X86_64SysV,
-    X86_64Win64,
-
-    AvrInterrupt,
-    AvrNonBlockingInterrupt,
-
-    RiscvInterrupt { kind: RiscvInterruptKind },
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum RiscvInterruptKind {
     Machine,
     Supervisor,
@@ -605,7 +569,7 @@ pub struct FnAbi<'a, Ty> {
     /// This can be used to know whether an argument is variadic or not.
     pub fixed_count: u32,
     /// The calling convention of this function.
-    pub conv: Conv,
+    pub conv: CanonAbi,
     /// Indicates if an unwind may happen across a call to this function.
     pub can_unwind: bool,
 }
@@ -696,7 +660,6 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "sparc" => sparc::compute_abi_info(cx, self),
             "sparc64" => sparc64::compute_abi_info(cx, self),
             "nvptx64" => {
-                let abi = cx.target_spec().adjust_abi(abi, self.c_variadic);
                 if abi == ExternAbi::PtxKernel || abi == ExternAbi::GpuKernel {
                     nvptx64::compute_ptx_kernel_abi_info(cx, self)
                 } else {
@@ -863,70 +826,6 @@ impl<'a, Ty> FnAbi<'a, Ty> {
     }
 }
 
-impl FromStr for Conv {
-    type Err = String;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "C" => Ok(Conv::C),
-            "Rust" => Ok(Conv::Rust),
-            "RustCold" => Ok(Conv::Rust),
-            "ArmAapcs" => Ok(Conv::ArmAapcs),
-            "CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall),
-            "CCmseNonSecureEntry" => Ok(Conv::CCmseNonSecureEntry),
-            "Msp430Intr" => Ok(Conv::Msp430Intr),
-            "X86Fastcall" => Ok(Conv::X86Fastcall),
-            "X86Intr" => Ok(Conv::X86Intr),
-            "X86Stdcall" => Ok(Conv::X86Stdcall),
-            "X86ThisCall" => Ok(Conv::X86ThisCall),
-            "X86VectorCall" => Ok(Conv::X86VectorCall),
-            "X86_64SysV" => Ok(Conv::X86_64SysV),
-            "X86_64Win64" => Ok(Conv::X86_64Win64),
-            "GpuKernel" => Ok(Conv::GpuKernel),
-            "AvrInterrupt" => Ok(Conv::AvrInterrupt),
-            "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt),
-            "RiscvInterrupt(machine)" => {
-                Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine })
-            }
-            "RiscvInterrupt(supervisor)" => {
-                Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor })
-            }
-            _ => Err(format!("'{s}' is not a valid value for entry function call convention.")),
-        }
-    }
-}
-
-fn conv_to_externabi(conv: &Conv) -> ExternAbi {
-    match conv {
-        Conv::C => ExternAbi::C { unwind: false },
-        Conv::Rust => ExternAbi::Rust,
-        Conv::PreserveMost => ExternAbi::RustCold,
-        Conv::ArmAapcs => ExternAbi::Aapcs { unwind: false },
-        Conv::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall,
-        Conv::CCmseNonSecureEntry => ExternAbi::CCmseNonSecureEntry,
-        Conv::Msp430Intr => ExternAbi::Msp430Interrupt,
-        Conv::GpuKernel => ExternAbi::GpuKernel,
-        Conv::X86Fastcall => ExternAbi::Fastcall { unwind: false },
-        Conv::X86Intr => ExternAbi::X86Interrupt,
-        Conv::X86Stdcall => ExternAbi::Stdcall { unwind: false },
-        Conv::X86ThisCall => ExternAbi::Thiscall { unwind: false },
-        Conv::X86VectorCall => ExternAbi::Vectorcall { unwind: false },
-        Conv::X86_64SysV => ExternAbi::SysV64 { unwind: false },
-        Conv::X86_64Win64 => ExternAbi::Win64 { unwind: false },
-        Conv::AvrInterrupt => ExternAbi::AvrInterrupt,
-        Conv::AvrNonBlockingInterrupt => ExternAbi::AvrNonBlockingInterrupt,
-        Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine } => ExternAbi::RiscvInterruptM,
-        Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor } => ExternAbi::RiscvInterruptS,
-        Conv::Cold | Conv::PreserveAll => unreachable!(),
-    }
-}
-
-impl Display for Conv {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", conv_to_externabi(self))
-    }
-}
-
 // Some types are used a lot. Make sure they don't unintentionally get bigger.
 #[cfg(target_pointer_width = "64")]
 mod size_asserts {
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index 8d6f8f4c6f6..4fcc477921b 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -92,38 +92,6 @@ impl<A: ToJson> ToJson for Option<A> {
     }
 }
 
-impl ToJson for crate::callconv::Conv {
-    fn to_json(&self) -> Json {
-        let buf: String;
-        let s = match self {
-            Self::C => "C",
-            Self::Rust => "Rust",
-            Self::Cold => "Cold",
-            Self::PreserveMost => "PreserveMost",
-            Self::PreserveAll => "PreserveAll",
-            Self::ArmAapcs => "ArmAapcs",
-            Self::CCmseNonSecureCall => "CCmseNonSecureCall",
-            Self::CCmseNonSecureEntry => "CCmseNonSecureEntry",
-            Self::Msp430Intr => "Msp430Intr",
-            Self::X86Fastcall => "X86Fastcall",
-            Self::X86Intr => "X86Intr",
-            Self::X86Stdcall => "X86Stdcall",
-            Self::X86ThisCall => "X86ThisCall",
-            Self::X86VectorCall => "X86VectorCall",
-            Self::X86_64SysV => "X86_64SysV",
-            Self::X86_64Win64 => "X86_64Win64",
-            Self::GpuKernel => "GpuKernel",
-            Self::AvrInterrupt => "AvrInterrupt",
-            Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt",
-            Self::RiscvInterrupt { kind } => {
-                buf = format!("RiscvInterrupt({})", kind.as_str());
-                &buf
-            }
-        };
-        Json::String(s.to_owned())
-    }
-}
-
 impl ToJson for TargetMetadata {
     fn to_json(&self) -> Json {
         json!({
@@ -140,3 +108,9 @@ impl ToJson for rustc_abi::Endian {
         self.as_str().to_json()
     }
 }
+
+impl ToJson for rustc_abi::CanonAbi {
+    fn to_json(&self) -> Json {
+        self.to_string().to_json()
+    }
+}
diff --git a/compiler/rustc_target/src/spec/abi_map.rs b/compiler/rustc_target/src/spec/abi_map.rs
new file mode 100644
index 00000000000..d9101f79f04
--- /dev/null
+++ b/compiler/rustc_target/src/spec/abi_map.rs
@@ -0,0 +1,187 @@
+use rustc_abi::{ArmCall, CanonAbi, ExternAbi, InterruptKind, X86Call};
+
+use crate::spec::Target;
+
+/// Mapping for ExternAbi to CanonAbi according to a Target
+///
+/// A maybe-transitional structure circa 2025 for hosting future experiments in
+/// encapsulating arch-specific ABI lowering details to make them more testable.
+#[derive(Clone, Debug)]
+pub struct AbiMap {
+    arch: Arch,
+    os: OsKind,
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum AbiMapping {
+    /// this ABI is exactly mapped for this platform
+    Direct(CanonAbi),
+    /// we don't yet warn on this, but we will
+    Deprecated(CanonAbi),
+    Invalid,
+}
+
+impl AbiMapping {
+    pub fn into_option(self) -> Option<CanonAbi> {
+        match self {
+            Self::Direct(abi) | Self::Deprecated(abi) => Some(abi),
+            Self::Invalid => None,
+        }
+    }
+
+    pub fn unwrap(self) -> CanonAbi {
+        self.into_option().unwrap()
+    }
+
+    pub fn is_mapped(self) -> bool {
+        self.into_option().is_some()
+    }
+}
+
+impl AbiMap {
+    pub fn from_target(target: &Target) -> Self {
+        // the purpose of this little exercise is to force listing what affects these mappings
+        let arch = match &*target.arch {
+            "aarch64" => Arch::Aarch64,
+            "amdgpu" => Arch::Amdgpu,
+            "arm" if target.llvm_target.starts_with("thumbv8m") => Arch::Arm(ArmVer::ThumbV8M),
+            "arm" => Arch::Arm(ArmVer::Other),
+            "avr" => Arch::Avr,
+            "msp430" => Arch::Msp430,
+            "nvptx64" => Arch::Nvptx,
+            "riscv32" | "riscv64" => Arch::Riscv,
+            "x86" => Arch::X86,
+            "x86_64" => Arch::X86_64,
+            _ => Arch::Other,
+        };
+        let os = if target.is_like_windows { OsKind::Windows } else { OsKind::Other };
+        AbiMap { arch, os }
+    }
+
+    pub fn canonize_abi(&self, extern_abi: ExternAbi, has_c_varargs: bool) -> AbiMapping {
+        let AbiMap { os, arch } = *self;
+
+        let canon_abi = match (extern_abi, arch) {
+            // infallible lowerings
+            (ExternAbi::C { .. }, _) => CanonAbi::C,
+            (ExternAbi::Rust | ExternAbi::RustCall, _) => CanonAbi::Rust,
+            (ExternAbi::Unadjusted, _) => CanonAbi::C,
+
+            (ExternAbi::RustCold, _) if self.os == OsKind::Windows => CanonAbi::Rust,
+            (ExternAbi::RustCold, _) => CanonAbi::RustCold,
+
+            (ExternAbi::System { .. }, Arch::X86) if os == OsKind::Windows && !has_c_varargs => {
+                CanonAbi::X86(X86Call::Stdcall)
+            }
+            (ExternAbi::System { .. }, _) => CanonAbi::C,
+
+            // fallible lowerings
+            (ExternAbi::EfiApi, Arch::Arm(..)) => CanonAbi::Arm(ArmCall::Aapcs),
+            (ExternAbi::EfiApi, Arch::X86_64) => CanonAbi::X86(X86Call::Win64),
+            (ExternAbi::EfiApi, Arch::Aarch64 | Arch::Riscv | Arch::X86) => CanonAbi::C,
+            (ExternAbi::EfiApi, _) => return AbiMapping::Invalid,
+
+            (ExternAbi::Aapcs { .. }, Arch::Arm(..)) => CanonAbi::Arm(ArmCall::Aapcs),
+            (ExternAbi::Aapcs { .. }, _) => return AbiMapping::Invalid,
+
+            (ExternAbi::CCmseNonSecureCall, Arch::Arm(ArmVer::ThumbV8M)) => {
+                CanonAbi::Arm(ArmCall::CCmseNonSecureCall)
+            }
+            (ExternAbi::CCmseNonSecureEntry, Arch::Arm(ArmVer::ThumbV8M)) => {
+                CanonAbi::Arm(ArmCall::CCmseNonSecureEntry)
+            }
+            (ExternAbi::CCmseNonSecureCall | ExternAbi::CCmseNonSecureEntry, ..) => {
+                return AbiMapping::Invalid;
+            }
+
+            (ExternAbi::Cdecl { .. }, Arch::X86) => CanonAbi::C,
+            (ExternAbi::Cdecl { .. }, _) => return AbiMapping::Deprecated(CanonAbi::C),
+
+            (ExternAbi::Fastcall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Fastcall),
+            (ExternAbi::Fastcall { .. }, _) if os == OsKind::Windows => {
+                return AbiMapping::Deprecated(CanonAbi::C);
+            }
+            (ExternAbi::Fastcall { .. }, _) => return AbiMapping::Invalid,
+
+            (ExternAbi::Stdcall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Stdcall),
+            (ExternAbi::Stdcall { .. }, _) if os == OsKind::Windows => {
+                return AbiMapping::Deprecated(CanonAbi::C);
+            }
+            (ExternAbi::Stdcall { .. }, _) => return AbiMapping::Invalid,
+
+            (ExternAbi::Thiscall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Thiscall),
+            (ExternAbi::Thiscall { .. }, _) => return AbiMapping::Invalid,
+
+            (ExternAbi::Vectorcall { .. }, Arch::X86 | Arch::X86_64) => {
+                CanonAbi::X86(X86Call::Vectorcall)
+            }
+            (ExternAbi::Vectorcall { .. }, _) if os == OsKind::Windows => {
+                return AbiMapping::Deprecated(CanonAbi::C);
+            }
+            (ExternAbi::Vectorcall { .. }, _) => return AbiMapping::Invalid,
+
+            (ExternAbi::SysV64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::SysV64),
+            (ExternAbi::Win64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::Win64),
+            (ExternAbi::SysV64 { .. } | ExternAbi::Win64 { .. }, _) => return AbiMapping::Invalid,
+
+            (ExternAbi::PtxKernel, Arch::Nvptx) => CanonAbi::GpuKernel,
+            (ExternAbi::GpuKernel, Arch::Amdgpu | Arch::Nvptx) => CanonAbi::GpuKernel,
+            (ExternAbi::PtxKernel | ExternAbi::GpuKernel, _) => return AbiMapping::Invalid,
+
+            (ExternAbi::AvrInterrupt, Arch::Avr) => CanonAbi::Interrupt(InterruptKind::Avr),
+            (ExternAbi::AvrNonBlockingInterrupt, Arch::Avr) => {
+                CanonAbi::Interrupt(InterruptKind::AvrNonBlocking)
+            }
+            (ExternAbi::Msp430Interrupt, Arch::Msp430) => {
+                CanonAbi::Interrupt(InterruptKind::Msp430)
+            }
+            (ExternAbi::RiscvInterruptM, Arch::Riscv) => {
+                CanonAbi::Interrupt(InterruptKind::RiscvMachine)
+            }
+            (ExternAbi::RiscvInterruptS, Arch::Riscv) => {
+                CanonAbi::Interrupt(InterruptKind::RiscvSupervisor)
+            }
+            (ExternAbi::X86Interrupt, Arch::X86 | Arch::X86_64) => {
+                CanonAbi::Interrupt(InterruptKind::X86)
+            }
+            (
+                ExternAbi::AvrInterrupt
+                | ExternAbi::AvrNonBlockingInterrupt
+                | ExternAbi::Msp430Interrupt
+                | ExternAbi::RiscvInterruptM
+                | ExternAbi::RiscvInterruptS
+                | ExternAbi::X86Interrupt,
+                _,
+            ) => return AbiMapping::Invalid,
+        };
+
+        AbiMapping::Direct(canon_abi)
+    }
+}
+
+#[derive(Debug, PartialEq, Copy, Clone)]
+enum Arch {
+    Aarch64,
+    Amdgpu,
+    Arm(ArmVer),
+    Avr,
+    Msp430,
+    Nvptx,
+    Riscv,
+    X86,
+    X86_64,
+    /// Architectures which don't need other considerations for ABI lowering
+    Other,
+}
+
+#[derive(Debug, PartialEq, Copy, Clone)]
+enum OsKind {
+    Windows,
+    Other,
+}
+
+#[derive(Debug, PartialEq, Copy, Clone)]
+enum ArmVer {
+    ThumbV8M,
+    Other,
+}
diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs
index be71da76b4a..54b06d9f9b4 100644
--- a/compiler/rustc_target/src/spec/json.rs
+++ b/compiler/rustc_target/src/spec/json.rs
@@ -2,10 +2,12 @@ use std::borrow::Cow;
 use std::collections::BTreeMap;
 use std::str::FromStr;
 
+use rustc_abi::ExternAbi;
 use serde_json::Value;
 
 use super::{Target, TargetKind, TargetOptions, TargetWarnings};
 use crate::json::{Json, ToJson};
+use crate::spec::AbiMap;
 
 impl Target {
     /// Loads a target descriptor from a JSON object.
@@ -515,18 +517,6 @@ impl Target {
                     }
                 }
             } );
-            ($key_name:ident, Conv) => ( {
-                let name = (stringify!($key_name)).replace("_", "-");
-                obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
-                    match super::Conv::from_str(s) {
-                        Ok(c) => {
-                            base.$key_name = c;
-                            Some(Ok(()))
-                        }
-                        Err(e) => Some(Err(e))
-                    }
-                })).unwrap_or(Ok(()))
-            } );
         }
 
         if let Some(j) = obj.remove("target-endian") {
@@ -660,9 +650,23 @@ impl Target {
         key!(supports_stack_protector, bool);
         key!(small_data_threshold_support, SmallDataThresholdSupport)?;
         key!(entry_name);
-        key!(entry_abi, Conv)?;
         key!(supports_xray, bool);
 
+        // we're going to run `update_from_cli`, but that won't change the target's AbiMap
+        // FIXME: better factor the Target definition so we enforce this on a type level
+        let abi_map = AbiMap::from_target(&base);
+
+        if let Some(abi_str) = obj.remove("entry-abi") {
+            if let Json::String(abi_str) = abi_str {
+                match abi_str.parse::<ExternAbi>() {
+                    Ok(abi) => base.options.entry_abi = abi_map.canonize_abi(abi, false).unwrap(),
+                    Err(_) => return Err(format!("{abi_str} is not a valid ExternAbi")),
+                }
+            } else {
+                incorrect_type.push("entry-abi".to_owned())
+            }
+        }
+
         base.update_from_cli();
         base.check_consistency(TargetKind::Json)?;
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 303be54a6d7..6529c2d72c8 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -43,7 +43,7 @@ use std::str::FromStr;
 use std::{fmt, io};
 
 use rustc_abi::{
-    Align, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
+    Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
 };
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_fs_util::try_canonicalize;
@@ -53,15 +53,16 @@ use rustc_span::{Symbol, kw, sym};
 use serde_json::Value;
 use tracing::debug;
 
-use crate::callconv::Conv;
 use crate::json::{Json, ToJson};
 use crate::spec::crt_objects::CrtObjects;
 
 pub mod crt_objects;
 
+mod abi_map;
 mod base;
 mod json;
 
+pub use abi_map::AbiMap;
 pub use base::apple;
 pub use base::avr::ef_avr_arch;
 
@@ -2655,9 +2656,9 @@ pub struct TargetOptions {
     /// Default value is "main"
     pub entry_name: StaticCow<str>,
 
-    /// The ABI of entry function.
-    /// Default value is `Conv::C`, i.e. C call convention
-    pub entry_abi: Conv,
+    /// The ABI of the entry function.
+    /// Default value is `CanonAbi::C`
+    pub entry_abi: CanonAbi,
 
     /// Whether the target supports XRay instrumentation.
     pub supports_xray: bool,
@@ -2888,7 +2889,7 @@ impl Default for TargetOptions {
             generate_arange_section: true,
             supports_stack_protector: true,
             entry_name: "main".into(),
-            entry_abi: Conv::C,
+            entry_abi: CanonAbi::C,
             supports_xray: false,
             small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
         }
@@ -2914,114 +2915,9 @@ impl DerefMut for Target {
 }
 
 impl Target {
-    /// Given a function ABI, turn it into the correct ABI for this target.
-    pub fn adjust_abi(&self, abi: ExternAbi, c_variadic: bool) -> ExternAbi {
-        use ExternAbi::*;
-        match abi {
-            // On Windows, `extern "system"` behaves like msvc's `__stdcall`.
-            // `__stdcall` only applies on x86 and on non-variadic functions:
-            // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
-            System { unwind } => {
-                if self.is_like_windows && self.arch == "x86" && !c_variadic {
-                    Stdcall { unwind }
-                } else {
-                    C { unwind }
-                }
-            }
-
-            EfiApi => {
-                if self.arch == "arm" {
-                    Aapcs { unwind: false }
-                } else if self.arch == "x86_64" {
-                    Win64 { unwind: false }
-                } else {
-                    C { unwind: false }
-                }
-            }
-
-            // See commentary in `is_abi_supported`.
-            Stdcall { unwind } | Thiscall { unwind } | Fastcall { unwind } => {
-                if self.arch == "x86" { abi } else { C { unwind } }
-            }
-            Vectorcall { unwind } => {
-                if ["x86", "x86_64"].contains(&&*self.arch) {
-                    abi
-                } else {
-                    C { unwind }
-                }
-            }
-
-            // The Windows x64 calling convention we use for `extern "Rust"`
-            // <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions#register-volatility-and-preservation>
-            // expects the callee to save `xmm6` through `xmm15`, but `PreserveMost`
-            // (that we use by default for `extern "rust-cold"`) doesn't save any of those.
-            // So to avoid bloating callers, just use the Rust convention here.
-            RustCold if self.is_like_windows && self.arch == "x86_64" => Rust,
-
-            abi => abi,
-        }
-    }
-
     pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
-        use ExternAbi::*;
-        match abi {
-            Rust | C { .. } | System { .. } | RustCall | Unadjusted | Cdecl { .. } | RustCold => {
-                true
-            }
-            EfiApi => {
-                ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..])
-            }
-            X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
-            Aapcs { .. } => "arm" == self.arch,
-            CCmseNonSecureCall | CCmseNonSecureEntry => {
-                ["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"]
-                    .contains(&&self.llvm_target[..])
-            }
-            Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
-            PtxKernel => self.arch == "nvptx64",
-            GpuKernel => ["amdgpu", "nvptx64"].contains(&&self.arch[..]),
-            Msp430Interrupt => self.arch == "msp430",
-            RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]),
-            AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
-            Thiscall { .. } => self.arch == "x86",
-            // On windows these fall-back to platform native calling convention (C) when the
-            // architecture is not supported.
-            //
-            // This is I believe a historical accident that has occurred as part of Microsoft
-            // striving to allow most of the code to "just" compile when support for 64-bit x86
-            // was added and then later again, when support for ARM architectures was added.
-            //
-            // This is well documented across MSDN. Support for this in Rust has been added in
-            // #54576. This makes much more sense in context of Microsoft's C++ than it does in
-            // Rust, but there isn't much leeway remaining here to change it back at the time this
-            // comment has been written.
-            //
-            // Following are the relevant excerpts from the MSDN documentation.
-            //
-            // > The __vectorcall calling convention is only supported in native code on x86 and
-            // x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above.
-            // > ...
-            // > On ARM machines, __vectorcall is accepted and ignored by the compiler.
-            //
-            // -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160
-            //
-            // > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler;
-            //
-            // -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160
-            //
-            // > In most cases, keywords or compiler switches that specify an unsupported
-            // > convention on a particular platform are ignored, and the platform default
-            // > convention is used.
-            //
-            // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
-            Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true,
-            // Outside of Windows we want to only support these calling conventions for the
-            // architectures for which these calling conventions are actually well defined.
-            Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
-            Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
-            // Reject these calling conventions everywhere else.
-            Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => false,
-        }
+        let abi_map = AbiMap::from_target(self);
+        abi_map.canonize_abi(abi, false).is_mapped()
     }
 
     /// Minimum integer size in bits that this target can perform atomic
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
index 07f853dacaf..0cf6a879462 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
@@ -5,7 +5,8 @@
 // The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
 // LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
 
-use crate::callconv::Conv;
+use rustc_abi::{CanonAbi, X86Call};
+
 use crate::spec::{RustcAbi, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
@@ -13,7 +14,7 @@ pub(crate) fn target() -> Target {
     base.cpu = "x86-64".into();
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
-    base.entry_abi = Conv::X86_64Win64;
+    base.entry_abi = CanonAbi::X86(X86Call::Win64);
 
     // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
     // enable these CPU features explicitly before their first use, otherwise their instructions
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 576c9bd6b57..682c4c5068f 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -710,29 +710,35 @@ static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
+#[rustfmt::skip]
 const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("backchain", Unstable(sym::s390x_target_feature), &[]),
+    ("concurrent-functions", Unstable(sym::s390x_target_feature), &[]),
     ("deflate-conversion", Unstable(sym::s390x_target_feature), &[]),
     ("enhanced-sort", Unstable(sym::s390x_target_feature), &[]),
     ("guarded-storage", Unstable(sym::s390x_target_feature), &[]),
     ("high-word", Unstable(sym::s390x_target_feature), &[]),
+    // LLVM does not define message-security-assist-extension versions 1, 2, 6, 10 and 11.
+    ("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]),
+    ("message-security-assist-extension3", Unstable(sym::s390x_target_feature), &[]),
+    ("message-security-assist-extension4", Unstable(sym::s390x_target_feature), &[]),
+    ("message-security-assist-extension5", Unstable(sym::s390x_target_feature), &[]),
+    ("message-security-assist-extension8", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3"]),
+    ("message-security-assist-extension9", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3", "message-security-assist-extension4"]),
+    ("miscellaneous-extensions-2", Unstable(sym::s390x_target_feature), &[]),
+    ("miscellaneous-extensions-3", Unstable(sym::s390x_target_feature), &[]),
+    ("miscellaneous-extensions-4", Unstable(sym::s390x_target_feature), &[]),
     ("nnp-assist", Unstable(sym::s390x_target_feature), &["vector"]),
     ("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
     ("vector", Unstable(sym::s390x_target_feature), &[]),
     ("vector-enhancements-1", Unstable(sym::s390x_target_feature), &["vector"]),
     ("vector-enhancements-2", Unstable(sym::s390x_target_feature), &["vector-enhancements-1"]),
+    ("vector-enhancements-3", Unstable(sym::s390x_target_feature), &["vector-enhancements-2"]),
     ("vector-packed-decimal", Unstable(sym::s390x_target_feature), &["vector"]),
-    (
-        "vector-packed-decimal-enhancement",
-        Unstable(sym::s390x_target_feature),
-        &["vector-packed-decimal"],
-    ),
-    (
-        "vector-packed-decimal-enhancement-2",
-        Unstable(sym::s390x_target_feature),
-        &["vector-packed-decimal-enhancement"],
-    ),
+    ("vector-packed-decimal-enhancement", Unstable(sym::s390x_target_feature), &["vector-packed-decimal"]),
+    ("vector-packed-decimal-enhancement-2", Unstable(sym::s390x_target_feature), &["vector-packed-decimal-enhancement"]),
+    ("vector-packed-decimal-enhancement-3", Unstable(sym::s390x_target_feature), &["vector-packed-decimal-enhancement-2"]),
     // tidy-alphabetical-end
 ];