[llvm] r326704 - TableGen: Introduce an abstract variable resolver interface

Nicolai Haehnle via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 5 07:20:51 PST 2018


Author: nha
Date: Mon Mar  5 07:20:51 2018
New Revision: 326704

URL: http://llvm.org/viewvc/llvm-project?rev=326704&view=rev
Log:
TableGen: Introduce an abstract variable resolver interface

Summary:
The intention is to allow us to more easily restructure how resolving is
done, e.g. resolving multiple variables simultaneously, or using the
resolving mechanism to implement !foreach.

Change-Id: I4b976b54a32e240ad4f562f7eb86a4d663a20ea8

Reviewers: arsenm, craig.topper, tra, MartinO

Subscribers: wdng, llvm-commits

Differential Revision: https://reviews.llvm.org/D43564

Modified:
    llvm/trunk/include/llvm/TableGen/Record.h
    llvm/trunk/lib/TableGen/Record.cpp
    llvm/trunk/lib/TableGen/TGParser.cpp

Modified: llvm/trunk/include/llvm/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=326704&r1=326703&r2=326704&view=diff
==============================================================================
--- llvm/trunk/include/llvm/TableGen/Record.h (original)
+++ llvm/trunk/include/llvm/TableGen/Record.h Mon Mar  5 07:20:51 2018
@@ -16,6 +16,7 @@
 #define LLVM_TABLEGEN_RECORD_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallVector.h"
@@ -42,6 +43,7 @@ struct MultiClass;
 class Record;
 class RecordKeeper;
 class RecordVal;
+class Resolver;
 class StringInit;
 
 //===----------------------------------------------------------------------===//
@@ -360,7 +362,7 @@ public:
   /// variables which may not be defined at the time the 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, const RecordVal *RV) const {
+  virtual Init *resolveReferences(Resolver &R) const {
     return const_cast<Init *>(this);
   }
 
@@ -508,7 +510,7 @@ public:
 
   std::string getAsString() const override;
 
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   Init *getBit(unsigned Bit) const override {
     assert(Bit < NumBits && "Bit index out of range!");
@@ -653,7 +655,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.
   ///
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   std::string getAsString() const override;
 
@@ -746,7 +748,7 @@ public:
   // possible to fold.
   Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;
 
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   std::string getAsString() const override;
 };
@@ -800,7 +802,7 @@ public:
   // possible to fold.
   Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override;
 
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   std::string getAsString() const override;
 };
@@ -862,7 +864,7 @@ public:
     return LHS->isComplete() && MHS->isComplete() && RHS->isComplete();
   }
 
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   std::string getAsString() const override;
 };
@@ -897,7 +899,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.
   ///
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   Init *getBit(unsigned Bit) const override;
 
@@ -934,7 +936,7 @@ public:
   unsigned getBitNum() const override { return Bit; }
 
   std::string getAsString() const override;
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   Init *getBit(unsigned B) const override {
     assert(B < 1 && "Bit index out of range!");
@@ -970,7 +972,7 @@ public:
   unsigned getElementNum() const { return Element; }
 
   std::string getAsString() const override;
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   Init *getBit(unsigned Bit) const override;
 };
@@ -1030,7 +1032,7 @@ public:
 
   Init *getBit(unsigned Bit) const override;
 
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   std::string getAsString() const override {
     return Rec->getAsString() + "." + FieldName->getValue().str();
@@ -1105,7 +1107,7 @@ public:
     return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames);
   }
 
-  Init *resolveReferences(Record &R, const RecordVal *RV) const override;
+  Init *resolveReferences(Resolver &R) const override;
 
   std::string getAsString() const override;
 
@@ -1605,6 +1607,63 @@ raw_ostream &operator<<(raw_ostream &OS,
 Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
                   Init *Name, StringRef Scoper);
 
+//===----------------------------------------------------------------------===//
+//  Resolvers
+//===----------------------------------------------------------------------===//
+
+/// Interface for looking up the initializer for a variable name, used by
+/// Init::resolveReferences.
+class Resolver {
+  Record *CurRec;
+
+public:
+  explicit Resolver(Record *CurRec) : CurRec(CurRec) {}
+  virtual ~Resolver() {}
+
+  Record *getCurrentRecord() const { return CurRec; }
+
+  /// Return the initializer for the given variable name (should normally be a
+  /// StringInit), or nullptr if the name could not be resolved.
+  virtual Init *resolve(Init *VarName) = 0;
+
+  // Whether bits in a BitsInit should stay unresolved if resolving them would
+  // result in a ? (UnsetInit). This behavior is used to represent instruction
+  // encodings by keeping references to unset variables within a record.
+  virtual bool keepUnsetBits() const { return false; }
+};
+
+/// Resolve all variables from a record except for unset variables.
+class RecordResolver final : public Resolver {
+  DenseMap<Init *, Init *> Cache;
+  SmallVector<Init *, 4> Stack;
+
+public:
+  explicit RecordResolver(Record &R) : Resolver(&R) {}
+
+  Init *resolve(Init *VarName) override;
+
+  bool keepUnsetBits() const override { return true; }
+};
+
+/// Resolve all references to a specific RecordVal.
+//
+// TODO: This is used for resolving references to template arguments, in a
+//       rather inefficient way. Change those uses to resolve all template
+//       arguments simultaneously and get rid of this class.
+class RecordValResolver final : public Resolver {
+  const RecordVal *RV;
+
+public:
+  explicit RecordValResolver(Record &R, const RecordVal *RV)
+      : Resolver(&R), RV(RV) {}
+
+  Init *resolve(Init *VarName) override {
+    if (VarName == RV->getNameInit())
+      return RV->getValue();
+    return nullptr;
+  }
+};
+
 } // end namespace llvm
 
 #endif // LLVM_TABLEGEN_RECORD_H

Modified: llvm/trunk/lib/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=326704&r1=326703&r2=326704&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/Record.cpp (original)
+++ llvm/trunk/lib/TableGen/Record.cpp Mon Mar  5 07:20:51 2018
@@ -312,15 +312,15 @@ std::string BitsInit::getAsString() cons
 // Fix bit initializer to preserve the behavior that bit reference from a unset
 // bits initializer will resolve into VarBitInit to keep the field name and bit
 // number used in targets with fixed insn length.
-static Init *fixBitInit(const RecordVal *RV, Init *Before, Init *After) {
-  if (RV || !isa<UnsetInit>(After))
+static Init *fixBitInit(const Resolver &R, Init *Before, Init *After) {
+  if (!isa<UnsetInit>(After) || !R.keepUnsetBits())
     return After;
   return Before;
 }
 
 // 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, const RecordVal *RV) const {
+Init *BitsInit::resolveReferences(Resolver &R) const {
   bool Changed = false;
   SmallVector<Init *, 16> NewBits(getNumBits());
 
@@ -337,7 +337,7 @@ Init *BitsInit::resolveReferences(Record
     if (CurBitVar == CachedBitVar) {
       if (CachedBitVarChanged) {
         Init *Bit = CachedInit->getBit(CurBit->getBitNum());
-        NewBits[i] = fixBitInit(RV, CurBit, Bit);
+        NewBits[i] = fixBitInit(R, CurBit, Bit);
       }
       continue;
     }
@@ -347,7 +347,7 @@ Init *BitsInit::resolveReferences(Record
     Init *B;
     do {
       B = CurBitVar;
-      CurBitVar = CurBitVar->resolveReferences(R, RV);
+      CurBitVar = CurBitVar->resolveReferences(R);
       CachedBitVarChanged |= B != CurBitVar;
       Changed |= B != CurBitVar;
     } while (B != CurBitVar);
@@ -355,7 +355,7 @@ Init *BitsInit::resolveReferences(Record
 
     if (CachedBitVarChanged) {
       Init *Bit = CurBitVar->getBit(CurBit->getBitNum());
-      NewBits[i] = fixBitInit(RV, CurBit, Bit);
+      NewBits[i] = fixBitInit(R, CurBit, Bit);
     }
   }
 
@@ -543,7 +543,7 @@ Record *ListInit::getElementAsRecord(uns
   return DI->getDef();
 }
 
-Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) const {
+Init *ListInit::resolveReferences(Resolver &R) const {
   SmallVector<Init*, 8> Resolved;
   Resolved.reserve(size());
   bool Changed = false;
@@ -553,7 +553,7 @@ Init *ListInit::resolveReferences(Record
 
     do {
       E = CurElt;
-      CurElt = CurElt->resolveReferences(R, RV);
+      CurElt = CurElt->resolveReferences(R);
       Changed |= E != CurElt;
     } while (E != CurElt);
     Resolved.push_back(E);
@@ -706,12 +706,13 @@ Init *UnOpInit::Fold(Record *CurRec, Mul
   return const_cast<UnOpInit *>(this);
 }
 
-Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) const {
-  Init *lhs = LHS->resolveReferences(R, RV);
+Init *UnOpInit::resolveReferences(Resolver &R) const {
+  Init *lhs = LHS->resolveReferences(R);
 
   if (LHS != lhs)
-    return (UnOpInit::get(getOpcode(), lhs, getType()))->Fold(&R, nullptr);
-  return Fold(&R, nullptr);
+    return (UnOpInit::get(getOpcode(), lhs, getType()))
+        ->Fold(R.getCurrentRecord(), nullptr);
+  return Fold(R.getCurrentRecord(), nullptr);
 }
 
 std::string UnOpInit::getAsString() const {
@@ -854,13 +855,14 @@ Init *BinOpInit::Fold(Record *CurRec, Mu
   return const_cast<BinOpInit *>(this);
 }
 
-Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) const {
-  Init *lhs = LHS->resolveReferences(R, RV);
-  Init *rhs = RHS->resolveReferences(R, RV);
+Init *BinOpInit::resolveReferences(Resolver &R) const {
+  Init *lhs = LHS->resolveReferences(R);
+  Init *rhs = RHS->resolveReferences(R);
 
   if (LHS != lhs || RHS != rhs)
-    return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))->Fold(&R,nullptr);
-  return Fold(&R, nullptr);
+    return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))
+        ->Fold(R.getCurrentRecord(), nullptr);
+  return Fold(R.getCurrentRecord(), nullptr);
 }
 
 std::string BinOpInit::getAsString() const {
@@ -1058,9 +1060,8 @@ Init *TernOpInit::Fold(Record *CurRec, M
   return const_cast<TernOpInit *>(this);
 }
 
-Init *TernOpInit::resolveReferences(Record &R,
-                                    const RecordVal *RV) const {
-  Init *lhs = LHS->resolveReferences(R, RV);
+Init *TernOpInit::resolveReferences(Resolver &R) const {
+  Init *lhs = LHS->resolveReferences(R);
 
   if (getOpcode() == IF && lhs != LHS) {
     IntInit *Value = dyn_cast<IntInit>(lhs);
@@ -1069,23 +1070,23 @@ Init *TernOpInit::resolveReferences(Reco
     if (Value) {
       // Short-circuit
       if (Value->getValue()) {
-        Init *mhs = MHS->resolveReferences(R, RV);
-        return (TernOpInit::get(getOpcode(), lhs, mhs,
-                                RHS, getType()))->Fold(&R, nullptr);
+        Init *mhs = MHS->resolveReferences(R);
+        return (TernOpInit::get(getOpcode(), lhs, mhs, RHS, getType()))
+            ->Fold(R.getCurrentRecord(), nullptr);
       }
-      Init *rhs = RHS->resolveReferences(R, RV);
-      return (TernOpInit::get(getOpcode(), lhs, MHS,
-                              rhs, getType()))->Fold(&R, nullptr);
+      Init *rhs = RHS->resolveReferences(R);
+      return (TernOpInit::get(getOpcode(), lhs, MHS, rhs, getType()))
+          ->Fold(R.getCurrentRecord(), nullptr);
     }
   }
 
-  Init *mhs = MHS->resolveReferences(R, RV);
-  Init *rhs = RHS->resolveReferences(R, RV);
+  Init *mhs = MHS->resolveReferences(R);
+  Init *rhs = RHS->resolveReferences(R);
 
   if (LHS != lhs || MHS != mhs || RHS != rhs)
-    return (TernOpInit::get(getOpcode(), lhs, mhs, rhs,
-                            getType()))->Fold(&R, nullptr);
-  return Fold(&R, nullptr);
+    return (TernOpInit::get(getOpcode(), lhs, mhs, rhs, getType()))
+        ->Fold(R.getCurrentRecord(), nullptr);
+  return Fold(R.getCurrentRecord(), nullptr);
 }
 
 std::string TernOpInit::getAsString() const {
@@ -1248,10 +1249,9 @@ Init *VarInit::getBit(unsigned Bit) cons
   return VarBitInit::get(const_cast<VarInit*>(this), Bit);
 }
 
-Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const {
-  if (RecordVal *Val = R.getValue(VarName))
-    if (RV == Val || (!RV && !isa<UnsetInit>(Val->getValue())))
-      return Val->getValue();
+Init *VarInit::resolveReferences(Resolver &R) const {
+  if (Init *Val = R.resolve(VarName))
+    return Val;
   return const_cast<VarInit *>(this);
 }
 
@@ -1278,8 +1278,8 @@ std::string VarBitInit::getAsString() co
   return TI->getAsString() + "{" + utostr(Bit) + "}";
 }
 
-Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const {
-  Init *I = TI->resolveReferences(R, RV);
+Init *VarBitInit::resolveReferences(Resolver &R) const {
+  Init *I = TI->resolveReferences(R);
   if (TI != I)
     return I->getBit(getBitNum());
 
@@ -1302,9 +1302,8 @@ std::string VarListElementInit::getAsStr
   return TI->getAsString() + "[" + utostr(Element) + "]";
 }
 
-Init *
-VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const {
-  Init *NewTI = TI->resolveReferences(R, RV);
+Init *VarListElementInit::resolveReferences(Resolver &R) const {
+  Init *NewTI = TI->resolveReferences(R);
   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.
@@ -1360,12 +1359,12 @@ Init *FieldInit::getBit(unsigned Bit) co
   return VarBitInit::get(const_cast<FieldInit*>(this), Bit);
 }
 
-Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) const {
-  Init *NewRec = Rec->resolveReferences(R, RV);
+Init *FieldInit::resolveReferences(Resolver &R) const {
+  Init *NewRec = Rec->resolveReferences(R);
 
   if (DefInit *DI = dyn_cast<DefInit>(NewRec)) {
     Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
-    Init *BVR = FieldVal->resolveReferences(R, RV);
+    Init *BVR = FieldVal->resolveReferences(R);
     if (BVR->isComplete())
       return BVR;
   }
@@ -1438,17 +1437,17 @@ Init *DagInit::convertInitializerTo(RecT
   return nullptr;
 }
 
-Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const {
+Init *DagInit::resolveReferences(Resolver &R) const {
   SmallVector<Init*, 8> NewArgs;
   NewArgs.reserve(arg_size());
   bool ArgsChanged = false;
   for (const Init *Arg : getArgs()) {
-    Init *NewArg = Arg->resolveReferences(R, RV);
+    Init *NewArg = Arg->resolveReferences(R);
     NewArgs.push_back(NewArg);
     ArgsChanged |= NewArg != Arg;
   }
 
-  Init *Op = Val->resolveReferences(R, RV);
+  Init *Op = Val->resolveReferences(R);
   if (Op != Val || ArgsChanged)
     return DagInit::get(Op, ValName, NewArgs, getArgNames());
 
@@ -1538,11 +1537,19 @@ void Record::setName(Init *NewName) {
 }
 
 void Record::resolveReferencesTo(const RecordVal *RV) {
+  RecordResolver RecResolver(*this);
+  RecordValResolver RecValResolver(*this, RV);
+  Resolver *R;
+  if (RV)
+    R = &RecValResolver;
+  else
+    R = &RecResolver;
+
   for (RecordVal &Value : Values) {
     if (RV == &Value) // Skip resolve the same field as the given one
       continue;
     if (Init *V = Value.getValue())
-      if (Value.setValue(V->resolveReferences(*this, RV)))
+      if (Value.setValue(V->resolveReferences(*R)))
         PrintFatalError(getLoc(), "Invalid value is found when setting '" +
                         Value.getNameInitAsString() +
                         "' after resolving references" +
@@ -1552,7 +1559,7 @@ void Record::resolveReferencesTo(const R
                             : "") + "\n");
   }
   Init *OldName = getNameInit();
-  Init *NewName = Name->resolveReferences(*this, RV);
+  Init *NewName = Name->resolveReferences(*R);
   if (NewName != OldName) {
     // Re-register with RecordKeeper.
     setName(NewName);
@@ -1813,3 +1820,26 @@ Init *llvm::QualifyName(Record &CurRec,
     NewName = BinOp->Fold(&CurRec, CurMultiClass);
   return NewName;
 }
+
+Init *RecordResolver::resolve(Init *VarName) {
+  Init *Val = Cache.lookup(VarName);
+  if (Val)
+    return Val;
+
+  for (Init *S : Stack) {
+    if (S == VarName)
+      return nullptr; // prevent infinite recursion
+  }
+
+  if (RecordVal *RV = getCurrentRecord()->getValue(VarName)) {
+    if (!isa<UnsetInit>(RV->getValue())) {
+      Val = RV->getValue();
+      Stack.push_back(VarName);
+      Val = Val->resolveReferences(*this);
+      Stack.pop_back();
+    }
+  }
+
+  Cache[VarName] = Val;
+  return Val;
+}

Modified: llvm/trunk/lib/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=326704&r1=326703&r2=326704&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.cpp (original)
+++ llvm/trunk/lib/TableGen/TGParser.cpp Mon Mar  5 07:20:51 2018
@@ -320,7 +320,8 @@ bool TGParser::ProcessForeachDefs(Record
 
     // Process each value.
     for (unsigned i = 0; i < List->size(); ++i) {
-      Init *ItemVal = List->getElement(i)->resolveReferences(*CurRec, nullptr);
+      RecordResolver R(*CurRec);
+      Init *ItemVal = List->getElement(i)->resolveReferences(R);
       IterVals.push_back(IterRecord(CurLoop.IterVar, ItemVal));
       if (ProcessForeachDefs(CurRec, Loc, IterVals))
         return true;




More information about the llvm-commits mailing list