mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-16 04:55:22 +03:00
Add Swift function call ABI
Adds an unstable `extern "Swift"` ABI behind the `abi_swift` feature gate, mapping to LLVM's `swiftcc` calling convention. Cranelift and GCC backends fall back to the platform default since they have no equivalent.
This commit is contained in:
@@ -32,6 +32,10 @@ pub enum CanonAbi {
|
||||
/// An ABI that rustc does not know how to call or define.
|
||||
Custom,
|
||||
|
||||
/// Swift calling convention, exposed via LLVM's `swiftcc`. Cross-platform
|
||||
/// and not tied to a specific target architecture.
|
||||
Swift,
|
||||
|
||||
/// ABIs relevant to 32-bit Arm targets
|
||||
Arm(ArmCall),
|
||||
/// ABI relevant to GPUs: the entry point for a GPU kernel
|
||||
@@ -58,6 +62,7 @@ pub fn is_rustic_abi(self) -> bool {
|
||||
CanonAbi::Rust | CanonAbi::RustCold | CanonAbi::RustPreserveNone => true,
|
||||
CanonAbi::C
|
||||
| CanonAbi::Custom
|
||||
| CanonAbi::Swift
|
||||
| CanonAbi::Arm(_)
|
||||
| CanonAbi::GpuKernel
|
||||
| CanonAbi::Interrupt(_)
|
||||
@@ -77,6 +82,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
CanonAbi::RustCold => ExternAbi::RustCold,
|
||||
CanonAbi::RustPreserveNone => ExternAbi::RustPreserveNone,
|
||||
CanonAbi::Custom => ExternAbi::Custom,
|
||||
CanonAbi::Swift => ExternAbi::Swift,
|
||||
CanonAbi::Arm(arm_call) => match arm_call {
|
||||
ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false },
|
||||
ArmCall::CCmseNonSecureCall => ExternAbi::CmseNonSecureCall,
|
||||
|
||||
@@ -62,6 +62,10 @@ pub enum ExternAbi {
|
||||
/// and only valid on platforms that have a UEFI standard
|
||||
EfiApi,
|
||||
|
||||
/// Swift's calling convention, used to interoperate with Swift code without
|
||||
/// going through C as an intermediary.
|
||||
Swift,
|
||||
|
||||
/* arm */
|
||||
/// Arm Architecture Procedure Call Standard, sometimes `ExternAbi::C` is an alias for this
|
||||
Aapcs {
|
||||
@@ -173,6 +177,7 @@ fn from_str(s: &str) -> Result<$e_name, Self::Err> {
|
||||
C { unwind: false } =><= "C",
|
||||
C { unwind: true } =><= "C-unwind",
|
||||
Rust =><= "Rust",
|
||||
Swift =><= "Swift",
|
||||
Aapcs { unwind: false } =><= "aapcs",
|
||||
Aapcs { unwind: true } =><= "aapcs-unwind",
|
||||
AvrInterrupt =><= "avr-interrupt",
|
||||
@@ -348,7 +353,8 @@ pub fn supports_guaranteed_tail_call(self) -> bool {
|
||||
| Self::Vectorcall { .. }
|
||||
| Self::SysV64 { .. }
|
||||
| Self::Win64 { .. }
|
||||
| Self::RustPreserveNone => true,
|
||||
| Self::RustPreserveNone
|
||||
| Self::Swift => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,5 +144,8 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
|
||||
ExternAbi::Custom => {
|
||||
Err(UnstableAbi { abi, feature: sym::abi_custom, explain: GateReason::Experimental })
|
||||
}
|
||||
ExternAbi::Swift => {
|
||||
Err(UnstableAbi { abi, feature: sym::abi_swift, explain: GateReason::Experimental })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +424,7 @@ fn check_extern_fn_signature(&self, abi: ExternAbi, ctxt: FnCtxt, ident: &Ident,
|
||||
| CanonAbi::Rust
|
||||
| CanonAbi::RustCold
|
||||
| CanonAbi::RustPreserveNone
|
||||
| CanonAbi::Swift
|
||||
| CanonAbi::Arm(_)
|
||||
| CanonAbi::X86(_) => { /* nothing to check */ }
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ pub(crate) fn conv_to_call_conv(
|
||||
_ => default_call_conv,
|
||||
},
|
||||
|
||||
CanonAbi::Interrupt(_) | CanonAbi::Arm(_) => {
|
||||
CanonAbi::Interrupt(_) | CanonAbi::Arm(_) | CanonAbi::Swift => {
|
||||
sess.dcx().fatal("call conv {c:?} is not yet implemented")
|
||||
}
|
||||
CanonAbi::GpuKernel => {
|
||||
|
||||
@@ -245,6 +245,8 @@ pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option<FnAttri
|
||||
// possible to declare an `extern "custom"` block, so the backend still needs a calling
|
||||
// convention for declaring foreign functions.
|
||||
CanonAbi::Custom => return None,
|
||||
// gcc/gccjit does not have anything for Swift's calling convention.
|
||||
CanonAbi::Swift => panic!("gcc/gccjit backend does not support Swift calling convention"),
|
||||
CanonAbi::Arm(arm_call) => match arm_call {
|
||||
ArmCall::CCmseNonSecureCall => FnAttribute::ArmCmseNonsecureCall,
|
||||
ArmCall::CCmseNonSecureEntry => FnAttribute::ArmCmseNonsecureEntry,
|
||||
|
||||
@@ -722,6 +722,7 @@ pub(crate) fn to_llvm_calling_convention(sess: &Session, abi: CanonAbi) -> llvm:
|
||||
// possible to declare an `extern "custom"` block, so the backend still needs a calling
|
||||
// convention for declaring foreign functions.
|
||||
CanonAbi::Custom => llvm::CCallConv,
|
||||
CanonAbi::Swift => llvm::SwiftCallConv,
|
||||
CanonAbi::GpuKernel => match &sess.target.arch {
|
||||
Arch::AmdGpu => llvm::AmdgpuKernel,
|
||||
Arch::Nvptx64 => llvm::PtxKernel,
|
||||
|
||||
@@ -166,6 +166,7 @@ pub(crate) enum CallConv {
|
||||
ColdCallConv = 9,
|
||||
PreserveMost = 14,
|
||||
PreserveAll = 15,
|
||||
SwiftCallConv = 16,
|
||||
Tail = 18,
|
||||
PreserveNone = 21,
|
||||
X86StdcallCallConv = 64,
|
||||
|
||||
@@ -380,6 +380,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
(unstable, abi_ptx, "1.15.0", Some(38788)),
|
||||
/// Allows `extern "riscv-interrupt-m" fn()` and `extern "riscv-interrupt-s" fn()`.
|
||||
(unstable, abi_riscv_interrupt, "1.73.0", Some(111889)),
|
||||
/// Allows `extern "Swift" fn()`.
|
||||
(unstable, abi_swift, "CURRENT_RUSTC_VERSION", Some(156481)),
|
||||
/// Allows `extern "x86-interrupt" fn()`.
|
||||
(unstable, abi_x86_interrupt, "1.17.0", Some(40180)),
|
||||
/// Allows additional const parameter types, such as `[u8; 10]` or user defined types
|
||||
|
||||
@@ -202,6 +202,7 @@ pub(crate) fn check_call_abi(&self, abi: ExternAbi, span: Span) {
|
||||
| CanonAbi::Rust
|
||||
| CanonAbi::RustCold
|
||||
| CanonAbi::RustPreserveNone
|
||||
| CanonAbi::Swift
|
||||
| CanonAbi::Arm(_)
|
||||
| CanonAbi::X86(_) => {}
|
||||
}
|
||||
|
||||
@@ -1291,6 +1291,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
|
||||
| RiscvInterruptM
|
||||
| RiscvInterruptS
|
||||
| RustInvalid
|
||||
| Swift
|
||||
| Unadjusted => false,
|
||||
Rust | RustCall | RustCold | RustPreserveNone => tcx.sess.panic_strategy().unwinds(),
|
||||
}
|
||||
|
||||
@@ -458,6 +458,8 @@ pub enum CallConvention {
|
||||
|
||||
Custom,
|
||||
|
||||
Swift,
|
||||
|
||||
// Target-specific calling conventions.
|
||||
ArmAapcs,
|
||||
CCmseNonSecureCall,
|
||||
|
||||
@@ -1169,6 +1169,7 @@ pub enum Abi {
|
||||
RustPreserveNone,
|
||||
RustInvalid,
|
||||
Custom,
|
||||
Swift,
|
||||
}
|
||||
|
||||
/// A binder represents a possibly generic type and its bound vars.
|
||||
|
||||
@@ -619,6 +619,7 @@ fn internal<'tcx>(
|
||||
Abi::RiscvInterruptS => rustc_abi::ExternAbi::RiscvInterruptS,
|
||||
Abi::RustPreserveNone => rustc_abi::ExternAbi::RustPreserveNone,
|
||||
Abi::Custom => rustc_abi::ExternAbi::Custom,
|
||||
Abi::Swift => rustc_abi::ExternAbi::Swift,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>)
|
||||
CanonAbi::RustCold => CallConvention::Cold,
|
||||
CanonAbi::RustPreserveNone => CallConvention::PreserveNone,
|
||||
CanonAbi::Custom => CallConvention::Custom,
|
||||
CanonAbi::Swift => CallConvention::Swift,
|
||||
CanonAbi::Arm(arm_call) => match arm_call {
|
||||
ArmCall::Aapcs => CallConvention::ArmAapcs,
|
||||
ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
|
||||
|
||||
@@ -1050,6 +1050,7 @@ fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>)
|
||||
ExternAbi::RiscvInterruptM => Abi::RiscvInterruptM,
|
||||
ExternAbi::RiscvInterruptS => Abi::RiscvInterruptS,
|
||||
ExternAbi::Custom => Abi::Custom,
|
||||
ExternAbi::Swift => Abi::Swift,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,6 +355,7 @@
|
||||
abi_msp430_interrupt,
|
||||
abi_ptx,
|
||||
abi_riscv_interrupt,
|
||||
abi_swift,
|
||||
abi_sysv64,
|
||||
abi_thiscall,
|
||||
abi_unadjusted,
|
||||
|
||||
@@ -65,7 +65,9 @@ pub fn from_target(target: &Target) -> Self {
|
||||
_ => ArchKind::Other,
|
||||
};
|
||||
|
||||
let os = if target.is_like_windows {
|
||||
let os = if target.is_like_darwin {
|
||||
OsKind::Apple
|
||||
} else if target.is_like_windows {
|
||||
OsKind::Windows
|
||||
} else if target.is_like_vexos {
|
||||
OsKind::VEXos
|
||||
@@ -80,6 +82,15 @@ pub fn from_target(target: &Target) -> Self {
|
||||
pub fn canonize_abi(&self, extern_abi: ExternAbi, has_c_varargs: bool) -> AbiMapping {
|
||||
let AbiMap { os, arch } = *self;
|
||||
|
||||
if extern_abi == ExternAbi::Swift {
|
||||
// Per https://www.swift.org/blog/abi-stability-and-more/, Swift's ABI
|
||||
// is only stable on Apple platforms, so we reject it elsewhere.
|
||||
match os {
|
||||
OsKind::Apple => {}
|
||||
_ => return AbiMapping::Invalid,
|
||||
}
|
||||
}
|
||||
|
||||
let canon_abi = match (extern_abi, arch) {
|
||||
// infallible lowerings
|
||||
(ExternAbi::C { .. }, _) => CanonAbi::C,
|
||||
@@ -92,6 +103,8 @@ pub fn canonize_abi(&self, extern_abi: ExternAbi, has_c_varargs: bool) -> AbiMap
|
||||
|
||||
(ExternAbi::Custom, _) => CanonAbi::Custom,
|
||||
|
||||
(ExternAbi::Swift, _) => CanonAbi::Swift,
|
||||
|
||||
(ExternAbi::System { .. }, ArchKind::X86)
|
||||
if os == OsKind::Windows && !has_c_varargs =>
|
||||
{
|
||||
@@ -213,6 +226,7 @@ enum ArchKind {
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
enum OsKind {
|
||||
Apple,
|
||||
Windows,
|
||||
VEXos,
|
||||
Other,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//@ add-minicore
|
||||
//@ needs-llvm-components: x86
|
||||
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
|
||||
//@ ignore-backends: gcc
|
||||
#![no_core]
|
||||
#![feature(no_core, lang_items, abi_swift)]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
// The Swift ABI is only stable on Apple platforms, so it must be rejected
|
||||
// on other targets even when the `abi_swift` feature gate is enabled.
|
||||
|
||||
extern "Swift" fn f() {} //~ ERROR is not a supported ABI
|
||||
|
||||
trait T {
|
||||
extern "Swift" fn m(); //~ ERROR is not a supported ABI
|
||||
|
||||
extern "Swift" fn dm() {} //~ ERROR is not a supported ABI
|
||||
}
|
||||
|
||||
struct S;
|
||||
impl T for S {
|
||||
extern "Swift" fn m() {} //~ ERROR is not a supported ABI
|
||||
}
|
||||
|
||||
impl S {
|
||||
extern "Swift" fn im() {} //~ ERROR is not a supported ABI
|
||||
}
|
||||
|
||||
type TA = extern "Swift" fn(); //~ ERROR is not a supported ABI
|
||||
|
||||
extern "Swift" {} //~ ERROR is not a supported ABI
|
||||
@@ -0,0 +1,45 @@
|
||||
error[E0570]: "Swift" is not a supported ABI for the current target
|
||||
--> $DIR/swift-abi-non-apple.rs:14:8
|
||||
|
|
||||
LL | extern "Swift" fn f() {}
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0570]: "Swift" is not a supported ABI for the current target
|
||||
--> $DIR/swift-abi-non-apple.rs:17:12
|
||||
|
|
||||
LL | extern "Swift" fn m();
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0570]: "Swift" is not a supported ABI for the current target
|
||||
--> $DIR/swift-abi-non-apple.rs:19:12
|
||||
|
|
||||
LL | extern "Swift" fn dm() {}
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0570]: "Swift" is not a supported ABI for the current target
|
||||
--> $DIR/swift-abi-non-apple.rs:24:12
|
||||
|
|
||||
LL | extern "Swift" fn m() {}
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0570]: "Swift" is not a supported ABI for the current target
|
||||
--> $DIR/swift-abi-non-apple.rs:28:12
|
||||
|
|
||||
LL | extern "Swift" fn im() {}
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0570]: "Swift" is not a supported ABI for the current target
|
||||
--> $DIR/swift-abi-non-apple.rs:31:18
|
||||
|
|
||||
LL | type TA = extern "Swift" fn();
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0570]: "Swift" is not a supported ABI for the current target
|
||||
--> $DIR/swift-abi-non-apple.rs:33:8
|
||||
|
|
||||
LL | extern "Swift" {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0570`.
|
||||
@@ -0,0 +1,33 @@
|
||||
//@ add-minicore
|
||||
//@ needs-llvm-components: aarch64
|
||||
//@ compile-flags: --target=aarch64-apple-darwin --crate-type=rlib
|
||||
//@ ignore-backends: gcc
|
||||
#![no_core]
|
||||
#![feature(no_core, lang_items)]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
// Test that the "Swift" ABI is feature-gated, and cannot be used when
|
||||
// the `abi_swift` feature gate is not used.
|
||||
|
||||
extern "Swift" fn f() {} //~ ERROR "Swift" ABI is experimental
|
||||
|
||||
trait T {
|
||||
extern "Swift" fn m(); //~ ERROR "Swift" ABI is experimental
|
||||
|
||||
extern "Swift" fn dm() {} //~ ERROR "Swift" ABI is experimental
|
||||
}
|
||||
|
||||
struct S;
|
||||
impl T for S {
|
||||
extern "Swift" fn m() {} //~ ERROR "Swift" ABI is experimental
|
||||
}
|
||||
|
||||
impl S {
|
||||
extern "Swift" fn im() {} //~ ERROR "Swift" ABI is experimental
|
||||
}
|
||||
|
||||
type TA = extern "Swift" fn(); //~ ERROR "Swift" ABI is experimental
|
||||
|
||||
extern "Swift" {} //~ ERROR "Swift" ABI is experimental
|
||||
@@ -0,0 +1,73 @@
|
||||
error[E0658]: the extern "Swift" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi_swift.rs:14:8
|
||||
|
|
||||
LL | extern "Swift" fn f() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #156481 <https://github.com/rust-lang/rust/issues/156481> for more information
|
||||
= help: add `#![feature(abi_swift)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the extern "Swift" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi_swift.rs:17:12
|
||||
|
|
||||
LL | extern "Swift" fn m();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #156481 <https://github.com/rust-lang/rust/issues/156481> for more information
|
||||
= help: add `#![feature(abi_swift)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the extern "Swift" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi_swift.rs:19:12
|
||||
|
|
||||
LL | extern "Swift" fn dm() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #156481 <https://github.com/rust-lang/rust/issues/156481> for more information
|
||||
= help: add `#![feature(abi_swift)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the extern "Swift" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi_swift.rs:24:12
|
||||
|
|
||||
LL | extern "Swift" fn m() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #156481 <https://github.com/rust-lang/rust/issues/156481> for more information
|
||||
= help: add `#![feature(abi_swift)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the extern "Swift" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi_swift.rs:28:12
|
||||
|
|
||||
LL | extern "Swift" fn im() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #156481 <https://github.com/rust-lang/rust/issues/156481> for more information
|
||||
= help: add `#![feature(abi_swift)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the extern "Swift" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi_swift.rs:31:18
|
||||
|
|
||||
LL | type TA = extern "Swift" fn();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #156481 <https://github.com/rust-lang/rust/issues/156481> for more information
|
||||
= help: add `#![feature(abi_swift)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the extern "Swift" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi_swift.rs:33:8
|
||||
|
|
||||
LL | extern "Swift" {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #156481 <https://github.com/rust-lang/rust/issues/156481> for more information
|
||||
= help: add `#![feature(abi_swift)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
@@ -1,6 +1,7 @@
|
||||
C
|
||||
C-unwind
|
||||
Rust
|
||||
Swift
|
||||
aapcs
|
||||
aapcs-unwind
|
||||
avr-interrupt
|
||||
|
||||
Reference in New Issue
Block a user