From c1f10fd5b9a780d1c42dca7143d7a8acd9bd9377 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 23 Aug 2012 19:34:46 +0000 Subject: Tristate mayLoad, mayStore, and hasSideEffects. Keep track of the set/unset state of these bits along with their true/false values, but treat '?' as '0' for now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162461 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/TableGen/Record.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'lib/TableGen/Record.cpp') diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp index 99fdc1f..3176b2a 100644 --- a/lib/TableGen/Record.cpp +++ b/lib/TableGen/Record.cpp @@ -1963,6 +1963,23 @@ bool Record::getValueAsBit(StringRef FieldName) const { "' does not have a bit initializer!"; } +bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (R->getValue() == UnsetInit::get()) { + Unset = true; + return false; + } + Unset = false; + if (BitInit *BI = dynamic_cast(R->getValue())) + return BI->getValue(); + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a bit initializer!"; +} + /// getValueAsDag - This method looks up the specified field and returns its /// value as an Dag, throwing an exception if the field does not exist or if /// the value is not the right type. -- cgit v1.1 From 307525cd24c3b9c081ddb3c34a3418f2875cd556 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Thu, 6 Sep 2012 23:32:48 +0000 Subject: Re-work bit/bits value resolving in tblgen - This patch is inspired by the failure of the following code snippet which is used to convert enumerable values into encoding bits to improve the readability of td files. class S { bits<2> V = !if(!eq(s, 8), {0, 0}, !if(!eq(s, 16), {0, 1}, !if(!eq(s, 32), {1, 0}, !if(!eq(s, 64), {1, 1}, {?, ?})))); } Later, PR8330 is found to report not exactly the same bug relevant issue to bit/bits values. - Instead of resolving bit/bits values separately through resolveBitReference(), this patch adds getBit() for all Inits and resolves bit value by resolving plus getting the specified bit. This unifies the resolving of bit with other values and removes redundant logic for resolving bit only. In addition, BitsInit::resolveReferences() is optimized to take advantage of this origanization by resolving VarBitInit's variable reference first and then getting bits from it. - The type interference in '!if' operator is revised to support possible combinations of int and bits/bit in MHS and RHS. - As there may be illegal assignments from integer value to bit, says assign 2 to a bit, but we only check this during instantiation in some cases, e.g. bit V = !if(!eq(x, 17), 0, 2); Verbose diagnostic message is generated when invalid value is resolveed to help locating the error. - PR8330 is fixed as well. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/TableGen/Record.cpp | 197 ++++++++++++++++++++---------------------------- 1 file changed, 83 insertions(+), 114 deletions(-) (limited to 'lib/TableGen/Record.cpp') diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp index 3176b2a..b2a7b62 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(VI->getType())) + RecTy *Ty = VI->getType(); + if (dynamic_cast(Ty) || + dynamic_cast(Ty) || + dynamic_cast(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(VI->getType())) - if (BRT->Size == Size) { - SmallVector NewBits(Size); - - for (unsigned i = 0; i != Size; ++i) - NewBits[i] = VarBitInit::get(VI, i); - return BitsInit::get(NewBits); - } - if (Size == 1 && dynamic_cast(VI->getType())) return BitsInit::get(VI); - if (TernOpInit *Tern = dynamic_cast(VI)) { - if (Tern->getOpcode() == TernOpInit::IF) { - Init *LHS = Tern->getLHS(); - Init *MHS = Tern->getMHS(); - Init *RHS = Tern->getRHS(); - - IntInit *MHSi = dynamic_cast(MHS); - IntInit *RHSi = dynamic_cast(RHS); - - if (MHSi && RHSi) { - int64_t MHSVal = MHSi->getValue(); - int64_t RHSVal = RHSi->getValue(); - - if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) { - SmallVector 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 NewBits(Size); - return BitsInit::get(NewBits); - } - } else { - BitsInit *MHSbs = dynamic_cast(MHS); - BitsInit *RHSbs = dynamic_cast(RHS); - - if (MHSbs && RHSbs) { - SmallVector 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 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(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(this); + return VarBitInit::get(const_cast(this), Bit); +} + UnOpInit *UnOpInit::get(UnaryOp opc, Init *lhs, RecTy *Type) { typedef std::pair, 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(LHS->convertInitializerTo(IntRecTy::get())); - IntInit* R = + IntInit *R = dynamic_cast(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(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(B)) - return B; - return 0; +Init *VarInit::getBit(unsigned Bit) const { + if (getType() == BitRecTy::get()) + return const_cast(this); + return VarBitInit::get(const_cast(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(this); + Init *I = TI->resolveReferences(R, RV); + if (TI != I) + return I->getBit(getBitNum()); + + return const_cast(this); } VarListElementInit *VarListElementInit::get(TypedInit *T, @@ -1456,11 +1425,10 @@ VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const { return const_cast(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(this); + return VarBitInit::get(const_cast(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(BitsVal)) { - assert(Bit < BI->getNumBits() && "Bit reference out of range!"); - Init *B = BI->getBit(Bit); - - if (dynamic_cast(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(this); + return VarBitInit::get(const_cast(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); -- cgit v1.1