[llvm] 97a32f2 - MC: Add MCSpecifierExpr to unify target MCExprs

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 7 11:33:45 PDT 2025


Author: Fangrui Song
Date: 2025-06-07T11:33:40-07:00
New Revision: 97a32f2ad9ded95806db1dcfc281f64b0c1874a6

URL: https://github.com/llvm/llvm-project/commit/97a32f2ad9ded95806db1dcfc281f64b0c1874a6
DIFF: https://github.com/llvm/llvm-project/commit/97a32f2ad9ded95806db1dcfc281f64b0c1874a6.diff

LOG: MC: Add MCSpecifierExpr to unify target MCExprs

Many targets define MCTargetExpr subclasses just to encode an expression
with a relocation specifier. Create a generic MCSpecifierExpr to be
inherited instead. Migrate M68k and SPARC as examples.

Added: 
    

Modified: 
    llvm/include/llvm/MC/MCExpr.h
    llvm/lib/MC/MCExpr.cpp
    llvm/lib/MC/MCParser/AsmParser.cpp
    llvm/lib/MC/MCStreamer.cpp
    llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp
    llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.cpp
    llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.cpp
    llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.h
    llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
    llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
    llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
    llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
    llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index fd3bb36dcde4f..0ba5532aac994 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -38,6 +38,7 @@ class MCExpr {
     Constant,  ///< Constant expressions.
     SymbolRef, ///< References to labels and assigned expressions.
     Unary,     ///< Unary expressions.
+    Specifier, ///< Expression with a relocation specifier.
     Target     ///< Target specific expression.
   };
 
@@ -502,6 +503,33 @@ class LLVM_ABI MCTargetExpr : public MCExpr {
   }
 };
 
+/// Extension point for target-specific MCExpr subclasses with a relocation
+/// specifier, serving as a replacement for MCSymbolRefExpr::VariantKind.
+/// Limit this to top-level use, avoiding its inclusion as a subexpression.
+class LLVM_ABI MCSpecifierExpr : public MCExpr {
+protected:
+  using Spec = uint16_t;
+  const MCExpr *Expr;
+  // Target-specific relocation specifier code
+  const Spec specifier;
+
+protected:
+  explicit MCSpecifierExpr(const MCExpr *Expr, Spec S)
+      : MCExpr(Specifier, SMLoc()), Expr(Expr), specifier(S) {}
+  virtual ~MCSpecifierExpr();
+
+public:
+  Spec getSpecifier() const { return specifier; }
+  const MCExpr *getSubExpr() const { return Expr; }
+
+  virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0;
+  bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm) const;
+
+  static bool classof(const MCExpr *E) {
+    return E->getKind() == MCExpr::Specifier;
+  }
+};
+
 } // end namespace llvm
 
 #endif // LLVM_MC_MCEXPR_H

diff  --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index f7224d61614e1..b1e25a28f3ae4 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -15,6 +15,7 @@
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/Support/Casting.h"
@@ -171,6 +172,9 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI,
       OS << ')';
     return;
   }
+
+  case MCExpr::Specifier:
+    return cast<MCSpecifierExpr>(this)->printImpl(OS, MAI);
   }
 
   llvm_unreachable("Invalid expression kind!");
@@ -207,6 +211,9 @@ bool MCExpr::isSymbolUsedInExpression(const MCSymbol *Sym) const {
         static_cast<const MCUnaryExpr *>(this)->getSubExpr();
     return SubExpr->isSymbolUsedInExpression(Sym);
   }
+  case MCExpr::Specifier:
+    return static_cast<const MCSpecifierExpr *>(this)->isSymbolUsedInExpression(
+        Sym);
   }
 
   llvm_unreachable("Unknown expr kind!");
@@ -702,6 +709,8 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
 
     return true;
   }
+  case Specifier:
+    return cast<MCSpecifierExpr>(this)->evaluateAsRelocatableImpl(Res, Asm);
   }
 
   llvm_unreachable("Invalid assembly expression kind!");
@@ -750,7 +759,21 @@ MCFragment *MCExpr::findAssociatedFragment() const {
     // Otherwise, return the first non-null fragment.
     return LHS_F ? LHS_F : RHS_F;
   }
+
+  case Specifier:
+    return cast<MCSpecifierExpr>(this)->getSubExpr()->findAssociatedFragment();
   }
 
   llvm_unreachable("Invalid assembly expression kind!");
 }
+
+MCSpecifierExpr::~MCSpecifierExpr() {}
+
+bool MCSpecifierExpr::evaluateAsRelocatableImpl(MCValue &Res,
+                                                const MCAssembler *Asm) const {
+  if (!getSubExpr()->evaluateAsRelocatable(Res, Asm))
+    return false;
+
+  Res.setSpecifier(specifier);
+  return !Res.getSubSym();
+}

diff  --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 145f909b58e8e..bb8c45bd901cd 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1344,6 +1344,8 @@ const MCExpr *MCAsmParser::applySpecifier(const MCExpr *E, uint32_t Spec) {
   // Recurse over the given expression, rebuilding it to apply the given variant
   // if there is exactly one symbol.
   switch (E->getKind()) {
+  case MCExpr::Specifier:
+    llvm_unreachable("cannot apply another specifier to MCSpecifierExpr");
   case MCExpr::Target:
   case MCExpr::Constant:
     return nullptr;

diff  --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index 618a35b9596aa..d70639b7bfe20 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -1186,6 +1186,10 @@ void MCStreamer::visitUsedExpr(const MCExpr &Expr) {
   case MCExpr::Unary:
     visitUsedExpr(*cast<MCUnaryExpr>(Expr).getSubExpr());
     break;
+
+  case MCExpr::Specifier:
+    visitUsedExpr(*cast<MCSpecifierExpr>(Expr).getSubExpr());
+    break;
   }
 }
 

diff  --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp
index 34fe093a931db..ab7e51ac28322 100644
--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp
+++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp
@@ -547,6 +547,7 @@ static bool needsPCRel(const MCExpr *Expr) {
   }
   case MCExpr::Unary:
     return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
+  case MCExpr::Specifier:
   case MCExpr::Target:
   case MCExpr::Constant:
     return false;

diff  --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.cpp
index 8eecfb99c88d3..40b85cd8bb3b9 100644
--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.cpp
+++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.cpp
@@ -557,6 +557,8 @@ static void knownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,
   case MCExpr::ExprKind::Target: {
     targetOpKnownBitsMapHelper(Expr, KBM, Depth);
     return;
+  case MCExpr::Specifier:
+    llvm_unreachable("unused by this backend");
   }
   }
 }

diff  --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.cpp
index 03a174311a6ec..22d8da263cea5 100644
--- a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.cpp
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.cpp
@@ -19,14 +19,3 @@ const M68kMCExpr *M68kMCExpr::create(const MCExpr *Expr, Specifier S,
 }
 
 void M68kMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {}
-
-bool M68kMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
-                                           const MCAssembler *Asm) const {
-  if (!getSubExpr()->evaluateAsRelocatable(Res, Asm))
-    return false;
-
-  Res.setSpecifier(specifier);
-  return !Res.getSubSym();
-}
-
-void M68kMCExpr::visitUsedExpr(MCStreamer &S) const { S.visitUsedExpr(*Expr); }

diff  --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.h b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.h
index d9b72da6318fc..02bffdcb2889b 100644
--- a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.h
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCExpr.h
@@ -18,7 +18,7 @@
 
 namespace llvm {
 
-class M68kMCExpr : public MCTargetExpr {
+class M68kMCExpr : public MCSpecifierExpr {
 public:
   enum Specifier {
     VK_None,
@@ -34,27 +34,14 @@ class M68kMCExpr : public MCTargetExpr {
     VK_TPOFF,
   };
 
-private:
-  const MCExpr *Expr;
-  const Specifier specifier;
-
 protected:
   explicit M68kMCExpr(const MCExpr *Expr, Specifier S)
-      : Expr(Expr), specifier(S) {}
+      : MCSpecifierExpr(Expr, S) {}
 
 public:
   static const M68kMCExpr *create(const MCExpr *, Specifier, MCContext &);
 
-  Specifier getSpecifier() const { return specifier; }
-  const MCExpr *getSubExpr() const { return Expr; }
-
   void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
-  bool evaluateAsRelocatableImpl(MCValue &Res,
-                                 const MCAssembler *Asm) const override;
-  void visitUsedExpr(MCStreamer &Streamer) const override;
-  MCFragment *findAssociatedFragment() const override {
-    return getSubExpr()->findAssociatedFragment();
-  }
 };
 } // namespace llvm
 

diff  --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index d1b94410c601a..40552cbf8e4ff 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -1783,6 +1783,8 @@ static bool isEvaluated(const MCExpr *Expr) {
   }
   case MCExpr::Unary:
     return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
+  case MCExpr::Specifier:
+    llvm_unreachable("unused by this backend");
   case MCExpr::Target:
     return true;
   }

diff  --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index ab6d252975859..acf55a2143fc7 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -87,6 +87,8 @@ EvaluateCRExpr(const MCExpr *E) {
 
     return Res < 0 ? -1 : Res;
   }
+  case MCExpr::Specifier:
+    llvm_unreachable("unused by this backend");
   }
 
   llvm_unreachable("Invalid expression kind!");
@@ -1420,6 +1422,8 @@ const MCExpr *PPCAsmParser::extractSpecifier(const MCExpr *E,
       return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
     break;
   }
+  case MCExpr::Specifier:
+    llvm_unreachable("unused by this backend");
   }
 
   return E;

diff  --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index 46db96b5f893d..3deeac38e5604 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -1661,6 +1661,9 @@ static bool hasGOTReference(const MCExpr *Expr) {
 
   case MCExpr::Unary:
     return hasGOTReference(cast<MCUnaryExpr>(Expr)->getSubExpr());
+
+  case MCExpr::Specifier:
+    llvm_unreachable("unused by this backend");
   }
   return false;
 }

diff  --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
index 5dab9191d0cf4..09e55a66fcc6b 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
@@ -133,16 +133,3 @@ uint16_t SparcMCExpr::getFixupKind() const {
   assert(uint16_t(specifier) < FirstTargetFixupKind);
   return specifier;
 }
-
-bool SparcMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
-                                            const MCAssembler *Asm) const {
-  if (!getSubExpr()->evaluateAsRelocatable(Res, Asm))
-    return false;
-
-  Res.setSpecifier(specifier);
-  return true;
-}
-
-void SparcMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
-  Streamer.visitUsedExpr(*getSubExpr());
-}

diff  --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
index 095b115ea5a05..8368e8ff8795b 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
@@ -20,32 +20,17 @@
 namespace llvm {
 
 class StringRef;
-class SparcMCExpr : public MCTargetExpr {
+class SparcMCExpr : public MCSpecifierExpr {
 private:
-  const uint16_t specifier;
-  const MCExpr *Expr;
-
   explicit SparcMCExpr(uint16_t S, const MCExpr *Expr)
-      : specifier(S), Expr(Expr) {}
+      : MCSpecifierExpr(Expr, S) {}
 
 public:
   static const SparcMCExpr *create(uint16_t S, const MCExpr *Expr,
                                    MCContext &Ctx);
-  uint16_t getSpecifier() const { return specifier; }
-  const MCExpr *getSubExpr() const { return Expr; }
   uint16_t getFixupKind() const;
 
   void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
-  bool evaluateAsRelocatableImpl(MCValue &Res,
-                                 const MCAssembler *Asm) const override;
-  void visitUsedExpr(MCStreamer &Streamer) const override;
-  MCFragment *findAssociatedFragment() const override {
-    return getSubExpr()->findAssociatedFragment();
-  }
-
-  static bool classof(const MCExpr *E) {
-    return E->getKind() == MCExpr::Target;
-  }
 
   static uint16_t parseSpecifier(StringRef name);
   static StringRef getSpecifierName(uint16_t S);

diff  --git a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
index ab499b55ef9b5..be4a5ec4a66d2 100644
--- a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
+++ b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
@@ -1048,6 +1048,8 @@ const MCExpr *VEAsmParser::extractSpecifier(const MCExpr *E,
   case MCExpr::Target:
   case MCExpr::Constant:
     return nullptr;
+  case MCExpr::Specifier:
+    llvm_unreachable("unused by this backend");
 
   case MCExpr::SymbolRef: {
     const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);


        


More information about the llvm-commits mailing list