naked functions: emit .private_extern on macos

This commit is contained in:
Folkert de Vries 2025-10-31 19:07:29 +01:00
parent 0d162b25ed
commit 76d0843f8d
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
4 changed files with 54 additions and 2 deletions

View file

@ -181,7 +181,8 @@ fn prefix_and_suffix<'tcx>(
}
}
Linkage::Internal => {
// write nothing
// LTO can fail when internal linkage is used.
emit_fatal("naked functions may not have internal linkage")
}
Linkage::Common => emit_fatal("Functions may not have common linkage"),
Linkage::AvailableExternally => {

View file

@ -580,6 +580,16 @@ fn internalize_symbols<'tcx>(
}
}
// When LTO inlines the caller of a naked function, it will attempt but fail to make the
// naked function symbol visible. To ensure that LTO works correctly, do not default
// naked functions to internal linkage and default visibility.
if let MonoItem::Fn(instance) = item {
let flags = cx.tcx.codegen_instance_attrs(instance.def).flags;
if flags.contains(CodegenFnAttrFlags::NAKED) {
continue;
}
}
// If we got here, we did not find any uses from other CGUs, so
// it's fine to make this monomorphization internal.
data.linkage = Linkage::Internal;

View file

@ -9,7 +9,7 @@
//@[aix] needs-llvm-components: powerpc
#![crate_type = "lib"]
#![feature(no_core, asm_experimental_arch, f128, linkage, fn_align)]
#![feature(no_core, asm_experimental_arch)]
#![no_core]
// tests that naked functions work for the `powerpc64-ibm-aix` target.

View file

@ -0,0 +1,41 @@
//@ revisions: macos-x86 macos-aarch64 linux-x86
//@ add-minicore
//@ assembly-output: emit-asm
//
//@[macos-aarch64] compile-flags: --target aarch64-apple-darwin
//@[macos-aarch64] needs-llvm-components: aarch64
//
//@[macos-x86] compile-flags: --target x86_64-apple-darwin
//@[macos-x86] needs-llvm-components: x86
//
//@[linux-x86] compile-flags: --target x86_64-unknown-linux-gnu
//@[linux-x86] needs-llvm-components: x86
#![crate_type = "lib"]
#![feature(no_core, asm_experimental_arch)]
#![no_core]
// Tests that naked functions that are not externally linked (e.g. via `no_mangle`)
// are marked as `Visibility::Hidden` and emit `.private_extern` or `.hidden`.
//
// Without this directive, LTO may fail because the symbol is not visible.
// See also https://github.com/rust-lang/rust/issues/148307.
extern crate minicore;
use minicore::*;
// CHECK: .p2align 2
// macos-x86,macos-aarch64: .private_extern
// linux-x86: .globl
// linux-x86: .hidden
// CHECK: ret
#[unsafe(naked)]
extern "C" fn ret() {
naked_asm!("ret")
}
// CHECK-LABEL: entry
#[no_mangle]
pub fn entry() {
ret()
}