Skip to content

[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

Merged
merged 1 commit into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion llvm/lib/IR/Mangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Object/COFF.h"
Copy link
Collaborator

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?

Copy link
Contributor Author

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.

#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"

using namespace llvm;

namespace {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -233,6 +235,16 @@ void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
} else {
Mangler.getNameWithPrefix(OS, GV, false);
}
if (TT.isWindowsArm64EC()) {
// Use EXPORTAS for mangled ARM64EC symbols.
// FIXME: During LTO, we're invoked prior to the EC lowering pass,
// so symbols are not yet mangled. Emitting the unmangled name
// typically functions correctly; the linker can resolve the export
// with the demangled alias.
if (std::optional<std::string> demangledName =
object::getArm64ECDemangledFunctionName(GV->getName()))
OS << ",EXPORTAS," << *demangledName;
}
if (NeedQuotes)
OS << "\"";

Expand Down
39 changes: 39 additions & 0 deletions llvm/test/CodeGen/AArch64/dllexport.ll
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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-EC-NOT: -export:f
; CHECK-GNU-EC-NOT: -export:#f,EXPORTAS,f
; CHECK-GNU-EC: .ascii " -export:#g,EXPORTAS,g
; CHECK-GNU-EC: .ascii " -export:#h,EXPORTAS,h
; CHECK-GNU-EC-NOT: -export:i
; CHECK-GNU-EC-NOT: -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-EC-NOT: /EXPORT:f
; CHECK-MSVC-EC-NOT: /EXPORT:#f,EXPORTAS,f
; CHECK-MSVC-EC: .ascii " /EXPORT:#g,EXPORTAS,g"
; CHECK-MSVC-EC: .ascii " /EXPORT:#h,EXPORTAS,h"
; CHECK-MSVC-EC-NOT: /EXPORT:i
; CHECK-MSVC-EC-NOT: /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"