Skip to content
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
3 changes: 3 additions & 0 deletions llvm/lib/IR/Mangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV,
}

std::optional<std::string> llvm::getArm64ECMangledFunctionName(StringRef Name) {
assert(!Name.empty() &&
"getArm64ECMangledFunctionName requires non-empty name");

if (Name[0] != '?') {
// For non-C++ symbols, prefix the name with "#" unless it's already
// mangled.
Expand Down
18 changes: 13 additions & 5 deletions llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,14 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
return Thunk;
}

std::optional<std::string> getArm64ECMangledFunctionName(GlobalValue &GV) {
if (!GV.hasName()) {
GV.setName("__unnamed");
}

return llvm::getArm64ECMangledFunctionName(GV.getName());
}

// Builds the "guest exit thunk", a helper to call a function which may or may
// not be an exit thunk. (We optimistically assume non-dllimport function
// declarations refer to functions defined in AArch64 code; if the linker
Expand All @@ -608,7 +616,7 @@ Function *AArch64Arm64ECCallLowering::buildGuestExitThunk(Function *F) {
getThunkType(F->getFunctionType(), F->getAttributes(),
Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
ArgTranslations);
auto MangledName = getArm64ECMangledFunctionName(F->getName().str());
auto MangledName = getArm64ECMangledFunctionName(*F);
assert(MangledName && "Can't guest exit to function that's already native");
std::string ThunkName = *MangledName;
if (ThunkName[0] == '?' && ThunkName.find("@") != std::string::npos) {
Expand Down Expand Up @@ -790,7 +798,7 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) {
if (!F)
continue;
if (std::optional<std::string> MangledName =
getArm64ECMangledFunctionName(A.getName().str())) {
getArm64ECMangledFunctionName(A)) {
F->addMetadata("arm64ec_unmangled_name",
*MDNode::get(M->getContext(),
MDString::get(M->getContext(), A.getName())));
Expand All @@ -807,7 +815,7 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) {
cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts());
if (PersFn->getValueType() && PersFn->getValueType()->isFunctionTy()) {
if (std::optional<std::string> MangledName =
getArm64ECMangledFunctionName(PersFn->getName().str())) {
getArm64ECMangledFunctionName(*PersFn)) {
PersFn->setName(MangledName.value());
}
}
Expand All @@ -821,7 +829,7 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) {
// Rename hybrid patchable functions and change callers to use a global
// alias instead.
if (std::optional<std::string> MangledName =
getArm64ECMangledFunctionName(F.getName().str())) {
getArm64ECMangledFunctionName(F)) {
std::string OrigName(F.getName());
F.setName(MangledName.value() + HybridPatchableTargetSuffix);

Expand Down Expand Up @@ -926,7 +934,7 @@ bool AArch64Arm64ECCallLowering::processFunction(
// FIXME: Handle functions with weak linkage?
if (!F.hasLocalLinkage() || F.hasAddressTaken()) {
if (std::optional<std::string> MangledName =
getArm64ECMangledFunctionName(F.getName().str())) {
getArm64ECMangledFunctionName(F)) {
F.addMetadata("arm64ec_unmangled_name",
*MDNode::get(M->getContext(),
MDString::get(M->getContext(), F.getName())));
Expand Down
15 changes: 15 additions & 0 deletions llvm/test/CodeGen/AArch64/arm64ec-empty-name.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; RUN: llc -mtriple=arm64ec-pc-windows-msvc %s -o - | FileCheck %s

; Regression test: Arm64EC needs to look at the first character of a function
; to decide if it will be mangled like a C or C++ function name, which caused
; it to crash for empty function names.
define void @""() {
ret void
}

define void @""() {
ret void
}

; CHECK: "#__unnamed":
; CHECK: "#__unnamed.1":