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.
This commit is contained in:
@@ -38,6 +38,7 @@ public:
|
||||
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 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// 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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class M68kMCExpr : public MCTargetExpr {
|
||||
class M68kMCExpr : public MCSpecifierExpr {
|
||||
public:
|
||||
enum Specifier {
|
||||
VK_None,
|
||||
@@ -34,27 +34,14 @@ public:
|
||||
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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user