[llvm] r326704 - TableGen: Introduce an abstract variable resolver interface
Nicolai Haehnle via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 5 07:20:51 PST 2018
Author: nha
Date: Mon Mar 5 07:20:51 2018
New Revision: 326704
URL: http://llvm.org/viewvc/llvm-project?rev=326704&view=rev
Log:
TableGen: Introduce an abstract variable resolver interface
Summary:
The intention is to allow us to more easily restructure how resolving is
done, e.g. resolving multiple variables simultaneously, or using the
resolving mechanism to implement !foreach.
Change-Id: I4b976b54a32e240ad4f562f7eb86a4d663a20ea8
Reviewers: arsenm, craig.topper, tra, MartinO
Subscribers: wdng, llvm-commits
Differential Revision: https://reviews.llvm.org/D43564
Modified:
llvm/trunk/include/llvm/TableGen/Record.h
llvm/trunk/lib/TableGen/Record.cpp
llvm/trunk/lib/TableGen/TGParser.cpp
Modified: llvm/trunk/include/llvm/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=326704&r1=326703&r2=326704&view=diff
==============================================================================
--- llvm/trunk/include/llvm/TableGen/Record.h (original)
+++ llvm/trunk/include/llvm/TableGen/Record.h Mon Mar 5 07:20:51 2018
@@ -16,6 +16,7 @@
#define LLVM_TABLEGEN_RECORD_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
@@ -42,6 +43,7 @@ struct MultiClass;
class Record;
class RecordKeeper;
class RecordVal;
+class Resolver;
class StringInit;
//===----------------------------------------------------------------------===//
@@ -360,7 +362,7 @@ public:
/// variables which may not be defined at the time the expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
- virtual Init *resolveReferences(Record &R, const RecordVal *RV) const {
+ virtual Init *resolveReferences(Resolver &R) const {
return const_cast<Init *>(this);
}
@@ -508,7 +510,7 @@ public:
std::string getAsString() const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override {
assert(Bit < NumBits && "Bit index out of range!");
@@ -653,7 +655,7 @@ public:
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
///
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
@@ -746,7 +748,7 @@ public:
// possible to fold.
Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
};
@@ -800,7 +802,7 @@ public:
// possible to fold.
Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
};
@@ -862,7 +864,7 @@ public:
return LHS->isComplete() && MHS->isComplete() && RHS->isComplete();
}
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
};
@@ -897,7 +899,7 @@ public:
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
///
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override;
@@ -934,7 +936,7 @@ public:
unsigned getBitNum() const override { return Bit; }
std::string getAsString() const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned B) const override {
assert(B < 1 && "Bit index out of range!");
@@ -970,7 +972,7 @@ public:
unsigned getElementNum() const { return Element; }
std::string getAsString() const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override;
};
@@ -1030,7 +1032,7 @@ public:
Init *getBit(unsigned Bit) const override;
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override {
return Rec->getAsString() + "." + FieldName->getValue().str();
@@ -1105,7 +1107,7 @@ public:
return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames);
}
- Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+ Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
@@ -1605,6 +1607,63 @@ raw_ostream &operator<<(raw_ostream &OS,
Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
Init *Name, StringRef Scoper);
+//===----------------------------------------------------------------------===//
+// Resolvers
+//===----------------------------------------------------------------------===//
+
+/// Interface for looking up the initializer for a variable name, used by
+/// Init::resolveReferences.
+class Resolver {
+ Record *CurRec;
+
+public:
+ explicit Resolver(Record *CurRec) : CurRec(CurRec) {}
+ virtual ~Resolver() {}
+
+ Record *getCurrentRecord() const { return CurRec; }
+
+ /// Return the initializer for the given variable name (should normally be a
+ /// StringInit), or nullptr if the name could not be resolved.
+ virtual Init *resolve(Init *VarName) = 0;
+
+ // Whether bits in a BitsInit should stay unresolved if resolving them would
+ // result in a ? (UnsetInit). This behavior is used to represent instruction
+ // encodings by keeping references to unset variables within a record.
+ virtual bool keepUnsetBits() const { return false; }
+};
+
+/// Resolve all variables from a record except for unset variables.
+class RecordResolver final : public Resolver {
+ DenseMap<Init *, Init *> Cache;
+ SmallVector<Init *, 4> Stack;
+
+public:
+ explicit RecordResolver(Record &R) : Resolver(&R) {}
+
+ Init *resolve(Init *VarName) override;
+
+ bool keepUnsetBits() const override { return true; }
+};
+
+/// Resolve all references to a specific RecordVal.
+//
+// TODO: This is used for resolving references to template arguments, in a
+// rather inefficient way. Change those uses to resolve all template
+// arguments simultaneously and get rid of this class.
+class RecordValResolver final : public Resolver {
+ const RecordVal *RV;
+
+public:
+ explicit RecordValResolver(Record &R, const RecordVal *RV)
+ : Resolver(&R), RV(RV) {}
+
+ Init *resolve(Init *VarName) override {
+ if (VarName == RV->getNameInit())
+ return RV->getValue();
+ return nullptr;
+ }
+};
+
} // end namespace llvm
#endif // LLVM_TABLEGEN_RECORD_H
Modified: llvm/trunk/lib/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=326704&r1=326703&r2=326704&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/Record.cpp (original)
+++ llvm/trunk/lib/TableGen/Record.cpp Mon Mar 5 07:20:51 2018
@@ -312,15 +312,15 @@ std::string BitsInit::getAsString() cons
// Fix bit initializer to preserve the behavior that bit reference from a unset
// bits initializer will resolve into VarBitInit to keep the field name and bit
// number used in targets with fixed insn length.
-static Init *fixBitInit(const RecordVal *RV, Init *Before, Init *After) {
- if (RV || !isa<UnsetInit>(After))
+static Init *fixBitInit(const Resolver &R, Init *Before, Init *After) {
+ if (!isa<UnsetInit>(After) || !R.keepUnsetBits())
return After;
return Before;
}
// resolveReferences - If there are any field references that refer to fields
// that have been filled in, we can propagate the values now.
-Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) const {
+Init *BitsInit::resolveReferences(Resolver &R) const {
bool Changed = false;
SmallVector<Init *, 16> NewBits(getNumBits());
@@ -337,7 +337,7 @@ Init *BitsInit::resolveReferences(Record
if (CurBitVar == CachedBitVar) {
if (CachedBitVarChanged) {
Init *Bit = CachedInit->getBit(CurBit->getBitNum());
- NewBits[i] = fixBitInit(RV, CurBit, Bit);
+ NewBits[i] = fixBitInit(R, CurBit, Bit);
}
continue;
}
@@ -347,7 +347,7 @@ Init *BitsInit::resolveReferences(Record
Init *B;
do {
B = CurBitVar;
- CurBitVar = CurBitVar->resolveReferences(R, RV);
+ CurBitVar = CurBitVar->resolveReferences(R);
CachedBitVarChanged |= B != CurBitVar;
Changed |= B != CurBitVar;
} while (B != CurBitVar);
@@ -355,7 +355,7 @@ Init *BitsInit::resolveReferences(Record
if (CachedBitVarChanged) {
Init *Bit = CurBitVar->getBit(CurBit->getBitNum());
- NewBits[i] = fixBitInit(RV, CurBit, Bit);
+ NewBits[i] = fixBitInit(R, CurBit, Bit);
}
}
@@ -543,7 +543,7 @@ Record *ListInit::getElementAsRecord(uns
return DI->getDef();
}
-Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) const {
+Init *ListInit::resolveReferences(Resolver &R) const {
SmallVector<Init*, 8> Resolved;
Resolved.reserve(size());
bool Changed = false;
@@ -553,7 +553,7 @@ Init *ListInit::resolveReferences(Record
do {
E = CurElt;
- CurElt = CurElt->resolveReferences(R, RV);
+ CurElt = CurElt->resolveReferences(R);
Changed |= E != CurElt;
} while (E != CurElt);
Resolved.push_back(E);
@@ -706,12 +706,13 @@ Init *UnOpInit::Fold(Record *CurRec, Mul
return const_cast<UnOpInit *>(this);
}
-Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) const {
- Init *lhs = LHS->resolveReferences(R, RV);
+Init *UnOpInit::resolveReferences(Resolver &R) const {
+ Init *lhs = LHS->resolveReferences(R);
if (LHS != lhs)
- return (UnOpInit::get(getOpcode(), lhs, getType()))->Fold(&R, nullptr);
- return Fold(&R, nullptr);
+ return (UnOpInit::get(getOpcode(), lhs, getType()))
+ ->Fold(R.getCurrentRecord(), nullptr);
+ return Fold(R.getCurrentRecord(), nullptr);
}
std::string UnOpInit::getAsString() const {
@@ -854,13 +855,14 @@ Init *BinOpInit::Fold(Record *CurRec, Mu
return const_cast<BinOpInit *>(this);
}
-Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) const {
- Init *lhs = LHS->resolveReferences(R, RV);
- Init *rhs = RHS->resolveReferences(R, RV);
+Init *BinOpInit::resolveReferences(Resolver &R) const {
+ Init *lhs = LHS->resolveReferences(R);
+ Init *rhs = RHS->resolveReferences(R);
if (LHS != lhs || RHS != rhs)
- return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))->Fold(&R,nullptr);
- return Fold(&R, nullptr);
+ return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))
+ ->Fold(R.getCurrentRecord(), nullptr);
+ return Fold(R.getCurrentRecord(), nullptr);
}
std::string BinOpInit::getAsString() const {
@@ -1058,9 +1060,8 @@ Init *TernOpInit::Fold(Record *CurRec, M
return const_cast<TernOpInit *>(this);
}
-Init *TernOpInit::resolveReferences(Record &R,
- const RecordVal *RV) const {
- Init *lhs = LHS->resolveReferences(R, RV);
+Init *TernOpInit::resolveReferences(Resolver &R) const {
+ Init *lhs = LHS->resolveReferences(R);
if (getOpcode() == IF && lhs != LHS) {
IntInit *Value = dyn_cast<IntInit>(lhs);
@@ -1069,23 +1070,23 @@ Init *TernOpInit::resolveReferences(Reco
if (Value) {
// Short-circuit
if (Value->getValue()) {
- Init *mhs = MHS->resolveReferences(R, RV);
- return (TernOpInit::get(getOpcode(), lhs, mhs,
- RHS, getType()))->Fold(&R, nullptr);
+ Init *mhs = MHS->resolveReferences(R);
+ return (TernOpInit::get(getOpcode(), lhs, mhs, RHS, getType()))
+ ->Fold(R.getCurrentRecord(), nullptr);
}
- Init *rhs = RHS->resolveReferences(R, RV);
- return (TernOpInit::get(getOpcode(), lhs, MHS,
- rhs, getType()))->Fold(&R, nullptr);
+ Init *rhs = RHS->resolveReferences(R);
+ return (TernOpInit::get(getOpcode(), lhs, MHS, rhs, getType()))
+ ->Fold(R.getCurrentRecord(), nullptr);
}
}
- Init *mhs = MHS->resolveReferences(R, RV);
- Init *rhs = RHS->resolveReferences(R, RV);
+ Init *mhs = MHS->resolveReferences(R);
+ Init *rhs = RHS->resolveReferences(R);
if (LHS != lhs || MHS != mhs || RHS != rhs)
- return (TernOpInit::get(getOpcode(), lhs, mhs, rhs,
- getType()))->Fold(&R, nullptr);
- return Fold(&R, nullptr);
+ return (TernOpInit::get(getOpcode(), lhs, mhs, rhs, getType()))
+ ->Fold(R.getCurrentRecord(), nullptr);
+ return Fold(R.getCurrentRecord(), nullptr);
}
std::string TernOpInit::getAsString() const {
@@ -1248,10 +1249,9 @@ Init *VarInit::getBit(unsigned Bit) cons
return VarBitInit::get(const_cast<VarInit*>(this), Bit);
}
-Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const {
- if (RecordVal *Val = R.getValue(VarName))
- if (RV == Val || (!RV && !isa<UnsetInit>(Val->getValue())))
- return Val->getValue();
+Init *VarInit::resolveReferences(Resolver &R) const {
+ if (Init *Val = R.resolve(VarName))
+ return Val;
return const_cast<VarInit *>(this);
}
@@ -1278,8 +1278,8 @@ std::string VarBitInit::getAsString() co
return TI->getAsString() + "{" + utostr(Bit) + "}";
}
-Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const {
- Init *I = TI->resolveReferences(R, RV);
+Init *VarBitInit::resolveReferences(Resolver &R) const {
+ Init *I = TI->resolveReferences(R);
if (TI != I)
return I->getBit(getBitNum());
@@ -1302,9 +1302,8 @@ std::string VarListElementInit::getAsStr
return TI->getAsString() + "[" + utostr(Element) + "]";
}
-Init *
-VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const {
- Init *NewTI = TI->resolveReferences(R, RV);
+Init *VarListElementInit::resolveReferences(Resolver &R) const {
+ Init *NewTI = TI->resolveReferences(R);
if (ListInit *List = dyn_cast<ListInit>(NewTI)) {
// Leave out-of-bounds array references as-is. This can happen without
// being an error, e.g. in the untaken "branch" of an !if expression.
@@ -1360,12 +1359,12 @@ Init *FieldInit::getBit(unsigned Bit) co
return VarBitInit::get(const_cast<FieldInit*>(this), Bit);
}
-Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) const {
- Init *NewRec = Rec->resolveReferences(R, RV);
+Init *FieldInit::resolveReferences(Resolver &R) const {
+ Init *NewRec = Rec->resolveReferences(R);
if (DefInit *DI = dyn_cast<DefInit>(NewRec)) {
Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
- Init *BVR = FieldVal->resolveReferences(R, RV);
+ Init *BVR = FieldVal->resolveReferences(R);
if (BVR->isComplete())
return BVR;
}
@@ -1438,17 +1437,17 @@ Init *DagInit::convertInitializerTo(RecT
return nullptr;
}
-Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const {
+Init *DagInit::resolveReferences(Resolver &R) const {
SmallVector<Init*, 8> NewArgs;
NewArgs.reserve(arg_size());
bool ArgsChanged = false;
for (const Init *Arg : getArgs()) {
- Init *NewArg = Arg->resolveReferences(R, RV);
+ Init *NewArg = Arg->resolveReferences(R);
NewArgs.push_back(NewArg);
ArgsChanged |= NewArg != Arg;
}
- Init *Op = Val->resolveReferences(R, RV);
+ Init *Op = Val->resolveReferences(R);
if (Op != Val || ArgsChanged)
return DagInit::get(Op, ValName, NewArgs, getArgNames());
@@ -1538,11 +1537,19 @@ void Record::setName(Init *NewName) {
}
void Record::resolveReferencesTo(const RecordVal *RV) {
+ RecordResolver RecResolver(*this);
+ RecordValResolver RecValResolver(*this, RV);
+ Resolver *R;
+ if (RV)
+ R = &RecValResolver;
+ else
+ R = &RecResolver;
+
for (RecordVal &Value : Values) {
if (RV == &Value) // Skip resolve the same field as the given one
continue;
if (Init *V = Value.getValue())
- if (Value.setValue(V->resolveReferences(*this, RV)))
+ if (Value.setValue(V->resolveReferences(*R)))
PrintFatalError(getLoc(), "Invalid value is found when setting '" +
Value.getNameInitAsString() +
"' after resolving references" +
@@ -1552,7 +1559,7 @@ void Record::resolveReferencesTo(const R
: "") + "\n");
}
Init *OldName = getNameInit();
- Init *NewName = Name->resolveReferences(*this, RV);
+ Init *NewName = Name->resolveReferences(*R);
if (NewName != OldName) {
// Re-register with RecordKeeper.
setName(NewName);
@@ -1813,3 +1820,26 @@ Init *llvm::QualifyName(Record &CurRec,
NewName = BinOp->Fold(&CurRec, CurMultiClass);
return NewName;
}
+
+Init *RecordResolver::resolve(Init *VarName) {
+ Init *Val = Cache.lookup(VarName);
+ if (Val)
+ return Val;
+
+ for (Init *S : Stack) {
+ if (S == VarName)
+ return nullptr; // prevent infinite recursion
+ }
+
+ if (RecordVal *RV = getCurrentRecord()->getValue(VarName)) {
+ if (!isa<UnsetInit>(RV->getValue())) {
+ Val = RV->getValue();
+ Stack.push_back(VarName);
+ Val = Val->resolveReferences(*this);
+ Stack.pop_back();
+ }
+ }
+
+ Cache[VarName] = Val;
+ return Val;
+}
Modified: llvm/trunk/lib/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=326704&r1=326703&r2=326704&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.cpp (original)
+++ llvm/trunk/lib/TableGen/TGParser.cpp Mon Mar 5 07:20:51 2018
@@ -320,7 +320,8 @@ bool TGParser::ProcessForeachDefs(Record
// Process each value.
for (unsigned i = 0; i < List->size(); ++i) {
- Init *ItemVal = List->getElement(i)->resolveReferences(*CurRec, nullptr);
+ RecordResolver R(*CurRec);
+ Init *ItemVal = List->getElement(i)->resolveReferences(R);
IterVals.push_back(IterRecord(CurLoop.IterVar, ItemVal));
if (ProcessForeachDefs(CurRec, Loc, IterVals))
return true;
More information about the llvm-commits
mailing list