use extern "custom" on naked functions with a custom calling convention

This commit is contained in:
Folkert de Vries 2025-06-14 20:17:23 +02:00 committed by GitHub
parent 3dc3017691
commit a413cca7d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 19 additions and 28 deletions

View file

@ -5,7 +5,7 @@ use core::intrinsics;
intrinsics! {
#[unsafe(naked)]
#[cfg(all(target_os = "uefi", not(feature = "no-asm")))]
pub unsafe extern "C" fn __chkstk() {
pub unsafe extern "custom" fn __chkstk() {
core::arch::naked_asm!(
".p2align 2",
"lsl x16, x15, #4",

View file

@ -9,11 +9,10 @@ unsafe extern "C" {
}
// SAFETY: these are defined in compiler-builtins
// FIXME(extern_custom), this isn't always the correct ABI
unsafe extern "aapcs" {
unsafe extern "custom" {
// AAPCS is not always the correct ABI for these intrinsics, but we only use this to
// forward another `__aeabi_` call so it doesn't matter.
fn __aeabi_idiv(a: i32, b: i32) -> i32;
fn __aeabi_idiv();
}
intrinsics! {
@ -21,7 +20,7 @@ intrinsics! {
// custom calling convention which can't be implemented using a normal Rust function.
#[unsafe(naked)]
#[cfg(not(target_env = "msvc"))]
pub unsafe extern "C" fn __aeabi_uidivmod() {
pub unsafe extern "custom" fn __aeabi_uidivmod() {
core::arch::naked_asm!(
"push {{lr}}",
"sub sp, sp, #4",
@ -35,7 +34,7 @@ intrinsics! {
}
#[unsafe(naked)]
pub unsafe extern "C" fn __aeabi_uldivmod() {
pub unsafe extern "custom" fn __aeabi_uldivmod() {
core::arch::naked_asm!(
"push {{r4, lr}}",
"sub sp, sp, #16",
@ -51,7 +50,7 @@ intrinsics! {
}
#[unsafe(naked)]
pub unsafe extern "C" fn __aeabi_idivmod() {
pub unsafe extern "custom" fn __aeabi_idivmod() {
core::arch::naked_asm!(
"push {{r0, r1, r4, lr}}",
"bl {trampoline}",
@ -64,7 +63,7 @@ intrinsics! {
}
#[unsafe(naked)]
pub unsafe extern "C" fn __aeabi_ldivmod() {
pub unsafe extern "custom" fn __aeabi_ldivmod() {
core::arch::naked_asm!(
"push {{r4, lr}}",
"sub sp, sp, #16",

View file

@ -44,7 +44,7 @@ intrinsics! {
}
#[unsafe(naked)]
pub unsafe extern "C" fn __udivmodqi4() {
pub unsafe extern "custom" fn __udivmodqi4() {
// compute unsigned 8-bit `n / d` and `n % d`.
//
// Note: GCC implements a [non-standard calling convention](https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention) for this function.

View file

@ -1,5 +1,6 @@
#![cfg_attr(feature = "compiler-builtins", compiler_builtins)]
#![cfg_attr(all(target_family = "wasm"), feature(wasm_numeric_instr))]
#![feature(abi_custom)]
#![feature(abi_unadjusted)]
#![feature(asm_experimental_arch)]
#![feature(cfg_target_has_atomic)]

View file

@ -52,15 +52,12 @@
// Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax,
// ensuring that if any pages are unmapped we'll make a page fault.
//
// FIXME(abi_custom): This function is unsafe because it uses a custom ABI,
// it does not actually match `extern "C"`.
//
// The ABI here is that the stack frame size is located in `%rax`. Upon
// return we're not supposed to modify `%rsp` or `%rax`.
#[cfg(target_arch = "x86_64")]
#[unsafe(naked)]
#[rustc_std_internal_symbol]
pub unsafe extern "C" fn __rust_probestack() {
pub unsafe extern "custom" fn __rust_probestack() {
#[cfg(not(all(target_env = "sgx", target_vendor = "fortanix")))]
macro_rules! ret {
() => {
@ -144,13 +141,10 @@ pub unsafe extern "C" fn __rust_probestack() {
// that on Unix we're expected to restore everything as it was, this
// function basically can't tamper with anything.
//
// FIXME(abi_custom): This function is unsafe because it uses a custom ABI,
// it does not actually match `extern "C"`.
//
// The ABI here is the same as x86_64, except everything is 32-bits large.
#[unsafe(naked)]
#[rustc_std_internal_symbol]
pub unsafe extern "C" fn __rust_probestack() {
pub unsafe extern "custom" fn __rust_probestack() {
core::arch::naked_asm!(
"
.cfi_startproc
@ -192,9 +186,6 @@ pub unsafe extern "C" fn __rust_probestack() {
// probestack function will also do things like _chkstk in MSVC.
// So we need to sub %ax %sp in probestack when arch is x86.
//
// FIXME(abi_custom): This function is unsafe because it uses a custom ABI,
// it does not actually match `extern "C"`.
//
// REF: Rust commit(74e80468347)
// rust\src\llvm-project\llvm\lib\Target\X86\X86FrameLowering.cpp: 805
// Comments in LLVM:
@ -203,7 +194,7 @@ pub unsafe extern "C" fn __rust_probestack() {
// themselves.
#[unsafe(naked)]
#[rustc_std_internal_symbol]
pub unsafe extern "C" fn __rust_probestack() {
pub unsafe extern "custom" fn __rust_probestack() {
core::arch::naked_asm!(
"
.cfi_startproc

View file

@ -2,7 +2,7 @@
use core::intrinsics;
// NOTE These functions are implemented using assembly because they using a custom
// NOTE These functions are implemented using assembly because they use a custom
// calling convention which can't be implemented using a normal Rust function
// NOTE These functions are never mangled as they are not tested against compiler-rt
@ -13,10 +13,10 @@ intrinsics! {
any(all(windows, target_env = "gnu"), target_os = "uefi"),
not(feature = "no-asm")
))]
pub unsafe extern "C" fn __chkstk() {
pub unsafe extern "custom" fn __chkstk() {
core::arch::naked_asm!(
"jmp __alloca", // Jump to __alloca since fallthrough may be unreliable"
options(att_syntax)
"jmp {}", // Jump to __alloca since fallthrough may be unreliable"
sym crate::x86::_alloca::_alloca,
);
}
@ -25,7 +25,7 @@ intrinsics! {
any(all(windows, target_env = "gnu"), target_os = "uefi"),
not(feature = "no-asm")
))]
pub unsafe extern "C" fn _alloca() {
pub unsafe extern "custom" fn _alloca() {
// __chkstk and _alloca are the same function
core::arch::naked_asm!(
"push %ecx",

View file

@ -2,7 +2,7 @@
use core::intrinsics;
// NOTE These functions are implemented using assembly because they using a custom
// NOTE These functions are implemented using assembly because they use a custom
// calling convention which can't be implemented using a normal Rust function
// NOTE These functions are never mangled as they are not tested against compiler-rt
@ -17,7 +17,7 @@ intrinsics! {
),
not(feature = "no-asm")
))]
pub unsafe extern "C" fn ___chkstk_ms() {
pub unsafe extern "custom" fn ___chkstk_ms() {
core::arch::naked_asm!(
"push %rcx",
"push %rax",