Skip to content

Commit c3e1d05

Browse files
committed
add extern "rust-tail" calling convention
1 parent 5043948 commit c3e1d05

23 files changed

Lines changed: 250 additions & 9 deletions

File tree

compiler/rustc_abi/src/canon_abi.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub enum CanonAbi {
2828
Rust,
2929
RustCold,
3030
RustPreserveNone,
31+
RustTail,
3132

3233
/// An ABI that rustc does not know how to call or define.
3334
Custom,
@@ -59,7 +60,10 @@ pub enum CanonAbi {
5960
impl CanonAbi {
6061
pub fn is_rustic_abi(self) -> bool {
6162
match self {
62-
CanonAbi::Rust | CanonAbi::RustCold | CanonAbi::RustPreserveNone => true,
63+
CanonAbi::Rust
64+
| CanonAbi::RustCold
65+
| CanonAbi::RustPreserveNone
66+
| CanonAbi::RustTail => true,
6367
CanonAbi::C
6468
| CanonAbi::Custom
6569
| CanonAbi::Swift
@@ -81,6 +85,7 @@ impl fmt::Display for CanonAbi {
8185
CanonAbi::Rust => ExternAbi::Rust,
8286
CanonAbi::RustCold => ExternAbi::RustCold,
8387
CanonAbi::RustPreserveNone => ExternAbi::RustPreserveNone,
88+
CanonAbi::RustTail => ExternAbi::RustTail,
8489
CanonAbi::Custom => ExternAbi::Custom,
8590
CanonAbi::Swift => ExternAbi::Swift,
8691
CanonAbi::Arm(arm_call) => match arm_call {

compiler/rustc_abi/src/extern_abi.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ pub enum ExternAbi {
4949
/// forcing callers to save all registers.
5050
RustPreserveNone,
5151

52+
/// Ensures that calls in tail position can always be optimized into a jump.
53+
///
54+
/// This ABI is not stable, and relies on LLVM implementation details.
55+
RustTail,
56+
5257
/// Unstable impl detail that directly uses Rust types to describe the ABI to LLVM.
5358
/// Even normally-compatible Rust types can become ABI-incompatible with this ABI!
5459
Unadjusted,
@@ -199,6 +204,7 @@ abi_impls! {
199204
RustCold =><= "rust-cold",
200205
RustInvalid =><= "rust-invalid",
201206
RustPreserveNone =><= "rust-preserve-none",
207+
RustTail =><= "rust-tail",
202208
Stdcall { unwind: false } =><= "stdcall",
203209
Stdcall { unwind: true } =><= "stdcall-unwind",
204210
System { unwind: false } =><= "system",
@@ -280,7 +286,7 @@ impl ExternAbi {
280286
/// - are subject to change between compiler versions
281287
pub fn is_rustic_abi(self) -> bool {
282288
use ExternAbi::*;
283-
matches!(self, Rust | RustCall | RustCold | RustPreserveNone)
289+
matches!(self, Rust | RustCall | RustCold | RustPreserveNone | RustTail)
284290
}
285291

286292
/// Returns whether the ABI supports C variadics. This only controls whether we allow *imports*
@@ -354,6 +360,7 @@ impl ExternAbi {
354360
| Self::SysV64 { .. }
355361
| Self::Win64 { .. }
356362
| Self::RustPreserveNone
363+
| Self::RustTail
357364
| Self::Swift => true,
358365
}
359366
}

compiler/rustc_ast_lowering/src/stability.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
100100
feature: sym::rust_preserve_none_cc,
101101
explain: GateReason::Experimental,
102102
}),
103+
ExternAbi::RustTail => {
104+
Err(UnstableAbi { abi, feature: sym::rust_tail_cc, explain: GateReason::Experimental })
105+
}
103106
ExternAbi::RustInvalid => {
104107
Err(UnstableAbi { abi, feature: sym::rustc_attrs, explain: GateReason::ImplDetail })
105108
}

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ impl<'a> AstValidator<'a> {
424424
| CanonAbi::Rust
425425
| CanonAbi::RustCold
426426
| CanonAbi::RustPreserveNone
427+
| CanonAbi::RustTail
427428
| CanonAbi::Swift
428429
| CanonAbi::Arm(_)
429430
| CanonAbi::X86(_) => { /* nothing to check */ }

compiler/rustc_codegen_cranelift/src/abi/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ pub(crate) fn conv_to_call_conv(
5555
match c {
5656
CanonAbi::Rust | CanonAbi::RustCold | CanonAbi::C => default_call_conv,
5757

58-
// Cranelift doesn't currently have anything for this.
59-
CanonAbi::RustPreserveNone => default_call_conv,
58+
CanonAbi::RustPreserveNone | CanonAbi::RustTail => {
59+
sess.dcx().fatal(format!("call conv {c:?} is LLVM-specific"))
60+
}
6061

6162
// Functions with this calling convention can only be called from assembly, but it is
6263
// possible to declare an `extern "custom"` block, so the backend still needs a calling
@@ -71,7 +72,7 @@ pub(crate) fn conv_to_call_conv(
7172
},
7273

7374
CanonAbi::Interrupt(_) | CanonAbi::Arm(_) | CanonAbi::Swift => {
74-
sess.dcx().fatal("call conv {c:?} is not yet implemented")
75+
sess.dcx().fatal(format!("call conv {c:?} is not yet implemented"))
7576
}
7677
CanonAbi::GpuKernel => {
7778
unreachable!("tried to use {c:?} call conv which only exists on an unsupported target")

compiler/rustc_codegen_gcc/src/abi.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,14 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
238238
pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option<FnAttribute<'gcc>> {
239239
let attribute = match conv {
240240
CanonAbi::C | CanonAbi::Rust => return None,
241-
// gcc/gccjit does not have anything for this.
242-
CanonAbi::RustPreserveNone => return None,
241+
CanonAbi::RustPreserveNone => {
242+
// This calling convention is LLVM-specific and unspecified.
243+
panic!("gcc/gccjit backend does not support RustPreserveNone calling convention")
244+
}
245+
CanonAbi::RustTail => {
246+
// This calling convention is LLVM-specific and unspecified.
247+
panic!("gcc/gccjit backend does not support RustTail calling convention")
248+
}
243249
CanonAbi::RustCold => FnAttribute::Cold,
244250
// Functions with this calling convention can only be called from assembly, but it is
245251
// possible to declare an `extern "custom"` block, so the backend still needs a calling

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,10 @@ pub(crate) fn to_llvm_calling_convention(sess: &Session, abi: CanonAbi) -> llvm:
718718
Arch::X86_64 | Arch::AArch64 => llvm::PreserveNone,
719719
_ => llvm::CCallConv,
720720
},
721+
CanonAbi::RustTail => match &sess.target.arch {
722+
Arch::X86_64 | Arch::AArch64 => llvm::Tail,
723+
_ => sess.dcx().fatal("extern \"rust-tail\" is only supported on x86_64 and aarch64"),
724+
},
721725
// Functions with this calling convention can only be called from assembly, but it is
722726
// possible to declare an `extern "custom"` block, so the backend still needs a calling
723727
// convention for declaring foreign functions.

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,8 @@ declare_features! (
709709
(unstable, rust_cold_cc, "1.63.0", Some(97544)),
710710
/// Allows `extern "rust-preserve-none"`.
711711
(unstable, rust_preserve_none_cc, "1.95.0", Some(151401)),
712+
/// Allows `extern "rust-tail-cc"`.
713+
(unstable, rust_tail_cc, "CURRENT_RUSTC_VERSION", Some(123)), // FIXME needs an issue
712714
/// Target features on s390x.
713715
(unstable, s390x_target_feature, "1.82.0", Some(150259)),
714716
/// Allows the use of the `sanitize` attribute.

compiler/rustc_hir_typeck/src/callee.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
202202
| CanonAbi::Rust
203203
| CanonAbi::RustCold
204204
| CanonAbi::RustPreserveNone
205+
| CanonAbi::RustTail
205206
| CanonAbi::Swift
206207
| CanonAbi::Arm(_)
207208
| CanonAbi::X86(_) => {}

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,9 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
12921292
| RustInvalid
12931293
| Swift
12941294
| Unadjusted => false,
1295-
Rust | RustCall | RustCold | RustPreserveNone => tcx.sess.panic_strategy().unwinds(),
1295+
Rust | RustCall | RustCold | RustPreserveNone | RustTail => {
1296+
tcx.sess.panic_strategy().unwinds()
1297+
}
12961298
}
12971299
}
12981300

0 commit comments

Comments
 (0)