[llvm] Fix #195006 Assembly failure with -save-temps when a function name matches a register name (PR #195538)
via llvm-commits
llvm-commits at lists.llvm.org
Sun May 3 10:35:22 PDT 2026
https://github.com/rishabhmadan19 created https://github.com/llvm/llvm-project/pull/195538
Resolved the bug where AArch64 assembly fails when function/variable names match register names. The assembler was interpreting unquoted symbols as registers instead of function/symbol names.
Solution Implemented
Implemented register name checking in AArch64 backend following X86's approach (#186570):
Implementation Files Modified (3):
1. AArch64MCAsmInfo.h - Added StringSet<> ReservedIdentifiers and isValidUnquotedName() overrides
2. AArch64MCAsmInfo.cpp - Implemented validation logic using helper function
3. AArch64MCTargetDesc.cpp - Added populateAArch64ReservedIdentifiers() to dynamically populate register names
>From 131871fdc81602bb4c2bd61925750a965e04596f Mon Sep 17 00:00:00 2001
From: rishabhmadan19 <rishabhkec at gmail.com>
Date: Sun, 3 May 2026 22:55:59 +0530
Subject: [PATCH] Fix #195006 Assembly failure with -save-temps when a function
name matches a register name
---
.../AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp | 30 +++++++++++++
.../AArch64/MCTargetDesc/AArch64MCAsmInfo.h | 9 ++++
.../MCTargetDesc/AArch64MCTargetDesc.cpp | 42 ++++++++++++++-----
.../CodeGen/AArch64/fold-global-offsets.ll | 36 ++++++++--------
llvm/test/CodeGen/AArch64/ghc-cc.ll | 4 +-
llvm/test/CodeGen/AArch64/win64_vararg.ll | 4 +-
6 files changed, 93 insertions(+), 32 deletions(-)
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
index ab7670e4758ef..2170b36663b55 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "AArch64MCAsmInfo.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCStreamer.h"
@@ -31,6 +32,19 @@ static cl::opt<AsmWriterVariantTy> AsmWriterVariant(
cl::values(clEnumValN(Generic, "generic", "Emit generic NEON assembly"),
clEnumValN(Apple, "apple", "Emit Apple-style NEON assembly")));
+// Helper function to check if a symbol name matches an AArch64 register name.
+// Uses the ReservedIdentifiers set populated from MCRegisterInfo.
+static bool isValidAArch64UnquotedName(const MCAsmInfo &MAI,
+ const StringSet<> &ReservedIdentifiers,
+ StringRef Name) {
+ // First check base class validation (character validity, etc.)
+ if (!MAI.MCAsmInfo::isValidUnquotedName(Name))
+ return false;
+
+ // Check if the name conflicts with a register name
+ return !ReservedIdentifiers.contains(Name.lower());
+}
+
const MCAsmInfo::AtSpecifier COFFAtSpecifiers[] = {
{MCSymbolRefExpr::VK_COFF_IMGREL32, "IMGREL"},
{AArch64::S_MACHO_PAGEOFF, "PAGEOFF"},
@@ -205,6 +219,10 @@ bool AArch64MCAsmInfoDarwin::evaluateAsRelocatableImpl(
return evaluate(Expr, Res, Asm);
}
+bool AArch64MCAsmInfoDarwin::isValidUnquotedName(StringRef Name) const {
+ return isValidAArch64UnquotedName(*this, ReservedIdentifiers, Name);
+}
+
AArch64MCAsmInfoELF::AArch64MCAsmInfoELF(const Triple &T,
const MCTargetOptions &Options)
: MCAsmInfoELF(Options) {
@@ -261,6 +279,10 @@ bool AArch64MCAsmInfoELF::evaluateAsRelocatableImpl(
return evaluate(Expr, Res, Asm);
}
+bool AArch64MCAsmInfoELF::isValidUnquotedName(StringRef Name) const {
+ return isValidAArch64UnquotedName(*this, ReservedIdentifiers, Name);
+}
+
AArch64MCAsmInfoMicrosoftCOFF::AArch64MCAsmInfoMicrosoftCOFF(
const MCTargetOptions &Options)
: MCAsmInfoMicrosoft(Options) {
@@ -293,6 +315,10 @@ bool AArch64MCAsmInfoMicrosoftCOFF::evaluateAsRelocatableImpl(
return evaluate(Expr, Res, Asm);
}
+bool AArch64MCAsmInfoMicrosoftCOFF::isValidUnquotedName(StringRef Name) const {
+ return isValidAArch64UnquotedName(*this, ReservedIdentifiers, Name);
+}
+
AArch64MCAsmInfoGNUCOFF::AArch64MCAsmInfoGNUCOFF(const MCTargetOptions &Options)
: MCAsmInfoGNUCOFF(Options) {
InternalSymbolPrefix = ".L";
@@ -323,3 +349,7 @@ bool AArch64MCAsmInfoGNUCOFF::evaluateAsRelocatableImpl(
const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {
return evaluate(Expr, Res, Asm);
}
+
+bool AArch64MCAsmInfoGNUCOFF::isValidUnquotedName(StringRef Name) const {
+ return isValidAArch64UnquotedName(*this, ReservedIdentifiers, Name);
+}
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
index 7a914967df636..4271618237383 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
@@ -14,6 +14,7 @@
#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCASMINFO_H
#include "Utils/AArch64BaseInfo.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/MC/MCAsmInfoCOFF.h"
#include "llvm/MC/MCAsmInfoDarwin.h"
#include "llvm/MC/MCAsmInfoELF.h"
@@ -26,6 +27,7 @@ class MCValue;
class Triple;
struct AArch64MCAsmInfoDarwin : public MCAsmInfoDarwin {
+ StringSet<> ReservedIdentifiers;
explicit AArch64MCAsmInfoDarwin(bool IsILP32, const MCTargetOptions &Options);
const MCExpr *
getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding,
@@ -34,30 +36,37 @@ struct AArch64MCAsmInfoDarwin : public MCAsmInfoDarwin {
const MCSpecifierExpr &Expr) const override;
bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res,
const MCAssembler *Asm) const override;
+ bool isValidUnquotedName(StringRef Name) const override;
};
struct AArch64MCAsmInfoELF : public MCAsmInfoELF {
+ StringSet<> ReservedIdentifiers;
explicit AArch64MCAsmInfoELF(const Triple &T, const MCTargetOptions &Options);
void printSpecifierExpr(raw_ostream &OS,
const MCSpecifierExpr &Expr) const override;
bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res,
const MCAssembler *Asm) const override;
+ bool isValidUnquotedName(StringRef Name) const override;
};
struct AArch64MCAsmInfoMicrosoftCOFF : public MCAsmInfoMicrosoft {
+ StringSet<> ReservedIdentifiers;
explicit AArch64MCAsmInfoMicrosoftCOFF(const MCTargetOptions &Options);
void printSpecifierExpr(raw_ostream &OS,
const MCSpecifierExpr &Expr) const override;
bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res,
const MCAssembler *Asm) const override;
+ bool isValidUnquotedName(StringRef Name) const override;
};
struct AArch64MCAsmInfoGNUCOFF : public MCAsmInfoGNUCOFF {
+ StringSet<> ReservedIdentifiers;
explicit AArch64MCAsmInfoGNUCOFF(const MCTargetOptions &Options);
void printSpecifierExpr(raw_ostream &OS,
const MCSpecifierExpr &Expr) const override;
bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res,
const MCAssembler *Asm) const override;
+ bool isValidUnquotedName(StringRef Name) const override;
};
namespace AArch64 {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
index 19cd509179709..14632e2af522e 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
@@ -18,6 +18,7 @@
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "MCTargetDesc/AArch64InstPrinter.h"
#include "TargetInfo/AArch64TargetInfo.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
@@ -344,21 +345,42 @@ static MCRegisterInfo *createAArch64MCRegisterInfo(const Triple &Triple) {
return X;
}
+// Populate the set of reserved identifiers (register names) that should be
+// quoted when used as symbol names in assembly output.
+static void populateAArch64ReservedIdentifiers(StringSet<> &Set,
+ const MCRegisterInfo &MRI) {
+ for (unsigned i = 1, e = MRI.getNumRegs(); i < e; ++i) {
+ if (const char *Name = MRI.getName(i)) {
+ if (Name[0])
+ Set.insert(StringRef(Name).lower());
+ }
+ }
+}
+
static MCAsmInfo *createAArch64MCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TheTriple,
const MCTargetOptions &Options) {
MCAsmInfo *MAI;
- if (TheTriple.isOSBinFormatMachO())
- MAI = new AArch64MCAsmInfoDarwin(TheTriple.getArch() == Triple::aarch64_32,
- Options);
- else if (TheTriple.isOSBinFormatELF())
- MAI = new AArch64MCAsmInfoELF(TheTriple, Options);
- else if (TheTriple.isWindowsMSVCEnvironment())
- MAI = new AArch64MCAsmInfoMicrosoftCOFF(Options);
- else if (TheTriple.isOSBinFormatCOFF())
- MAI = new AArch64MCAsmInfoGNUCOFF(Options);
- else
+ if (TheTriple.isOSBinFormatMachO()) {
+ auto *DarwinMAI = new AArch64MCAsmInfoDarwin(
+ TheTriple.getArch() == Triple::aarch64_32, Options);
+ populateAArch64ReservedIdentifiers(DarwinMAI->ReservedIdentifiers, MRI);
+ MAI = DarwinMAI;
+ } else if (TheTriple.isOSBinFormatELF()) {
+ auto *ELFMAI = new AArch64MCAsmInfoELF(TheTriple, Options);
+ populateAArch64ReservedIdentifiers(ELFMAI->ReservedIdentifiers, MRI);
+ MAI = ELFMAI;
+ } else if (TheTriple.isWindowsMSVCEnvironment()) {
+ auto *COFFMAI = new AArch64MCAsmInfoMicrosoftCOFF(Options);
+ populateAArch64ReservedIdentifiers(COFFMAI->ReservedIdentifiers, MRI);
+ MAI = COFFMAI;
+ } else if (TheTriple.isOSBinFormatCOFF()) {
+ auto *GNUCOFFMAI = new AArch64MCAsmInfoGNUCOFF(Options);
+ populateAArch64ReservedIdentifiers(GNUCOFFMAI->ReservedIdentifiers, MRI);
+ MAI = GNUCOFFMAI;
+ } else {
reportFatalUsageError("unsupported object format");
+ }
// Initial state of the frame pointer is SP.
unsigned Reg = MRI.getDwarfRegNum(AArch64::SP, true);
diff --git a/llvm/test/CodeGen/AArch64/fold-global-offsets.ll b/llvm/test/CodeGen/AArch64/fold-global-offsets.ll
index 8c2f019fd4735..b7529941d29dc 100644
--- a/llvm/test/CodeGen/AArch64/fold-global-offsets.ll
+++ b/llvm/test/CodeGen/AArch64/fold-global-offsets.ll
@@ -9,8 +9,8 @@
define i64 @f1() {
; CHECK-LABEL: f1:
; CHECK: // %bb.0:
-; CHECK-NEXT: adrp x8, x1+16
-; CHECK-NEXT: ldr x0, [x8, :lo12:x1+16]
+; CHECK-NEXT: adrp x8, "x1"+16
+; CHECK-NEXT: ldr x0, [x8, :lo12:"x1"+16]
; CHECK-NEXT: ret
%l = load i64, ptr getelementptr ([2 x i64], ptr @x1, i64 0, i64 2)
ret i64 %l
@@ -19,8 +19,8 @@ define i64 @f1() {
define i64 @f2() {
; CHECK-LABEL: f2:
; CHECK: // %bb.0:
-; CHECK-NEXT: adrp x8, x1
-; CHECK-NEXT: add x8, x8, :lo12:x1
+; CHECK-NEXT: adrp x8, "x1"
+; CHECK-NEXT: add x8, x8, :lo12:"x1"
; CHECK-NEXT: ldr x0, [x8, #24]
; CHECK-NEXT: ret
@@ -31,8 +31,8 @@ define i64 @f2() {
define i64 @f3() {
; CHECK-LABEL: f3:
; CHECK: // %bb.0:
-; CHECK-NEXT: adrp x8, x1+1
-; CHECK-NEXT: add x8, x8, :lo12:x1+1
+; CHECK-NEXT: adrp x8, "x1"+1
+; CHECK-NEXT: add x8, x8, :lo12:"x1"+1
; CHECK-NEXT: ldr x0, [x8]
; CHECK-NEXT: ret
%l = load i64, ptr getelementptr (i8, ptr @x1, i64 1)
@@ -44,17 +44,17 @@ define [2 x i64] @f4() {
;
; CHECK-SD-LABEL: f4:
; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: adrp x8, x2+8
-; CHECK-SD-NEXT: add x8, x8, :lo12:x2+8
+; CHECK-SD-NEXT: adrp x8, "x2"+8
+; CHECK-SD-NEXT: add x8, x8, :lo12:"x2"+8
; CHECK-SD-NEXT: ldp x0, x1, [x8]
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: f4:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: adrp x8, x2+8
-; CHECK-GI-NEXT: adrp x9, x2+8
-; CHECK-GI-NEXT: add x9, x9, :lo12:x2+8
-; CHECK-GI-NEXT: ldr x0, [x8, :lo12:x2+8]
+; CHECK-GI-NEXT: adrp x8, "x2"+8
+; CHECK-GI-NEXT: adrp x9, "x2"+8
+; CHECK-GI-NEXT: add x9, x9, :lo12:"x2"+8
+; CHECK-GI-NEXT: ldr x0, [x8, :lo12:"x2"+8]
; CHECK-GI-NEXT: ldr x1, [x9, #8]
; CHECK-GI-NEXT: ret
%l = load [2 x i64], ptr getelementptr (i8, ptr @x2, i64 8)
@@ -64,8 +64,8 @@ define [2 x i64] @f4() {
define i64 @f5() {
; CHECK-LABEL: f5:
; CHECK: // %bb.0:
-; CHECK-NEXT: adrp x8, x2+1048568
-; CHECK-NEXT: ldr x0, [x8, :lo12:x2+1048568]
+; CHECK-NEXT: adrp x8, "x2"+1048568
+; CHECK-NEXT: ldr x0, [x8, :lo12:"x2"+1048568]
; CHECK-NEXT: ret
%l = load i64, ptr getelementptr ([16777216 x i64], ptr @x2, i64 0, i64 131071)
ret i64 %l
@@ -75,8 +75,8 @@ define i64 @f6() {
; CHECK-LABEL: f6:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, #1048576 // =0x100000
-; CHECK-NEXT: adrp x9, x2
-; CHECK-NEXT: add x9, x9, :lo12:x2
+; CHECK-NEXT: adrp x9, "x2"
+; CHECK-NEXT: add x9, x9, :lo12:"x2"
; CHECK-NEXT: ldr x0, [x9, x8]
; CHECK-NEXT: ret
%l = load i64, ptr getelementptr ([16777216 x i64], ptr @x2, i64 0, i64 131072)
@@ -86,8 +86,8 @@ define i64 @f6() {
define i32 @f7() {
; CHECK-LABEL: f7:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: adrp x8, x3+108
-; CHECK-NEXT: ldr w0, [x8, :lo12:x3+108]
+; CHECK-NEXT: adrp x8, "x3"+108
+; CHECK-NEXT: ldr w0, [x8, :lo12:"x3"+108]
; CHECK-NEXT: ret
entry:
diff --git a/llvm/test/CodeGen/AArch64/ghc-cc.ll b/llvm/test/CodeGen/AArch64/ghc-cc.ll
index 5db7336ac47c2..ac9de3d2b2f01 100644
--- a/llvm/test/CodeGen/AArch64/ghc-cc.ll
+++ b/llvm/test/CodeGen/AArch64/ghc-cc.ll
@@ -72,8 +72,8 @@ entry:
define ghccc void @foo_double () nounwind {
entry:
; CHECK-LABEL: foo_double
- ; CHECK: adrp {{x[0-9]+}}, d1
- ; CHECK-NEXT: ldr d12, [{{x[0-9]+}}, :lo12:d1]
+ ; CHECK: adrp {{x[0-9]+}}, "d1"
+ ; CHECK-NEXT: ldr d12, [{{x[0-9]+}}, :lo12:"d1"]
; CHECK-NEXT: bl bar_double
; CHECK-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/win64_vararg.ll b/llvm/test/CodeGen/AArch64/win64_vararg.ll
index 0f4cb44a6f73b..0717ebfa8649b 100644
--- a/llvm/test/CodeGen/AArch64/win64_vararg.ll
+++ b/llvm/test/CodeGen/AArch64/win64_vararg.ll
@@ -104,8 +104,8 @@ declare i32 @__stdio_common_vsprintf(i64, ptr, i64, ptr, ptr, ptr) local_unnamed
declare ptr @__local_stdio_printf_options() local_unnamed_addr #4
define i32 @fp(ptr, i64, ptr, ...) local_unnamed_addr #6 {
-; CHECK-LABEL: fp:
-; CHECK: .seh_proc fp
+; CHECK-LABEL: "fp":
+; CHECK: .seh_proc "fp"
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: stp x19, x20, [sp, #-96]! // 16-byte Folded Spill
; CHECK-NEXT: .seh_save_regp_x x19, 96
More information about the llvm-commits
mailing list