diff options
author | Bill Wendling <isanbard@gmail.com> | 2010-12-13 01:46:19 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2010-12-13 01:46:19 +0000 |
commit | 548f5a0b751aafba88473e4863c2baf7741b56a5 (patch) | |
tree | a27b4776c6bc3c5ee1d938632121d9d6e2664e61 /utils | |
parent | dcb54ce3da15ba41adeee020288e6c62cfae8c42 (diff) | |
download | external_llvm-548f5a0b751aafba88473e4863c2baf7741b56a5.zip external_llvm-548f5a0b751aafba88473e4863c2baf7741b56a5.tar.gz external_llvm-548f5a0b751aafba88473e4863c2baf7741b56a5.tar.bz2 |
Add support for using the `!if' operator when initializing variables:
class A<bit a, bits<3> x, bits<3> y> {
bits<3> z;
let z = !if(a, x, y);
}
The variable z will get the value of x when 'a' is 1 and 'y' when a is '0'.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121666 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/Record.cpp | 72 | ||||
-rw-r--r-- | utils/TableGen/Record.h | 2 | ||||
-rw-r--r-- | utils/TableGen/TGParser.cpp | 44 |
3 files changed, 100 insertions, 18 deletions
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; |