summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/TableGen/Record.h119
-rw-r--r--lib/TableGen/Record.cpp197
-rw-r--r--lib/TableGen/TGParser.cpp41
-rw-r--r--test/TableGen/if.td46
-rw-r--r--test/TableGen/list-element-bitref.td15
-rw-r--r--test/TableGen/pr8330.td29
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp2
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp2
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));