Skip to content

Commit 606e0b4

Browse files
authored
[ARM64EC] Add support for function aliases on ARM64EC (#132295)
Required for mingw-w64, which uses the alias attribute in its CRT. Follows ARM64EC mangling rules by mangling the alias symbol and emitting an unmangled anti-dependency alias. Since metadata is not allowed on GlobalAlias objects, extend arm64ec_unmangled_name to support multiple unmangled names and attach the alias anti-dependency name to the target function's metadata.
1 parent 1dee125 commit 606e0b4

File tree

4 files changed

+92
-29
lines changed

4 files changed

+92
-29
lines changed

llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -627,10 +627,10 @@ Function *AArch64Arm64ECCallLowering::buildGuestExitThunk(Function *F) {
627627
Function::Create(Arm64Ty, GlobalValue::WeakODRLinkage, 0, ThunkName, M);
628628
GuestExit->setComdat(M->getOrInsertComdat(ThunkName));
629629
GuestExit->setSection(".wowthk$aa");
630-
GuestExit->setMetadata(
630+
GuestExit->addMetadata(
631631
"arm64ec_unmangled_name",
632-
MDNode::get(M->getContext(),
633-
MDString::get(M->getContext(), F->getName())));
632+
*MDNode::get(M->getContext(),
633+
MDString::get(M->getContext(), F->getName())));
634634
GuestExit->setMetadata(
635635
"arm64ec_ecmangled_name",
636636
MDNode::get(M->getContext(),
@@ -803,6 +803,23 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) {
803803
DispatchFnGlobal =
804804
M->getOrInsertGlobal("__os_arm64x_dispatch_call", DispatchFnPtrType);
805805

806+
// Mangle names of function aliases and add the alias name to
807+
// arm64ec_unmangled_name metadata to ensure a weak anti-dependency symbol is
808+
// emitted for the alias as well. Do this early, before handling
809+
// hybrid_patchable functions, to avoid mangling their aliases.
810+
for (GlobalAlias &A : Mod.aliases()) {
811+
auto F = dyn_cast_or_null<Function>(A.getAliaseeObject());
812+
if (!F)
813+
continue;
814+
if (std::optional<std::string> MangledName =
815+
getArm64ECMangledFunctionName(A.getName().str())) {
816+
F->addMetadata("arm64ec_unmangled_name",
817+
*MDNode::get(M->getContext(),
818+
MDString::get(M->getContext(), A.getName())));
819+
A.setName(MangledName.value());
820+
}
821+
}
822+
806823
DenseMap<GlobalAlias *, GlobalAlias *> FnsMap;
807824
SetVector<GlobalAlias *> PatchableFns;
808825

@@ -837,20 +854,24 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) {
837854
// emitGlobalAlias to emit the right alias.
838855
auto *A =
839856
GlobalAlias::create(GlobalValue::LinkOnceODRLinkage, OrigName, &F);
857+
auto *AM = GlobalAlias::create(GlobalValue::LinkOnceODRLinkage,
858+
MangledName.value(), &F);
859+
F.replaceUsesWithIf(AM,
860+
[](Use &U) { return isa<GlobalAlias>(U.getUser()); });
840861
F.replaceAllUsesWith(A);
841862
F.setMetadata("arm64ec_exp_name",
842863
MDNode::get(M->getContext(),
843864
MDString::get(M->getContext(),
844865
"EXP+" + MangledName.value())));
845866
A->setAliasee(&F);
867+
AM->setAliasee(&F);
846868

847869
if (F.hasDLLExportStorageClass()) {
848870
A->setDLLStorageClass(GlobalValue::DLLExportStorageClass);
849871
F.setDLLStorageClass(GlobalValue::DefaultStorageClass);
850872
}
851873

852-
FnsMap[A] = GlobalAlias::create(GlobalValue::LinkOnceODRLinkage,
853-
MangledName.value(), &F);
874+
FnsMap[A] = AM;
854875
PatchableFns.insert(A);
855876
}
856877
}
@@ -928,9 +949,9 @@ bool AArch64Arm64ECCallLowering::processFunction(
928949
if (!F.hasLocalLinkage() || F.hasAddressTaken()) {
929950
if (std::optional<std::string> MangledName =
930951
getArm64ECMangledFunctionName(F.getName().str())) {
931-
F.setMetadata("arm64ec_unmangled_name",
932-
MDNode::get(M->getContext(),
933-
MDString::get(M->getContext(), F.getName())));
952+
F.addMetadata("arm64ec_unmangled_name",
953+
*MDNode::get(M->getContext(),
954+
MDString::get(M->getContext(), F.getName())));
934955
if (F.hasComdat() && F.getComdat()->getName() == F.getName()) {
935956
Comdat *MangledComdat = M->getOrInsertComdat(MangledName.value());
936957
SmallVector<GlobalObject *> ComdatUsers =

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "llvm/CodeGen/TargetRegisterInfo.h"
4646
#include "llvm/IR/DataLayout.h"
4747
#include "llvm/IR/DebugInfoMetadata.h"
48+
#include "llvm/IR/Mangler.h"
4849
#include "llvm/IR/Module.h"
4950
#include "llvm/MC/MCAsmInfo.h"
5051
#include "llvm/MC/MCContext.h"
@@ -1387,22 +1388,21 @@ void AArch64AsmPrinter::emitFunctionEntryLabel() {
13871388
return Sym;
13881389
};
13891390

1390-
if (MCSymbol *UnmangledSym =
1391-
getSymbolFromMetadata("arm64ec_unmangled_name")) {
1392-
MCSymbol *ECMangledSym = getSymbolFromMetadata("arm64ec_ecmangled_name");
1393-
1394-
if (ECMangledSym) {
1395-
// An external function, emit the alias from the unmangled symbol to
1396-
// mangled symbol name and the alias from the mangled symbol to guest
1397-
// exit thunk.
1391+
SmallVector<MDNode *> UnmangledNames;
1392+
MF->getFunction().getMetadata("arm64ec_unmangled_name", UnmangledNames);
1393+
for (MDNode *Node : UnmangledNames) {
1394+
StringRef NameStr = cast<MDString>(Node->getOperand(0))->getString();
1395+
MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1396+
if (std::optional<std::string> MangledName =
1397+
getArm64ECMangledFunctionName(UnmangledSym->getName())) {
1398+
MCSymbol *ECMangledSym =
1399+
MMI->getContext().getOrCreateSymbol(*MangledName);
13981400
emitFunctionAlias(UnmangledSym, ECMangledSym);
1399-
emitFunctionAlias(ECMangledSym, CurrentFnSym);
1400-
} else {
1401-
// A function implementation, emit the alias from the unmangled symbol
1402-
// to mangled symbol name.
1403-
emitFunctionAlias(UnmangledSym, CurrentFnSym);
14041401
}
14051402
}
1403+
if (MCSymbol *ECMangledSym =
1404+
getSymbolFromMetadata("arm64ec_ecmangled_name"))
1405+
emitFunctionAlias(ECMangledSym, CurrentFnSym);
14061406
}
14071407
}
14081408

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; RUN: llc -mtriple arm64ec-windows-msvc -filetype asm -o - %s | FileCheck %s
2+
3+
define void @func() {
4+
ret void
5+
}
6+
7+
define dso_local void @patchable_func() hybrid_patchable {
8+
ret void
9+
}
10+
11+
@func_alias = alias void (), ptr @func
12+
@func_alias2 = alias void (), ptr @func_alias
13+
@patchable_alias = alias void (), ptr @patchable_func
14+
15+
; CHECK: .weak_anti_dep func_alias
16+
; CHECK-NEXT: .set func_alias, "#func_alias"
17+
; CHECK-NEXT: .weak_anti_dep func_alias2
18+
; CHECK-NEXT: .set func_alias2, "#func_alias2"
19+
; CHECK-NEXT: .weak_anti_dep func
20+
; CHECK-NEXT: .set func, "#func"
21+
; CHECK: .weak_anti_dep patchable_alias
22+
; CHECK-NEXT: .set patchable_alias, "#patchable_alias"
23+
24+
; CHECK: .globl "#func_alias"
25+
; CHECK-NEXT: .def "#func_alias";
26+
; CHECK-NEXT: .scl 2;
27+
; CHECK-NEXT: .type 32;
28+
; CHECK-NEXT: .endef
29+
; CHECK-NEXT: .set "#func_alias", "#func"
30+
; CHECK-NEXT: .globl "#func_alias2"
31+
; CHECK-NEXT: .def "#func_alias2";
32+
; CHECK-NEXT: .scl 2;
33+
; CHECK-NEXT: .type 32;
34+
; CHECK-NEXT: .endef
35+
; CHECK-NEXT: .set "#func_alias2", "#func_alias"
36+
37+
; CHECK: .globl "#patchable_alias"
38+
; CHECK-NEXT: .def "#patchable_alias";
39+
; CHECK-NEXT: .scl 2;
40+
; CHECK-NEXT: .type 32;
41+
; CHECK-NEXT: .endef
42+
; CHECK-NEXT: .set "#patchable_alias", "#patchable_func"

llvm/test/CodeGen/AArch64/dllexport.ll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ define weak_odr dllexport void @l() {
8888
; CHECK-GNU-EC: .ascii " -export:o,data"
8989
; CHECK-GNU-EC: .ascii " -export:p,data"
9090
; CHECK-GNU-EC: .ascii " -export:q,data"
91-
; CHECK-GNU-EC: .ascii " -export:r"
92-
; CHECK-GNU-EC: .ascii " -export:s"
93-
; CHECK-GNU-EC: .ascii " -export:t"
94-
; CHECK-GNU-EC: .ascii " -export:u"
91+
; CHECK-GNU-EC: .ascii " -export:#r,EXPORTAS,r"
92+
; CHECK-GNU-EC: .ascii " -export:#s,EXPORTAS,s"
93+
; CHECK-GNU-EC: .ascii " -export:#t,EXPORTAS,t"
94+
; CHECK-GNU-EC: .ascii " -export:#u,EXPORTAS,u"
9595
; CHECK-MSVC-EC-NOT: /EXPORT:f
9696
; CHECK-MSVC-EC-NOT: /EXPORT:#f,EXPORTAS,f
9797
; CHECK-MSVC-EC: .ascii " /EXPORT:#g,EXPORTAS,g"
@@ -106,7 +106,7 @@ define weak_odr dllexport void @l() {
106106
; CHECK-MSVC-EC: .ascii " /EXPORT:o,DATA"
107107
; CHECK-MSVC-EC: .ascii " /EXPORT:p,DATA"
108108
; CHECK-MSVC-EC: .ascii " /EXPORT:q,DATA"
109-
; CHECK-MSVC-EC: .ascii " /EXPORT:r"
110-
; CHECK-MSVC-EC: .ascii " /EXPORT:s"
111-
; CHECK-MSVC-EC: .ascii " /EXPORT:t"
112-
; CHECK-MSVC-EC: .ascii " /EXPORT:u"
109+
; CHECK-MSVC-EC: .ascii " /EXPORT:#r,EXPORTAS,r"
110+
; CHECK-MSVC-EC: .ascii " /EXPORT:#s,EXPORTAS,s"
111+
; CHECK-MSVC-EC: .ascii " /EXPORT:#t,EXPORTAS,t"
112+
; CHECK-MSVC-EC: .ascii " /EXPORT:#u,EXPORTAS,u"

0 commit comments

Comments
 (0)