diff --git a/test/TableGen/2010-03-24-PrematureDefaults.td b/test/TableGen/2010-03-24-PrematureDefaults.td new file mode 100644 index 00000000000..42f2632ab8c --- /dev/null +++ b/test/TableGen/2010-03-24-PrematureDefaults.td @@ -0,0 +1,43 @@ +// RUN: tblgen %s | FileCheck %s + +class A<int k, bits<2> x = 1> { + int K = k; + bits<2> Bits = x; +} + +// CHECK: def a1 +// CHECK: Bits = { 0, 1 } +def a1 : A<12>; + +// CHECK: def a2 +// CHECK: Bits = { 1, 0 } +def a2 : A<13, 2>; + +// Here was the bug: X.Bits would get resolved to the default a1.Bits while +// resolving the first template argument. When the second template argument +// was processed, X would be set correctly, but Bits retained the default +// value. +class B<int k, A x = a1> { + A X = x; + bits<2> Bits = X.Bits; +} + +// CHECK: def b1 +// CHECK: Bits = { 0, 1 } +def b1 : B<27>; + +// CHECK: def b2 +// CHECK: Bits = { 1, 0 } +def b2 : B<28, a2>; + +class C<A x = a1> { + bits<2> Bits = x.Bits; +} + +// CHECK: def c1 +// CHECK: Bits = { 0, 1 } +def c1 : C; + +// CHECK: def c2 +// CHECK: Bits = { 1, 0 } +def c2 : C<a2>; diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index b9facb4c2a6..0e3593b6a11 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -1108,12 +1108,15 @@ RecTy *VarInit::getFieldType(const std::string &FieldName) const { return 0; } -Init *VarInit::getFieldInit(Record &R, const std::string &FieldName) const { +Init *VarInit::getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { if (dynamic_cast<RecordRecTy*>(getType())) - if (const RecordVal *RV = R.getValue(VarName)) { - Init *TheInit = RV->getValue(); + if (const RecordVal *Val = R.getValue(VarName)) { + if (RV != Val && (RV || dynamic_cast<UnsetInit*>(Val->getValue()))) + return 0; + Init *TheInit = Val->getValue(); assert(TheInit != this && "Infinite loop detected!"); - if (Init *I = TheInit->getFieldInit(R, FieldName)) + if (Init *I = TheInit->getFieldInit(R, RV, FieldName)) return I; else return 0; @@ -1174,7 +1177,8 @@ RecTy *DefInit::getFieldType(const std::string &FieldName) const { return 0; } -Init *DefInit::getFieldInit(Record &R, const std::string &FieldName) const { +Init *DefInit::getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { return Def->getValue(FieldName)->getValue(); } @@ -1185,7 +1189,7 @@ std::string DefInit::getAsString() const { Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, unsigned Bit) { - if (Init *BitsVal = Rec->getFieldInit(R, FieldName)) + if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName)) if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) { assert(Bit < BI->getNumBits() && "Bit reference out of range!"); Init *B = BI->getBit(Bit); @@ -1198,7 +1202,7 @@ Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, unsigned Elt) { - if (Init *ListVal = Rec->getFieldInit(R, FieldName)) + if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName)) if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) { if (Elt >= LI->getSize()) return 0; Init *E = LI->getElement(Elt); @@ -1215,7 +1219,7 @@ Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) { Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec; - Init *BitsVal = NewRec->getFieldInit(R, FieldName); + Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName); if (BitsVal) { Init *BVR = BitsVal->resolveReferences(R, RV); return BVR->isComplete() ? BVR : this; diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 90096e98e20..55c1a80f9b6 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -503,7 +503,8 @@ struct Init { /// initializer for the specified field. If getFieldType returns non-null /// this method should return non-null, otherwise it returns null. /// - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const { + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { return 0; } @@ -950,7 +951,8 @@ public: unsigned Elt); virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const; /// resolveReferences - This method is used by classes that refer to other /// variables which may not be defined at the time they expression is formed. @@ -1035,7 +1037,8 @@ public: //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits); virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const; virtual std::string getAsString() const;