Skip to content

[AArch64] Transition from MCSymbolRefExpr::VariantKind constants #133214

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

MaskRay
Copy link
Member

@MaskRay MaskRay commented Mar 27, 2025

Shift ELF @plt and @gotpcrel references in data directives, as well as
Mach-O @specifier notations, to use AArch64MCExpr::Specifier constants.
This is a follow-up to #132595. COFF-specific specifiers are not moved
yet.

In addition, partition @-specifiers into COFF, ELF, and Mach-O, so that
mix-and-match is rejected at parse time.

ELF and Mach-O specifiers are distinct, with None being the only
shared value. For Mach-O-specific specifiers, we adopt the M_xxx naming
convention.

Created using spr 1.3.5-bogner
@llvmbot llvmbot added backend:AArch64 mc Machine (object) code labels Mar 27, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 27, 2025

@llvm/pr-subscribers-backend-aarch64

Author: Fangrui Song (MaskRay)

Changes

Shift ELF @<!-- -->plt and @<!-- -->gotpcrel references in data directives, as well as
Mach-O @<!-- -->specifier notations, to use AArch64MCExpr::Specifier constants.
This is a follow-up to #132595. COFF-specific specifiers are not moved
yet.

In addition, partition @-specifiers into COFF, ELF, and Mach-O, so that
mix-and-match is rejected at parse time.

ELF and Mach-O specifiers are distinct, with None being the only
shared value. For Mach-O-specific specifiers, we adopt the M_xxx naming
convention.


Patch is 32.07 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133214.diff

15 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (+1-1)
  • (modified) llvm/include/llvm/MC/MCAsmInfo.h (+4-1)
  • (modified) llvm/include/llvm/MC/MCExpr.h (-7)
  • (modified) llvm/lib/Target/AArch64/AArch64MCInstLower.cpp (+9-8)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp (+6-3)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.h (-5)
  • (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+37-36)
  • (modified) llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp (+11-10)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp (+9-12)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp (+24-16)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h (+22)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MachObjectWriter.cpp (+12-12)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp (+2-2)
  • (modified) llvm/test/MC/AArch64/coff-relocations.s (+7)
  • (modified) llvm/test/MC/AArch64/data-directive-specifier.s (+8)
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 76571690eeda0..8e321591b7190 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -37,7 +37,7 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
   SmallPtrSet<GlobalObject *, 2> Used;
 
 protected:
-  uint8_t PLTRelativeSpecifier = 0;
+  uint16_t PLTRelativeSpecifier = 0;
 
 public:
   TargetLoweringObjectFileELF();
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index d7beebf614516..2d5e9a51688aa 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -65,10 +65,13 @@ class MCAsmInfo {
                             /// quote, e.g., `'A`.
   };
 
-  struct VariantKindDesc {
+  // This describes a @ style relocation specifier (expr@specifier) supported by
+  // AsmParser::parsePrimaryExpr.
+  struct AtSpecifier {
     uint32_t Kind;
     StringRef Name;
   };
+  using VariantKindDesc = AtSpecifier;
 
 protected:
   //===------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 5bfbd2d9f8e71..83e122c6b38b4 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -199,13 +199,6 @@ class MCSymbolRefExpr : public MCExpr {
     VK_GOT,
     VK_GOTPCREL,
     VK_PLT,
-    VK_TLVP,    // Mach-O thread local variable relocations
-    VK_TLVPPAGE,
-    VK_TLVPPAGEOFF,
-    VK_PAGE,
-    VK_PAGEOFF,
-    VK_GOTPAGE,
-    VK_GOTPAGEOFF,
     VK_SECREL,
     VK_WEAKREF, // The link between the symbols in .weakref foo, bar
 
diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
index 6a02a75ddbb4d..165b7d8ad6330 100644
--- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
@@ -151,31 +151,32 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandMachO(const MachineOperand &MO,
                                                       MCSymbol *Sym) const {
   // FIXME: We would like an efficient form for this, so we don't have to do a
   // lot of extra uniquing.
-  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
+  auto Spec = AArch64MCExpr::None;
   if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
-      RefKind = MCSymbolRefExpr::VK_GOTPAGE;
+      Spec = AArch64MCExpr::M_GOTPAGE;
     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
              AArch64II::MO_PAGEOFF)
-      RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
+      Spec = AArch64MCExpr::M_GOTPAGEOFF;
     else
       llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
   } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
-      RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
+      Spec = AArch64MCExpr::M_TLVPPAGE;
     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
              AArch64II::MO_PAGEOFF)
-      RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
+      Spec = AArch64MCExpr::M_TLVPPAGEOFF;
     else
       llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
   } else {
     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
-      RefKind = MCSymbolRefExpr::VK_PAGE;
+      Spec = AArch64MCExpr::M_PAGE;
     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
              AArch64II::MO_PAGEOFF)
-      RefKind = MCSymbolRefExpr::VK_PAGEOFF;
+      Spec = AArch64MCExpr::M_PAGEOFF;
   }
-  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
+  // TODO: Migrate to AArch64MCExpr::create like ELF.
+  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Spec, Ctx);
   if (!MO.isJTI() && MO.getOffset())
     Expr = MCBinaryExpr::createAdd(
         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
index b662e75741d38..2649b060c6c9d 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
@@ -25,6 +25,9 @@ using namespace dwarf;
 void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
                                              const TargetMachine &TM) {
   TargetLoweringObjectFileELF::Initialize(Ctx, TM);
+  PLTRelativeSpecifier = AArch64MCExpr::VK_PLT;
+  SupportIndirectSymViaGOTPCRel = true;
+
   // AARCH64 ELF ABI does not define static relocation type for TLS offset
   // within a module.  Do not generate AT_location for TLS variables.
   SupportDebugThreadLocalLocation = false;
@@ -58,7 +61,7 @@ const MCExpr *AArch64_ELFTargetObjectFile::getIndirectSymViaGOTPCRel(
     int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
   int64_t FinalOffset = Offset + MV.getConstant();
   const MCExpr *Res =
-      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, getContext());
+      MCSymbolRefExpr::create(Sym, AArch64MCExpr::VK_GOTPCREL, getContext());
   const MCExpr *Off = MCConstantExpr::create(FinalOffset, getContext());
   return MCBinaryExpr::createAdd(Res, Off, getContext());
 }
@@ -77,7 +80,7 @@ const MCExpr *AArch64_MachoTargetObjectFile::getTTypeGlobalReference(
   if (Encoding & (DW_EH_PE_indirect | DW_EH_PE_pcrel)) {
     const MCSymbol *Sym = TM.getSymbol(GV);
     const MCExpr *Res =
-        MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, getContext());
+        MCSymbolRefExpr::create(Sym, AArch64MCExpr::M_GOT, getContext());
     MCSymbol *PCSym = getContext().createTempSymbol();
     Streamer.emitLabel(PCSym);
     const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
@@ -102,7 +105,7 @@ const MCExpr *AArch64_MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
   // On ARM64 Darwin, we can reference symbols with foo@GOT-., which
   // is an indirect pc-relative reference.
   const MCExpr *Res =
-      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, getContext());
+      MCSymbolRefExpr::create(Sym, AArch64MCExpr::VK_GOT, getContext());
   MCSymbol *PCSym = getContext().createTempSymbol();
   Streamer.emitLabel(PCSym);
   const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
index de79acd229873..6b3381452c70b 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
@@ -20,11 +20,6 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
   void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
 
 public:
-  AArch64_ELFTargetObjectFile() {
-    PLTRelativeSpecifier = MCSymbolRefExpr::VK_PLT;
-    SupportIndirectSymViaGOTPCRel = true;
-  }
-
   const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV,
                                           const MCSymbol *Sym,
                                           const MCValue &MV, int64_t Offset,
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 5be4bd9ec6b26..0caa1c997ccc6 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -339,7 +339,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
 
   static bool classifySymbolRef(const MCExpr *Expr,
                                 AArch64MCExpr::Specifier &ELFSpec,
-                                MCSymbolRefExpr::VariantKind &DarwinRefKind,
+                                AArch64MCExpr::Specifier &DarwinSpec,
                                 int64_t &Addend);
 };
 
@@ -889,16 +889,16 @@ class AArch64Operand : public MCParsedAsmOperand {
 
   bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
     AArch64MCExpr::Specifier ELFSpec;
-    MCSymbolRefExpr::VariantKind DarwinRefKind;
+    AArch64MCExpr::Specifier DarwinSpec;
     int64_t Addend;
-    if (!AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinRefKind,
+    if (!AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinSpec,
                                              Addend)) {
       // If we don't understand the expression, assume the best and
       // let the fixup and relocation code deal with it.
       return true;
     }
 
-    if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
+    if (DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
         llvm::is_contained(
             {AArch64MCExpr::VK_LO12, AArch64MCExpr::VK_GOT_LO12,
              AArch64MCExpr::VK_GOT_AUTH_LO12, AArch64MCExpr::VK_DTPREL_LO12,
@@ -912,8 +912,8 @@ class AArch64Operand : public MCParsedAsmOperand {
       // size when converted, so there is no "out of range" condition when using
       // @pageoff.
       return true;
-    } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
-               DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
+    } else if (DarwinSpec == AArch64MCExpr::M_GOTPAGEOFF ||
+               DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF) {
       // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
       return Addend == 0;
     }
@@ -1006,13 +1006,13 @@ class AArch64Operand : public MCParsedAsmOperand {
     }
 
     AArch64MCExpr::Specifier ELFSpec;
-    MCSymbolRefExpr::VariantKind DarwinRefKind;
+    AArch64MCExpr::Specifier DarwinSpec;
     int64_t Addend;
-    if (AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinRefKind,
+    if (AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinSpec,
                                             Addend)) {
-      return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
-             DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF ||
-             (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) ||
+      return DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
+             DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF ||
+             (DarwinSpec == AArch64MCExpr::M_GOTPAGEOFF && Addend == 0) ||
              llvm::is_contained(
                  {AArch64MCExpr::VK_LO12, AArch64MCExpr::VK_GOT_AUTH_LO12,
                   AArch64MCExpr::VK_DTPREL_HI12, AArch64MCExpr::VK_DTPREL_LO12,
@@ -1120,13 +1120,13 @@ class AArch64Operand : public MCParsedAsmOperand {
       return false;
 
     AArch64MCExpr::Specifier ELFSpec;
-    MCSymbolRefExpr::VariantKind DarwinRefKind;
+    AArch64MCExpr::Specifier DarwinSpec;
     int64_t Addend;
-    if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFSpec, DarwinRefKind,
+    if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFSpec, DarwinSpec,
                                              Addend)) {
       return false;
     }
-    if (DarwinRefKind != MCSymbolRefExpr::VK_None)
+    if (DarwinSpec != AArch64MCExpr::None)
       return false;
 
     return llvm::is_contained(AllowedModifiers, ELFSpec);
@@ -3297,22 +3297,22 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
     return ParseStatus::Failure;
 
   AArch64MCExpr::Specifier ELFSpec;
-  MCSymbolRefExpr::VariantKind DarwinRefKind;
+  AArch64MCExpr::Specifier DarwinSpec;
   int64_t Addend;
-  if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
-    if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
+  if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
+    if (DarwinSpec == AArch64MCExpr::None &&
         ELFSpec == AArch64MCExpr::VK_INVALID) {
       // No modifier was specified at all; this is the syntax for an ELF basic
       // ADRP relocation (unfortunately).
       Expr =
           AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
-    } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
-                DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
+    } else if ((DarwinSpec == AArch64MCExpr::M_GOTPAGE ||
+                DarwinSpec == AArch64MCExpr::M_TLVPPAGE) &&
                Addend != 0) {
       return Error(S, "gotpage label reference not allowed an addend");
-    } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
-               DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
-               DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
+    } else if (DarwinSpec != AArch64MCExpr::M_PAGE &&
+               DarwinSpec != AArch64MCExpr::M_GOTPAGE &&
+               DarwinSpec != AArch64MCExpr::M_TLVPPAGE &&
                ELFSpec != AArch64MCExpr::VK_ABS_PAGE_NC &&
                ELFSpec != AArch64MCExpr::VK_GOT_PAGE &&
                ELFSpec != AArch64MCExpr::VK_GOT_AUTH_PAGE &&
@@ -3351,10 +3351,10 @@ ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
     return ParseStatus::Failure;
 
   AArch64MCExpr::Specifier ELFSpec;
-  MCSymbolRefExpr::VariantKind DarwinRefKind;
+  AArch64MCExpr::Specifier DarwinSpec;
   int64_t Addend;
-  if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
-    if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
+  if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
+    if (DarwinSpec == AArch64MCExpr::None &&
         ELFSpec == AArch64MCExpr::VK_INVALID) {
       // No modifier was specified at all; this is the syntax for an ELF basic
       // ADR relocation (unfortunately).
@@ -5817,13 +5817,13 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
     if (Inst.getOperand(2).isExpr()) {
       const MCExpr *Expr = Inst.getOperand(2).getExpr();
       AArch64MCExpr::Specifier ELFSpec;
-      MCSymbolRefExpr::VariantKind DarwinRefKind;
+      AArch64MCExpr::Specifier DarwinSpec;
       int64_t Addend;
-      if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
+      if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
 
         // Only allow these with ADDXri.
-        if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
-             DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
+        if ((DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
+             DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF) &&
             Inst.getOpcode() == AArch64::ADDXri)
           return false;
 
@@ -8192,11 +8192,12 @@ bool AArch64AsmParser::parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc) {
   return false;
 }
 
-bool AArch64AsmParser::classifySymbolRef(
-    const MCExpr *Expr, AArch64MCExpr::Specifier &ELFSpec,
-    MCSymbolRefExpr::VariantKind &DarwinRefKind, int64_t &Addend) {
+bool AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
+                                         AArch64MCExpr::Specifier &ELFSpec,
+                                         AArch64MCExpr::Specifier &DarwinSpec,
+                                         int64_t &Addend) {
   ELFSpec = AArch64MCExpr::VK_INVALID;
-  DarwinRefKind = MCSymbolRefExpr::VK_None;
+  DarwinSpec = AArch64MCExpr::None;
   Addend = 0;
 
   if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
@@ -8207,7 +8208,7 @@ bool AArch64AsmParser::classifySymbolRef(
   const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
   if (SE) {
     // It's a simple symbol reference with no addend.
-    DarwinRefKind = SE->getKind();
+    DarwinSpec = AArch64MCExpr::Specifier(SE->getKind());
     return true;
   }
 
@@ -8223,13 +8224,13 @@ bool AArch64AsmParser::classifySymbolRef(
     return false;
 
   if (Res.getSymA())
-    DarwinRefKind = Res.getSymA()->getKind();
+    DarwinSpec = AArch64MCExpr::Specifier(Res.getSymA()->getKind());
   Addend = Res.getConstant();
 
   // It's some symbol reference + a constant addend, but really
   // shouldn't use both Darwin and ELF syntax.
   return ELFSpec == AArch64MCExpr::VK_INVALID ||
-         DarwinRefKind == MCSymbolRefExpr::VK_None;
+         DarwinSpec == AArch64MCExpr::None;
 }
 
 /// Force static initialization.
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp
index 09d706f0a303b..a9f237a5e6d1b 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "AArch64ExternalSymbolizer.h"
+#include "MCTargetDesc/AArch64MCExpr.h"
 #include "Utils/AArch64BaseInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
@@ -19,23 +20,23 @@ using namespace llvm;
 
 #define DEBUG_TYPE "aarch64-disassembler"
 
-static MCSymbolRefExpr::VariantKind
+static AArch64MCExpr::Specifier
 getVariant(uint64_t LLVMDisassembler_VariantKind) {
   switch (LLVMDisassembler_VariantKind) {
   case LLVMDisassembler_VariantKind_None:
-    return MCSymbolRefExpr::VK_None;
+    return AArch64MCExpr::None;
   case LLVMDisassembler_VariantKind_ARM64_PAGE:
-    return MCSymbolRefExpr::VK_PAGE;
+    return AArch64MCExpr::VK_PAGE;
   case LLVMDisassembler_VariantKind_ARM64_PAGEOFF:
-    return MCSymbolRefExpr::VK_PAGEOFF;
+    return AArch64MCExpr::VK_PAGEOFF;
   case LLVMDisassembler_VariantKind_ARM64_GOTPAGE:
-    return MCSymbolRefExpr::VK_GOTPAGE;
+    return AArch64MCExpr::M_GOTPAGE;
   case LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF:
-    return MCSymbolRefExpr::VK_GOTPAGEOFF;
+    return AArch64MCExpr::M_GOTPAGEOFF;
   case LLVMDisassembler_VariantKind_ARM64_TLVP:
-    return MCSymbolRefExpr::VK_TLVPPAGE;
+    return AArch64MCExpr::M_TLVPPAGE;
   case LLVMDisassembler_VariantKind_ARM64_TLVOFF:
-    return MCSymbolRefExpr::VK_TLVPPAGEOFF;
+    return AArch64MCExpr::M_TLVPPAGEOFF;
   default:
     llvm_unreachable("bad LLVMDisassembler_VariantKind");
   }
@@ -170,8 +171,8 @@ bool AArch64ExternalSymbolizer::tryAddingSymbolicOperand(
     if (SymbolicOp.AddSymbol.Name) {
       StringRef Name(SymbolicOp.AddSymbol.Name);
       MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
-      MCSymbolRefExpr::VariantKind Variant = getVariant(SymbolicOp.VariantKind);
-      if (Variant != MCSymbolRefExpr::VK_None)
+      auto Variant = getVariant(SymbolicOp.VariantKind);
+      if (Variant != AArch64MCExpr::None)
         Add = MCSymbolRefExpr::create(Sym, Variant, Ctx);
       else
         Add = MCSymbolRefExpr::create(Sym, Ctx);
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index a509edf160d32..fa72cbf032cdf 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -117,13 +117,9 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
   bool IsNC = AArch64MCExpr::isNotChecked(RefKind);
 
   assert((!Target.getSymA() ||
-          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None ||
-          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_PLT ||
-          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOTPCREL) &&
-         "Should only be expression-level modifiers here");
-
-  assert((!Target.getSymB() ||
-          Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
+          getSpecifier(Target.getSymA()) == AArch64MCExpr::None ||
+          getSpecifier(Target.getSymA()) == AArch64MCExpr::VK_PLT ||
+          getSpecifier(Target.getSymA()) == AArch64MCExpr::VK_GOTPCREL) &&
          "Should only be expression-level modifiers here");
 
   switch (SymLoc) {
@@ -147,7 +143,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
     case FK_Data_2:
       return R_CLS(PREL16);
     case FK_Data_4: {
-      return Target.getAccessVariant() == MCSymbolRefExpr::VK_PLT
+      return AArch64MCExpr::Specifier(Target.getAccessVariant()) ==
+                     AArch64MCExpr::VK_PLT
                  ? R_CLS(PLT32)
                  : R_CLS(PREL32);
     }
@@ -258,8 +255,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
     case FK_Data_2:
       return R_CLS(ABS16);
     case FK_Data_4:
-      return (!IsILP32 &&
-              Target.getAccessVariant() == MCSymbolRefExpr::VK_GOTPCREL)
+      return (!IsILP32 && AArch64MCExpr::Specifier(Target.getAccessVariant()) ==
+                              AArch64MCExpr::VK_GOTPCREL)
                  ? ELF::R_AARCH64_GOTPCREL32
     ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 27, 2025

@llvm/pr-subscribers-mc

Author: Fangrui Song (MaskRay)

Changes

Shift ELF @<!-- -->plt and @<!-- -->gotpcrel references in data directives, as well as
Mach-O @<!-- -->specifier notations, to use AArch64MCExpr::Specifier constants.
This is a follow-up to #132595. COFF-specific specifiers are not moved
yet.

In addition, partition @-specifiers into COFF, ELF, and Mach-O, so that
mix-and-match is rejected at parse time.

ELF and Mach-O specifiers are distinct, with None being the only
shared value. For Mach-O-specific specifiers, we adopt the M_xxx naming
convention.


Patch is 32.07 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133214.diff

15 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (+1-1)
  • (modified) llvm/include/llvm/MC/MCAsmInfo.h (+4-1)
  • (modified) llvm/include/llvm/MC/MCExpr.h (-7)
  • (modified) llvm/lib/Target/AArch64/AArch64MCInstLower.cpp (+9-8)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp (+6-3)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.h (-5)
  • (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+37-36)
  • (modified) llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp (+11-10)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp (+9-12)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp (+24-16)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h (+22)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MachObjectWriter.cpp (+12-12)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp (+2-2)
  • (modified) llvm/test/MC/AArch64/coff-relocations.s (+7)
  • (modified) llvm/test/MC/AArch64/data-directive-specifier.s (+8)
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 76571690eeda0..8e321591b7190 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -37,7 +37,7 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
   SmallPtrSet<GlobalObject *, 2> Used;
 
 protected:
-  uint8_t PLTRelativeSpecifier = 0;
+  uint16_t PLTRelativeSpecifier = 0;
 
 public:
   TargetLoweringObjectFileELF();
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index d7beebf614516..2d5e9a51688aa 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -65,10 +65,13 @@ class MCAsmInfo {
                             /// quote, e.g., `'A`.
   };
 
-  struct VariantKindDesc {
+  // This describes a @ style relocation specifier (expr@specifier) supported by
+  // AsmParser::parsePrimaryExpr.
+  struct AtSpecifier {
     uint32_t Kind;
     StringRef Name;
   };
+  using VariantKindDesc = AtSpecifier;
 
 protected:
   //===------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 5bfbd2d9f8e71..83e122c6b38b4 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -199,13 +199,6 @@ class MCSymbolRefExpr : public MCExpr {
     VK_GOT,
     VK_GOTPCREL,
     VK_PLT,
-    VK_TLVP,    // Mach-O thread local variable relocations
-    VK_TLVPPAGE,
-    VK_TLVPPAGEOFF,
-    VK_PAGE,
-    VK_PAGEOFF,
-    VK_GOTPAGE,
-    VK_GOTPAGEOFF,
     VK_SECREL,
     VK_WEAKREF, // The link between the symbols in .weakref foo, bar
 
diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
index 6a02a75ddbb4d..165b7d8ad6330 100644
--- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
@@ -151,31 +151,32 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandMachO(const MachineOperand &MO,
                                                       MCSymbol *Sym) const {
   // FIXME: We would like an efficient form for this, so we don't have to do a
   // lot of extra uniquing.
-  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
+  auto Spec = AArch64MCExpr::None;
   if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
-      RefKind = MCSymbolRefExpr::VK_GOTPAGE;
+      Spec = AArch64MCExpr::M_GOTPAGE;
     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
              AArch64II::MO_PAGEOFF)
-      RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
+      Spec = AArch64MCExpr::M_GOTPAGEOFF;
     else
       llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
   } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
-      RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
+      Spec = AArch64MCExpr::M_TLVPPAGE;
     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
              AArch64II::MO_PAGEOFF)
-      RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
+      Spec = AArch64MCExpr::M_TLVPPAGEOFF;
     else
       llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
   } else {
     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
-      RefKind = MCSymbolRefExpr::VK_PAGE;
+      Spec = AArch64MCExpr::M_PAGE;
     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
              AArch64II::MO_PAGEOFF)
-      RefKind = MCSymbolRefExpr::VK_PAGEOFF;
+      Spec = AArch64MCExpr::M_PAGEOFF;
   }
-  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
+  // TODO: Migrate to AArch64MCExpr::create like ELF.
+  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Spec, Ctx);
   if (!MO.isJTI() && MO.getOffset())
     Expr = MCBinaryExpr::createAdd(
         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
index b662e75741d38..2649b060c6c9d 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
@@ -25,6 +25,9 @@ using namespace dwarf;
 void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
                                              const TargetMachine &TM) {
   TargetLoweringObjectFileELF::Initialize(Ctx, TM);
+  PLTRelativeSpecifier = AArch64MCExpr::VK_PLT;
+  SupportIndirectSymViaGOTPCRel = true;
+
   // AARCH64 ELF ABI does not define static relocation type for TLS offset
   // within a module.  Do not generate AT_location for TLS variables.
   SupportDebugThreadLocalLocation = false;
@@ -58,7 +61,7 @@ const MCExpr *AArch64_ELFTargetObjectFile::getIndirectSymViaGOTPCRel(
     int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
   int64_t FinalOffset = Offset + MV.getConstant();
   const MCExpr *Res =
-      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, getContext());
+      MCSymbolRefExpr::create(Sym, AArch64MCExpr::VK_GOTPCREL, getContext());
   const MCExpr *Off = MCConstantExpr::create(FinalOffset, getContext());
   return MCBinaryExpr::createAdd(Res, Off, getContext());
 }
@@ -77,7 +80,7 @@ const MCExpr *AArch64_MachoTargetObjectFile::getTTypeGlobalReference(
   if (Encoding & (DW_EH_PE_indirect | DW_EH_PE_pcrel)) {
     const MCSymbol *Sym = TM.getSymbol(GV);
     const MCExpr *Res =
-        MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, getContext());
+        MCSymbolRefExpr::create(Sym, AArch64MCExpr::M_GOT, getContext());
     MCSymbol *PCSym = getContext().createTempSymbol();
     Streamer.emitLabel(PCSym);
     const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
@@ -102,7 +105,7 @@ const MCExpr *AArch64_MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
   // On ARM64 Darwin, we can reference symbols with foo@GOT-., which
   // is an indirect pc-relative reference.
   const MCExpr *Res =
-      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, getContext());
+      MCSymbolRefExpr::create(Sym, AArch64MCExpr::VK_GOT, getContext());
   MCSymbol *PCSym = getContext().createTempSymbol();
   Streamer.emitLabel(PCSym);
   const MCExpr *PC = MCSymbolRefExpr::create(PCSym, getContext());
diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
index de79acd229873..6b3381452c70b 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
@@ -20,11 +20,6 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
   void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
 
 public:
-  AArch64_ELFTargetObjectFile() {
-    PLTRelativeSpecifier = MCSymbolRefExpr::VK_PLT;
-    SupportIndirectSymViaGOTPCRel = true;
-  }
-
   const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV,
                                           const MCSymbol *Sym,
                                           const MCValue &MV, int64_t Offset,
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 5be4bd9ec6b26..0caa1c997ccc6 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -339,7 +339,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
 
   static bool classifySymbolRef(const MCExpr *Expr,
                                 AArch64MCExpr::Specifier &ELFSpec,
-                                MCSymbolRefExpr::VariantKind &DarwinRefKind,
+                                AArch64MCExpr::Specifier &DarwinSpec,
                                 int64_t &Addend);
 };
 
@@ -889,16 +889,16 @@ class AArch64Operand : public MCParsedAsmOperand {
 
   bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
     AArch64MCExpr::Specifier ELFSpec;
-    MCSymbolRefExpr::VariantKind DarwinRefKind;
+    AArch64MCExpr::Specifier DarwinSpec;
     int64_t Addend;
-    if (!AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinRefKind,
+    if (!AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinSpec,
                                              Addend)) {
       // If we don't understand the expression, assume the best and
       // let the fixup and relocation code deal with it.
       return true;
     }
 
-    if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
+    if (DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
         llvm::is_contained(
             {AArch64MCExpr::VK_LO12, AArch64MCExpr::VK_GOT_LO12,
              AArch64MCExpr::VK_GOT_AUTH_LO12, AArch64MCExpr::VK_DTPREL_LO12,
@@ -912,8 +912,8 @@ class AArch64Operand : public MCParsedAsmOperand {
       // size when converted, so there is no "out of range" condition when using
       // @pageoff.
       return true;
-    } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
-               DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
+    } else if (DarwinSpec == AArch64MCExpr::M_GOTPAGEOFF ||
+               DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF) {
       // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
       return Addend == 0;
     }
@@ -1006,13 +1006,13 @@ class AArch64Operand : public MCParsedAsmOperand {
     }
 
     AArch64MCExpr::Specifier ELFSpec;
-    MCSymbolRefExpr::VariantKind DarwinRefKind;
+    AArch64MCExpr::Specifier DarwinSpec;
     int64_t Addend;
-    if (AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinRefKind,
+    if (AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinSpec,
                                             Addend)) {
-      return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
-             DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF ||
-             (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) ||
+      return DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
+             DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF ||
+             (DarwinSpec == AArch64MCExpr::M_GOTPAGEOFF && Addend == 0) ||
              llvm::is_contained(
                  {AArch64MCExpr::VK_LO12, AArch64MCExpr::VK_GOT_AUTH_LO12,
                   AArch64MCExpr::VK_DTPREL_HI12, AArch64MCExpr::VK_DTPREL_LO12,
@@ -1120,13 +1120,13 @@ class AArch64Operand : public MCParsedAsmOperand {
       return false;
 
     AArch64MCExpr::Specifier ELFSpec;
-    MCSymbolRefExpr::VariantKind DarwinRefKind;
+    AArch64MCExpr::Specifier DarwinSpec;
     int64_t Addend;
-    if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFSpec, DarwinRefKind,
+    if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFSpec, DarwinSpec,
                                              Addend)) {
       return false;
     }
-    if (DarwinRefKind != MCSymbolRefExpr::VK_None)
+    if (DarwinSpec != AArch64MCExpr::None)
       return false;
 
     return llvm::is_contained(AllowedModifiers, ELFSpec);
@@ -3297,22 +3297,22 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
     return ParseStatus::Failure;
 
   AArch64MCExpr::Specifier ELFSpec;
-  MCSymbolRefExpr::VariantKind DarwinRefKind;
+  AArch64MCExpr::Specifier DarwinSpec;
   int64_t Addend;
-  if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
-    if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
+  if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
+    if (DarwinSpec == AArch64MCExpr::None &&
         ELFSpec == AArch64MCExpr::VK_INVALID) {
       // No modifier was specified at all; this is the syntax for an ELF basic
       // ADRP relocation (unfortunately).
       Expr =
           AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
-    } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
-                DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
+    } else if ((DarwinSpec == AArch64MCExpr::M_GOTPAGE ||
+                DarwinSpec == AArch64MCExpr::M_TLVPPAGE) &&
                Addend != 0) {
       return Error(S, "gotpage label reference not allowed an addend");
-    } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
-               DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
-               DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
+    } else if (DarwinSpec != AArch64MCExpr::M_PAGE &&
+               DarwinSpec != AArch64MCExpr::M_GOTPAGE &&
+               DarwinSpec != AArch64MCExpr::M_TLVPPAGE &&
                ELFSpec != AArch64MCExpr::VK_ABS_PAGE_NC &&
                ELFSpec != AArch64MCExpr::VK_GOT_PAGE &&
                ELFSpec != AArch64MCExpr::VK_GOT_AUTH_PAGE &&
@@ -3351,10 +3351,10 @@ ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
     return ParseStatus::Failure;
 
   AArch64MCExpr::Specifier ELFSpec;
-  MCSymbolRefExpr::VariantKind DarwinRefKind;
+  AArch64MCExpr::Specifier DarwinSpec;
   int64_t Addend;
-  if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
-    if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
+  if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
+    if (DarwinSpec == AArch64MCExpr::None &&
         ELFSpec == AArch64MCExpr::VK_INVALID) {
       // No modifier was specified at all; this is the syntax for an ELF basic
       // ADR relocation (unfortunately).
@@ -5817,13 +5817,13 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
     if (Inst.getOperand(2).isExpr()) {
       const MCExpr *Expr = Inst.getOperand(2).getExpr();
       AArch64MCExpr::Specifier ELFSpec;
-      MCSymbolRefExpr::VariantKind DarwinRefKind;
+      AArch64MCExpr::Specifier DarwinSpec;
       int64_t Addend;
-      if (classifySymbolRef(Expr, ELFSpec, DarwinRefKind, Addend)) {
+      if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
 
         // Only allow these with ADDXri.
-        if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
-             DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
+        if ((DarwinSpec == AArch64MCExpr::M_PAGEOFF ||
+             DarwinSpec == AArch64MCExpr::M_TLVPPAGEOFF) &&
             Inst.getOpcode() == AArch64::ADDXri)
           return false;
 
@@ -8192,11 +8192,12 @@ bool AArch64AsmParser::parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc) {
   return false;
 }
 
-bool AArch64AsmParser::classifySymbolRef(
-    const MCExpr *Expr, AArch64MCExpr::Specifier &ELFSpec,
-    MCSymbolRefExpr::VariantKind &DarwinRefKind, int64_t &Addend) {
+bool AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
+                                         AArch64MCExpr::Specifier &ELFSpec,
+                                         AArch64MCExpr::Specifier &DarwinSpec,
+                                         int64_t &Addend) {
   ELFSpec = AArch64MCExpr::VK_INVALID;
-  DarwinRefKind = MCSymbolRefExpr::VK_None;
+  DarwinSpec = AArch64MCExpr::None;
   Addend = 0;
 
   if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
@@ -8207,7 +8208,7 @@ bool AArch64AsmParser::classifySymbolRef(
   const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
   if (SE) {
     // It's a simple symbol reference with no addend.
-    DarwinRefKind = SE->getKind();
+    DarwinSpec = AArch64MCExpr::Specifier(SE->getKind());
     return true;
   }
 
@@ -8223,13 +8224,13 @@ bool AArch64AsmParser::classifySymbolRef(
     return false;
 
   if (Res.getSymA())
-    DarwinRefKind = Res.getSymA()->getKind();
+    DarwinSpec = AArch64MCExpr::Specifier(Res.getSymA()->getKind());
   Addend = Res.getConstant();
 
   // It's some symbol reference + a constant addend, but really
   // shouldn't use both Darwin and ELF syntax.
   return ELFSpec == AArch64MCExpr::VK_INVALID ||
-         DarwinRefKind == MCSymbolRefExpr::VK_None;
+         DarwinSpec == AArch64MCExpr::None;
 }
 
 /// Force static initialization.
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp
index 09d706f0a303b..a9f237a5e6d1b 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64ExternalSymbolizer.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "AArch64ExternalSymbolizer.h"
+#include "MCTargetDesc/AArch64MCExpr.h"
 #include "Utils/AArch64BaseInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
@@ -19,23 +20,23 @@ using namespace llvm;
 
 #define DEBUG_TYPE "aarch64-disassembler"
 
-static MCSymbolRefExpr::VariantKind
+static AArch64MCExpr::Specifier
 getVariant(uint64_t LLVMDisassembler_VariantKind) {
   switch (LLVMDisassembler_VariantKind) {
   case LLVMDisassembler_VariantKind_None:
-    return MCSymbolRefExpr::VK_None;
+    return AArch64MCExpr::None;
   case LLVMDisassembler_VariantKind_ARM64_PAGE:
-    return MCSymbolRefExpr::VK_PAGE;
+    return AArch64MCExpr::VK_PAGE;
   case LLVMDisassembler_VariantKind_ARM64_PAGEOFF:
-    return MCSymbolRefExpr::VK_PAGEOFF;
+    return AArch64MCExpr::VK_PAGEOFF;
   case LLVMDisassembler_VariantKind_ARM64_GOTPAGE:
-    return MCSymbolRefExpr::VK_GOTPAGE;
+    return AArch64MCExpr::M_GOTPAGE;
   case LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF:
-    return MCSymbolRefExpr::VK_GOTPAGEOFF;
+    return AArch64MCExpr::M_GOTPAGEOFF;
   case LLVMDisassembler_VariantKind_ARM64_TLVP:
-    return MCSymbolRefExpr::VK_TLVPPAGE;
+    return AArch64MCExpr::M_TLVPPAGE;
   case LLVMDisassembler_VariantKind_ARM64_TLVOFF:
-    return MCSymbolRefExpr::VK_TLVPPAGEOFF;
+    return AArch64MCExpr::M_TLVPPAGEOFF;
   default:
     llvm_unreachable("bad LLVMDisassembler_VariantKind");
   }
@@ -170,8 +171,8 @@ bool AArch64ExternalSymbolizer::tryAddingSymbolicOperand(
     if (SymbolicOp.AddSymbol.Name) {
       StringRef Name(SymbolicOp.AddSymbol.Name);
       MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
-      MCSymbolRefExpr::VariantKind Variant = getVariant(SymbolicOp.VariantKind);
-      if (Variant != MCSymbolRefExpr::VK_None)
+      auto Variant = getVariant(SymbolicOp.VariantKind);
+      if (Variant != AArch64MCExpr::None)
         Add = MCSymbolRefExpr::create(Sym, Variant, Ctx);
       else
         Add = MCSymbolRefExpr::create(Sym, Ctx);
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index a509edf160d32..fa72cbf032cdf 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -117,13 +117,9 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
   bool IsNC = AArch64MCExpr::isNotChecked(RefKind);
 
   assert((!Target.getSymA() ||
-          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None ||
-          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_PLT ||
-          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOTPCREL) &&
-         "Should only be expression-level modifiers here");
-
-  assert((!Target.getSymB() ||
-          Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
+          getSpecifier(Target.getSymA()) == AArch64MCExpr::None ||
+          getSpecifier(Target.getSymA()) == AArch64MCExpr::VK_PLT ||
+          getSpecifier(Target.getSymA()) == AArch64MCExpr::VK_GOTPCREL) &&
          "Should only be expression-level modifiers here");
 
   switch (SymLoc) {
@@ -147,7 +143,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
     case FK_Data_2:
       return R_CLS(PREL16);
     case FK_Data_4: {
-      return Target.getAccessVariant() == MCSymbolRefExpr::VK_PLT
+      return AArch64MCExpr::Specifier(Target.getAccessVariant()) ==
+                     AArch64MCExpr::VK_PLT
                  ? R_CLS(PLT32)
                  : R_CLS(PREL32);
     }
@@ -258,8 +255,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
     case FK_Data_2:
       return R_CLS(ABS16);
     case FK_Data_4:
-      return (!IsILP32 &&
-              Target.getAccessVariant() == MCSymbolRefExpr::VK_GOTPCREL)
+      return (!IsILP32 && AArch64MCExpr::Specifier(Target.getAccessVariant()) ==
+                              AArch64MCExpr::VK_GOTPCREL)
                  ? ELF::R_AARCH64_GOTPCREL32
     ...
[truncated]

Copy link
Collaborator

@smithp35 smithp35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At a glance, this looks reasonable to me. I like that the COFF, ELF and Darwin specifiers are now separated.

Apologies not had much time to look in detail. Will try and take a deeper look next week.

MaskRay added a commit to MaskRay/llvm-project that referenced this pull request Mar 29, 2025
Shift ELF `@plt` and `@gotpcrel` references in data directives, as well as
Mach-O `@specifier` notations, to use `AArch64MCExpr::Specifier` constants.
This is a follow-up to llvm#132595. COFF-specific specifiers are not moved
yet.

In addition, partition @-specifiers into COFF, ELF, and Mach-O, so that
mix-and-match is rejected at parse time.

ELF and Mach-O specifiers are distinct, with `None` being the only
shared value. For Mach-O-specific specifiers, we adopt the `M_xxx` naming
convention.

Pull Request: llvm#133214
@MaskRay
Copy link
Member Author

MaskRay commented Apr 2, 2025

Ping:)

@smithp35
Copy link
Collaborator

smithp35 commented Apr 2, 2025

I'll try and take a look tomorrow. Apologies for the delay.

Copy link
Collaborator

@smithp35 smithp35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question about an assert that was removed that I couldn't easily see why.

When that's resolved I can approve on the ELF side. It seems to affect Darwin more than it does ELF, so we should give Apple folks time to object.

Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOTPCREL) &&
"Should only be expression-level modifiers here");

assert((!Target.getSymB() ||
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assert has been removed. I would expect it to be writeable using getSpecifier like this

assert((!Target.getSymB() || getSpecifier(Target.getSymB()) == AArch64MCExpr::None &&
"Should only be expression-level modifiers here");

Is there another reason why this isn't necessary that I'm missing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A relocatable expression (specifier(SymA-SymB+C)) cannot have a legacy VariantKind on SymB.
Such an expression would have been rejected by MCAssembler::evaluateFixup "unsupported subtraction of qualified symbol".

I am actually changing MCValue::SymB from MCSymbolRefExpr to MCSymbol * so that getSpecifier(Target.getSymB()) would be impossible per the data representation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation!

Copy link
Collaborator

@smithp35 smithp35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM on the ELF side. Would be good to leave the Apple folk some time to look to see if they've got comments.

MaskRay added 3 commits April 4, 2025 10:19
Created using spr 1.3.5-bogner
Created using spr 1.3.5-bogner
.
Created using spr 1.3.5-bogner
@MaskRay MaskRay merged commit 71884b6 into main Apr 5, 2025
6 of 11 checks passed
@MaskRay MaskRay deleted the users/MaskRay/spr/aarch64-transition-from-mcsymbolrefexprvariantkind-constants branch April 5, 2025 02:57
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 5, 2025
…stants

Shift ELF `@plt` and `@gotpcrel` references in data directives, as well as
Mach-O `@specifier` notations, to use `AArch64MCExpr::Specifier` constants.
This is a follow-up to #132595. COFF-specific specifiers are not moved
yet.

In addition, partition @-specifiers into COFF, ELF, and Mach-O, so that
mix-and-match is rejected at parse time.

ELF and Mach-O specifiers are distinct, with `None` being the only
shared value. For Mach-O-specific specifiers, we adopt the `M_xxx` naming
convention.

Pull Request: llvm/llvm-project#133214
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants