Skip to content

Commit

Permalink
use LinkageKind to our advantage for naked functions
Browse files Browse the repository at this point in the history
  • Loading branch information
folkertdev committed Aug 7, 2024
1 parent 74e6e2e commit 7fc596f
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 11 deletions.
10 changes: 1 addition & 9 deletions compiler/rustc_codegen_llvm/src/mono_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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);
Expand Down
24 changes: 22 additions & 2 deletions compiler/rustc_codegen_ssa/src/mono_item.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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(..) => {}
}
Expand Down

0 comments on commit 7fc596f

Please sign in to comment.