Skip to content

Commit b188b60

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

22 files changed

Lines changed: 235 additions & 3 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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ pub(crate) fn conv_to_call_conv(
5858
// Cranelift doesn't currently have anything for this.
5959
CanonAbi::RustPreserveNone => default_call_conv,
6060

61+
// Cranelift doesn't currently have anything for this.
62+
CanonAbi::RustTail => default_call_conv,
63+
6164
// Functions with this calling convention can only be called from assembly, but it is
6265
// possible to declare an `extern "custom"` block, so the backend still needs a calling
6366
// convention for declaring foreign functions.

compiler/rustc_codegen_gcc/src/abi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option<FnAttri
240240
CanonAbi::C | CanonAbi::Rust => return None,
241241
// gcc/gccjit does not have anything for this.
242242
CanonAbi::RustPreserveNone => return None,
243+
// gcc/gccjit does not have anything for this.
244+
CanonAbi::RustTail => return None,
243245
CanonAbi::RustCold => FnAttribute::Cold,
244246
// Functions with this calling convention can only be called from assembly, but it is
245247
// 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+
_ => llvm::CCallConv,
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)