mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
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
This commit is contained in:
parent
dcb54ce3da
commit
548f5a0b75
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user