diff --git a/utils/TableGen/FileParser.y b/utils/TableGen/FileParser.y index e7d50322ef4..4dbd84ab78d 100644 --- a/utils/TableGen/FileParser.y +++ b/utils/TableGen/FileParser.y @@ -25,6 +25,7 @@ namespace llvm { extern int Filelineno; static Record *CurRec = 0; +static bool ParsingTemplateArgs = false; typedef std::pair*> SubClassRefTy; @@ -133,6 +134,8 @@ static void setValue(const std::string &ValName, } } +// addSubClass - Add SC as a subclass to CurRec, resolving TemplateArgs as SC's +// template arguments. static void addSubClass(Record *SC, const std::vector &TemplateArgs) { // Add all of the values in the subclass into the current class... const std::vector &Vals = SC->getValues(); @@ -147,11 +150,19 @@ static void addSubClass(Record *SC, const std::vector &TemplateArgs) { exit(1); } else { // This class expects template arguments... // Loop over all of the template arguments, setting them to the specified - // value or leaving them as the default as necessary. + // value or leaving them as the default if necessary. for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { if (i < TemplateArgs.size()) { // A value is specified for this temp-arg? // Set it now. setValue(TArgs[i], 0, TemplateArgs[i]); + + // Resolve it next. + CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); + + + // Now remove it. + CurRec->removeValue(TArgs[i]); + } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { err() << "ERROR: Value not specified for template argument #" << i << " (" << TArgs[i] << ") of subclass '" << SC->getName() @@ -268,6 +279,10 @@ Value : INTVAL { } | ID { if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) { $$ = new VarInit(*$1, RV->getType()); + } else if (CurRec && CurRec->isTemplateArg(CurRec->getName()+":"+*$1)) { + const RecordVal *RV = CurRec->getValue(CurRec->getName()+":"+*$1); + assert(RV && "Template arg doesn't exist??"); + $$ = new VarInit(CurRec->getName()+":"+*$1, RV->getType()); } else if (Record *D = Records.getDef(*$1)) { $$ = new DefInit(D); } else { @@ -434,9 +449,13 @@ ValueListNE : Value { }; Declaration : OptPrefix Type ID OptValue { - addValue(RecordVal(*$3, $2, $1)); - setValue(*$3, 0, $4); - $$ = $3; + std::string DecName = *$3; + if (ParsingTemplateArgs) + DecName = CurRec->getName() + ":" + DecName; + + addValue(RecordVal(DecName, $2, $1)); + setValue(DecName, 0, $4); + $$ = new std::string(DecName); }; BodyItem : Declaration ';' { @@ -492,12 +511,15 @@ ObjectBody : OptID { *$1 = "anonymous."+utostr(AnonCounter++); CurRec = new Record(*$1); delete $1; + ParsingTemplateArgs = true; } OptTemplateArgList ClassList { + ParsingTemplateArgs = false; for (unsigned i = 0, e = $4->size(); i != e; ++i) { addSubClass((*$4)[i].first, *(*$4)[i].second); // Delete the template arg values for the class delete (*$4)[i].second; } + delete $4; // Delete the class list... // Process any variables on the set stack... for (unsigned i = 0, e = LetStack.size(); i != e; ++i) @@ -506,22 +528,9 @@ ObjectBody : OptID { LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0, LetStack[i][j].Value); } Body { - CurRec->resolveReferences(); - - // Now that all of the references have been resolved, we can delete template - // arguments for superclasses, so they don't pollute our record, and so that - // their names won't conflict with later uses of the name... - for (unsigned i = 0, e = $4->size(); i != e; ++i) { - Record *SuperClass = (*$4)[i].first; - for (unsigned i = 0, e = SuperClass->getTemplateArgs().size(); i != e; ++i) - if (!CurRec->isTemplateArg(SuperClass->getTemplateArgs()[i])) - CurRec->removeValue(SuperClass->getTemplateArgs()[i]); - } - delete $4; // Delete the class list... - - $$ = CurRec; - CurRec = 0; -}; + $$ = CurRec; + CurRec = 0; + }; ClassInst : CLASS ObjectBody { if (Records.getClass($2->getName())) { @@ -532,6 +541,8 @@ ClassInst : CLASS ObjectBody { }; DefInst : DEF ObjectBody { + $2->resolveReferences(); + if (!$2->getTemplateArgs().empty()) { err() << "Def '" << $2->getName() << "' is not permitted to have template arguments!\n"; diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index d2422ff74b3..41dbdd6140a 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -275,7 +275,7 @@ bool BitsInit::printAsUnset(std::ostream &OS) const { // 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) { +Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) { bool Changed = false; BitsInit *New = new BitsInit(getNumBits()); @@ -285,7 +285,7 @@ Init *BitsInit::resolveReferences(Record &R) { do { B = CurBit; - CurBit = CurBit->resolveReferences(R); + CurBit = CurBit->resolveReferences(R, RV); Changed |= B != CurBit; } while (B != CurBit); New->setBit(i, CurBit); @@ -334,7 +334,7 @@ Init *ListInit::convertInitListSlice(const std::vector &Elements) { return new ListInit(Vals); } -Init *ListInit::resolveReferences(Record &R) { +Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) { std::vector Resolved; Resolved.reserve(getSize()); bool Changed = false; @@ -345,7 +345,7 @@ Init *ListInit::resolveReferences(Record &R) { do { E = CurElt; - CurElt = CurElt->resolveReferences(R); + CurElt = CurElt->resolveReferences(R, RV); Changed |= E != CurElt; } while (E != CurElt); Resolved.push_back(E); @@ -396,9 +396,10 @@ Init *TypedInit::convertInitListSlice(const std::vector &Elements) { } -Init *VarInit::resolveBitReference(Record &R, unsigned Bit) { - if (R.isTemplateArg(getName())) - return 0; +Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV, + unsigned Bit) { + if (R.isTemplateArg(getName())) return 0; + if (IRV && IRV->getName() != getName()) return 0; RecordVal *RV = R.getValue(getName()); assert(RV && "Reference to a non-existant variable?"); @@ -413,9 +414,10 @@ Init *VarInit::resolveBitReference(Record &R, unsigned Bit) { return 0; } -Init *VarInit::resolveListElementReference(Record &R, unsigned Elt) { - if (R.isTemplateArg(getName())) - return 0; +Init *VarInit::resolveListElementReference(Record &R, const RecordVal *IRV, + unsigned Elt) { + if (R.isTemplateArg(getName())) return 0; + if (IRV && IRV->getName() != getName()) return 0; RecordVal *RV = R.getValue(getName()); assert(RV && "Reference to a non-existant variable?"); @@ -456,33 +458,36 @@ Init *VarInit::getFieldInit(Record &R, const std::string &FieldName) const { /// 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 *VarInit::resolveReferences(Record &R) { +Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) { if (RecordVal *Val = R.getValue(VarName)) - if (!dynamic_cast(Val->getValue())) + if (RV == Val || (RV == 0 && !dynamic_cast(Val->getValue()))) return Val->getValue(); return this; } -Init *VarBitInit::resolveReferences(Record &R) { - if (Init *I = getVariable()->resolveBitReference(R, getBitNum())) +Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) { + if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum())) return I; return this; } -Init *VarListElementInit::resolveReferences(Record &R) { - if (Init *I = getVariable()->resolveListElementReference(R, getElementNum())) +Init *VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) { + if (Init *I = getVariable()->resolveListElementReference(R, RV, + getElementNum())) return I; return this; } -Init *VarListElementInit::resolveBitReference(Record &R, unsigned Bit) { +Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV, + 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) { +Init *VarListElementInit:: +resolveListElementReference(Record &R, const RecordVal *RV, unsigned Elt) { // FIXME: This should be implemented, to support references like: // int B = AA[0][1]; return 0; @@ -503,7 +508,8 @@ void DefInit::print(std::ostream &OS) const { OS << Def->getName(); } -Init *FieldInit::resolveBitReference(Record &R, unsigned Bit) { +Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) { if (Init *BitsVal = Rec->getFieldInit(R, FieldName)) if (BitsInit *BI = dynamic_cast(BitsVal)) { assert(Bit < BI->getNumBits() && "Bit reference out of range!"); @@ -515,7 +521,8 @@ Init *FieldInit::resolveBitReference(Record &R, unsigned Bit) { return 0; } -Init *FieldInit::resolveListElementReference(Record &R, unsigned Elt) { +Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) { if (Init *ListVal = Rec->getFieldInit(R, FieldName)) if (ListInit *LI = dynamic_cast(ListVal)) { if (Elt >= LI->getSize()) return 0; @@ -527,12 +534,20 @@ Init *FieldInit::resolveListElementReference(Record &R, unsigned Elt) { return 0; } -Init *FieldInit::resolveReferences(Record &R) { - Init *BitsVal = Rec->getFieldInit(R, FieldName); +Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) { + Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec; + + Init *BitsVal = NewRec->getFieldInit(R, FieldName); if (BitsVal) { - Init *BVR = BitsVal->resolveReferences(R); + Init *BVR = BitsVal->resolveReferences(R, RV); return BVR->isComplete() ? BVR : this; } + + if (NewRec != Rec) { + dump(); + NewRec->dump(); std::cerr << "\n"; + return new FieldInit(NewRec, FieldName); + } return this; } @@ -566,20 +581,24 @@ void RecordVal::dump() const { std::cerr << *this; } void RecordVal::print(std::ostream &OS, bool PrintSem) const { if (getPrefix()) OS << "field "; OS << *getType() << " " << getName(); - if (getValue()) { + + if (getValue()) OS << " = " << *getValue(); - } + if (PrintSem) OS << ";\n"; } -// resolveReferences - If there are any field references that refer to fields -// that have been filled in, we can propagate the values now. -// -void Record::resolveReferences() { - for (unsigned i = 0, e = Values.size(); i != e; ++i) - Values[i].setValue(Values[i].getValue()->resolveReferences(*this)); +/// resolveReferencesTo - If anything in this record refers to RV, replace the +/// reference to RV with the RHS of RV. If RV is null, we resolve all possible +/// references. +void Record::resolveReferencesTo(const RecordVal *RV) { + for (unsigned i = 0, e = Values.size(); i != e; ++i) { + if (Init *V = Values[i].getValue()) + Values[i].setValue(V->resolveReferences(*this, RV)); + } } + void Record::dump() const { std::cerr << *this; } std::ostream &llvm::operator<<(std::ostream &OS, const Record &R) { diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 82db72094b3..59274535e90 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -23,7 +23,7 @@ namespace llvm { -// RecTy subclasses... +// RecTy subclasses. class BitRecTy; class BitsRecTy; class IntRecTy; @@ -33,7 +33,7 @@ class CodeRecTy; class DagRecTy; class RecordRecTy; -// Init subclasses... +// Init subclasses. struct Init; class UnsetInit; class BitInit; @@ -50,8 +50,9 @@ class FieldInit; class VarBitInit; class VarListElementInit; -// Other classes... +// Other classes. class Record; +class RecordVal; //===----------------------------------------------------------------------===// // Type Classes @@ -474,7 +475,9 @@ struct Init { /// 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) { return this; } + virtual Init *resolveReferences(Record &R, const RecordVal *RV) { + return this; + } }; inline std::ostream &operator<<(std::ostream &OS, const Init &I) { @@ -543,7 +546,7 @@ public: } virtual void print(std::ostream &OS) const; - virtual Init *resolveReferences(Record &R); + virtual Init *resolveReferences(Record &R, const RecordVal *RV); // printXX - Print this bitstream with the specified format, returning true if // it is not possible. @@ -631,7 +634,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. /// - virtual Init *resolveReferences(Record &R); + virtual Init *resolveReferences(Record &R, const RecordVal *RV); virtual void print(std::ostream &OS) const; }; @@ -654,12 +657,14 @@ public: /// VarBitInit::resolveReferences. If the bit is able to be resolved, we /// simply return the resolved value, otherwise we return null. /// - virtual Init *resolveBitReference(Record &R, unsigned Bit) = 0; + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + 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; + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) = 0; }; /// VarInit - 'Opcode' - Represent a reference to an entire variable object. @@ -675,8 +680,10 @@ public: const std::string &getName() const { return VarName; } - virtual Init *resolveBitReference(Record &R, unsigned Bit); - virtual Init *resolveListElementReference(Record &R, unsigned Elt); + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit); + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt); virtual RecTy *getFieldType(const std::string &FieldName) const; virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; @@ -686,7 +693,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. /// - virtual Init *resolveReferences(Record &R); + virtual Init *resolveReferences(Record &R, const RecordVal *RV); virtual void print(std::ostream &OS) const { OS << VarName; } }; @@ -714,7 +721,7 @@ public: virtual void print(std::ostream &OS) const { TI->print(OS); OS << "{" << Bit << "}"; } - virtual Init *resolveReferences(Record &R); + virtual Init *resolveReferences(Record &R, const RecordVal *RV); }; /// VarListElementInit - List[4] - Represent access to one element of a var or @@ -737,17 +744,19 @@ public: TypedInit *getVariable() const { return TI; } unsigned getElementNum() const { return Element; } - virtual Init *resolveBitReference(Record &R, unsigned Bit); + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + 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 Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt); virtual void print(std::ostream &OS) const { TI->print(OS); OS << "[" << Element << "]"; } - virtual Init *resolveReferences(Record &R); + virtual Init *resolveReferences(Record &R, const RecordVal *RV); }; /// DefInit - AL - Represent a reference to a 'def' in the description @@ -787,10 +796,12 @@ public: return Ty->convertValue(this); } - virtual Init *resolveBitReference(Record &R, unsigned Bit); - virtual Init *resolveListElementReference(Record &R, unsigned Elt); + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit); + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt); - virtual Init *resolveReferences(Record &R); + virtual Init *resolveReferences(Record &R, const RecordVal *RV); virtual void print(std::ostream &OS) const { Rec->print(OS); OS << "." << FieldName; @@ -949,10 +960,15 @@ public: SuperClasses.push_back(R); } - // resolveReferences - If there are any field references that refer to fields - // that have been filled in, we can propagate the values now. - // - void resolveReferences(); + /// resolveReferences - If there are any field references that refer to fields + /// that have been filled in, we can propagate the values now. + /// + void resolveReferences() { resolveReferencesTo(0); } + + /// resolveReferencesTo - If anything in this record refers to RV, replace the + /// reference to RV with the RHS of RV. If RV is null, we resolve all + /// possible references. + void resolveReferencesTo(const RecordVal *RV); void dump() const;