[llvm-commits] [llvm] r99492 - in /llvm/trunk: test/TableGen/2010-03-24-PrematureDefaults.td utils/TableGen/Record.cpp utils/TableGen/Record.h

Jakob Stoklund Olesen stoklund at 2pi.dk
Wed Mar 24 23:23:35 PDT 2010


Author: stoklund
Date: Thu Mar 25 01:23:34 2010
New Revision: 99492

URL: http://llvm.org/viewvc/llvm-project?rev=99492&view=rev
Log:
Fix evil TableGen bug in template parameters with defaults.

If a TableGen class has an initializer expression containing an X.Y subexpression,
AND X depends on template parameters,
AND those template parameters have defaults,
AND some parameters with defaults are beyond position 1,
THEN parts of the initializer expression are evaluated prematurely with the default values when the first explicit template parameter is substituted, before the remaining explicit template parameters have been substituted.

Added:
    llvm/trunk/test/TableGen/2010-03-24-PrematureDefaults.td
Modified:
    llvm/trunk/utils/TableGen/Record.cpp
    llvm/trunk/utils/TableGen/Record.h

Added: llvm/trunk/test/TableGen/2010-03-24-PrematureDefaults.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/2010-03-24-PrematureDefaults.td?rev=99492&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/2010-03-24-PrematureDefaults.td (added)
+++ llvm/trunk/test/TableGen/2010-03-24-PrematureDefaults.td Thu Mar 25 01:23:34 2010
@@ -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>;

Modified: llvm/trunk/utils/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.cpp?rev=99492&r1=99491&r2=99492&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/Record.cpp (original)
+++ llvm/trunk/utils/TableGen/Record.cpp Thu Mar 25 01:23:34 2010
@@ -1108,12 +1108,15 @@
   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 @@
   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 @@
 
 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::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::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;

Modified: llvm/trunk/utils/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.h?rev=99492&r1=99491&r2=99492&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/Record.h (original)
+++ llvm/trunk/utils/TableGen/Record.h Thu Mar 25 01:23:34 2010
@@ -503,7 +503,8 @@
   /// 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 @@
                                             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 @@
   //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;
 





More information about the llvm-commits mailing list