efriedma created this revision. Herald added subscribers: zzheng, kristof.beyls. Herald added a project: All. efriedma requested review of this revision. Herald added a project: clang.
Part of initial Arm64EC patchset. For the Arm64EC ABI, ARM64 functions have an alternate name. For C code, this name is just the original name prefixed with "#". For C++ code, we stick a "$$h" modifier in the middle of the mangling. For functions which are not hybrid_patchable, the normal name is then an alias for the alternate name. (For functions that are patchable, we have to do something more complicated to tell the linker to generate a stub; I haven't tried to implement that yet.) This doesn't emit quite the same symbols table as MSVC for simple cases: MSVC generates a IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY alias, where this just makes another symbol pointing at the function definition. This probably matters for the hybmp$x table, but I don't have the complete documentation at the moment. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D125418 Files: clang/include/clang/AST/Mangle.h clang/lib/AST/MicrosoftMangle.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/arm64ec.c clang/test/CodeGenCXX/arm64ec.cpp
Index: clang/test/CodeGenCXX/arm64ec.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/arm64ec.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -no-opaque-pointers -triple aarch64-windows-msvc_arm64ec -emit-llvm -o - %s | FileCheck %s + +// CHECK: @"?g@@YAXUA@@UB@@@Z" = alias void ([2 x float], [4 x float]), void ([2 x float], [4 x float])* @"?g@@$$hYAXUA@@UB@@@Z" +// CHECK: define dso_local void @"?g@@$$hYAXUA@@UB@@@Z" +typedef struct { float x[2]; } A; +typedef struct { float x[4]; } B; +void g(A a, B b) { } Index: clang/test/CodeGen/arm64ec.c =================================================================== --- /dev/null +++ clang/test/CodeGen/arm64ec.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -no-opaque-pointers -triple aarch64-windows-msvc_arm64ec -emit-llvm -o - %s | FileCheck %s + +// CHECK: @g = alias void ([2 x float], [4 x float]), void ([2 x float], [4 x float])* @"#g" +// CHECK: define dso_local void @"#g" +typedef struct { float x[2]; } A; +typedef struct { float x[4]; } B; +void g(A a, B b) { } Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -5117,6 +5117,23 @@ if (!GV->isDeclaration()) return; + if (getTriple().isWindowsArm64EC()) { + // For ARM64EC targets, a function definition's name is mangled differently + // from the normal symbol. We then emit an alias from the normal + // symbol to the remangled definition. + // FIXME: MSVC uses IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY, we just emit + // multiple definition symbols. Why does this matter? + // FIXME: For hybrid_patchable functions, the alias doesn't point + // to the function itself; it points to a stub for the compiler. + // FIXME: We also need to emit an entry thunk. + SmallString<256> MangledName; + llvm::raw_svector_ostream Out(MangledName); + getCXXABI().getMangleContext().mangleArm64ECFnDef(GD, Out); + auto *Alias = llvm::GlobalAlias::create("", GV); + Alias->takeName(GV); + GV->setName(MangledName); + } + // We need to set linkage and visibility on the function before // generating code for it because various parts of IR generation // want to propagate this information down (e.g. to local static Index: clang/lib/AST/MicrosoftMangle.cpp =================================================================== --- clang/lib/AST/MicrosoftMangle.cpp +++ clang/lib/AST/MicrosoftMangle.cpp @@ -298,6 +298,7 @@ return AnonymousNamespaceHash; } + void mangleArm64ECFnDef(GlobalDecl GD, raw_ostream &) override; private: void mangleInitFiniStub(const VarDecl *D, char CharCode, raw_ostream &Out); }; @@ -360,7 +361,7 @@ void mangle(GlobalDecl GD, StringRef Prefix = "?"); void mangleName(GlobalDecl GD); - void mangleFunctionEncoding(GlobalDecl GD, bool ShouldMangle); + void mangleFunctionEncoding(GlobalDecl GD, bool ShouldMangle, bool Arm64ECDef = false); void mangleVariableEncoding(const VarDecl *VD); void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD, StringRef Prefix = "$"); @@ -384,6 +385,7 @@ bool ForceThisQuals = false, bool MangleExceptionSpec = true); void mangleNestedName(GlobalDecl GD); + void mangleArm64ECFnDef(GlobalDecl GD); private: bool isStructorDecl(const NamedDecl *ND) const { @@ -573,7 +575,8 @@ } void MicrosoftCXXNameMangler::mangleFunctionEncoding(GlobalDecl GD, - bool ShouldMangle) { + bool ShouldMangle, + bool Arm64ECDef) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); // <type-encoding> ::= <function-class> <function-type> @@ -597,6 +600,8 @@ if (FD->isExternC() && FD->hasAttr<OverloadableAttr>()) Out << "$$J0"; + if (Arm64ECDef) + Out << "$$h"; mangleFunctionClass(FD); mangleFunctionType(FT, FD, false, false); @@ -3944,6 +3949,29 @@ Mangler.getStream() << '@'; } +void MicrosoftMangleContextImpl::mangleArm64ECFnDef(GlobalDecl GD, + raw_ostream &Out) { + const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl()); + PrettyStackTraceDecl CrashInfo(D, SourceLocation(), + getASTContext().getSourceManager(), + "Mangling Arm64EC function def"); + + if (!shouldMangleCXXName(D)) { + Out << '#' << D->getName(); + return; + } + + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); + return Mangler.mangleArm64ECFnDef(GD); +} + +void MicrosoftCXXNameMangler::mangleArm64ECFnDef(GlobalDecl GD) { + Out << '?'; + mangleName(GD); + mangleFunctionEncoding(GD, /*ShouldMangle*/true, /*Arm64ECDef*/true); +} + MicrosoftMangleContext * MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { return new MicrosoftMangleContextImpl(Context, Diags); Index: clang/include/clang/AST/Mangle.h =================================================================== --- clang/include/clang/AST/Mangle.h +++ clang/include/clang/AST/Mangle.h @@ -115,6 +115,10 @@ // FIXME: consider replacing raw_ostream & with something like SmallString &. void mangleName(GlobalDecl GD, raw_ostream &); + // Mangling for function definitions in Arm64EC ABI. + virtual void mangleArm64ECFnDef(GlobalDecl GD, raw_ostream &) { + llvm_unreachable("Unexpected ABI"); + } virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0; virtual void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits