diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp index 066d62b3d4b4b..9553a44fb317e 100644 --- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp @@ -627,10 +627,10 @@ Function *AArch64Arm64ECCallLowering::buildGuestExitThunk(Function *F) { Function::Create(Arm64Ty, GlobalValue::WeakODRLinkage, 0, ThunkName, M); GuestExit->setComdat(M->getOrInsertComdat(ThunkName)); GuestExit->setSection(".wowthk$aa"); - GuestExit->setMetadata( + GuestExit->addMetadata( "arm64ec_unmangled_name", - MDNode::get(M->getContext(), - MDString::get(M->getContext(), F->getName()))); + *MDNode::get(M->getContext(), + MDString::get(M->getContext(), F->getName()))); GuestExit->setMetadata( "arm64ec_ecmangled_name", MDNode::get(M->getContext(), @@ -803,6 +803,23 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) { DispatchFnGlobal = M->getOrInsertGlobal("__os_arm64x_dispatch_call", DispatchFnPtrType); + // Mangle names of function aliases and add the alias name to + // arm64ec_unmangled_name metadata to ensure a weak anti-dependency symbol is + // emitted for the alias as well. Do this early, before handling + // hybrid_patchable functions, to avoid mangling their aliases. + for (GlobalAlias &A : Mod.aliases()) { + auto F = dyn_cast_or_null(A.getAliaseeObject()); + if (!F) + continue; + if (std::optional MangledName = + getArm64ECMangledFunctionName(A.getName().str())) { + F->addMetadata("arm64ec_unmangled_name", + *MDNode::get(M->getContext(), + MDString::get(M->getContext(), A.getName()))); + A.setName(MangledName.value()); + } + } + DenseMap FnsMap; SetVector PatchableFns; @@ -837,20 +854,24 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) { // emitGlobalAlias to emit the right alias. auto *A = GlobalAlias::create(GlobalValue::LinkOnceODRLinkage, OrigName, &F); + auto *AM = GlobalAlias::create(GlobalValue::LinkOnceODRLinkage, + MangledName.value(), &F); + F.replaceUsesWithIf(AM, + [](Use &U) { return isa(U.getUser()); }); F.replaceAllUsesWith(A); F.setMetadata("arm64ec_exp_name", MDNode::get(M->getContext(), MDString::get(M->getContext(), "EXP+" + MangledName.value()))); A->setAliasee(&F); + AM->setAliasee(&F); if (F.hasDLLExportStorageClass()) { A->setDLLStorageClass(GlobalValue::DLLExportStorageClass); F.setDLLStorageClass(GlobalValue::DefaultStorageClass); } - FnsMap[A] = GlobalAlias::create(GlobalValue::LinkOnceODRLinkage, - MangledName.value(), &F); + FnsMap[A] = AM; PatchableFns.insert(A); } } @@ -928,9 +949,9 @@ bool AArch64Arm64ECCallLowering::processFunction( if (!F.hasLocalLinkage() || F.hasAddressTaken()) { if (std::optional MangledName = getArm64ECMangledFunctionName(F.getName().str())) { - F.setMetadata("arm64ec_unmangled_name", - MDNode::get(M->getContext(), - MDString::get(M->getContext(), F.getName()))); + F.addMetadata("arm64ec_unmangled_name", + *MDNode::get(M->getContext(), + MDString::get(M->getContext(), F.getName()))); if (F.hasComdat() && F.getComdat()->getName() == F.getName()) { Comdat *MangledComdat = M->getOrInsertComdat(MangledName.value()); SmallVector ComdatUsers = diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index d29a72a4f6884..db0652bc5949c 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -45,6 +45,7 @@ #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -1387,22 +1388,21 @@ void AArch64AsmPrinter::emitFunctionEntryLabel() { return Sym; }; - if (MCSymbol *UnmangledSym = - getSymbolFromMetadata("arm64ec_unmangled_name")) { - MCSymbol *ECMangledSym = getSymbolFromMetadata("arm64ec_ecmangled_name"); - - if (ECMangledSym) { - // An external function, emit the alias from the unmangled symbol to - // mangled symbol name and the alias from the mangled symbol to guest - // exit thunk. + SmallVector UnmangledNames; + MF->getFunction().getMetadata("arm64ec_unmangled_name", UnmangledNames); + for (MDNode *Node : UnmangledNames) { + StringRef NameStr = cast(Node->getOperand(0))->getString(); + MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr); + if (std::optional MangledName = + getArm64ECMangledFunctionName(UnmangledSym->getName())) { + MCSymbol *ECMangledSym = + MMI->getContext().getOrCreateSymbol(*MangledName); emitFunctionAlias(UnmangledSym, ECMangledSym); - emitFunctionAlias(ECMangledSym, CurrentFnSym); - } else { - // A function implementation, emit the alias from the unmangled symbol - // to mangled symbol name. - emitFunctionAlias(UnmangledSym, CurrentFnSym); } } + if (MCSymbol *ECMangledSym = + getSymbolFromMetadata("arm64ec_ecmangled_name")) + emitFunctionAlias(ECMangledSym, CurrentFnSym); } } diff --git a/llvm/test/CodeGen/AArch64/arm64ec-alias.ll b/llvm/test/CodeGen/AArch64/arm64ec-alias.ll new file mode 100644 index 0000000000000..03cc873136940 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/arm64ec-alias.ll @@ -0,0 +1,42 @@ +; RUN: llc -mtriple arm64ec-windows-msvc -filetype asm -o - %s | FileCheck %s + +define void @func() { + ret void +} + +define dso_local void @patchable_func() hybrid_patchable { + ret void +} + +@func_alias = alias void (), ptr @func +@func_alias2 = alias void (), ptr @func_alias +@patchable_alias = alias void (), ptr @patchable_func + +; CHECK: .weak_anti_dep func_alias +; CHECK-NEXT: .set func_alias, "#func_alias" +; CHECK-NEXT: .weak_anti_dep func_alias2 +; CHECK-NEXT: .set func_alias2, "#func_alias2" +; CHECK-NEXT: .weak_anti_dep func +; CHECK-NEXT: .set func, "#func" +; CHECK: .weak_anti_dep patchable_alias +; CHECK-NEXT: .set patchable_alias, "#patchable_alias" + +; CHECK: .globl "#func_alias" +; CHECK-NEXT: .def "#func_alias"; +; CHECK-NEXT: .scl 2; +; CHECK-NEXT: .type 32; +; CHECK-NEXT: .endef +; CHECK-NEXT: .set "#func_alias", "#func" +; CHECK-NEXT: .globl "#func_alias2" +; CHECK-NEXT: .def "#func_alias2"; +; CHECK-NEXT: .scl 2; +; CHECK-NEXT: .type 32; +; CHECK-NEXT: .endef +; CHECK-NEXT: .set "#func_alias2", "#func_alias" + +; CHECK: .globl "#patchable_alias" +; CHECK-NEXT: .def "#patchable_alias"; +; CHECK-NEXT: .scl 2; +; CHECK-NEXT: .type 32; +; CHECK-NEXT: .endef +; CHECK-NEXT: .set "#patchable_alias", "#patchable_func" diff --git a/llvm/test/CodeGen/AArch64/dllexport.ll b/llvm/test/CodeGen/AArch64/dllexport.ll index 580fb5fd9e79e..e15fc0a928b66 100644 --- a/llvm/test/CodeGen/AArch64/dllexport.ll +++ b/llvm/test/CodeGen/AArch64/dllexport.ll @@ -88,10 +88,10 @@ define weak_odr dllexport void @l() { ; CHECK-GNU-EC: .ascii " -export:o,data" ; CHECK-GNU-EC: .ascii " -export:p,data" ; CHECK-GNU-EC: .ascii " -export:q,data" -; CHECK-GNU-EC: .ascii " -export:r" -; CHECK-GNU-EC: .ascii " -export:s" -; CHECK-GNU-EC: .ascii " -export:t" -; CHECK-GNU-EC: .ascii " -export:u" +; CHECK-GNU-EC: .ascii " -export:#r,EXPORTAS,r" +; CHECK-GNU-EC: .ascii " -export:#s,EXPORTAS,s" +; CHECK-GNU-EC: .ascii " -export:#t,EXPORTAS,t" +; CHECK-GNU-EC: .ascii " -export:#u,EXPORTAS,u" ; CHECK-MSVC-EC-NOT: /EXPORT:f ; CHECK-MSVC-EC-NOT: /EXPORT:#f,EXPORTAS,f ; CHECK-MSVC-EC: .ascii " /EXPORT:#g,EXPORTAS,g" @@ -106,7 +106,7 @@ define weak_odr dllexport void @l() { ; CHECK-MSVC-EC: .ascii " /EXPORT:o,DATA" ; CHECK-MSVC-EC: .ascii " /EXPORT:p,DATA" ; CHECK-MSVC-EC: .ascii " /EXPORT:q,DATA" -; CHECK-MSVC-EC: .ascii " /EXPORT:r" -; CHECK-MSVC-EC: .ascii " /EXPORT:s" -; CHECK-MSVC-EC: .ascii " /EXPORT:t" -; CHECK-MSVC-EC: .ascii " /EXPORT:u" +; CHECK-MSVC-EC: .ascii " /EXPORT:#r,EXPORTAS,r" +; CHECK-MSVC-EC: .ascii " /EXPORT:#s,EXPORTAS,s" +; CHECK-MSVC-EC: .ascii " /EXPORT:#t,EXPORTAS,t" +; CHECK-MSVC-EC: .ascii " /EXPORT:#u,EXPORTAS,u"