From 577fc3f5760fd980e8b41fce3f6300b2ba6d5cfa Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 27 Jul 2004 01:01:21 +0000 Subject: [PATCH] Implement test/Regression/TableGen/ListSlices.td llvm-svn: 15249 --- llvm/utils/TableGen/Record.cpp | 115 ++++++++++++++++++++++++++------- llvm/utils/TableGen/Record.h | 56 ++++++++++++++-- 2 files changed, 142 insertions(+), 29 deletions(-) diff --git a/llvm/utils/TableGen/Record.cpp b/llvm/utils/TableGen/Record.cpp index fee36b023a38..717962794a07 100644 --- a/llvm/utils/TableGen/Record.cpp +++ b/llvm/utils/TableGen/Record.cpp @@ -320,6 +320,28 @@ Init *ListInit::convertInitListSlice(const std::vector &Elements) { return new ListInit(Vals); } +Init *ListInit::resolveReferences(Record &R) { + std::vector Resolved; + Resolved.reserve(getSize()); + bool Changed = false; + + for (unsigned i = 0, e = getSize(); i != e; ++i) { + Init *E; + Init *CurElt = getElement(i); + + do { + E = CurElt; + CurElt = CurElt->resolveReferences(R); + Changed |= E != CurElt; + } while (E != CurElt); + Resolved.push_back(E); + } + + if (Changed) + return new ListInit(Resolved); + return this; +} + void ListInit::print(std::ostream &OS) const { OS << "["; for (unsigned i = 0, e = Values.size(); i != e; ++i) { @@ -329,7 +351,7 @@ void ListInit::print(std::ostream &OS) const { OS << "]"; } -Init *VarInit::convertInitializerBitRange(const std::vector &Bits) { +Init *TypedInit::convertInitializerBitRange(const std::vector &Bits) { BitsRecTy *T = dynamic_cast(getType()); if (T == 0) return 0; // Cannot subscript a non-bits variable... unsigned NumBits = T->getNumBits(); @@ -345,9 +367,24 @@ Init *VarInit::convertInitializerBitRange(const std::vector &Bits) { return BI; } +Init *TypedInit::convertInitListSlice(const std::vector &Elements) { + ListRecTy *T = dynamic_cast(getType()); + if (T == 0) return 0; // Cannot subscript a non-list variable... + + if (Elements.size() == 1) + return new VarListElementInit(this, Elements[0]); + + std::vector ListInits; + ListInits.reserve(Elements.size()); + for (unsigned i = 0, e = Elements.size(); i != e; ++i) + ListInits.push_back(new VarListElementInit(this, Elements[i])); + return new ListInit(ListInits); +} + + Init *VarInit::resolveBitReference(Record &R, unsigned Bit) { if (R.isTemplateArg(getName())) - return this; + return 0; RecordVal *RV = R.getValue(getName()); assert(RV && "Reference to a non-existant variable?"); @@ -359,9 +396,27 @@ Init *VarInit::resolveBitReference(Record &R, unsigned Bit) { if (!dynamic_cast(B)) // If the bit is not set... return B; // Replace the VarBitInit with it. - return this; + return 0; } +Init *VarInit::resolveListElementReference(Record &R, unsigned Elt) { + if (R.isTemplateArg(getName())) + return 0; + + RecordVal *RV = R.getValue(getName()); + assert(RV && "Reference to a non-existant variable?"); + ListInit *LI = dynamic_cast(RV->getValue()); + assert(LI && "Invalid list element!"); + + if (Elt >= LI->getSize()) + return 0; // Out of range reference. + Init *E = LI->getElement(Elt); + if (!dynamic_cast(E)) // If the element is set + return E; // Replace the VarListElementInit with it. + return 0; +} + + RecTy *VarInit::getFieldType(const std::string &FieldName) const { if (RecordRecTy *RTy = dynamic_cast(getType())) if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName)) @@ -396,12 +451,29 @@ Init *VarInit::resolveReferences(Record &R) { Init *VarBitInit::resolveReferences(Record &R) { - Init *I = getVariable()->resolveBitReference(R, getBitNum()); - if (I != getVariable()) + if (Init *I = getVariable()->resolveBitReference(R, getBitNum())) return I; return this; } +Init *VarListElementInit::resolveReferences(Record &R) { + if (Init *I = getVariable()->resolveListElementReference(R, getElementNum())) + return I; + return this; +} + +Init *VarListElementInit::resolveBitReference(Record &R, unsigned Bit) { + // FIXME: This should be implemented, to support references like: + // bit B = AA[0]{1}; + return 0; +} + +Init *VarListElementInit::resolveListElementReference(Record &R, unsigned Elt) { + // FIXME: This should be implemented, to support references like: + // int B = AA[0][1]; + return 0; +} + RecTy *DefInit::getFieldType(const std::string &FieldName) const { if (const RecordVal *RV = Def->getValue(FieldName)) return RV->getType(); @@ -417,25 +489,8 @@ void DefInit::print(std::ostream &OS) const { OS << Def->getName(); } -Init *FieldInit::convertInitializerBitRange(const std::vector &Bits) { - BitsRecTy *T = dynamic_cast(getType()); - if (T == 0) return 0; // Cannot subscript a non-bits field... - unsigned NumBits = T->getNumBits(); - - BitsInit *BI = new BitsInit(Bits.size()); - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= NumBits) { - delete BI; - return 0; - } - BI->setBit(i, new VarBitInit(this, Bits[i])); - } - return BI; -} - Init *FieldInit::resolveBitReference(Record &R, unsigned Bit) { - Init *BitsVal = Rec->getFieldInit(R, FieldName); - if (BitsVal) + if (Init *BitsVal = Rec->getFieldInit(R, FieldName)) if (BitsInit *BI = dynamic_cast(BitsVal)) { assert(Bit < BI->getNumBits() && "Bit reference out of range!"); Init *B = BI->getBit(Bit); @@ -443,7 +498,19 @@ Init *FieldInit::resolveBitReference(Record &R, unsigned Bit) { if (dynamic_cast(B)) // If the bit is set... return B; // Replace the VarBitInit with it. } - return this; + return 0; +} + +Init *FieldInit::resolveListElementReference(Record &R, unsigned Elt) { + if (Init *ListVal = Rec->getFieldInit(R, FieldName)) + if (ListInit *LI = dynamic_cast(ListVal)) { + if (Elt >= LI->getSize()) return 0; + Init *E = LI->getElement(Elt); + + if (!dynamic_cast(E)) // If the bit is set... + return E; // Replace the VarListElementInit with it. + } + return 0; } Init *FieldInit::resolveReferences(Record &R) { diff --git a/llvm/utils/TableGen/Record.h b/llvm/utils/TableGen/Record.h index a9ccf40468ad..b628df2048ad 100644 --- a/llvm/utils/TableGen/Record.h +++ b/llvm/utils/TableGen/Record.h @@ -48,6 +48,7 @@ class TypedInit; class VarInit; class FieldInit; class VarBitInit; +class VarListElementInit; // Other classes... class Record; @@ -481,6 +482,13 @@ public: return Ty->convertValue(this); } + /// resolveReferences - This method is used by classes that refer to other + /// variables which may not be defined at the time they 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); + virtual void print(std::ostream &OS) const; }; @@ -495,11 +503,19 @@ public: RecTy *getType() const { return Ty; } + virtual Init *convertInitializerBitRange(const std::vector &Bits); + virtual Init *convertInitListSlice(const std::vector &Elements); + /// resolveBitReference - This method is used to implement /// VarBitInit::resolveReferences. If the bit is able to be resolved, we - /// simply return the resolved value, otherwise we return this. + /// simply return the resolved value, otherwise we return null. /// virtual Init *resolveBitReference(Record &R, unsigned Bit) = 0; + + /// 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. + virtual Init *resolveListElementReference(Record &R, unsigned Elt) = 0; }; /// VarInit - 'Opcode' - Represent a reference to an entire variable object. @@ -515,9 +531,8 @@ public: const std::string &getName() const { return VarName; } - virtual Init *convertInitializerBitRange(const std::vector &Bits); - virtual Init *resolveBitReference(Record &R, unsigned Bit); + virtual Init *resolveListElementReference(Record &R, unsigned Elt); virtual RecTy *getFieldType(const std::string &FieldName) const; virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; @@ -558,6 +573,38 @@ public: virtual Init *resolveReferences(Record &R); }; +/// VarListElementInit - List[4] - Represent access to one element of a var or +/// field. +class VarListElementInit : public TypedInit { + TypedInit *TI; + unsigned Element; +public: + VarListElementInit(TypedInit *T, unsigned E) + : TypedInit(dynamic_cast(T->getType())->getElementType()), + TI(T), Element(E) { + assert(T->getType() && dynamic_cast(T->getType()) && + "Illegal VarBitInit expression!"); + } + + virtual Init *convertInitializerTo(RecTy *Ty) { + return Ty->convertValue(this); + } + + TypedInit *getVariable() const { return TI; } + unsigned getElementNum() const { return Element; } + + virtual Init *resolveBitReference(Record &R, unsigned Bit); + + /// 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. + virtual Init *resolveListElementReference(Record &R, unsigned Elt); + + virtual void print(std::ostream &OS) const { + TI->print(OS); OS << "[" << Element << "]"; + } + virtual Init *resolveReferences(Record &R); +}; /// DefInit - AL - Represent a reference to a 'def' in the description /// @@ -596,9 +643,8 @@ public: return Ty->convertValue(this); } - virtual Init *convertInitializerBitRange(const std::vector &Bits); - virtual Init *resolveBitReference(Record &R, unsigned Bit); + virtual Init *resolveListElementReference(Record &R, unsigned Elt); virtual Init *resolveReferences(Record &R);