mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-05 13:26:55 +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:
@@ -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;
|
||||
|
Reference in New Issue
Block a user