mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +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 | FileCheck %s
|
||||||
// RUN: tblgen %s | grep {\\\[4, 5, 6\\\]} | count 2
|
|
||||||
// XFAIL: vg_leak
|
// 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> {
|
class A<list<list<int>> vals> {
|
||||||
list<int> first = vals[0];
|
list<int> first = vals[0];
|
||||||
list<int> rest = !if(!null(!cdr(vals)), vals[0], vals[1]);
|
list<int> rest = !if(!null(!cdr(vals)), vals[0], vals[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
def One : A<[[1,2,3]]>;
|
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> {
|
class B<list<int> v> {
|
||||||
list<int> vals = v;
|
list<int> vals = v;
|
||||||
|
@ -65,19 +65,27 @@ Init *BitsRecTy::convertValue(BitInit *UI) {
|
|||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertValue from Int initializer to bits type: Split the integer up into the
|
/// canFitInBitfield - Return true if the number of bits is large enough to hold
|
||||||
// appropriate bits.
|
/// 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) {
|
Init *BitsRecTy::convertValue(IntInit *II) {
|
||||||
int64_t Value = II->getValue();
|
int64_t Value = II->getValue();
|
||||||
// Make sure this bitfield is large enough to hold the integer value.
|
// Make sure this bitfield is large enough to hold the integer value.
|
||||||
if (Value >= 0) {
|
if (!canFitInBitfield(Value, Size))
|
||||||
if (Value & ~((1LL << Size)-1))
|
return 0;
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
if ((Value >> Size) != -1 || ((Value & (1LL << (Size-1))) == 0))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BitsInit *Ret = new BitsInit(Size);
|
BitsInit *Ret = new BitsInit(Size);
|
||||||
for (unsigned i = 0; i != Size; ++i)
|
for (unsigned i = 0; i != Size; ++i)
|
||||||
@ -101,12 +109,56 @@ Init *BitsRecTy::convertValue(TypedInit *VI) {
|
|||||||
Ret->setBit(i, new VarBitInit(VI, i));
|
Ret->setBit(i, new VarBitInit(VI, i));
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) {
|
if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) {
|
||||||
BitsInit *Ret = new BitsInit(1);
|
BitsInit *Ret = new BitsInit(1);
|
||||||
Ret->setBit(0, VI);
|
Ret->setBit(0, VI);
|
||||||
return Ret;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,6 +931,8 @@ public:
|
|||||||
// possible to fold.
|
// possible to fold.
|
||||||
Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
|
Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
|
||||||
|
|
||||||
|
virtual bool isComplete() const { return false; }
|
||||||
|
|
||||||
virtual Init *resolveReferences(Record &R, const RecordVal *RV);
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV);
|
||||||
|
|
||||||
virtual std::string getAsString() const;
|
virtual std::string getAsString() const;
|
||||||
|
@ -868,7 +868,6 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
|||||||
TernOpInit::TernaryOp Code;
|
TernOpInit::TernaryOp Code;
|
||||||
RecTy *Type = 0;
|
RecTy *Type = 0;
|
||||||
|
|
||||||
|
|
||||||
tgtok::TokKind LexCode = Lex.getCode();
|
tgtok::TokKind LexCode = Lex.getCode();
|
||||||
Lex.Lex(); // eat the operation
|
Lex.Lex(); // eat the operation
|
||||||
switch (LexCode) {
|
switch (LexCode) {
|
||||||
@ -919,16 +918,45 @@ Init *TGParser::ParseOperation(Record *CurRec) {
|
|||||||
switch (LexCode) {
|
switch (LexCode) {
|
||||||
default: assert(0 && "Unhandled code!");
|
default: assert(0 && "Unhandled code!");
|
||||||
case tgtok::XIf: {
|
case tgtok::XIf: {
|
||||||
TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
|
// FIXME: The `!if' operator doesn't handle non-TypedInit well at
|
||||||
TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
|
// all. This can be made much more robust.
|
||||||
if (MHSt == 0 || RHSt == 0) {
|
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");
|
TokError("could not get type for !if");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (MHSt->getType()->typeIsConvertibleTo(RHSt->getType())) {
|
|
||||||
Type = RHSt->getType();
|
if (MHSTy->typeIsConvertibleTo(RHSTy)) {
|
||||||
} else if (RHSt->getType()->typeIsConvertibleTo(MHSt->getType())) {
|
Type = RHSTy;
|
||||||
Type = MHSt->getType();
|
} else if (RHSTy->typeIsConvertibleTo(MHSTy)) {
|
||||||
|
Type = MHSTy;
|
||||||
} else {
|
} else {
|
||||||
TokError("inconsistent types for !if");
|
TokError("inconsistent types for !if");
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user