summaryrefslogtreecommitdiff
path: root/lib/TableGen/Record.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/TableGen/Record.cpp')
-rw-r--r--lib/TableGen/Record.cpp197
1 files changed, 83 insertions, 114 deletions
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);