[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