-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[IR] Use EXPORTAS for ARM64EC mangled symbols with dllexport attribute. #81940
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-ir Author: Jacek Caban (cjacek) ChangesWe currently just use mangled name. This works fine, because linker should detect that and demangle it for the export table. However, on MSVC, the compiler is more specific and passes demangled name as well, with EXPORTAS. This PR aims to match that. MSVC doesn't use quotes in this case, so I added '#' to the list of characters that don't need it. Full diff: https://github.com/llvm/llvm-project/pull/81940.diff 2 Files Affected:
diff --git a/llvm/lib/IR/Mangler.cpp b/llvm/lib/IR/Mangler.cpp
index 3acac2c3e3db16..9d6a0ef6ec3aae 100644
--- a/llvm/lib/IR/Mangler.cpp
+++ b/llvm/lib/IR/Mangler.cpp
@@ -20,6 +20,8 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
+#include "llvm/Object/COFF.h"
+
using namespace llvm;
namespace {
@@ -192,7 +194,7 @@ void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
// Check if the name needs quotes to be safe for the linker to interpret.
static bool canBeUnquotedInDirective(char C) {
- return isAlnum(C) || C == '_' || C == '@';
+ return isAlnum(C) || C == '_' || C == '@' || C == '#';
}
static bool canBeUnquotedInDirective(StringRef Name) {
@@ -233,6 +235,11 @@ void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
} else {
Mangler.getNameWithPrefix(OS, GV, false);
}
+ if (TT.isWindowsArm64EC()) {
+ if (std::optional<std::string> demangledName =
+ object::getArm64ECDemangledFunctionName(GV->getName()))
+ OS << ",EXPORTAS," << *demangledName;
+ }
if (NeedQuotes)
OS << "\"";
diff --git a/llvm/test/CodeGen/AArch64/dllexport.ll b/llvm/test/CodeGen/AArch64/dllexport.ll
index 81ba674a0dedc1..5f2628619dcc3d 100644
--- a/llvm/test/CodeGen/AArch64/dllexport.ll
+++ b/llvm/test/CodeGen/AArch64/dllexport.ll
@@ -1,5 +1,7 @@
; RUN: llc -mtriple aarch64-windows-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-GNU
; RUN: llc -mtriple aarch64-windows-msvc -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MSVC
+; RUN: llc -mtriple arm64ec-windows-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-GNU-EC
+; RUN: llc -mtriple arm64ec-windows-msvc -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MSVC-EC
define void @f() {
ret void
@@ -71,3 +73,40 @@ define weak_odr dllexport void @l() {
; CHECK-MSVC: .ascii " /EXPORT:s"
; CHECK-MSVC: .ascii " /EXPORT:t"
; CHECK-MSVC: .ascii " /EXPORT:u"
+
+; CHECK-GNU-NOT-EC: -export:f
+; CHECK-GNU-NOT-EC: -export:#f,EXPORTAS,f
+; CHECK-GNU-EC: .ascii " -export:#g,EXPORTAS,g
+; CHECK-GNU-EC: .ascii " -export:#h,EXPORTAS,h
+; CHECK-GNU-NOT-EC: -export:i
+; CHECK-GNU-NOT-EC: -export:#i,EXPORTAS,i
+; CHECK-GNU-EC: .ascii " -export:#j,EXPORTAS,j"
+; CHECK-GNU-EC: .ascii " -export:#k,EXPORTAS,k"
+; CHECK-GNU-EC: .ascii " -export:#l,EXPORTAS,l"
+; CHECK-GNU-EC: .ascii " -export:m,data"
+; CHECK-GNU-EC: .ascii " -export:n,data"
+; 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-MSVC-NOT-EC: /EXPORT:f
+; CHECK-MSVC-NOT-EC: /EXPORT:#f,EXPORTAS,f
+; CHECK-MSVC-EC: .ascii " /EXPORT:#g,EXPORTAS,g"
+; CHECK-MSVC-EC: .ascii " /EXPORT:#h,EXPORTAS,h"
+; CHECK-MSVC-NOT-EC: /EXPORT:i
+; CHECK-MSVC-NOT-EC: /EXPORT:#i,EXPORTAS,i
+; CHECK-MSVC-EC: .ascii " /EXPORT:#j,EXPORTAS,j"
+; CHECK-MSVC-EC: .ascii " /EXPORT:#k,EXPORTAS,k"
+; CHECK-MSVC-EC: .ascii " /EXPORT:#l,EXPORTAS,l"
+; CHECK-MSVC-EC: .ascii " /EXPORT:m,DATA"
+; CHECK-MSVC-EC: .ascii " /EXPORT:n,DATA"
+; 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"
|
@llvm/pr-subscribers-backend-aarch64 Author: Jacek Caban (cjacek) ChangesWe currently just use mangled name. This works fine, because linker should detect that and demangle it for the export table. However, on MSVC, the compiler is more specific and passes demangled name as well, with EXPORTAS. This PR aims to match that. MSVC doesn't use quotes in this case, so I added '#' to the list of characters that don't need it. Full diff: https://github.com/llvm/llvm-project/pull/81940.diff 2 Files Affected:
diff --git a/llvm/lib/IR/Mangler.cpp b/llvm/lib/IR/Mangler.cpp
index 3acac2c3e3db16..9d6a0ef6ec3aae 100644
--- a/llvm/lib/IR/Mangler.cpp
+++ b/llvm/lib/IR/Mangler.cpp
@@ -20,6 +20,8 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
+#include "llvm/Object/COFF.h"
+
using namespace llvm;
namespace {
@@ -192,7 +194,7 @@ void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
// Check if the name needs quotes to be safe for the linker to interpret.
static bool canBeUnquotedInDirective(char C) {
- return isAlnum(C) || C == '_' || C == '@';
+ return isAlnum(C) || C == '_' || C == '@' || C == '#';
}
static bool canBeUnquotedInDirective(StringRef Name) {
@@ -233,6 +235,11 @@ void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
} else {
Mangler.getNameWithPrefix(OS, GV, false);
}
+ if (TT.isWindowsArm64EC()) {
+ if (std::optional<std::string> demangledName =
+ object::getArm64ECDemangledFunctionName(GV->getName()))
+ OS << ",EXPORTAS," << *demangledName;
+ }
if (NeedQuotes)
OS << "\"";
diff --git a/llvm/test/CodeGen/AArch64/dllexport.ll b/llvm/test/CodeGen/AArch64/dllexport.ll
index 81ba674a0dedc1..5f2628619dcc3d 100644
--- a/llvm/test/CodeGen/AArch64/dllexport.ll
+++ b/llvm/test/CodeGen/AArch64/dllexport.ll
@@ -1,5 +1,7 @@
; RUN: llc -mtriple aarch64-windows-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-GNU
; RUN: llc -mtriple aarch64-windows-msvc -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MSVC
+; RUN: llc -mtriple arm64ec-windows-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-GNU-EC
+; RUN: llc -mtriple arm64ec-windows-msvc -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MSVC-EC
define void @f() {
ret void
@@ -71,3 +73,40 @@ define weak_odr dllexport void @l() {
; CHECK-MSVC: .ascii " /EXPORT:s"
; CHECK-MSVC: .ascii " /EXPORT:t"
; CHECK-MSVC: .ascii " /EXPORT:u"
+
+; CHECK-GNU-NOT-EC: -export:f
+; CHECK-GNU-NOT-EC: -export:#f,EXPORTAS,f
+; CHECK-GNU-EC: .ascii " -export:#g,EXPORTAS,g
+; CHECK-GNU-EC: .ascii " -export:#h,EXPORTAS,h
+; CHECK-GNU-NOT-EC: -export:i
+; CHECK-GNU-NOT-EC: -export:#i,EXPORTAS,i
+; CHECK-GNU-EC: .ascii " -export:#j,EXPORTAS,j"
+; CHECK-GNU-EC: .ascii " -export:#k,EXPORTAS,k"
+; CHECK-GNU-EC: .ascii " -export:#l,EXPORTAS,l"
+; CHECK-GNU-EC: .ascii " -export:m,data"
+; CHECK-GNU-EC: .ascii " -export:n,data"
+; 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-MSVC-NOT-EC: /EXPORT:f
+; CHECK-MSVC-NOT-EC: /EXPORT:#f,EXPORTAS,f
+; CHECK-MSVC-EC: .ascii " /EXPORT:#g,EXPORTAS,g"
+; CHECK-MSVC-EC: .ascii " /EXPORT:#h,EXPORTAS,h"
+; CHECK-MSVC-NOT-EC: /EXPORT:i
+; CHECK-MSVC-NOT-EC: /EXPORT:#i,EXPORTAS,i
+; CHECK-MSVC-EC: .ascii " /EXPORT:#j,EXPORTAS,j"
+; CHECK-MSVC-EC: .ascii " /EXPORT:#k,EXPORTAS,k"
+; CHECK-MSVC-EC: .ascii " /EXPORT:#l,EXPORTAS,l"
+; CHECK-MSVC-EC: .ascii " /EXPORT:m,DATA"
+; CHECK-MSVC-EC: .ascii " /EXPORT:n,DATA"
+; 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:#g,EXPORTAS,g" | ||
; CHECK-MSVC-EC: .ascii " /EXPORT:#h,EXPORTAS,h" | ||
; CHECK-MSVC-NOT-EC: /EXPORT:i | ||
; CHECK-MSVC-NOT-EC: /EXPORT:#i,EXPORTAS,i |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think "CHECK-MSVC-NOT-EC" will be parsed by any of the FileCheck commands?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right. I pushed a fix, thanks.
I'm a bit concerned about the interaction between emitLinkerFlagsForGlobalCOFF() and the EC lowering pass. It looks like emitLinkerFlagsForGlobalCOFF() is used by LTO to compute this data in some (?) cases. This is before we'd normally do EC lowering. But the code generator calls it late, after EC lowering. So there's going to be some inconsistency there. That said, I'm not really sure what the linker is actually doing with the flags before LTO. And I guess supporting LTO isn't really a high priority at the moment. Maybe worth leaving a FIXME, at least. |
I can reproduce the inconsistency. In fact, it's already there: for LTO we use demangled names, while for the regular compilation we use mangled ones. In practice, this is fine with the linker as it will resolve demangled name from generated aliases, but it differs from the regular build. I'm not sure what would be the best way to use EXPORTAS in that case. I was thinking about predicting that demangled functions will get mangled later anyway and mangling them using BTW, simple LTO cases seem to work with my WIP branch implementing ARM64EC in LLD (https://github.com/cjacek/llvm-project/commits/arm64ec). Hacking use of EXPORTAS as I described above actually makes it not work, because then linker doesn't know that bitcode will eventually expose ARM64EC symbols. This seems to be a more general problem, I didn't really look deeper at it yet as I'd like to get basics right first. It's likely that the fix should be in LLD, but possibly not only. I think that a FIXME comment is best for now, I will add one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -18,8 +18,10 @@ | |||
#include "llvm/IR/DerivedTypes.h" | |||
#include "llvm/IR/Function.h" | |||
#include "llvm/IR/Module.h" | |||
#include "llvm/Object/COFF.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(this comes up when I tried to fix the upstream bazel build failure)
We seem to introduce a cycle dependency here, in bazel config, we have
- llvm:Core target which includes all lib/IR/* files
- llvm:Object target depends on llvm:Core
This change makes llvm:Core depends on llvm:Object. Can we remove this dependency? We only need object::getArm64ECDemangledFunctionName
in this file, is it possible (and sensible) to move this inline getArm64ECDemangledFunctionName
from COFF.h
to Mangler.h
or a new file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know that inline functions are a problem, sorry. I created #87191 moving those helpers to Mangler.h
.
We currently just use mangled name. This works fine, because linker should detect that and demangle it for the export table. However, on MSVC, the compiler is more specific and passes demangled name as well, with EXPORTAS. This PR aims to match that. MSVC doesn't use quotes in this case, so I added '#' to the list of characters that don't need it.