From 7fc596fb67d31a9d5266302771022ec14e22e1e8 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 31 Jul 2024 20:05:29 +0200 Subject: [PATCH] use `LinkageKind` to our advantage for naked functions --- compiler/rustc_codegen_llvm/src/mono_item.rs | 10 +------- compiler/rustc_codegen_ssa/src/mono_item.rs | 24 ++++++++++++++++++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index fda3176ece82f..8e8558d6a6672 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -2,7 +2,6 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; @@ -63,14 +62,7 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance)); let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); - let llvm_linkage = - if attrs.flags.contains(CodegenFnAttrFlags::NAKED) && linkage == Linkage::Internal { - // this is effectively an extern fn, and must have external linkage - llvm::Linkage::ExternalLinkage - } else { - base::linkage_to_llvm(linkage) - }; - unsafe { llvm::LLVMRustSetLinkage(lldecl, llvm_linkage) }; + unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; base::set_link_section(lldecl, attrs); if linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR { llvm::SetUniqueComdat(self.llmod, lldecl); diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 5a0d46ea999c9..889ff9865f53b 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -1,6 +1,7 @@ use rustc_hir as hir; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; +use rustc_middle::mir::mono::{Linkage, LinkageKind, MonoItem, Visibility}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::Instance; use rustc_middle::{span_bug, ty}; @@ -135,7 +136,26 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { cx.predefine_static(def_id, linkage_kind.into_linkage(), visibility, symbol_name); } MonoItem::Fn(instance) => { - cx.predefine_fn(instance, linkage_kind.into_linkage(), visibility, symbol_name); + let linkage = match linkage_kind { + LinkageKind::Explicit(linkage) => linkage, + LinkageKind::ImplicitExternal => Linkage::External, + LinkageKind::ImplicitInternal => { + let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()); + if attrs.flags.contains(CodegenFnAttrFlags::NAKED) { + // to connect the extern fn declaration and the global asm definition of + // a naked function, the linkage must be some flavor of external. + // `LinkageKind::ImplicitInternal` indicates that rust does not really care about + // the linkage, and did not find any references outside of the current CGU. That + // means we're free to pick a different linkage here that is just for the backend, + // and should not influence the symbol visibility in a meaningful way. + Linkage::External + } else { + Linkage::Internal + } + } + }; + + cx.predefine_fn(instance, linkage, visibility, symbol_name); } MonoItem::GlobalAsm(..) => {} }