[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