diff options
-rw-r--r-- | include/llvm/TableGen/Record.h | 119 | ||||
-rw-r--r-- | lib/TableGen/Record.cpp | 197 | ||||
-rw-r--r-- | lib/TableGen/TGParser.cpp | 41 | ||||
-rw-r--r-- | test/TableGen/if.td | 46 | ||||
-rw-r--r-- | test/TableGen/list-element-bitref.td | 15 | ||||
-rw-r--r-- | test/TableGen/pr8330.td | 29 | ||||
-rw-r--r-- | utils/TableGen/CodeEmitterGen.cpp | 2 | ||||
-rw-r--r-- | utils/TableGen/FixedLenDecoderEmitter.cpp | 2 |
8 files changed, 250 insertions, 201 deletions
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 75ca88a1ed..c7baaeb9d9 100644 --- a/include/llvm/TableGen/Record.h +++ b/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/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp index 3176b2af63..b2a7b628e4 100644 --- a/lib/TableGen/Record.cpp +++ b/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/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp index 5e2b66ed69..aee93e7696 100644 --- a/lib/TableGen/TGParser.cpp +++ b/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/test/TableGen/if.td b/test/TableGen/if.td index 18de368af9..1d8d62329a 100644 --- a/test/TableGen/if.td +++ b/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/test/TableGen/list-element-bitref.td b/test/TableGen/list-element-bitref.td new file mode 100644 index 0000000000..5f3e3dabf4 --- /dev/null +++ b/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/test/TableGen/pr8330.td b/test/TableGen/pr8330.td new file mode 100644 index 0000000000..7779b635e3 --- /dev/null +++ b/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/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 31a39b1f04..9c8ad67b42 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/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/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index e89c393b6a..aa6d7962a0 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/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)); |