diff options
| -rw-r--r-- | llvm/include/llvm/TableGen/Record.h | 119 | ||||
| -rw-r--r-- | llvm/lib/TableGen/Record.cpp | 197 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 41 | ||||
| -rw-r--r-- | llvm/test/TableGen/if.td | 46 | ||||
| -rw-r--r-- | llvm/test/TableGen/list-element-bitref.td | 15 | ||||
| -rw-r--r-- | llvm/test/TableGen/pr8330.td | 29 | ||||
| -rw-r--r-- | llvm/utils/TableGen/CodeEmitterGen.cpp | 2 | ||||
| -rw-r--r-- | llvm/utils/TableGen/FixedLenDecoderEmitter.cpp | 2 | 
8 files changed, 250 insertions, 201 deletions
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h index 75ca88a1ed8..c7baaeb9d90 100644 --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -509,6 +509,18 @@ public:    virtual Init *resolveReferences(Record &R, const RecordVal *RV) const {      return const_cast<Init *>(this);    } + +  /// getBit - This method is used to return the initializer for the specified +  /// bit. +  virtual Init *getBit(unsigned Bit) const = 0; + +  /// getBitVar - This method is used to retrieve the initializer for bit +  /// reference. For non-VarBitInit, it simply returns itself. +  virtual Init *getBitVar() const { return const_cast<Init*>(this); } + +  /// getBitNum - This method is used to retrieve the bit number of a bit +  /// reference. For non-VarBitInit, it simply returns 0. +  virtual unsigned getBitNum() const { return 0; }  };  inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { @@ -541,13 +553,6 @@ public:    ///    virtual RecTy *getFieldType(const std::string &FieldName) const; -  /// 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 null. -  /// -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const = 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. @@ -571,6 +576,10 @@ public:      return Ty->convertValue(const_cast<UnsetInit *>(this));    } +  virtual Init *getBit(unsigned Bit) const { +    return const_cast<UnsetInit*>(this); +  } +    virtual bool isComplete() const { return false; }    virtual std::string getAsString() const { return "?"; }  }; @@ -595,6 +604,11 @@ public:      return Ty->convertValue(const_cast<BitInit *>(this));    } +  virtual Init *getBit(unsigned Bit) const { +    assert(Bit < 1 && "Bit index out of range!"); +    return const_cast<BitInit*>(this); +  } +    virtual std::string getAsString() const { return Value ? "1" : "0"; }  }; @@ -616,11 +630,6 @@ public:    unsigned getNumBits() const { return Bits.size(); } -  Init *getBit(unsigned Bit) const { -    assert(Bit < Bits.size() && "Bit index out of range!"); -    return Bits[Bit]; -  } -    virtual Init *convertInitializerTo(RecTy *Ty) const {      return Ty->convertValue(const_cast<BitsInit *>(this));    } @@ -640,6 +649,11 @@ public:    virtual std::string getAsString() const;    virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + +  virtual Init *getBit(unsigned Bit) const { +    assert(Bit < Bits.size() && "Bit index out of range!"); +    return Bits[Bit]; +  }  }; @@ -666,15 +680,6 @@ public:    virtual std::string getAsString() const; -  /// 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 null. -  /// -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const { -    llvm_unreachable("Illegal bit reference off int"); -  } -    /// 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. @@ -682,6 +687,10 @@ public:                                              unsigned Elt) const {      llvm_unreachable("Illegal element reference off int");    } + +  virtual Init *getBit(unsigned Bit) const { +    return BitInit::get((Value & (1 << Bit)) != 0); +  }  }; @@ -709,15 +718,6 @@ public:    virtual std::string getAsString() const { return "\"" + Value + "\""; }    virtual std::string getAsUnquotedString() const { return Value; } -  /// 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 null. -  /// -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const { -    llvm_unreachable("Illegal bit reference off string"); -  } -    /// 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. @@ -725,6 +725,10 @@ public:                                              unsigned Elt) const {      llvm_unreachable("Illegal element reference off string");    } + +  virtual Init *getBit(unsigned Bit) const { +    llvm_unreachable("Illegal bit reference off string"); +  }  };  /// ListInit - [AL, AH, CL] - Represent a list of defs @@ -777,20 +781,15 @@ public:    inline size_t         size () const { return Values.size();  }    inline bool           empty() const { return Values.empty(); } -  /// 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 null. -  /// -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const { -    llvm_unreachable("Illegal bit reference off list"); -  } -    /// 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, const RecordVal *RV,                                              unsigned Elt) const; + +  virtual Init *getBit(unsigned Bit) const { +    llvm_unreachable("Illegal bit reference off list"); +  }  }; @@ -818,10 +817,10 @@ public:      return Ty->convertValue(const_cast<OpInit *>(this));    } -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const;    virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,                                              unsigned Elt) const; + +  virtual Init *getBit(unsigned Bit) const;  }; @@ -1003,8 +1002,6 @@ public:      return getNameInit()->getAsUnquotedString();    } -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const;    virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,                                              unsigned Elt) const; @@ -1019,6 +1016,8 @@ public:    ///    virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; +  virtual Init *getBit(unsigned Bit) const; +    virtual std::string getAsString() const { return getName(); }  }; @@ -1030,8 +1029,10 @@ class VarBitInit : public Init {    unsigned Bit;    VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) { -    assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) && -           ((BitsRecTy*)T->getType())->getNumBits() > B && +    assert(T->getType() && +           (dynamic_cast<IntRecTy*>(T->getType()) || +            (dynamic_cast<BitsRecTy*>(T->getType()) && +             dynamic_cast<BitsRecTy*>(T->getType())->getNumBits() > B)) &&             "Illegal VarBitInit expression!");    } @@ -1045,11 +1046,16 @@ public:      return Ty->convertValue(const_cast<VarBitInit *>(this));    } -  TypedInit *getVariable() const { return TI; } -  unsigned getBitNum() const { return Bit; } +  virtual Init *getBitVar() const { return TI; } +  virtual unsigned getBitNum() const { return Bit; }    virtual std::string getAsString() const;    virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + +  virtual Init *getBit(unsigned B) const { +    assert(B < 1 && "Bit index out of range!"); +    return const_cast<VarBitInit*>(this); +  }  };  /// VarListElementInit - List[4] - Represent access to one element of a var or @@ -1080,9 +1086,6 @@ public:    TypedInit *getVariable() const { return TI; }    unsigned getElementNum() const { return Element; } -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const; -    /// 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. @@ -1092,6 +1095,8 @@ public:    virtual std::string getAsString() const;    virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + +  virtual Init *getBit(unsigned Bit) const;  };  /// DefInit - AL - Represent a reference to a 'def' in the description @@ -1122,12 +1127,7 @@ public:    virtual std::string getAsString() const; -  /// 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 null. -  /// -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const { +  virtual Init *getBit(unsigned Bit) const {      llvm_unreachable("Illegal bit reference off def");    } @@ -1163,8 +1163,8 @@ public:      return Ty->convertValue(const_cast<FieldInit *>(this));    } -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const; +  virtual Init *getBit(unsigned Bit) const; +    virtual Init *resolveListElementReference(Record &R,                                              const RecordVal *RV,                                              unsigned Elt) const; @@ -1243,8 +1243,7 @@ public:    inline size_t              name_size () const { return ArgNames.size();  }    inline bool                name_empty() const { return ArgNames.empty(); } -  virtual Init *resolveBitReference(Record &R, const RecordVal *RV, -                                    unsigned Bit) const { +  virtual Init *getBit(unsigned Bit) const {      llvm_unreachable("Illegal bit reference off dag");    } diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index 3176b2af635..b2a7b628e4c 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -112,7 +112,10 @@ Init *BitRecTy::convertValue(IntInit *II) {  }  Init *BitRecTy::convertValue(TypedInit *VI) { -  if (dynamic_cast<BitRecTy*>(VI->getType())) +  RecTy *Ty = VI->getType(); +  if (dynamic_cast<BitRecTy*>(Ty) || +      dynamic_cast<BitsRecTy*>(Ty) || +      dynamic_cast<IntRecTy*>(Ty))      return VI;  // Accept variable if it is already of bit type!    return 0;  } @@ -178,60 +181,15 @@ Init *BitsRecTy::convertValue(BitsInit *BI) {  }  Init *BitsRecTy::convertValue(TypedInit *VI) { -  if (BitsRecTy *BRT = dynamic_cast<BitsRecTy*>(VI->getType())) -    if (BRT->Size == Size) { -      SmallVector<Init *, 16> NewBits(Size); -  -      for (unsigned i = 0; i != Size; ++i) -        NewBits[i] = VarBitInit::get(VI, i); -      return BitsInit::get(NewBits); -    } -    if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType()))      return BitsInit::get(VI); -  if (TernOpInit *Tern = dynamic_cast<TernOpInit*>(VI)) { -    if (Tern->getOpcode() == TernOpInit::IF) { -      Init *LHS = Tern->getLHS(); -      Init *MHS = Tern->getMHS(); -      Init *RHS = Tern->getRHS(); - -      IntInit *MHSi = dynamic_cast<IntInit*>(MHS); -      IntInit *RHSi = dynamic_cast<IntInit*>(RHS); - -      if (MHSi && RHSi) { -        int64_t MHSVal = MHSi->getValue(); -        int64_t RHSVal = RHSi->getValue(); - -        if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) { -          SmallVector<Init *, 16> NewBits(Size); - -          for (unsigned i = 0; i != Size; ++i) -            NewBits[i] = -              TernOpInit::get(TernOpInit::IF, LHS, -                              IntInit::get((MHSVal & (1LL << i)) ? 1 : 0), -                              IntInit::get((RHSVal & (1LL << i)) ? 1 : 0), -                              VI->getType()); +  if (VI->getType()->typeIsConvertibleTo(this)) { +    SmallVector<Init *, 16> NewBits(Size); -          return BitsInit::get(NewBits); -        } -      } else { -        BitsInit *MHSbs = dynamic_cast<BitsInit*>(MHS); -        BitsInit *RHSbs = dynamic_cast<BitsInit*>(RHS); - -        if (MHSbs && RHSbs) { -          SmallVector<Init *, 16> NewBits(Size); - -          for (unsigned i = 0; i != Size; ++i) -            NewBits[i] = TernOpInit::get(TernOpInit::IF, LHS, -                                         MHSbs->getBit(i), -                                         RHSbs->getBit(i), -                                         VI->getType()); - -          return BitsInit::get(NewBits); -        } -      } -    } +    for (unsigned i = 0; i != Size; ++i) +      NewBits[i] = VarBitInit::get(VI, i); +    return BitsInit::get(NewBits);    }    return 0; @@ -519,6 +477,15 @@ std::string BitsInit::getAsString() const {    return Result + " }";  } +// 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 || After != UnsetInit::get()) +    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.  // @@ -526,16 +493,39 @@ Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) const {    bool Changed = false;    SmallVector<Init *, 16> NewBits(getNumBits()); -  for (unsigned i = 0, e = Bits.size(); i != e; ++i) { -    Init *B; -    Init *CurBit = getBit(i); +  Init *CachedInit = 0; +  Init *CachedBitVar = 0; +  bool CachedBitVarChanged = false; + +  for (unsigned i = 0, e = getNumBits(); i != e; ++i) { +    Init *CurBit = Bits[i]; +    Init *CurBitVar = CurBit->getBitVar(); -    do { -      B = CurBit; -      CurBit = CurBit->resolveReferences(R, RV); -      Changed |= B != CurBit; -    } while (B != CurBit);      NewBits[i] = CurBit; + +    if (CurBitVar == CachedBitVar) { +      if (CachedBitVarChanged) { +        Init *Bit = CachedInit->getBit(CurBit->getBitNum()); +        NewBits[i] = fixBitInit(RV, CurBit, Bit); +      } +      continue; +    } +    CachedBitVar = CurBitVar; +    CachedBitVarChanged = false; + +    Init *B; +    do { +      B = CurBitVar; +      CurBitVar = CurBitVar->resolveReferences(R, RV); +      CachedBitVarChanged |= B != CurBitVar; +      Changed |= B != CurBitVar; +    } while (B != CurBitVar); +    CachedInit = CurBitVar; + +    if (CachedBitVarChanged) { +      Init *Bit = CurBitVar->getBit(CurBit->getBitNum()); +      NewBits[i] = fixBitInit(RV, CurBit, Bit); +    }    }    if (Changed) @@ -682,20 +672,6 @@ std::string ListInit::getAsString() const {    return Result + "]";  } -Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV, -                                  unsigned Bit) const { -  Init *Folded = Fold(&R, 0); - -  if (Folded != this) { -    TypedInit *Typed = dynamic_cast<TypedInit *>(Folded); -    if (Typed) { -      return Typed->resolveBitReference(R, IRV, Bit); -    } -  } - -  return 0; -} -  Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV,                                            unsigned Elt) const {    Init *Resolved = resolveReferences(R, IRV); @@ -718,6 +694,12 @@ Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV,    return 0;  } +Init *OpInit::getBit(unsigned Bit) const { +  if (getType() == BitRecTy::get()) +    return const_cast<OpInit*>(this); +  return VarBitInit::get(const_cast<OpInit*>(this), Bit); +} +  UnOpInit *UnOpInit::get(UnaryOp opc, Init *lhs, RecTy *Type) {    typedef std::pair<std::pair<unsigned, Init *>, RecTy *> Key; @@ -922,9 +904,9 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {    case EQ: {      // try to fold eq comparison for 'bit' and 'int', otherwise fallback      // to string objects. -    IntInit* L = +    IntInit *L =        dynamic_cast<IntInit*>(LHS->convertInitializerTo(IntRecTy::get())); -    IntInit* R = +    IntInit *R =        dynamic_cast<IntInit*>(RHS->convertInitializerTo(IntRecTy::get()));      if (L && R) @@ -1324,25 +1306,10 @@ const std::string &VarInit::getName() const {    return NameString->getValue();  } -Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV, -                                   unsigned Bit) const { -  if (R.isTemplateArg(getNameInit())) return 0; -  if (IRV && IRV->getNameInit() != getNameInit()) return 0; - -  RecordVal *RV = R.getValue(getNameInit()); -  assert(RV && "Reference to a non-existent variable?"); -  assert(dynamic_cast<BitsInit*>(RV->getValue())); -  BitsInit *BI = (BitsInit*)RV->getValue(); - -  assert(Bit < BI->getNumBits() && "Bit reference out of range!"); -  Init *B = BI->getBit(Bit); - -  // If the bit is set to some value, or if we are resolving a reference to a -  // specific variable and that variable is explicitly unset, then replace the -  // VarBitInit with it. -  if (IRV || !dynamic_cast<UnsetInit*>(B)) -    return B; -  return 0; +Init *VarInit::getBit(unsigned Bit) const { +  if (getType() == BitRecTy::get()) +    return const_cast<VarInit*>(this); +  return VarBitInit::get(const_cast<VarInit*>(this), Bit);  }  Init *VarInit::resolveListElementReference(Record &R, @@ -1425,9 +1392,11 @@ std::string VarBitInit::getAsString() const {  }  Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const { -  if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum())) -    return I; -  return const_cast<VarBitInit *>(this); +  Init *I = TI->resolveReferences(R, RV); +  if (TI != I) +    return I->getBit(getBitNum()); + +  return const_cast<VarBitInit*>(this);  }  VarListElementInit *VarListElementInit::get(TypedInit *T, @@ -1456,11 +1425,10 @@ VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const {    return const_cast<VarListElementInit *>(this);  } -Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV, -                                              unsigned Bit) const { -  // FIXME: This should be implemented, to support references like: -  // bit B = AA[0]{1}; -  return 0; +Init *VarListElementInit::getBit(unsigned Bit) const { +  if (getType() == BitRecTy::get()) +    return const_cast<VarListElementInit*>(this); +  return VarBitInit::get(const_cast<VarListElementInit*>(this), Bit);  }  Init *VarListElementInit:: resolveListElementReference(Record &R, @@ -1513,17 +1481,10 @@ FieldInit *FieldInit::get(Init *R, const std::string &FN) {    return I;  } -Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, -                                     unsigned Bit) const { -  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); - -      if (dynamic_cast<BitInit*>(B))  // If the bit is set. -        return B;                     // Replace the VarBitInit with it. -    } -  return 0; +Init *FieldInit::getBit(unsigned Bit) const { +  if (getType() == BitRecTy::get()) +    return const_cast<FieldInit*>(this); +  return VarBitInit::get(const_cast<FieldInit*>(this), Bit);  }  Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, @@ -1751,7 +1712,15 @@ void Record::resolveReferencesTo(const RecordVal *RV) {      if (RV == &Values[i]) // Skip resolve the same field as the given one        continue;      if (Init *V = Values[i].getValue()) -      Values[i].setValue(V->resolveReferences(*this, RV)); +      if (Values[i].setValue(V->resolveReferences(*this, RV))) +        throw TGError(getLoc(), "Invalid value is found when setting '" +                      + Values[i].getNameInitAsString() +                      + "' after resolving references" +                      + (RV ? " against '" + RV->getNameInitAsString() +                              + "' of (" +                              + RV->getValue()->getAsUnquotedString() + ")" +                            : "") +                      + "\n");    }    Init *OldName = getNameInit();    Init *NewName = Name->resolveReferences(*this, RV); diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index 5e2b66ed69d..aee93e7696b 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -1044,35 +1044,28 @@ Init *TGParser::ParseOperation(Record *CurRec) {      switch (LexCode) {      default: llvm_unreachable("Unhandled code!");      case tgtok::XIf: { -      // FIXME: The `!if' operator doesn't handle non-TypedInit well at -      // all. This can be made much more robust. -      TypedInit *MHSt = dynamic_cast<TypedInit*>(MHS); -      TypedInit *RHSt = dynamic_cast<TypedInit*>(RHS); -        RecTy *MHSTy = 0;        RecTy *RHSTy = 0; -      if (MHSt == 0 && RHSt == 0) { -        BitsInit *MHSbits = dynamic_cast<BitsInit*>(MHS); -        BitsInit *RHSbits = dynamic_cast<BitsInit*>(RHS); - -        if (MHSbits && RHSbits && -            MHSbits->getNumBits() == RHSbits->getNumBits()) { -          Type = BitRecTy::get(); -          break; -        } else { -          BitInit *MHSbit = dynamic_cast<BitInit*>(MHS); -          BitInit *RHSbit = dynamic_cast<BitInit*>(RHS); - -          if (MHSbit && RHSbit) { -            Type = BitRecTy::get(); -            break; -          } -        } -      } else if (MHSt != 0 && RHSt != 0) { +      if (TypedInit *MHSt = dynamic_cast<TypedInit*>(MHS))          MHSTy = MHSt->getType(); +      if (BitsInit *MHSbits = dynamic_cast<BitsInit*>(MHS)) +        MHSTy = BitsRecTy::get(MHSbits->getNumBits()); +      if (dynamic_cast<BitInit*>(MHS)) +        MHSTy = BitRecTy::get(); + +      if (TypedInit *RHSt = dynamic_cast<TypedInit*>(RHS))          RHSTy = RHSt->getType(); -      } +      if (BitsInit *RHSbits = dynamic_cast<BitsInit*>(RHS)) +        RHSTy = BitsRecTy::get(RHSbits->getNumBits()); +      if (dynamic_cast<BitInit*>(RHS)) +        RHSTy = BitRecTy::get(); + +      // For UnsetInit, it's typed from the other hand. +      if (dynamic_cast<UnsetInit*>(MHS)) +        MHSTy = RHSTy; +      if (dynamic_cast<UnsetInit*>(RHS)) +        RHSTy = MHSTy;        if (!MHSTy || !RHSTy) {          TokError("could not get type for !if"); diff --git a/llvm/test/TableGen/if.td b/llvm/test/TableGen/if.td index 18de368af9f..1d8d62329ae 100644 --- a/llvm/test/TableGen/if.td +++ b/llvm/test/TableGen/if.td @@ -3,15 +3,59 @@  // Support for an `!if' operator as part of a `let' statement.  // CHECK:      class C -// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, ?, ?, ?, !if({ C:x{2} }, 0, 1), !if({ C:x{2} }, 1, 1), !if({ C:x{2} }, 0, 0), !if({ C:x{1} }, C:y{3}, 0), !if({ C:x{1} }, C:y{2}, 1), !if({ C:x{0} }, C:y{3}, C:z), !if({ C:x{0} }, C:y{2}, C:y{2}), !if({ C:x{0} }, C:y{1}, C:y{1}), !if({ C:x{0} }, C:y{0}, C:y{0}) }; +// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, !if({ C:y{3} }, 1, !if({ C:y{2} }, { C:x{0} }, !if({ C:y{1} }, { C:x{1} }, !if({ C:y{0} }, { C:x{2} }, ?)))){0}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){1}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){0}, !if({ C:x{2} }, 2, 6){2}, !if({ C:x{2} }, 2, 6){1}, !if({ C:x{2} }, 2, 6){0}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){1}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){0}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){3}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){2}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){1}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){0} };  class C<bits<3> x, bits<4> y, bit z> {    bits<16> n; +  let n{11}  = !if(y{3}, 1, +               !if(y{2}, x{0}, +               !if(y{1}, x{1}, +               !if(y{0}, x{2}, ?)))); +  let n{10-9}= !if(x{2}, y{3-2}, +               !if(x{1}, y{2-1}, +               !if(x{0}, y{1-0}, ?)));    let n{8-6} = !if(x{2}, 0b010, 0b110);    let n{5-4} = !if(x{1}, y{3-2}, {0, 1});    let n{3-0} = !if(x{0}, y{3-0}, {z, y{2}, y{1}, y{0}});  } +def C1 : C<{1, 0, 1}, {0, 1, 0, 1}, 0>; +def C2 : C<{0, 1, 0}, {1, 0, 1, 0}, 1>; +def C3 : C<{0, 0, 0}, {1, 0, 1, 0}, 0>; +def C4 : C<{0, 0, 0}, {0, 0, 0, 0}, 0>; + +// CHECK: def C1 +// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 }; +// CHECK: def C2 +// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0 }; +// CHECK: def C3 +// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, ?, ?, 1, 1, 0, 0, 1, 0, 0, 1, 0 }; +// CHECK: def C4 +// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, ?, ?, ?, 1, 1, 0, 0, 1, 0, 0, 0, 0 }; + +class S<int s> { +  bits<2> val = !if(!eq(s, 8),  {0, 0}, +                !if(!eq(s, 16), 0b01, +                !if(!eq(s, 32), 2, +                !if(!eq(s, 64), {1, 1}, ?)))); +} + +def D8  : S<8>; +def D16 : S<16>; +def D32 : S<32>; +def D64 : S<64>; +def D128: S<128>; +// CHECK: def D128 +// CHECK-NEXT: bits<2> val = { ?, ? }; +// CHECK: def D16 +// CHECK-NEXT: bits<2> val = { 0, 1 }; +// CHECK: def D32 +// CHECK-NEXT: bits<2> val = { 1, 0 }; +// CHECK: def D64 +// CHECK-NEXT: bits<2> val = { 1, 1 }; +// CHECK: def D8 +// CHECK-NEXT: bits<2> val = { 0, 0 }; +  // CHECK:      def One  // CHECK-NEXT: list<int> first = [1, 2, 3];  // CHECK-NEXT: list<int> rest = [1, 2, 3]; diff --git a/llvm/test/TableGen/list-element-bitref.td b/llvm/test/TableGen/list-element-bitref.td new file mode 100644 index 00000000000..5f3e3dabf4d --- /dev/null +++ b/llvm/test/TableGen/list-element-bitref.td @@ -0,0 +1,15 @@ +// RUN: llvm-tblgen %s | FileCheck %s +// XFAIL: vg_leak + +class C<list<bits<8>> L> { +  bits<2> V0 = L[0]{1-0}; +  bits<2> V1 = L[1]{3-2}; +  string V2 = !if(L[0]{0}, "Odd", "Even"); +} + +def c0 : C<[0b0101, 0b1010]>; + +// CHECK: def c0 +// CHECk-NEXT: bits<2> V0 = { 0, 1 }; +// CHECk-NEXT: bits<2> V1 = { 1, 0 }; +// CHECk-NEXT: string V2 = "Odd"; diff --git a/llvm/test/TableGen/pr8330.td b/llvm/test/TableGen/pr8330.td new file mode 100644 index 00000000000..7779b635e33 --- /dev/null +++ b/llvm/test/TableGen/pr8330.td @@ -0,0 +1,29 @@ +// RUN: llvm-tblgen %s | FileCheck %s +// XFAIL: vg_leak + +class Or4<bits<8> Val> { +  bits<8> V = {Val{7}, Val{6}, Val{5}, Val{4}, Val{3}, 1, Val{1}, Val{0} }; +} + +class Whatev<bits<8> x>; + +class Whatever<bits<8> x> { +  bits<8> W = {x{0}, x{1}, x{2}, x{3}, x{4}, x{5}, x{6}, x{7} }; +} + +multiclass X<bits<8> BaseOpc> { + def bar : Whatev<Or4<BaseOpc>.V >; +} + +multiclass Y<bits<8> BaseOpc> { + def foo : Whatever<Or4<BaseOpc>.V >; +} + +defm a : X<4>; + +// CHECK: def abar + +defm b : Y<8>; + +// CHECK: def bfoo +// CHECK-NEXT: bits<8> W = { 0, 0, 1, 1, 0, 0, 0, 0 }; diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index 31a39b1f042..9c8ad67b423 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -92,7 +92,7 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {  int CodeEmitterGen::getVariableBit(const std::string &VarName,                                     BitsInit *BI, int bit) {    if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) { -    if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getVariable())) +    if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getBitVar()))        if (VI->getName() == VarName)          return VBI->getBitNum();    } else if (VarInit *VI = dynamic_cast<VarInit*>(BI->getBit(bit))) { diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index e89c393b6a9..aa6d7962a07 100644 --- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1783,7 +1783,7 @@ static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc,        VarInit *Var = 0;        VarBitInit *BI = dynamic_cast<VarBitInit*>(Bits.getBit(bi));        if (BI) -        Var = dynamic_cast<VarInit*>(BI->getVariable()); +        Var = dynamic_cast<VarInit*>(BI->getBitVar());        else          Var = dynamic_cast<VarInit*>(Bits.getBit(bi));  | 

