diff options
Diffstat (limited to 'compiler/rustc_target/src')
| -rw-r--r-- | compiler/rustc_target/src/spec/abi/mod.rs | 333 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/abi/tests.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/mod.rs | 8 |
3 files changed, 7 insertions, 363 deletions
diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs deleted file mode 100644 index c2095155afa..00000000000 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ /dev/null @@ -1,333 +0,0 @@ -use std::fmt; - -use rustc_macros::{Decodable, Encodable, HashStable_Generic}; -use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol}; - -#[cfg(test)] -mod tests; - -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)] -#[derive(HashStable_Generic, Encodable, Decodable)] -pub enum Abi { - // 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 - // churn. The specific values are meaningless. - Rust, - C { - unwind: bool, - }, - Cdecl { - unwind: bool, - }, - Stdcall { - unwind: bool, - }, - Fastcall { - unwind: bool, - }, - Vectorcall { - unwind: bool, - }, - Thiscall { - unwind: bool, - }, - Aapcs { - unwind: bool, - }, - Win64 { - unwind: bool, - }, - SysV64 { - unwind: bool, - }, - PtxKernel, - Msp430Interrupt, - X86Interrupt, - EfiApi, - AvrInterrupt, - AvrNonBlockingInterrupt, - CCmseNonSecureCall, - CCmseNonSecureEntry, - System { - unwind: bool, - }, - RustIntrinsic, - RustCall, - /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even - /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI! - Unadjusted, - /// For things unlikely to be called, where reducing register pressure in - /// `extern "Rust"` callers is worth paying extra cost in the callee. - /// Stronger than just `#[cold]` because `fn` pointers might be incompatible. - RustCold, - RiscvInterruptM, - RiscvInterruptS, -} - -impl Abi { - 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. - // * EfiApi is based on Win64 or C, so it also supports it. - // * System falls back to C for functions with varargs. - // - // * Stdcall does not, because it would be impossible for the callee to clean - // up the arguments. (callee doesn't know how many arguments are there) - // * Same for Fastcall, Vectorcall and Thiscall. - // * Other calling conventions are related to hardware or the compiler itself. - match self { - Self::C { .. } - | Self::Cdecl { .. } - | Self::System { .. } - | Self::Aapcs { .. } - | Self::Win64 { .. } - | Self::SysV64 { .. } - | Self::EfiApi => true, - _ => false, - } - } -} - -#[derive(Copy, Clone)] -pub struct AbiData { - abi: Abi, - - /// Name of this ABI as we like it called. - name: &'static str, -} - -#[allow(non_upper_case_globals)] -const AbiDatas: &[AbiData] = &[ - AbiData { abi: Abi::Rust, name: "Rust" }, - AbiData { abi: Abi::C { unwind: false }, name: "C" }, - AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" }, - AbiData { abi: Abi::Cdecl { unwind: false }, name: "cdecl" }, - AbiData { abi: Abi::Cdecl { unwind: true }, name: "cdecl-unwind" }, - AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" }, - AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" }, - AbiData { abi: Abi::Fastcall { unwind: false }, name: "fastcall" }, - AbiData { abi: Abi::Fastcall { unwind: true }, name: "fastcall-unwind" }, - AbiData { abi: Abi::Vectorcall { unwind: false }, name: "vectorcall" }, - AbiData { abi: Abi::Vectorcall { unwind: true }, name: "vectorcall-unwind" }, - AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" }, - AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" }, - AbiData { abi: Abi::Aapcs { unwind: false }, name: "aapcs" }, - AbiData { abi: Abi::Aapcs { unwind: true }, name: "aapcs-unwind" }, - AbiData { abi: Abi::Win64 { unwind: false }, name: "win64" }, - AbiData { abi: Abi::Win64 { unwind: true }, name: "win64-unwind" }, - AbiData { abi: Abi::SysV64 { unwind: false }, name: "sysv64" }, - AbiData { abi: Abi::SysV64 { unwind: true }, name: "sysv64-unwind" }, - AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" }, - AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" }, - AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" }, - AbiData { abi: Abi::EfiApi, name: "efiapi" }, - AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" }, - AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" }, - AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" }, - AbiData { abi: Abi::CCmseNonSecureEntry, name: "C-cmse-nonsecure-entry" }, - AbiData { abi: Abi::System { unwind: false }, name: "system" }, - AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" }, - AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" }, - AbiData { abi: Abi::RustCall, name: "rust-call" }, - AbiData { abi: Abi::Unadjusted, name: "unadjusted" }, - AbiData { abi: Abi::RustCold, name: "rust-cold" }, - AbiData { abi: Abi::RiscvInterruptM, name: "riscv-interrupt-m" }, - AbiData { abi: Abi::RiscvInterruptS, name: "riscv-interrupt-s" }, -]; - -#[derive(Copy, Clone, Debug)] -pub enum AbiUnsupported { - Unrecognized, - Reason { explain: &'static str }, -} - -/// 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(|| match name { - "riscv-interrupt" => AbiUnsupported::Reason { - explain: "please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively", - }, - "riscv-interrupt-u" => AbiUnsupported::Reason { - explain: "user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314", - }, - "wasm" => AbiUnsupported::Reason { - explain: "non-standard wasm ABI is no longer supported", - }, - - _ => AbiUnsupported::Unrecognized, - - }) -} - -pub fn all_names() -> Vec<&'static str> { - AbiDatas.iter().map(|d| d.name).collect() -} - -pub fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> { - AbiDatas - .iter() - .map(|d| d.name) - .filter(|name| is_enabled(features, span, name).is_ok()) - .collect() -} - -pub enum AbiDisabled { - Unstable { feature: Symbol, explain: &'static str }, - Unrecognized, -} - -pub fn is_enabled( - features: &rustc_feature::Features, - span: Span, - name: &str, -) -> Result<(), AbiDisabled> { - let s = is_stable(name); - if let Err(AbiDisabled::Unstable { feature, .. }) = s { - if features.enabled(feature) || span.allows_unstable(feature) { - return Ok(()); - } - } - s -} - -pub fn is_stable(name: &str) -> Result<(), AbiDisabled> { - match name { - // Stable - "Rust" | "C" | "C-unwind" | "cdecl" | "cdecl-unwind" | "stdcall" | "stdcall-unwind" - | "fastcall" | "fastcall-unwind" | "aapcs" | "aapcs-unwind" | "win64" | "win64-unwind" - | "sysv64" | "sysv64-unwind" | "system" | "system-unwind" | "efiapi" | "thiscall" - | "thiscall-unwind" => Ok(()), - "rust-intrinsic" => Err(AbiDisabled::Unstable { - feature: sym::intrinsics, - explain: "intrinsics are subject to change", - }), - "vectorcall" => Err(AbiDisabled::Unstable { - feature: sym::abi_vectorcall, - explain: "vectorcall is experimental and subject to change", - }), - "vectorcall-unwind" => Err(AbiDisabled::Unstable { - feature: sym::abi_vectorcall, - explain: "vectorcall-unwind ABI is experimental and subject to change", - }), - "rust-call" => Err(AbiDisabled::Unstable { - feature: sym::unboxed_closures, - explain: "rust-call ABI is subject to change", - }), - "rust-cold" => Err(AbiDisabled::Unstable { - feature: sym::rust_cold_cc, - explain: "rust-cold is experimental and subject to change", - }), - "ptx-kernel" => Err(AbiDisabled::Unstable { - feature: sym::abi_ptx, - explain: "PTX ABIs are experimental and subject to change", - }), - "unadjusted" => Err(AbiDisabled::Unstable { - feature: sym::abi_unadjusted, - explain: "unadjusted ABI is an implementation detail and perma-unstable", - }), - "msp430-interrupt" => Err(AbiDisabled::Unstable { - feature: sym::abi_msp430_interrupt, - explain: "msp430-interrupt ABI is experimental and subject to change", - }), - "x86-interrupt" => Err(AbiDisabled::Unstable { - feature: sym::abi_x86_interrupt, - explain: "x86-interrupt ABI is experimental and subject to change", - }), - "avr-interrupt" | "avr-non-blocking-interrupt" => Err(AbiDisabled::Unstable { - feature: sym::abi_avr_interrupt, - explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change", - }), - "riscv-interrupt-m" | "riscv-interrupt-s" => Err(AbiDisabled::Unstable { - feature: sym::abi_riscv_interrupt, - explain: "riscv-interrupt ABIs are experimental and subject to change", - }), - "C-cmse-nonsecure-call" => Err(AbiDisabled::Unstable { - feature: sym::abi_c_cmse_nonsecure_call, - explain: "C-cmse-nonsecure-call ABI is experimental and subject to change", - }), - "C-cmse-nonsecure-entry" => Err(AbiDisabled::Unstable { - feature: sym::cmse_nonsecure_entry, - explain: "C-cmse-nonsecure-entry ABI is experimental and subject to change", - }), - _ => Err(AbiDisabled::Unrecognized), - } -} - -impl Abi { - /// Default ABI chosen for `extern fn` declarations without an explicit ABI. - pub const FALLBACK: Abi = Abi::C { unwind: false }; - - #[inline] - pub fn index(self) -> usize { - // N.B., this ordering MUST match the AbiDatas array above. - // (This is ensured by the test indices_are_correct().) - use Abi::*; - let i = match self { - // Cross-platform ABIs - Rust => 0, - C { unwind: false } => 1, - C { unwind: true } => 2, - // Platform-specific ABIs - Cdecl { unwind: false } => 3, - Cdecl { unwind: true } => 4, - Stdcall { unwind: false } => 5, - Stdcall { unwind: true } => 6, - Fastcall { unwind: false } => 7, - Fastcall { unwind: true } => 8, - Vectorcall { unwind: false } => 9, - Vectorcall { unwind: true } => 10, - Thiscall { unwind: false } => 11, - Thiscall { unwind: true } => 12, - Aapcs { unwind: false } => 13, - Aapcs { unwind: true } => 14, - Win64 { unwind: false } => 15, - Win64 { unwind: true } => 16, - SysV64 { unwind: false } => 17, - SysV64 { unwind: true } => 18, - PtxKernel => 19, - Msp430Interrupt => 20, - X86Interrupt => 21, - EfiApi => 22, - AvrInterrupt => 23, - AvrNonBlockingInterrupt => 24, - CCmseNonSecureCall => 25, - CCmseNonSecureEntry => 26, - // Cross-platform ABIs - System { unwind: false } => 27, - System { unwind: true } => 28, - RustIntrinsic => 29, - RustCall => 30, - Unadjusted => 31, - RustCold => 32, - RiscvInterruptM => 33, - RiscvInterruptS => 34, - }; - debug_assert!( - AbiDatas - .iter() - .enumerate() - .find(|(_, AbiData { abi, .. })| *abi == self) - .map(|(index, _)| index) - .expect("abi variant has associated data") - == i, - "Abi index did not match `AbiDatas` ordering" - ); - i - } - - #[inline] - pub fn data(self) -> &'static AbiData { - &AbiDatas[self.index()] - } - - pub fn name(self) -> &'static str { - self.data().name - } -} - -impl fmt::Display for Abi { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "\"{}\"", self.name()) - } -} diff --git a/compiler/rustc_target/src/spec/abi/tests.rs b/compiler/rustc_target/src/spec/abi/tests.rs deleted file mode 100644 index 4823058dd69..00000000000 --- a/compiler/rustc_target/src/spec/abi/tests.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::assert_matches::assert_matches; - -use super::*; - -#[allow(non_snake_case)] -#[test] -fn lookup_Rust() { - let abi = lookup("Rust"); - assert!(abi.is_ok() && abi.unwrap().data().name == "Rust"); -} - -#[test] -fn lookup_cdecl() { - let abi = lookup("cdecl"); - assert!(abi.is_ok() && abi.unwrap().data().name == "cdecl"); -} - -#[test] -fn lookup_baz() { - let abi = lookup("baz"); - assert_matches!(abi, Err(AbiUnsupported::Unrecognized)); -} - -#[test] -fn indices_are_correct() { - for (i, abi_data) in AbiDatas.iter().enumerate() { - assert_eq!(i, abi_data.abi.index()); - } -} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f4cbe47e0f3..3e7b42d3d1c 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -55,9 +55,15 @@ use crate::json::{Json, ToJson}; use crate::spec::abi::Abi; use crate::spec::crt_objects::CrtObjects; -pub mod abi; pub mod crt_objects; +pub mod abi { + pub use rustc_abi::{ + AbiDisabled, AbiUnsupported, ExternAbi as Abi, all_names, enabled_names, is_enabled, + is_stable, lookup, + }; +} + mod base; pub use base::apple::{ deployment_target_for_target as current_apple_deployment_target, |
