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

Reply via email to