diff options
-rw-r--r-- | test/TableGen/if.td | 30 | ||||
-rw-r--r-- | utils/TableGen/Record.cpp | 72 | ||||
-rw-r--r-- | utils/TableGen/Record.h | 2 | ||||
-rw-r--r-- | utils/TableGen/TGParser.cpp | 44 |
4 files changed, 127 insertions, 21 deletions
diff --git a/test/TableGen/if.td b/test/TableGen/if.td index 0bac0ba..bff9278 100644 --- a/test/TableGen/if.td +++ b/test/TableGen/if.td @@ -1,14 +1,38 @@ -// RUN: tblgen %s | grep {\\\[1, 2, 3\\\]} | count 4 -// RUN: tblgen %s | grep {\\\[4, 5, 6\\\]} | count 2 +// RUN: tblgen %s | FileCheck %s // XFAIL: vg_leak +// 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}) }; +class C<bits<3> x, bits<4> y, bit z> { + bits<16> n; + + 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}}); +} + +// CHECK: def One +// CHECK-NEXT: list<int> first = [1, 2, 3]; +// CHECK-NEXT: list<int> rest = [1, 2, 3]; + +// CHECK: def OneB +// CHECK-NEXT: list<int> vals = [1, 2, 3]; + +// CHECK: def Two +// CHECK-NEXT: list<int> first = [1, 2, 3]; +// CHECK-NEXT: list<int> rest = [4, 5, 6]; + +// CHECK: def TwoB +// CHECK-NEXT: list<int> vals = [4, 5, 6]; + class A<list<list<int>> vals> { list<int> first = vals[0]; list<int> rest = !if(!null(!cdr(vals)), vals[0], vals[1]); } def One : A<[[1,2,3]]>; -def Two : A<[[1,2,3],[4,5,6]]>; +def Two : A<[[1,2,3], [4,5,6]]>; class B<list<int> v> { list<int> vals = v; diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index a34618c..00bb2a7 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -65,19 +65,27 @@ Init *BitsRecTy::convertValue(BitInit *UI) { return Ret; } -// convertValue from Int initializer to bits type: Split the integer up into the -// appropriate bits. -// +/// canFitInBitfield - Return true if the number of bits is large enough to hold +/// the integer value. +static bool canFitInBitfield(int64_t Value, unsigned NumBits) { + if (Value >= 0) { + if (Value & ~((1LL << NumBits) - 1)) + return false; + } else if ((Value >> NumBits) != -1 || (Value & (1LL << (NumBits-1))) == 0) { + return false; + } + + return true; +} + +/// convertValue from Int initializer to bits type: Split the integer up into the +/// appropriate bits. +/// Init *BitsRecTy::convertValue(IntInit *II) { int64_t Value = II->getValue(); // Make sure this bitfield is large enough to hold the integer value. - if (Value >= 0) { - if (Value & ~((1LL << Size)-1)) - return 0; - } else { - if ((Value >> Size) != -1 || ((Value & (1LL << (Size-1))) == 0)) - return 0; - } + if (!canFitInBitfield(Value, Size)) + return 0; BitsInit *Ret = new BitsInit(Size); for (unsigned i = 0; i != Size; ++i) @@ -101,12 +109,56 @@ Init *BitsRecTy::convertValue(TypedInit *VI) { Ret->setBit(i, new VarBitInit(VI, i)); return Ret; } + if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) { BitsInit *Ret = new BitsInit(1); Ret->setBit(0, VI); return Ret; } + 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)) { + BitsInit *Ret = new BitsInit(Size); + + for (unsigned i = 0; i != Size; ++i) + Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS, + new IntInit((MHSVal & (1LL << i)) ? 1 : 0), + new IntInit((RHSVal & (1LL << i)) ? 1 : 0), + VI->getType())); + + return Ret; + } + } else { + BitsInit *MHSbs = dynamic_cast<BitsInit*>(MHS); + BitsInit *RHSbs = dynamic_cast<BitsInit*>(RHS); + + if (MHSbs && RHSbs) { + BitsInit *Ret = new BitsInit(Size); + + for (unsigned i = 0; i != Size; ++i) + Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS, + MHSbs->getBit(i), + RHSbs->getBit(i), + VI->getType())); + + return Ret; + } + } + } + } + return 0; } diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 0853037..f8873cf 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -931,6 +931,8 @@ public: // possible to fold. Init *Fold(Record *CurRec, MultiClass *CurMultiClass); + virtual bool isComplete() const { return false; } + virtual Init *resolveReferences(Record &R, const RecordVal *RV); virtual std::string getAsString() const; diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index d99632e..57e9f83 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -868,7 +868,6 @@ Init *TGParser::ParseOperation(Record *CurRec) { TernOpInit::TernaryOp Code; RecTy *Type = 0; - tgtok::TokKind LexCode = Lex.getCode(); Lex.Lex(); // eat the operation switch (LexCode) { @@ -919,16 +918,45 @@ Init *TGParser::ParseOperation(Record *CurRec) { switch (LexCode) { default: assert(0 && "Unhandled code!"); case tgtok::XIf: { - TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS); - TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS); - if (MHSt == 0 || RHSt == 0) { + // 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 = new BitRecTy(); + break; + } else { + BitInit *MHSbit = dynamic_cast<BitInit*>(MHS); + BitInit *RHSbit = dynamic_cast<BitInit*>(RHS); + + if (MHSbit && RHSbit) { + Type = new BitRecTy(); + break; + } + } + } else if (MHSt != 0 && RHSt != 0) { + MHSTy = MHSt->getType(); + RHSTy = RHSt->getType(); + } + + if (!MHSTy || !RHSTy) { TokError("could not get type for !if"); return 0; } - if (MHSt->getType()->typeIsConvertibleTo(RHSt->getType())) { - Type = RHSt->getType(); - } else if (RHSt->getType()->typeIsConvertibleTo(MHSt->getType())) { - Type = MHSt->getType(); + + if (MHSTy->typeIsConvertibleTo(RHSTy)) { + Type = RHSTy; + } else if (RHSTy->typeIsConvertibleTo(MHSTy)) { + Type = MHSTy; } else { TokError("inconsistent types for !if"); return 0; |