llvm.org GIT mirror llvm / 548f5a0
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 Bill Wendling 8 years ago
4 changed file(s) with 127 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
None // RUN: tblgen %s | grep {\\\[1, 2, 3\\\]} | count 4
1 // RUN: tblgen %s | grep {\\\[4, 5, 6\\\]} | count 2
0 // RUN: tblgen %s | FileCheck %s
21 // XFAIL: vg_leak
2
3 // Support for an `!if' operator as part of a `let' statement.
4 // CHECK: class C
5 // 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}) };
6 class C x, bits<4> y, bit z> {
7 bits<16> n;
8
9 let n{8-6} = !if(x{2}, 0b010, 0b110);
10 let n{5-4} = !if(x{1}, y{3-2}, {0, 1});
11 let n{3-0} = !if(x{0}, y{3-0}, {z, y{2}, y{1}, y{0}});
12 }
13
14 // CHECK: def One
15 // CHECK-NEXT: list first = [1, 2, 3];
16 // CHECK-NEXT: list rest = [1, 2, 3];
17
18 // CHECK: def OneB
19 // CHECK-NEXT: list vals = [1, 2, 3];
20
21 // CHECK: def Two
22 // CHECK-NEXT: list first = [1, 2, 3];
23 // CHECK-NEXT: list rest = [4, 5, 6];
24
25 // CHECK: def TwoB
26 // CHECK-NEXT: list vals = [4, 5, 6];
327
428 class A> vals> {
529 list first = vals[0];
731 }
832
933 def One : A<[[1,2,3]]>;
10 def Two : A<[[1,2,3],[4,5,6]]>;
34 def Two : A<[[1,2,3], [4,5,6]]>;
1135
1236 class B v> {
1337 list vals = v;
6464 return Ret;
6565 }
6666
67 // convertValue from Int initializer to bits type: Split the integer up into the
68 // appropriate bits.
69 //
67 /// canFitInBitfield - Return true if the number of bits is large enough to hold
68 /// the integer value.
69 static bool canFitInBitfield(int64_t Value, unsigned NumBits) {
70 if (Value >= 0) {
71 if (Value & ~((1LL << NumBits) - 1))
72 return false;
73 } else if ((Value >> NumBits) != -1 || (Value & (1LL << (NumBits-1))) == 0) {
74 return false;
75 }
76
77 return true;
78 }
79
80 /// convertValue from Int initializer to bits type: Split the integer up into the
81 /// appropriate bits.
82 ///
7083 Init *BitsRecTy::convertValue(IntInit *II) {
7184 int64_t Value = II->getValue();
7285 // Make sure this bitfield is large enough to hold the integer value.
73 if (Value >= 0) {
74 if (Value & ~((1LL << Size)-1))
75 return 0;
76 } else {
77 if ((Value >> Size) != -1 || ((Value & (1LL << (Size-1))) == 0))
78 return 0;
79 }
86 if (!canFitInBitfield(Value, Size))
87 return 0;
8088
8189 BitsInit *Ret = new BitsInit(Size);
8290 for (unsigned i = 0; i != Size; ++i)
100108 Ret->setBit(i, new VarBitInit(VI, i));
101109 return Ret;
102110 }
111
103112 if (Size == 1 && dynamic_cast(VI->getType())) {
104113 BitsInit *Ret = new BitsInit(1);
105114 Ret->setBit(0, VI);
106115 return Ret;
116 }
117
118 if (TernOpInit *Tern = dynamic_cast(VI)) {
119 if (Tern->getOpcode() == TernOpInit::IF) {
120 Init *LHS = Tern->getLHS();
121 Init *MHS = Tern->getMHS();
122 Init *RHS = Tern->getRHS();
123
124 IntInit *MHSi = dynamic_cast(MHS);
125 IntInit *RHSi = dynamic_cast(RHS);
126
127 if (MHSi && RHSi) {
128 int64_t MHSVal = MHSi->getValue();
129 int64_t RHSVal = RHSi->getValue();
130
131 if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) {
132 BitsInit *Ret = new BitsInit(Size);
133
134 for (unsigned i = 0; i != Size; ++i)
135 Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS,
136 new IntInit((MHSVal & (1LL << i)) ? 1 : 0),
137 new IntInit((RHSVal & (1LL << i)) ? 1 : 0),
138 VI->getType()));
139
140 return Ret;
141 }
142 } else {
143 BitsInit *MHSbs = dynamic_cast(MHS);
144 BitsInit *RHSbs = dynamic_cast(RHS);
145
146 if (MHSbs && RHSbs) {
147 BitsInit *Ret = new BitsInit(Size);
148
149 for (unsigned i = 0; i != Size; ++i)
150 Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS,
151 MHSbs->getBit(i),
152 RHSbs->getBit(i),
153 VI->getType()));
154
155 return Ret;
156 }
157 }
158 }
107159 }
108160
109161 return 0;
930930 // possible to fold.
931931 Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
932932
933 virtual bool isComplete() const { return false; }
934
933935 virtual Init *resolveReferences(Record &R, const RecordVal *RV);
934936
935937 virtual std::string getAsString() const;
867867 TernOpInit::TernaryOp Code;
868868 RecTy *Type = 0;
869869
870
871870 tgtok::TokKind LexCode = Lex.getCode();
872871 Lex.Lex(); // eat the operation
873872 switch (LexCode) {
918917 switch (LexCode) {
919918 default: assert(0 && "Unhandled code!");
920919 case tgtok::XIf: {
921 TypedInit *MHSt = dynamic_cast(MHS);
922 TypedInit *RHSt = dynamic_cast(RHS);
923 if (MHSt == 0 || RHSt == 0) {
920 // FIXME: The `!if' operator doesn't handle non-TypedInit well at
921 // all. This can be made much more robust.
922 TypedInit *MHSt = dynamic_cast(MHS);
923 TypedInit *RHSt = dynamic_cast(RHS);
924
925 RecTy *MHSTy = 0;
926 RecTy *RHSTy = 0;
927
928 if (MHSt == 0 && RHSt == 0) {
929 BitsInit *MHSbits = dynamic_cast(MHS);
930 BitsInit *RHSbits = dynamic_cast(RHS);
931
932 if (MHSbits && RHSbits &&
933 MHSbits->getNumBits() == RHSbits->getNumBits()) {
934 Type = new BitRecTy();
935 break;
936 } else {
937 BitInit *MHSbit = dynamic_cast(MHS);
938 BitInit *RHSbit = dynamic_cast(RHS);
939
940 if (MHSbit && RHSbit) {
941 Type = new BitRecTy();
942 break;
943 }
944 }
945 } else if (MHSt != 0 && RHSt != 0) {
946 MHSTy = MHSt->getType();
947 RHSTy = RHSt->getType();
948 }
949
950 if (!MHSTy || !RHSTy) {
924951 TokError("could not get type for !if");
925952 return 0;
926953 }
927 if (MHSt->getType()->typeIsConvertibleTo(RHSt->getType())) {
928 Type = RHSt->getType();
929 } else if (RHSt->getType()->typeIsConvertibleTo(MHSt->getType())) {
930 Type = MHSt->getType();
954
955 if (MHSTy->typeIsConvertibleTo(RHSTy)) {
956 Type = RHSTy;
957 } else if (RHSTy->typeIsConvertibleTo(MHSTy)) {
958 Type = MHSTy;
931959 } else {
932960 TokError("inconsistent types for !if");
933961 return 0;