abi: add a rust-preserve-none calling convention

This is the conceptual opposite of the rust-cold calling convention and
is particularly useful in combination with the new `explicit_tail_calls`
feature.

For relatively tight loops implemented with tail calling (`become`) each
of the function with the regular calling convention is still responsible
for restoring the initial value of the preserved registers. So it is not
unusual to end up with a situation where each step in the tail call loop
is spilling and reloading registers, along the lines of:

    foo:
        push r12
        ; do things
        pop r12
        jmp next_step

This adds up quickly, especially when most of the clobberable registers
are already used to pass arguments or other uses.

I was thinking of making the name of this ABI a little less LLVM-derived
and more like a conceptual inverse of `rust-cold`, but could not come
with a great name (`rust-cold` is itself not a great name: cold in what
context? from which perspective? is it supposed to mean that the
function is rarely called?)
This commit is contained in:
Simonas Kazlauskas 2026-01-13 16:52:02 +02:00
parent b2a322beb2
commit 6db94dbc25
26 changed files with 241 additions and 5 deletions

View file

@ -432,6 +432,7 @@ pub enum CallConvention {
Cold,
PreserveMost,
PreserveAll,
PreserveNone,
Custom,

View file

@ -1139,6 +1139,7 @@ pub enum Abi {
RustCold,
RiscvInterruptM,
RiscvInterruptS,
RustPreserveNone,
RustInvalid,
Custom,
}

View file

@ -615,6 +615,7 @@ impl RustcInternal for Abi {
Abi::RustInvalid => rustc_abi::ExternAbi::RustInvalid,
Abi::RiscvInterruptM => rustc_abi::ExternAbi::RiscvInterruptM,
Abi::RiscvInterruptS => rustc_abi::ExternAbi::RiscvInterruptS,
Abi::RustPreserveNone => rustc_abi::ExternAbi::RustPreserveNone,
Abi::Custom => rustc_abi::ExternAbi::Custom,
}
}

View file

@ -123,6 +123,7 @@ impl<'tcx> Stable<'tcx> for CanonAbi {
CanonAbi::C => CallConvention::C,
CanonAbi::Rust => CallConvention::Rust,
CanonAbi::RustCold => CallConvention::Cold,
CanonAbi::RustPreserveNone => CallConvention::PreserveNone,
CanonAbi::Custom => CallConvention::Custom,
CanonAbi::Arm(arm_call) => match arm_call {
ArmCall::Aapcs => CallConvention::ArmAapcs,

View file

@ -1020,6 +1020,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi {
ExternAbi::RustCall => Abi::RustCall,
ExternAbi::Unadjusted => Abi::Unadjusted,
ExternAbi::RustCold => Abi::RustCold,
ExternAbi::RustPreserveNone => Abi::RustPreserveNone,
ExternAbi::RustInvalid => Abi::RustInvalid,
ExternAbi::RiscvInterruptM => Abi::RiscvInterruptM,
ExternAbi::RiscvInterruptS => Abi::RiscvInterruptS,