forked from OSchip/llvm-project
TableGen: Remove Init::resolveListElementReference
Summary: Resolving a VarListElementInit should just resolve the list and then take its element. This eliminates a lot of duplicated logic and simplifies the next steps of refactoring resolveReferences. This does potentially cause sub-elements of the entire list to be resolved resulting in more work, but I didn't notice a measurable change in performance, and a later patch adds a caching mechanism that covers at least the common case of `var[i]` in a more generic way. Change-Id: I7b59185b855c7368585c329c31e5be38c5749dac Reviewers: arsenm, craig.topper, tra, MartinO Subscribers: wdng, llvm-commits Differential Revision: https://reviews.llvm.org/D43562 llvm-svn: 326059
This commit is contained in:
parent
836684aff3
commit
801403acb3
|
@ -419,12 +419,6 @@ public:
|
|||
/// they are of record type.
|
||||
///
|
||||
RecTy *getFieldType(StringInit *FieldName) const override;
|
||||
|
||||
/// This method is used to implement
|
||||
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
||||
/// now, we return the resolved value, otherwise we return null.
|
||||
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const = 0;
|
||||
};
|
||||
|
||||
/// '?' - Represents an uninitialized value
|
||||
|
@ -471,11 +465,6 @@ public:
|
|||
|
||||
Init *convertInitializerTo(RecTy *Ty) const override;
|
||||
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override {
|
||||
llvm_unreachable("Illegal element reference off bit");
|
||||
}
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
assert(Bit < 1 && "Bit index out of range!");
|
||||
return const_cast<BitInit*>(this);
|
||||
|
@ -527,14 +516,6 @@ public:
|
|||
|
||||
std::string getAsString() const override;
|
||||
|
||||
/// This method is used to implement
|
||||
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
||||
/// now, we return the resolved value, otherwise we return null.
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override {
|
||||
llvm_unreachable("Illegal element reference off bits<n>");
|
||||
}
|
||||
|
||||
Init *resolveReferences(Record &R, const RecordVal *RV) const override;
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
|
@ -567,14 +548,6 @@ public:
|
|||
|
||||
std::string getAsString() const override;
|
||||
|
||||
/// This method is used to implement
|
||||
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
||||
/// now, we return the resolved value, otherwise we return null.
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override {
|
||||
llvm_unreachable("Illegal element reference off int");
|
||||
}
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
return BitInit::get((Value & (1ULL << Bit)) != 0);
|
||||
}
|
||||
|
@ -605,14 +578,6 @@ public:
|
|||
|
||||
std::string getAsUnquotedString() const override { return Value; }
|
||||
|
||||
/// resolveListElementReference - This method is used to implement
|
||||
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
||||
/// now, we return the resolved value, otherwise we return null.
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override {
|
||||
llvm_unreachable("Illegal element reference off string");
|
||||
}
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
llvm_unreachable("Illegal bit reference off string");
|
||||
}
|
||||
|
@ -645,14 +610,6 @@ public:
|
|||
|
||||
std::string getAsUnquotedString() const override { return Value; }
|
||||
|
||||
/// This method is used to implement
|
||||
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
||||
/// now, we return the resolved value, otherwise we return null.
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override {
|
||||
llvm_unreachable("Illegal element reference off string");
|
||||
}
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
llvm_unreachable("Illegal bit reference off string");
|
||||
}
|
||||
|
@ -718,12 +675,6 @@ public:
|
|||
size_t size () const { return NumValues; }
|
||||
bool empty() const { return NumValues == 0; }
|
||||
|
||||
/// This method is used to implement
|
||||
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
||||
/// now, we return the resolved value, otherwise we return null.
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override;
|
||||
|
||||
Init *getBit(unsigned Bit) const override {
|
||||
llvm_unreachable("Illegal bit reference off list");
|
||||
}
|
||||
|
@ -755,9 +706,6 @@ public:
|
|||
// possible to fold.
|
||||
virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0;
|
||||
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override;
|
||||
|
||||
Init *getBit(unsigned Bit) const override;
|
||||
};
|
||||
|
||||
|
@ -952,9 +900,6 @@ public:
|
|||
return getNameInit()->getAsUnquotedString();
|
||||
}
|
||||
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override;
|
||||
|
||||
RecTy *getFieldType(StringInit *FieldName) const override;
|
||||
Init *getFieldInit(Record &R, const RecordVal *RV,
|
||||
StringInit *FieldName) const override;
|
||||
|
@ -1003,11 +948,6 @@ public:
|
|||
std::string getAsString() const override;
|
||||
Init *resolveReferences(Record &R, const RecordVal *RV) const override;
|
||||
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override {
|
||||
llvm_unreachable("Illegal element reference off bit");
|
||||
}
|
||||
|
||||
Init *getBit(unsigned B) const override {
|
||||
assert(B < 1 && "Bit index out of range!");
|
||||
return const_cast<VarBitInit*>(this);
|
||||
|
@ -1041,12 +981,6 @@ public:
|
|||
TypedInit *getVariable() const { return TI; }
|
||||
unsigned getElementNum() const { return Element; }
|
||||
|
||||
/// This method is used to implement
|
||||
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
||||
/// now, we return the resolved value, otherwise we return null.
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override;
|
||||
|
||||
std::string getAsString() const override;
|
||||
Init *resolveReferences(Record &R, const RecordVal *RV) const override;
|
||||
|
||||
|
@ -1086,14 +1020,6 @@ public:
|
|||
Init *getBit(unsigned Bit) const override {
|
||||
llvm_unreachable("Illegal bit reference off def");
|
||||
}
|
||||
|
||||
/// This method is used to implement
|
||||
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
||||
/// now, we return the resolved value, otherwise we return null.
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override {
|
||||
llvm_unreachable("Illegal element reference off def");
|
||||
}
|
||||
};
|
||||
|
||||
/// X.Y - Represent a reference to a subfield of a variable
|
||||
|
@ -1118,9 +1044,6 @@ public:
|
|||
|
||||
Init *getBit(unsigned Bit) const override;
|
||||
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override;
|
||||
|
||||
Init *resolveReferences(Record &R, const RecordVal *RV) const override;
|
||||
|
||||
std::string getAsString() const override {
|
||||
|
@ -1218,11 +1141,6 @@ public:
|
|||
Init *getBit(unsigned Bit) const override {
|
||||
llvm_unreachable("Illegal bit reference off dag");
|
||||
}
|
||||
|
||||
Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const override {
|
||||
llvm_unreachable("Illegal element reference off dag");
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -564,19 +564,6 @@ Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
|||
return const_cast<ListInit *>(this);
|
||||
}
|
||||
|
||||
Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV,
|
||||
unsigned Elt) const {
|
||||
if (Elt >= size())
|
||||
return nullptr; // Out of range reference.
|
||||
Init *E = getElement(Elt);
|
||||
// If the element is set to some value, or if we are resolving a reference
|
||||
// to a specific variable and that variable is explicitly unset, then
|
||||
// replace the VarListElementInit with it.
|
||||
if (IRV || !isa<UnsetInit>(E))
|
||||
return E;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string ListInit::getAsString() const {
|
||||
std::string Result = "[";
|
||||
const char *sep = "";
|
||||
|
@ -588,24 +575,6 @@ std::string ListInit::getAsString() const {
|
|||
return Result + "]";
|
||||
}
|
||||
|
||||
Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV,
|
||||
unsigned Elt) const {
|
||||
Init *Resolved = resolveReferences(R, IRV);
|
||||
OpInit *OResolved = dyn_cast<OpInit>(Resolved);
|
||||
if (OResolved) {
|
||||
Resolved = OResolved->Fold(&R, nullptr);
|
||||
}
|
||||
|
||||
if (Resolved != this) {
|
||||
TypedInit *Typed = cast<TypedInit>(Resolved);
|
||||
if (Init *New = Typed->resolveListElementReference(R, IRV, Elt))
|
||||
return New;
|
||||
return VarListElementInit::get(Typed, Elt);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Init *OpInit::getBit(unsigned Bit) const {
|
||||
if (getType() == BitRecTy::get())
|
||||
return const_cast<OpInit*>(this);
|
||||
|
@ -1279,29 +1248,6 @@ Init *VarInit::getBit(unsigned Bit) const {
|
|||
return VarBitInit::get(const_cast<VarInit*>(this), Bit);
|
||||
}
|
||||
|
||||
Init *VarInit::resolveListElementReference(Record &R,
|
||||
const RecordVal *IRV,
|
||||
unsigned Elt) const {
|
||||
if (R.isTemplateArg(getNameInit())) return nullptr;
|
||||
if (IRV && IRV->getNameInit() != getNameInit()) return nullptr;
|
||||
|
||||
RecordVal *RV = R.getValue(getNameInit());
|
||||
assert(RV && "Reference to a non-existent variable?");
|
||||
ListInit *LI = dyn_cast<ListInit>(RV->getValue());
|
||||
if (!LI)
|
||||
return VarListElementInit::get(cast<TypedInit>(RV->getValue()), Elt);
|
||||
|
||||
if (Elt >= LI->size())
|
||||
return nullptr; // Out of range reference.
|
||||
Init *E = LI->getElement(Elt);
|
||||
// If the element is set to some value, or if we are resolving a reference
|
||||
// to a specific variable and that variable is explicitly unset, then
|
||||
// replace the VarListElementInit with it.
|
||||
if (IRV || !isa<UnsetInit>(E))
|
||||
return E;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RecTy *VarInit::getFieldType(StringInit *FieldName) const {
|
||||
if (RecordRecTy *RTy = dyn_cast<RecordRecTy>(getType()))
|
||||
if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName))
|
||||
|
@ -1380,9 +1326,15 @@ std::string VarListElementInit::getAsString() const {
|
|||
|
||||
Init *
|
||||
VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
||||
if (Init *I = getVariable()->resolveListElementReference(R, RV,
|
||||
getElementNum()))
|
||||
return I;
|
||||
Init *NewTI = TI->resolveReferences(R, RV);
|
||||
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.
|
||||
if (getElementNum() < List->size())
|
||||
return List->getElement(getElementNum());
|
||||
}
|
||||
if (NewTI != TI && isa<TypedInit>(NewTI))
|
||||
return VarListElementInit::get(cast<TypedInit>(NewTI), getElementNum());
|
||||
return const_cast<VarListElementInit *>(this);
|
||||
}
|
||||
|
||||
|
@ -1392,21 +1344,6 @@ Init *VarListElementInit::getBit(unsigned Bit) const {
|
|||
return VarBitInit::get(const_cast<VarListElementInit*>(this), Bit);
|
||||
}
|
||||
|
||||
Init *VarListElementInit:: resolveListElementReference(Record &R,
|
||||
const RecordVal *RV,
|
||||
unsigned Elt) const {
|
||||
if (Init *Result = TI->resolveListElementReference(R, RV, Element)) {
|
||||
if (TypedInit *TInit = dyn_cast<TypedInit>(Result)) {
|
||||
if (Init *Result2 = TInit->resolveListElementReference(R, RV, Elt))
|
||||
return Result2;
|
||||
return VarListElementInit::get(TInit, Elt);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DefInit *DefInit::get(Record *R) {
|
||||
return R->getDefInit();
|
||||
}
|
||||
|
@ -1450,22 +1387,6 @@ Init *FieldInit::getBit(unsigned Bit) const {
|
|||
return VarBitInit::get(const_cast<FieldInit*>(this), Bit);
|
||||
}
|
||||
|
||||
Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
|
||||
unsigned Elt) const {
|
||||
if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName))
|
||||
if (ListInit *LI = dyn_cast<ListInit>(ListVal)) {
|
||||
if (Elt >= LI->size()) return nullptr;
|
||||
Init *E = LI->getElement(Elt);
|
||||
|
||||
// If the element is set to some value, or if we are resolving a
|
||||
// reference to a specific variable and that variable is explicitly
|
||||
// unset, then replace the VarListElementInit with it.
|
||||
if (RV || !isa<UnsetInit>(E))
|
||||
return E;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
||||
Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec;
|
||||
|
||||
|
|
Loading…
Reference in New Issue