1use std::fmt;23#[cfg(feature = "nightly")]4use rustc_macros::StableHash;56use crate::ExternAbi;78/// Calling convention to determine codegen9///10/// CanonAbi erases certain distinctions ExternAbi preserves, but remains target-dependent.11/// There are still both target-specific variants and aliasing variants, though much fewer.12/// The reason for this step is the frontend may wish to show an ExternAbi but implement that ABI13/// using a different ABI than the string per se, or describe irrelevant differences, e.g.14/// - extern "system"15/// - extern "cdecl"16/// - extern "C-unwind"17/// In that sense, this erases mere syntactic distinctions to create a canonical *directive*,18/// rather than picking the "actual" ABI.19#[derive(Copy, Clone, Debug)]20#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]21#[cfg_attr(feature = "nightly", derive(StableHash))]22pub enum CanonAbi {23 // NOTE: the use of nested variants for some ABIs is for many targets they don't matter,24 // and this pushes the complexity of their reasoning to target-specific code,25 // allowing a `match` to easily exhaustively ignore these subcategories of variants.26 // Otherwise it is very tempting to avoid matching exhaustively!27 C,28 Rust,29 RustCold,30 RustPreserveNone,3132 /// An ABI that rustc does not know how to call or define.33 Custom,3435 /// ABIs relevant to 32-bit Arm targets36 Arm(ArmCall),37 /// ABI relevant to GPUs: the entry point for a GPU kernel38 GpuKernel,3940 /// ABIs relevant to bare-metal interrupt targets41 // FIXME(workingjubilee): a particular reason for this nesting is we might not need these?42 // interrupt ABIs should have the same properties:43 // - uncallable by Rust calls, as LLVM rejects it in most cases44 // - uses a preserve-all-registers *callee* convention45 // - should always return `-> !` (effectively... it can't use normal `ret`)46 // what differs between targets is47 // - allowed arguments: x86 differs slightly, having 2-3 arguments which are handled magically48 // - may need special prologues/epilogues for some interrupts, without affecting "call ABI"49 Interrupt(InterruptKind),5051 /// ABIs relevant to Windows or x86 targets52 X86(X86Call),53}5455impl CanonAbi {56 pub fn is_rustic_abi(self) -> bool {57 match self {58 CanonAbi::Rust | CanonAbi::RustCold | CanonAbi::RustPreserveNone => true,59 CanonAbi::C60 | CanonAbi::Custom61 | CanonAbi::Arm(_)62 | CanonAbi::GpuKernel63 | CanonAbi::Interrupt(_)64 | CanonAbi::X86(_) => false,65 }66 }67}6869impl fmt::Display for CanonAbi {70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {71 // convert to the ExternAbi that *shares a string* with this CanonAbi.72 // FIXME: ideally we'd avoid printing `CanonAbi`, and preserve `ExternAbi` everywhere73 // that we need to generate error messages.74 let erased_abi = match self {75 CanonAbi::C => ExternAbi::C { unwind: false },76 CanonAbi::Rust => ExternAbi::Rust,77 CanonAbi::RustCold => ExternAbi::RustCold,78 CanonAbi::RustPreserveNone => ExternAbi::RustPreserveNone,79 CanonAbi::Custom => ExternAbi::Custom,80 CanonAbi::Arm(arm_call) => match arm_call {81 ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false },82 ArmCall::CCmseNonSecureCall => ExternAbi::CmseNonSecureCall,83 ArmCall::CCmseNonSecureEntry => ExternAbi::CmseNonSecureEntry,84 },85 CanonAbi::GpuKernel => ExternAbi::GpuKernel,86 CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {87 InterruptKind::Avr => ExternAbi::AvrInterrupt,88 InterruptKind::AvrNonBlocking => ExternAbi::AvrNonBlockingInterrupt,89 InterruptKind::Msp430 => ExternAbi::Msp430Interrupt,90 InterruptKind::RiscvMachine => ExternAbi::RiscvInterruptM,91 InterruptKind::RiscvSupervisor => ExternAbi::RiscvInterruptS,92 InterruptKind::X86 => ExternAbi::X86Interrupt,93 },94 CanonAbi::X86(x86_call) => match x86_call {95 X86Call::Fastcall => ExternAbi::Fastcall { unwind: false },96 X86Call::Stdcall => ExternAbi::Stdcall { unwind: false },97 X86Call::SysV64 => ExternAbi::SysV64 { unwind: false },98 X86Call::Thiscall => ExternAbi::Thiscall { unwind: false },99 X86Call::Vectorcall => ExternAbi::Vectorcall { unwind: false },100 X86Call::Win64 => ExternAbi::Win64 { unwind: false },101 },102 };103 erased_abi.as_str().fmt(f)104 }105}106107/// Callee codegen for interrupts108///109/// This is named differently from the "Call" enums because it is different:110/// these "ABI" differences are not relevant to callers, since there is "no caller".111/// These only affect callee codegen. making their categorization as distinct ABIs a bit peculiar.112#[derive(Copy, Clone, Debug)]113#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]114#[cfg_attr(feature = "nightly", derive(StableHash))]115pub enum InterruptKind {116 Avr,117 AvrNonBlocking,118 Msp430,119 RiscvMachine,120 RiscvSupervisor,121 X86,122}123124/// ABIs defined for x86-{32,64}125///126/// One of SysV64 or Win64 may alias the C ABI, and arguably Win64 is cross-platform now?127#[derive(Clone, Copy, Debug)]128#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]129#[cfg_attr(feature = "nightly", derive(StableHash))]130pub enum X86Call {131 /// "fastcall" has both GNU and Windows variants132 Fastcall,133 /// "stdcall" has both GNU and Windows variants134 Stdcall,135 SysV64,136 Thiscall,137 Vectorcall,138 Win64,139}140141/// ABIs defined for 32-bit Arm142#[derive(Copy, Clone, Debug)]143#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]144#[cfg_attr(feature = "nightly", derive(StableHash))]145pub enum ArmCall {146 Aapcs,147 CCmseNonSecureCall,148 CCmseNonSecureEntry,149}
Findings
✓ No findings reported for this file.