1 | //===- Record.cpp - Record implementation ---------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Implement the tablegen record classes. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/TableGen/Record.h" |
14 | #include "llvm/ADT/ArrayRef.h" |
15 | #include "llvm/ADT/DenseMap.h" |
16 | #include "llvm/ADT/FoldingSet.h" |
17 | #include "llvm/ADT/SmallString.h" |
18 | #include "llvm/ADT/SmallVector.h" |
19 | #include "llvm/ADT/StringExtras.h" |
20 | #include "llvm/ADT/StringMap.h" |
21 | #include "llvm/ADT/StringRef.h" |
22 | #include "llvm/Config/llvm-config.h" |
23 | #include "llvm/Support/Allocator.h" |
24 | #include "llvm/Support/Casting.h" |
25 | #include "llvm/Support/Compiler.h" |
26 | #include "llvm/Support/ErrorHandling.h" |
27 | #include "llvm/Support/MathExtras.h" |
28 | #include "llvm/Support/Regex.h" |
29 | #include "llvm/Support/SMLoc.h" |
30 | #include "llvm/Support/raw_ostream.h" |
31 | #include "llvm/TableGen/Error.h" |
32 | #include "llvm/TableGen/TGTimer.h" |
33 | #include <cassert> |
34 | #include <cstdint> |
35 | #include <map> |
36 | #include <memory> |
37 | #include <string> |
38 | #include <utility> |
39 | #include <vector> |
40 | |
41 | using namespace llvm; |
42 | |
43 | #define DEBUG_TYPE "tblgen-records" |
44 | |
45 | //===----------------------------------------------------------------------===// |
46 | // Context |
47 | //===----------------------------------------------------------------------===// |
48 | |
49 | namespace llvm { |
50 | namespace detail { |
51 | /// This class represents the internal implementation of the RecordKeeper. |
52 | /// It contains all of the contextual static state of the Record classes. It is |
53 | /// kept out-of-line to simplify dependencies, and also make it easier for |
54 | /// internal classes to access the uniquer state of the keeper. |
55 | struct RecordKeeperImpl { |
56 | RecordKeeperImpl(RecordKeeper &RK) |
57 | : SharedBitRecTy(RK), SharedIntRecTy(RK), SharedStringRecTy(RK), |
58 | SharedDagRecTy(RK), AnyRecord(RK, {}), TheUnsetInit(RK), |
59 | TrueBitInit(true, &SharedBitRecTy), |
60 | FalseBitInit(false, &SharedBitRecTy), StringInitStringPool(Allocator), |
61 | StringInitCodePool(Allocator), AnonCounter(0), LastRecordID(0) {} |
62 | |
63 | BumpPtrAllocator Allocator; |
64 | std::vector<BitsRecTy *> SharedBitsRecTys; |
65 | BitRecTy SharedBitRecTy; |
66 | IntRecTy SharedIntRecTy; |
67 | StringRecTy SharedStringRecTy; |
68 | DagRecTy SharedDagRecTy; |
69 | |
70 | RecordRecTy AnyRecord; |
71 | UnsetInit TheUnsetInit; |
72 | BitInit TrueBitInit; |
73 | BitInit FalseBitInit; |
74 | |
75 | FoldingSet<ArgumentInit> TheArgumentInitPool; |
76 | FoldingSet<BitsInit> TheBitsInitPool; |
77 | std::map<int64_t, IntInit *> TheIntInitPool; |
78 | StringMap<const StringInit *, BumpPtrAllocator &> StringInitStringPool; |
79 | StringMap<const StringInit *, BumpPtrAllocator &> StringInitCodePool; |
80 | FoldingSet<ListInit> TheListInitPool; |
81 | FoldingSet<UnOpInit> TheUnOpInitPool; |
82 | FoldingSet<BinOpInit> TheBinOpInitPool; |
83 | FoldingSet<TernOpInit> TheTernOpInitPool; |
84 | FoldingSet<FoldOpInit> TheFoldOpInitPool; |
85 | FoldingSet<IsAOpInit> TheIsAOpInitPool; |
86 | FoldingSet<ExistsOpInit> TheExistsOpInitPool; |
87 | FoldingSet<InstancesOpInit> TheInstancesOpInitPool; |
88 | DenseMap<std::pair<const RecTy *, const Init *>, VarInit *> TheVarInitPool; |
89 | DenseMap<std::pair<const TypedInit *, unsigned>, VarBitInit *> |
90 | TheVarBitInitPool; |
91 | FoldingSet<VarDefInit> TheVarDefInitPool; |
92 | DenseMap<std::pair<const Init *, const StringInit *>, FieldInit *> |
93 | TheFieldInitPool; |
94 | FoldingSet<CondOpInit> TheCondOpInitPool; |
95 | FoldingSet<DagInit> TheDagInitPool; |
96 | FoldingSet<RecordRecTy> RecordTypePool; |
97 | |
98 | unsigned AnonCounter; |
99 | unsigned LastRecordID; |
100 | |
101 | void dumpAllocationStats(raw_ostream &OS) const; |
102 | }; |
103 | } // namespace detail |
104 | } // namespace llvm |
105 | |
106 | void detail::RecordKeeperImpl::dumpAllocationStats(raw_ostream &OS) const { |
107 | // Dump memory allocation related stats. |
108 | OS << "TheArgumentInitPool size = " << TheArgumentInitPool.size() << '\n'; |
109 | OS << "TheBitsInitPool size = " << TheBitsInitPool.size() << '\n'; |
110 | OS << "TheIntInitPool size = " << TheIntInitPool.size() << '\n'; |
111 | OS << "StringInitStringPool size = " << StringInitStringPool.size() << '\n'; |
112 | OS << "StringInitCodePool size = " << StringInitCodePool.size() << '\n'; |
113 | OS << "TheListInitPool size = " << TheListInitPool.size() << '\n'; |
114 | OS << "TheUnOpInitPool size = " << TheUnOpInitPool.size() << '\n'; |
115 | OS << "TheBinOpInitPool size = " << TheBinOpInitPool.size() << '\n'; |
116 | OS << "TheTernOpInitPool size = " << TheTernOpInitPool.size() << '\n'; |
117 | OS << "TheFoldOpInitPool size = " << TheFoldOpInitPool.size() << '\n'; |
118 | OS << "TheIsAOpInitPool size = " << TheIsAOpInitPool.size() << '\n'; |
119 | OS << "TheExistsOpInitPool size = " << TheExistsOpInitPool.size() << '\n'; |
120 | OS << "TheCondOpInitPool size = " << TheCondOpInitPool.size() << '\n'; |
121 | OS << "TheDagInitPool size = " << TheDagInitPool.size() << '\n'; |
122 | OS << "RecordTypePool size = " << RecordTypePool.size() << '\n'; |
123 | OS << "TheVarInitPool size = " << TheVarInitPool.size() << '\n'; |
124 | OS << "TheVarBitInitPool size = " << TheVarBitInitPool.size() << '\n'; |
125 | OS << "TheVarDefInitPool size = " << TheVarDefInitPool.size() << '\n'; |
126 | OS << "TheFieldInitPool size = " << TheFieldInitPool.size() << '\n'; |
127 | OS << "Bytes allocated = " << Allocator.getBytesAllocated() << '\n'; |
128 | OS << "Total allocator memory = " << Allocator.getTotalMemory() << "\n\n" ; |
129 | |
130 | OS << "Number of records instantiated = " << LastRecordID << '\n'; |
131 | OS << "Number of anonymous records = " << AnonCounter << '\n'; |
132 | } |
133 | |
134 | //===----------------------------------------------------------------------===// |
135 | // Type implementations |
136 | //===----------------------------------------------------------------------===// |
137 | |
138 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
139 | LLVM_DUMP_METHOD void RecTy::dump() const { print(errs()); } |
140 | #endif |
141 | |
142 | const ListRecTy *RecTy::getListTy() const { |
143 | if (!ListTy) |
144 | ListTy = new (RK.getImpl().Allocator) ListRecTy(this); |
145 | return ListTy; |
146 | } |
147 | |
148 | bool RecTy::typeIsConvertibleTo(const RecTy *RHS) const { |
149 | assert(RHS && "NULL pointer" ); |
150 | return Kind == RHS->getRecTyKind(); |
151 | } |
152 | |
153 | bool RecTy::typeIsA(const RecTy *RHS) const { return this == RHS; } |
154 | |
155 | const BitRecTy *BitRecTy::get(RecordKeeper &RK) { |
156 | return &RK.getImpl().SharedBitRecTy; |
157 | } |
158 | |
159 | bool BitRecTy::typeIsConvertibleTo(const RecTy *RHS) const{ |
160 | if (RecTy::typeIsConvertibleTo(RHS) || RHS->getRecTyKind() == IntRecTyKind) |
161 | return true; |
162 | if (const auto *BitsTy = dyn_cast<BitsRecTy>(Val: RHS)) |
163 | return BitsTy->getNumBits() == 1; |
164 | return false; |
165 | } |
166 | |
167 | const BitsRecTy *BitsRecTy::get(RecordKeeper &RK, unsigned Sz) { |
168 | detail::RecordKeeperImpl &RKImpl = RK.getImpl(); |
169 | if (Sz >= RKImpl.SharedBitsRecTys.size()) |
170 | RKImpl.SharedBitsRecTys.resize(new_size: Sz + 1); |
171 | BitsRecTy *&Ty = RKImpl.SharedBitsRecTys[Sz]; |
172 | if (!Ty) |
173 | Ty = new (RKImpl.Allocator) BitsRecTy(RK, Sz); |
174 | return Ty; |
175 | } |
176 | |
177 | std::string BitsRecTy::getAsString() const { |
178 | return "bits<" + utostr(X: Size) + ">" ; |
179 | } |
180 | |
181 | bool BitsRecTy::typeIsConvertibleTo(const RecTy *RHS) const { |
182 | if (RecTy::typeIsConvertibleTo(RHS)) //argument and the sender are same type |
183 | return cast<BitsRecTy>(Val: RHS)->Size == Size; |
184 | RecTyKind kind = RHS->getRecTyKind(); |
185 | return (kind == BitRecTyKind && Size == 1) || (kind == IntRecTyKind); |
186 | } |
187 | |
188 | const IntRecTy *IntRecTy::get(RecordKeeper &RK) { |
189 | return &RK.getImpl().SharedIntRecTy; |
190 | } |
191 | |
192 | bool IntRecTy::typeIsConvertibleTo(const RecTy *RHS) const { |
193 | RecTyKind kind = RHS->getRecTyKind(); |
194 | return kind==BitRecTyKind || kind==BitsRecTyKind || kind==IntRecTyKind; |
195 | } |
196 | |
197 | const StringRecTy *StringRecTy::get(RecordKeeper &RK) { |
198 | return &RK.getImpl().SharedStringRecTy; |
199 | } |
200 | |
201 | std::string StringRecTy::getAsString() const { |
202 | return "string" ; |
203 | } |
204 | |
205 | bool StringRecTy::typeIsConvertibleTo(const RecTy *RHS) const { |
206 | RecTyKind Kind = RHS->getRecTyKind(); |
207 | return Kind == StringRecTyKind; |
208 | } |
209 | |
210 | std::string ListRecTy::getAsString() const { |
211 | return "list<" + ElementTy->getAsString() + ">" ; |
212 | } |
213 | |
214 | bool ListRecTy::typeIsConvertibleTo(const RecTy *RHS) const { |
215 | if (const auto *ListTy = dyn_cast<ListRecTy>(Val: RHS)) |
216 | return ElementTy->typeIsConvertibleTo(RHS: ListTy->getElementType()); |
217 | return false; |
218 | } |
219 | |
220 | bool ListRecTy::typeIsA(const RecTy *RHS) const { |
221 | if (const auto *RHSl = dyn_cast<ListRecTy>(Val: RHS)) |
222 | return getElementType()->typeIsA(RHS: RHSl->getElementType()); |
223 | return false; |
224 | } |
225 | |
226 | const DagRecTy *DagRecTy::get(RecordKeeper &RK) { |
227 | return &RK.getImpl().SharedDagRecTy; |
228 | } |
229 | |
230 | std::string DagRecTy::getAsString() const { |
231 | return "dag" ; |
232 | } |
233 | |
234 | static void ProfileRecordRecTy(FoldingSetNodeID &ID, |
235 | ArrayRef<const Record *> Classes) { |
236 | ID.AddInteger(I: Classes.size()); |
237 | for (const Record *R : Classes) |
238 | ID.AddPointer(Ptr: R); |
239 | } |
240 | |
241 | RecordRecTy::RecordRecTy(RecordKeeper &RK, ArrayRef<const Record *> Classes) |
242 | : RecTy(RecordRecTyKind, RK), NumClasses(Classes.size()) { |
243 | llvm::uninitialized_copy(Src&: Classes, Dst: getTrailingObjects()); |
244 | } |
245 | |
246 | const RecordRecTy *RecordRecTy::get(RecordKeeper &RK, |
247 | ArrayRef<const Record *> UnsortedClasses) { |
248 | detail::RecordKeeperImpl &RKImpl = RK.getImpl(); |
249 | if (UnsortedClasses.empty()) |
250 | return &RKImpl.AnyRecord; |
251 | |
252 | FoldingSet<RecordRecTy> &ThePool = RKImpl.RecordTypePool; |
253 | |
254 | SmallVector<const Record *, 4> Classes(UnsortedClasses); |
255 | llvm::sort(C&: Classes, Comp: [](const Record *LHS, const Record *RHS) { |
256 | return LHS->getNameInitAsString() < RHS->getNameInitAsString(); |
257 | }); |
258 | |
259 | FoldingSetNodeID ID; |
260 | ProfileRecordRecTy(ID, Classes); |
261 | |
262 | void *IP = nullptr; |
263 | if (RecordRecTy *Ty = ThePool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
264 | return Ty; |
265 | |
266 | #ifndef NDEBUG |
267 | // Check for redundancy. |
268 | for (unsigned i = 0; i < Classes.size(); ++i) { |
269 | for (unsigned j = 0; j < Classes.size(); ++j) { |
270 | assert(i == j || !Classes[i]->isSubClassOf(Classes[j])); |
271 | } |
272 | assert(&Classes[0]->getRecords() == &Classes[i]->getRecords()); |
273 | } |
274 | #endif |
275 | |
276 | void *Mem = RKImpl.Allocator.Allocate( |
277 | Size: totalSizeToAlloc<const Record *>(Counts: Classes.size()), Alignment: alignof(RecordRecTy)); |
278 | RecordRecTy *Ty = new (Mem) RecordRecTy(RK, Classes); |
279 | ThePool.InsertNode(N: Ty, InsertPos: IP); |
280 | return Ty; |
281 | } |
282 | |
283 | const RecordRecTy *RecordRecTy::get(const Record *Class) { |
284 | assert(Class && "unexpected null class" ); |
285 | return get(RK&: Class->getRecords(), UnsortedClasses: {Class}); |
286 | } |
287 | |
288 | void RecordRecTy::Profile(FoldingSetNodeID &ID) const { |
289 | ProfileRecordRecTy(ID, Classes: getClasses()); |
290 | } |
291 | |
292 | std::string RecordRecTy::getAsString() const { |
293 | if (NumClasses == 1) |
294 | return getClasses()[0]->getNameInitAsString(); |
295 | |
296 | std::string Str = "{" ; |
297 | ListSeparator LS; |
298 | for (const Record *R : getClasses()) { |
299 | Str += LS; |
300 | Str += R->getNameInitAsString(); |
301 | } |
302 | Str += "}" ; |
303 | return Str; |
304 | } |
305 | |
306 | bool RecordRecTy::isSubClassOf(const Record *Class) const { |
307 | return llvm::any_of(Range: getClasses(), P: [Class](const Record *MySuperClass) { |
308 | return MySuperClass == Class || MySuperClass->isSubClassOf(R: Class); |
309 | }); |
310 | } |
311 | |
312 | bool RecordRecTy::typeIsConvertibleTo(const RecTy *RHS) const { |
313 | if (this == RHS) |
314 | return true; |
315 | |
316 | const auto *RTy = dyn_cast<RecordRecTy>(Val: RHS); |
317 | if (!RTy) |
318 | return false; |
319 | |
320 | return llvm::all_of(Range: RTy->getClasses(), P: [this](const Record *TargetClass) { |
321 | return isSubClassOf(Class: TargetClass); |
322 | }); |
323 | } |
324 | |
325 | bool RecordRecTy::typeIsA(const RecTy *RHS) const { |
326 | return typeIsConvertibleTo(RHS); |
327 | } |
328 | |
329 | static const RecordRecTy *resolveRecordTypes(const RecordRecTy *T1, |
330 | const RecordRecTy *T2) { |
331 | SmallVector<const Record *, 4> CommonSuperClasses; |
332 | SmallVector<const Record *, 4> Stack(T1->getClasses()); |
333 | |
334 | while (!Stack.empty()) { |
335 | const Record *R = Stack.pop_back_val(); |
336 | |
337 | if (T2->isSubClassOf(Class: R)) |
338 | CommonSuperClasses.push_back(Elt: R); |
339 | else |
340 | llvm::append_range(C&: Stack, R: make_first_range(c: R->getDirectSuperClasses())); |
341 | } |
342 | |
343 | return RecordRecTy::get(RK&: T1->getRecordKeeper(), UnsortedClasses: CommonSuperClasses); |
344 | } |
345 | |
346 | const RecTy *llvm::resolveTypes(const RecTy *T1, const RecTy *T2) { |
347 | if (T1 == T2) |
348 | return T1; |
349 | |
350 | if (const auto *RecTy1 = dyn_cast<RecordRecTy>(Val: T1)) { |
351 | if (const auto *RecTy2 = dyn_cast<RecordRecTy>(Val: T2)) |
352 | return resolveRecordTypes(T1: RecTy1, T2: RecTy2); |
353 | } |
354 | |
355 | assert(T1 != nullptr && "Invalid record type" ); |
356 | if (T1->typeIsConvertibleTo(RHS: T2)) |
357 | return T2; |
358 | |
359 | assert(T2 != nullptr && "Invalid record type" ); |
360 | if (T2->typeIsConvertibleTo(RHS: T1)) |
361 | return T1; |
362 | |
363 | if (const auto *ListTy1 = dyn_cast<ListRecTy>(Val: T1)) { |
364 | if (const auto *ListTy2 = dyn_cast<ListRecTy>(Val: T2)) { |
365 | const RecTy *NewType = |
366 | resolveTypes(T1: ListTy1->getElementType(), T2: ListTy2->getElementType()); |
367 | if (NewType) |
368 | return NewType->getListTy(); |
369 | } |
370 | } |
371 | |
372 | return nullptr; |
373 | } |
374 | |
375 | //===----------------------------------------------------------------------===// |
376 | // Initializer implementations |
377 | //===----------------------------------------------------------------------===// |
378 | |
379 | void Init::anchor() {} |
380 | |
381 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
382 | LLVM_DUMP_METHOD void Init::dump() const { return print(errs()); } |
383 | #endif |
384 | |
385 | RecordKeeper &Init::getRecordKeeper() const { |
386 | if (auto *TyInit = dyn_cast<TypedInit>(Val: this)) |
387 | return TyInit->getType()->getRecordKeeper(); |
388 | if (auto *ArgInit = dyn_cast<ArgumentInit>(Val: this)) |
389 | return ArgInit->getRecordKeeper(); |
390 | return cast<UnsetInit>(Val: this)->getRecordKeeper(); |
391 | } |
392 | |
393 | UnsetInit *UnsetInit::get(RecordKeeper &RK) { |
394 | return &RK.getImpl().TheUnsetInit; |
395 | } |
396 | |
397 | const Init *UnsetInit::getCastTo(const RecTy *Ty) const { return this; } |
398 | |
399 | const Init *UnsetInit::convertInitializerTo(const RecTy *Ty) const { |
400 | return this; |
401 | } |
402 | |
403 | static void ProfileArgumentInit(FoldingSetNodeID &ID, const Init *Value, |
404 | ArgAuxType Aux) { |
405 | auto I = Aux.index(); |
406 | ID.AddInteger(I); |
407 | if (I == ArgumentInit::Positional) |
408 | ID.AddInteger(I: std::get<ArgumentInit::Positional>(v&: Aux)); |
409 | if (I == ArgumentInit::Named) |
410 | ID.AddPointer(Ptr: std::get<ArgumentInit::Named>(v&: Aux)); |
411 | ID.AddPointer(Ptr: Value); |
412 | } |
413 | |
414 | void ArgumentInit::Profile(FoldingSetNodeID &ID) const { |
415 | ProfileArgumentInit(ID, Value, Aux); |
416 | } |
417 | |
418 | const ArgumentInit *ArgumentInit::get(const Init *Value, ArgAuxType Aux) { |
419 | FoldingSetNodeID ID; |
420 | ProfileArgumentInit(ID, Value, Aux); |
421 | |
422 | RecordKeeper &RK = Value->getRecordKeeper(); |
423 | detail::RecordKeeperImpl &RKImpl = RK.getImpl(); |
424 | void *IP = nullptr; |
425 | if (const ArgumentInit *I = |
426 | RKImpl.TheArgumentInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
427 | return I; |
428 | |
429 | ArgumentInit *I = new (RKImpl.Allocator) ArgumentInit(Value, Aux); |
430 | RKImpl.TheArgumentInitPool.InsertNode(N: I, InsertPos: IP); |
431 | return I; |
432 | } |
433 | |
434 | const Init *ArgumentInit::resolveReferences(Resolver &R) const { |
435 | const Init *NewValue = Value->resolveReferences(R); |
436 | if (NewValue != Value) |
437 | return cloneWithValue(Value: NewValue); |
438 | |
439 | return this; |
440 | } |
441 | |
442 | BitInit *BitInit::get(RecordKeeper &RK, bool V) { |
443 | return V ? &RK.getImpl().TrueBitInit : &RK.getImpl().FalseBitInit; |
444 | } |
445 | |
446 | const Init *BitInit::convertInitializerTo(const RecTy *Ty) const { |
447 | if (isa<BitRecTy>(Val: Ty)) |
448 | return this; |
449 | |
450 | if (isa<IntRecTy>(Val: Ty)) |
451 | return IntInit::get(RK&: getRecordKeeper(), V: getValue()); |
452 | |
453 | if (auto *BRT = dyn_cast<BitsRecTy>(Val: Ty)) { |
454 | // Can only convert single bit. |
455 | if (BRT->getNumBits() == 1) |
456 | return BitsInit::get(RK&: getRecordKeeper(), Range: this); |
457 | } |
458 | |
459 | return nullptr; |
460 | } |
461 | |
462 | static void ProfileBitsInit(FoldingSetNodeID &ID, |
463 | ArrayRef<const Init *> Range) { |
464 | ID.AddInteger(I: Range.size()); |
465 | |
466 | for (const Init *I : Range) |
467 | ID.AddPointer(Ptr: I); |
468 | } |
469 | |
470 | BitsInit::BitsInit(RecordKeeper &RK, ArrayRef<const Init *> Bits) |
471 | : TypedInit(IK_BitsInit, BitsRecTy::get(RK, Sz: Bits.size())), |
472 | NumBits(Bits.size()) { |
473 | llvm::uninitialized_copy(Src&: Bits, Dst: getTrailingObjects()); |
474 | } |
475 | |
476 | BitsInit *BitsInit::get(RecordKeeper &RK, ArrayRef<const Init *> Bits) { |
477 | FoldingSetNodeID ID; |
478 | ProfileBitsInit(ID, Range: Bits); |
479 | |
480 | detail::RecordKeeperImpl &RKImpl = RK.getImpl(); |
481 | void *IP = nullptr; |
482 | if (BitsInit *I = RKImpl.TheBitsInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
483 | return I; |
484 | |
485 | void *Mem = RKImpl.Allocator.Allocate( |
486 | Size: totalSizeToAlloc<const Init *>(Counts: Bits.size()), Alignment: alignof(BitsInit)); |
487 | BitsInit *I = new (Mem) BitsInit(RK, Bits); |
488 | RKImpl.TheBitsInitPool.InsertNode(N: I, InsertPos: IP); |
489 | return I; |
490 | } |
491 | |
492 | void BitsInit::Profile(FoldingSetNodeID &ID) const { |
493 | ProfileBitsInit(ID, Range: getBits()); |
494 | } |
495 | |
496 | const Init *BitsInit::convertInitializerTo(const RecTy *Ty) const { |
497 | if (isa<BitRecTy>(Val: Ty)) { |
498 | if (getNumBits() != 1) return nullptr; // Only accept if just one bit! |
499 | return getBit(Bit: 0); |
500 | } |
501 | |
502 | if (auto *BRT = dyn_cast<BitsRecTy>(Val: Ty)) { |
503 | // If the number of bits is right, return it. Otherwise we need to expand |
504 | // or truncate. |
505 | if (getNumBits() != BRT->getNumBits()) return nullptr; |
506 | return this; |
507 | } |
508 | |
509 | if (isa<IntRecTy>(Val: Ty)) { |
510 | std::optional<int64_t> Result = convertInitializerToInt(); |
511 | if (Result) |
512 | return IntInit::get(RK&: getRecordKeeper(), V: *Result); |
513 | } |
514 | |
515 | return nullptr; |
516 | } |
517 | |
518 | std::optional<int64_t> BitsInit::convertInitializerToInt() const { |
519 | int64_t Result = 0; |
520 | for (auto [Idx, InitV] : enumerate(First: getBits())) |
521 | if (auto *Bit = dyn_cast<BitInit>(Val: InitV)) |
522 | Result |= static_cast<int64_t>(Bit->getValue()) << Idx; |
523 | else |
524 | return std::nullopt; |
525 | return Result; |
526 | } |
527 | |
528 | const Init * |
529 | BitsInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { |
530 | SmallVector<const Init *, 16> NewBits(Bits.size()); |
531 | |
532 | for (auto [Bit, NewBit] : zip_equal(t&: Bits, u&: NewBits)) { |
533 | if (Bit >= getNumBits()) |
534 | return nullptr; |
535 | NewBit = getBit(Bit); |
536 | } |
537 | return BitsInit::get(RK&: getRecordKeeper(), Bits: NewBits); |
538 | } |
539 | |
540 | bool BitsInit::isComplete() const { |
541 | return all_of(Range: getBits(), P: [](const Init *Bit) { return Bit->isComplete(); }); |
542 | } |
543 | bool BitsInit::allInComplete() const { |
544 | return all_of(Range: getBits(), P: [](const Init *Bit) { return !Bit->isComplete(); }); |
545 | } |
546 | bool BitsInit::isConcrete() const { |
547 | return all_of(Range: getBits(), P: [](const Init *Bit) { return Bit->isConcrete(); }); |
548 | } |
549 | |
550 | std::string BitsInit::getAsString() const { |
551 | std::string Result = "{ " ; |
552 | ListSeparator LS; |
553 | for (const Init *Bit : reverse(C: getBits())) { |
554 | Result += LS; |
555 | if (Bit) |
556 | Result += Bit->getAsString(); |
557 | else |
558 | Result += "*" ; |
559 | } |
560 | return Result + " }" ; |
561 | } |
562 | |
563 | // resolveReferences - If there are any field references that refer to fields |
564 | // that have been filled in, we can propagate the values now. |
565 | const Init *BitsInit::resolveReferences(Resolver &R) const { |
566 | bool Changed = false; |
567 | SmallVector<const Init *, 16> NewBits(getNumBits()); |
568 | |
569 | const Init *CachedBitVarRef = nullptr; |
570 | const Init *CachedBitVarResolved = nullptr; |
571 | |
572 | for (auto [CurBit, NewBit] : zip_equal(t: getBits(), u&: NewBits)) { |
573 | NewBit = CurBit; |
574 | |
575 | if (const auto *CurBitVar = dyn_cast<VarBitInit>(Val: CurBit)) { |
576 | if (CurBitVar->getBitVar() != CachedBitVarRef) { |
577 | CachedBitVarRef = CurBitVar->getBitVar(); |
578 | CachedBitVarResolved = CachedBitVarRef->resolveReferences(R); |
579 | } |
580 | assert(CachedBitVarResolved && "Unresolved bitvar reference" ); |
581 | NewBit = CachedBitVarResolved->getBit(Bit: CurBitVar->getBitNum()); |
582 | } else { |
583 | // getBit(0) implicitly converts int and bits<1> values to bit. |
584 | NewBit = CurBit->resolveReferences(R)->getBit(Bit: 0); |
585 | } |
586 | |
587 | if (isa<UnsetInit>(Val: NewBit) && R.keepUnsetBits()) |
588 | NewBit = CurBit; |
589 | Changed |= CurBit != NewBit; |
590 | } |
591 | |
592 | if (Changed) |
593 | return BitsInit::get(RK&: getRecordKeeper(), Bits: NewBits); |
594 | |
595 | return this; |
596 | } |
597 | |
598 | IntInit *IntInit::get(RecordKeeper &RK, int64_t V) { |
599 | IntInit *&I = RK.getImpl().TheIntInitPool[V]; |
600 | if (!I) |
601 | I = new (RK.getImpl().Allocator) IntInit(RK, V); |
602 | return I; |
603 | } |
604 | |
605 | std::string IntInit::getAsString() const { |
606 | return itostr(X: Value); |
607 | } |
608 | |
609 | static bool canFitInBitfield(int64_t Value, unsigned NumBits) { |
610 | // For example, with NumBits == 4, we permit Values from [-7 .. 15]. |
611 | return (NumBits >= sizeof(Value) * 8) || |
612 | (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1); |
613 | } |
614 | |
615 | const Init *IntInit::convertInitializerTo(const RecTy *Ty) const { |
616 | if (isa<IntRecTy>(Val: Ty)) |
617 | return this; |
618 | |
619 | if (isa<BitRecTy>(Val: Ty)) { |
620 | int64_t Val = getValue(); |
621 | if (Val != 0 && Val != 1) return nullptr; // Only accept 0 or 1 for a bit! |
622 | return BitInit::get(RK&: getRecordKeeper(), V: Val != 0); |
623 | } |
624 | |
625 | if (const auto *BRT = dyn_cast<BitsRecTy>(Val: Ty)) { |
626 | int64_t Value = getValue(); |
627 | // Make sure this bitfield is large enough to hold the integer value. |
628 | if (!canFitInBitfield(Value, NumBits: BRT->getNumBits())) |
629 | return nullptr; |
630 | |
631 | SmallVector<const Init *, 16> NewBits(BRT->getNumBits()); |
632 | for (unsigned i = 0; i != BRT->getNumBits(); ++i) |
633 | NewBits[i] = |
634 | BitInit::get(RK&: getRecordKeeper(), V: Value & ((i < 64) ? (1LL << i) : 0)); |
635 | |
636 | return BitsInit::get(RK&: getRecordKeeper(), Bits: NewBits); |
637 | } |
638 | |
639 | return nullptr; |
640 | } |
641 | |
642 | const Init *IntInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { |
643 | SmallVector<const Init *, 16> NewBits(Bits.size()); |
644 | |
645 | for (auto [Bit, NewBit] : zip_equal(t&: Bits, u&: NewBits)) { |
646 | if (Bit >= 64) |
647 | return nullptr; |
648 | |
649 | NewBit = BitInit::get(RK&: getRecordKeeper(), V: Value & (INT64_C(1) << Bit)); |
650 | } |
651 | return BitsInit::get(RK&: getRecordKeeper(), Bits: NewBits); |
652 | } |
653 | |
654 | AnonymousNameInit *AnonymousNameInit::get(RecordKeeper &RK, unsigned V) { |
655 | return new (RK.getImpl().Allocator) AnonymousNameInit(RK, V); |
656 | } |
657 | |
658 | const StringInit *AnonymousNameInit::getNameInit() const { |
659 | return StringInit::get(RK&: getRecordKeeper(), getAsString()); |
660 | } |
661 | |
662 | std::string AnonymousNameInit::getAsString() const { |
663 | return "anonymous_" + utostr(X: Value); |
664 | } |
665 | |
666 | const Init *AnonymousNameInit::resolveReferences(Resolver &R) const { |
667 | auto *Old = this; |
668 | auto *New = R.resolve(VarName: Old); |
669 | New = New ? New : Old; |
670 | if (R.isFinal()) |
671 | if (const auto *Anonymous = dyn_cast<AnonymousNameInit>(Val: New)) |
672 | return Anonymous->getNameInit(); |
673 | return New; |
674 | } |
675 | |
676 | const StringInit *StringInit::get(RecordKeeper &RK, StringRef V, |
677 | StringFormat Fmt) { |
678 | detail::RecordKeeperImpl &RKImpl = RK.getImpl(); |
679 | auto &InitMap = Fmt == SF_String ? RKImpl.StringInitStringPool |
680 | : RKImpl.StringInitCodePool; |
681 | auto &Entry = *InitMap.try_emplace(Key: V, Args: nullptr).first; |
682 | if (!Entry.second) |
683 | Entry.second = new (RKImpl.Allocator) StringInit(RK, Entry.getKey(), Fmt); |
684 | return Entry.second; |
685 | } |
686 | |
687 | const Init *StringInit::convertInitializerTo(const RecTy *Ty) const { |
688 | if (isa<StringRecTy>(Val: Ty)) |
689 | return this; |
690 | |
691 | return nullptr; |
692 | } |
693 | |
694 | static void ProfileListInit(FoldingSetNodeID &ID, |
695 | ArrayRef<const Init *> Elements, |
696 | const RecTy *EltTy) { |
697 | ID.AddInteger(I: Elements.size()); |
698 | ID.AddPointer(Ptr: EltTy); |
699 | |
700 | for (const Init *E : Elements) |
701 | ID.AddPointer(Ptr: E); |
702 | } |
703 | |
704 | ListInit::ListInit(ArrayRef<const Init *> Elements, const RecTy *EltTy) |
705 | : TypedInit(IK_ListInit, ListRecTy::get(T: EltTy)), |
706 | NumElements(Elements.size()) { |
707 | llvm::uninitialized_copy(Src&: Elements, Dst: getTrailingObjects()); |
708 | } |
709 | |
710 | const ListInit *ListInit::get(ArrayRef<const Init *> Elements, |
711 | const RecTy *EltTy) { |
712 | FoldingSetNodeID ID; |
713 | ProfileListInit(ID, Elements, EltTy); |
714 | |
715 | detail::RecordKeeperImpl &RK = EltTy->getRecordKeeper().getImpl(); |
716 | void *IP = nullptr; |
717 | if (const ListInit *I = RK.TheListInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
718 | return I; |
719 | |
720 | assert(Elements.empty() || !isa<TypedInit>(Elements[0]) || |
721 | cast<TypedInit>(Elements[0])->getType()->typeIsConvertibleTo(EltTy)); |
722 | |
723 | void *Mem = RK.Allocator.Allocate( |
724 | Size: totalSizeToAlloc<const Init *>(Counts: Elements.size()), Alignment: alignof(ListInit)); |
725 | ListInit *I = new (Mem) ListInit(Elements, EltTy); |
726 | RK.TheListInitPool.InsertNode(N: I, InsertPos: IP); |
727 | return I; |
728 | } |
729 | |
730 | void ListInit::Profile(FoldingSetNodeID &ID) const { |
731 | const RecTy *EltTy = cast<ListRecTy>(Val: getType())->getElementType(); |
732 | ProfileListInit(ID, Elements: getElements(), EltTy); |
733 | } |
734 | |
735 | const Init *ListInit::convertInitializerTo(const RecTy *Ty) const { |
736 | if (getType() == Ty) |
737 | return this; |
738 | |
739 | if (const auto *LRT = dyn_cast<ListRecTy>(Val: Ty)) { |
740 | SmallVector<const Init *, 8> Elements; |
741 | Elements.reserve(N: size()); |
742 | |
743 | // Verify that all of the elements of the list are subclasses of the |
744 | // appropriate class! |
745 | bool Changed = false; |
746 | const RecTy *ElementType = LRT->getElementType(); |
747 | for (const Init *I : getElements()) |
748 | if (const Init *CI = I->convertInitializerTo(Ty: ElementType)) { |
749 | Elements.push_back(Elt: CI); |
750 | if (CI != I) |
751 | Changed = true; |
752 | } else { |
753 | return nullptr; |
754 | } |
755 | |
756 | if (!Changed) |
757 | return this; |
758 | return ListInit::get(Elements, EltTy: ElementType); |
759 | } |
760 | |
761 | return nullptr; |
762 | } |
763 | |
764 | const Record *ListInit::getElementAsRecord(unsigned Idx) const { |
765 | const auto *DI = dyn_cast<DefInit>(Val: getElement(Idx)); |
766 | if (!DI) |
767 | PrintFatalError(Msg: "Expected record in list!" ); |
768 | return DI->getDef(); |
769 | } |
770 | |
771 | const Init *ListInit::resolveReferences(Resolver &R) const { |
772 | SmallVector<const Init *, 8> Resolved; |
773 | Resolved.reserve(N: size()); |
774 | bool Changed = false; |
775 | |
776 | for (const Init *CurElt : getElements()) { |
777 | const Init *E = CurElt->resolveReferences(R); |
778 | Changed |= E != CurElt; |
779 | Resolved.push_back(Elt: E); |
780 | } |
781 | |
782 | if (Changed) |
783 | return ListInit::get(Elements: Resolved, EltTy: getElementType()); |
784 | return this; |
785 | } |
786 | |
787 | bool ListInit::isComplete() const { |
788 | return all_of(Range: *this, |
789 | P: [](const Init *Element) { return Element->isComplete(); }); |
790 | } |
791 | |
792 | bool ListInit::isConcrete() const { |
793 | return all_of(Range: *this, |
794 | P: [](const Init *Element) { return Element->isConcrete(); }); |
795 | } |
796 | |
797 | std::string ListInit::getAsString() const { |
798 | std::string Result = "[" ; |
799 | ListSeparator LS; |
800 | for (const Init *Element : *this) { |
801 | Result += LS; |
802 | Result += Element->getAsString(); |
803 | } |
804 | return Result + "]" ; |
805 | } |
806 | |
807 | const Init *OpInit::getBit(unsigned Bit) const { |
808 | if (getType() == BitRecTy::get(RK&: getRecordKeeper())) |
809 | return this; |
810 | return VarBitInit::get(T: this, B: Bit); |
811 | } |
812 | |
813 | static void ProfileUnOpInit(FoldingSetNodeID &ID, unsigned Opcode, |
814 | const Init *Op, const RecTy *Type) { |
815 | ID.AddInteger(I: Opcode); |
816 | ID.AddPointer(Ptr: Op); |
817 | ID.AddPointer(Ptr: Type); |
818 | } |
819 | |
820 | const UnOpInit *UnOpInit::get(UnaryOp Opc, const Init *LHS, const RecTy *Type) { |
821 | FoldingSetNodeID ID; |
822 | ProfileUnOpInit(ID, Opcode: Opc, Op: LHS, Type); |
823 | |
824 | detail::RecordKeeperImpl &RK = Type->getRecordKeeper().getImpl(); |
825 | void *IP = nullptr; |
826 | if (const UnOpInit *I = RK.TheUnOpInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
827 | return I; |
828 | |
829 | UnOpInit *I = new (RK.Allocator) UnOpInit(Opc, LHS, Type); |
830 | RK.TheUnOpInitPool.InsertNode(N: I, InsertPos: IP); |
831 | return I; |
832 | } |
833 | |
834 | void UnOpInit::Profile(FoldingSetNodeID &ID) const { |
835 | ProfileUnOpInit(ID, Opcode: getOpcode(), Op: getOperand(), Type: getType()); |
836 | } |
837 | |
838 | const Init *UnOpInit::Fold(const Record *CurRec, bool IsFinal) const { |
839 | RecordKeeper &RK = getRecordKeeper(); |
840 | switch (getOpcode()) { |
841 | case REPR: |
842 | if (LHS->isConcrete()) { |
843 | // If it is a Record, print the full content. |
844 | if (const auto *Def = dyn_cast<DefInit>(Val: LHS)) { |
845 | std::string S; |
846 | raw_string_ostream OS(S); |
847 | OS << *Def->getDef(); |
848 | return StringInit::get(RK, V: S); |
849 | } else { |
850 | // Otherwise, print the value of the variable. |
851 | // |
852 | // NOTE: we could recursively !repr the elements of a list, |
853 | // but that could produce a lot of output when printing a |
854 | // defset. |
855 | return StringInit::get(RK, V: LHS->getAsString()); |
856 | } |
857 | } |
858 | break; |
859 | case TOLOWER: |
860 | if (const auto *LHSs = dyn_cast<StringInit>(Val: LHS)) |
861 | return StringInit::get(RK, V: LHSs->getValue().lower()); |
862 | break; |
863 | case TOUPPER: |
864 | if (const auto *LHSs = dyn_cast<StringInit>(Val: LHS)) |
865 | return StringInit::get(RK, V: LHSs->getValue().upper()); |
866 | break; |
867 | case CAST: |
868 | if (isa<StringRecTy>(Val: getType())) { |
869 | if (const auto *LHSs = dyn_cast<StringInit>(Val: LHS)) |
870 | return LHSs; |
871 | |
872 | if (const auto *LHSd = dyn_cast<DefInit>(Val: LHS)) |
873 | return StringInit::get(RK, V: LHSd->getAsString()); |
874 | |
875 | if (const auto *LHSi = dyn_cast_or_null<IntInit>( |
876 | Val: LHS->convertInitializerTo(Ty: IntRecTy::get(RK)))) |
877 | return StringInit::get(RK, V: LHSi->getAsString()); |
878 | |
879 | } else if (isa<RecordRecTy>(Val: getType())) { |
880 | if (const auto *Name = dyn_cast<StringInit>(Val: LHS)) { |
881 | const Record *D = RK.getDef(Name: Name->getValue()); |
882 | if (!D && CurRec) { |
883 | // Self-references are allowed, but their resolution is delayed until |
884 | // the final resolve to ensure that we get the correct type for them. |
885 | auto *Anonymous = dyn_cast<AnonymousNameInit>(Val: CurRec->getNameInit()); |
886 | if (Name == CurRec->getNameInit() || |
887 | (Anonymous && Name == Anonymous->getNameInit())) { |
888 | if (!IsFinal) |
889 | break; |
890 | D = CurRec; |
891 | } |
892 | } |
893 | |
894 | auto PrintFatalErrorHelper = [CurRec](const Twine &T) { |
895 | if (CurRec) |
896 | PrintFatalError(ErrorLoc: CurRec->getLoc(), Msg: T); |
897 | else |
898 | PrintFatalError(Msg: T); |
899 | }; |
900 | |
901 | if (!D) { |
902 | if (IsFinal) { |
903 | PrintFatalErrorHelper(Twine("Undefined reference to record: '" ) + |
904 | Name->getValue() + "'\n" ); |
905 | } |
906 | break; |
907 | } |
908 | |
909 | DefInit *DI = D->getDefInit(); |
910 | if (!DI->getType()->typeIsA(RHS: getType())) { |
911 | PrintFatalErrorHelper(Twine("Expected type '" ) + |
912 | getType()->getAsString() + "', got '" + |
913 | DI->getType()->getAsString() + "' in: " + |
914 | getAsString() + "\n" ); |
915 | } |
916 | return DI; |
917 | } |
918 | } |
919 | |
920 | if (const Init *NewInit = LHS->convertInitializerTo(Ty: getType())) |
921 | return NewInit; |
922 | break; |
923 | |
924 | case INITIALIZED: |
925 | if (isa<UnsetInit>(Val: LHS)) |
926 | return IntInit::get(RK, V: 0); |
927 | if (LHS->isConcrete()) |
928 | return IntInit::get(RK, V: 1); |
929 | break; |
930 | |
931 | case NOT: |
932 | if (const auto *LHSi = dyn_cast_or_null<IntInit>( |
933 | Val: LHS->convertInitializerTo(Ty: IntRecTy::get(RK)))) |
934 | return IntInit::get(RK, V: LHSi->getValue() ? 0 : 1); |
935 | break; |
936 | |
937 | case HEAD: |
938 | if (const auto *LHSl = dyn_cast<ListInit>(Val: LHS)) { |
939 | assert(!LHSl->empty() && "Empty list in head" ); |
940 | return LHSl->getElement(Idx: 0); |
941 | } |
942 | break; |
943 | |
944 | case TAIL: |
945 | if (const auto *LHSl = dyn_cast<ListInit>(Val: LHS)) { |
946 | assert(!LHSl->empty() && "Empty list in tail" ); |
947 | // Note the slice(1). We can't just pass the result of getElements() |
948 | // directly. |
949 | return ListInit::get(Elements: LHSl->getElements().slice(N: 1), |
950 | EltTy: LHSl->getElementType()); |
951 | } |
952 | break; |
953 | |
954 | case SIZE: |
955 | if (const auto *LHSl = dyn_cast<ListInit>(Val: LHS)) |
956 | return IntInit::get(RK, V: LHSl->size()); |
957 | if (const auto *LHSd = dyn_cast<DagInit>(Val: LHS)) |
958 | return IntInit::get(RK, V: LHSd->arg_size()); |
959 | if (const auto *LHSs = dyn_cast<StringInit>(Val: LHS)) |
960 | return IntInit::get(RK, V: LHSs->getValue().size()); |
961 | break; |
962 | |
963 | case EMPTY: |
964 | if (const auto *LHSl = dyn_cast<ListInit>(Val: LHS)) |
965 | return IntInit::get(RK, V: LHSl->empty()); |
966 | if (const auto *LHSd = dyn_cast<DagInit>(Val: LHS)) |
967 | return IntInit::get(RK, V: LHSd->arg_empty()); |
968 | if (const auto *LHSs = dyn_cast<StringInit>(Val: LHS)) |
969 | return IntInit::get(RK, V: LHSs->getValue().empty()); |
970 | break; |
971 | |
972 | case GETDAGOP: |
973 | if (const auto *Dag = dyn_cast<DagInit>(Val: LHS)) { |
974 | // TI is not necessarily a def due to the late resolution in multiclasses, |
975 | // but has to be a TypedInit. |
976 | auto *TI = cast<TypedInit>(Val: Dag->getOperator()); |
977 | if (!TI->getType()->typeIsA(RHS: getType())) { |
978 | PrintFatalError(ErrorLoc: CurRec->getLoc(), |
979 | Msg: Twine("Expected type '" ) + getType()->getAsString() + |
980 | "', got '" + TI->getType()->getAsString() + |
981 | "' in: " + getAsString() + "\n" ); |
982 | } else { |
983 | return Dag->getOperator(); |
984 | } |
985 | } |
986 | break; |
987 | |
988 | case LOG2: |
989 | if (const auto *LHSi = dyn_cast_or_null<IntInit>( |
990 | Val: LHS->convertInitializerTo(Ty: IntRecTy::get(RK)))) { |
991 | int64_t LHSv = LHSi->getValue(); |
992 | if (LHSv <= 0) { |
993 | PrintFatalError(ErrorLoc: CurRec->getLoc(), |
994 | Msg: "Illegal operation: logtwo is undefined " |
995 | "on arguments less than or equal to 0" ); |
996 | } else { |
997 | uint64_t Log = Log2_64(Value: LHSv); |
998 | assert(Log <= INT64_MAX && |
999 | "Log of an int64_t must be smaller than INT64_MAX" ); |
1000 | return IntInit::get(RK, V: static_cast<int64_t>(Log)); |
1001 | } |
1002 | } |
1003 | break; |
1004 | |
1005 | case LISTFLATTEN: |
1006 | if (const auto *LHSList = dyn_cast<ListInit>(Val: LHS)) { |
1007 | const auto *InnerListTy = dyn_cast<ListRecTy>(Val: LHSList->getElementType()); |
1008 | // list of non-lists, !listflatten() is a NOP. |
1009 | if (!InnerListTy) |
1010 | return LHS; |
1011 | |
1012 | auto Flatten = |
1013 | [](const ListInit *List) -> std::optional<std::vector<const Init *>> { |
1014 | std::vector<const Init *> Flattened; |
1015 | // Concatenate elements of all the inner lists. |
1016 | for (const Init *InnerInit : List->getElements()) { |
1017 | const auto *InnerList = dyn_cast<ListInit>(Val: InnerInit); |
1018 | if (!InnerList) |
1019 | return std::nullopt; |
1020 | llvm::append_range(C&: Flattened, R: InnerList->getElements()); |
1021 | }; |
1022 | return Flattened; |
1023 | }; |
1024 | |
1025 | auto Flattened = Flatten(LHSList); |
1026 | if (Flattened) |
1027 | return ListInit::get(Elements: *Flattened, EltTy: InnerListTy->getElementType()); |
1028 | } |
1029 | break; |
1030 | } |
1031 | return this; |
1032 | } |
1033 | |
1034 | const Init *UnOpInit::resolveReferences(Resolver &R) const { |
1035 | const Init *lhs = LHS->resolveReferences(R); |
1036 | |
1037 | if (LHS != lhs || (R.isFinal() && getOpcode() == CAST)) |
1038 | return (UnOpInit::get(Opc: getOpcode(), LHS: lhs, Type: getType())) |
1039 | ->Fold(CurRec: R.getCurrentRecord(), IsFinal: R.isFinal()); |
1040 | return this; |
1041 | } |
1042 | |
1043 | std::string UnOpInit::getAsString() const { |
1044 | std::string Result; |
1045 | switch (getOpcode()) { |
1046 | case CAST: Result = "!cast<" + getType()->getAsString() + ">" ; break; |
1047 | case NOT: Result = "!not" ; break; |
1048 | case HEAD: Result = "!head" ; break; |
1049 | case TAIL: Result = "!tail" ; break; |
1050 | case SIZE: Result = "!size" ; break; |
1051 | case EMPTY: Result = "!empty" ; break; |
1052 | case GETDAGOP: Result = "!getdagop" ; break; |
1053 | case LOG2 : Result = "!logtwo" ; break; |
1054 | case LISTFLATTEN: |
1055 | Result = "!listflatten" ; |
1056 | break; |
1057 | case REPR: |
1058 | Result = "!repr" ; |
1059 | break; |
1060 | case TOLOWER: |
1061 | Result = "!tolower" ; |
1062 | break; |
1063 | case TOUPPER: |
1064 | Result = "!toupper" ; |
1065 | break; |
1066 | case INITIALIZED: |
1067 | Result = "!initialized" ; |
1068 | break; |
1069 | } |
1070 | return Result + "(" + LHS->getAsString() + ")" ; |
1071 | } |
1072 | |
1073 | static void ProfileBinOpInit(FoldingSetNodeID &ID, unsigned Opcode, |
1074 | const Init *LHS, const Init *RHS, |
1075 | const RecTy *Type) { |
1076 | ID.AddInteger(I: Opcode); |
1077 | ID.AddPointer(Ptr: LHS); |
1078 | ID.AddPointer(Ptr: RHS); |
1079 | ID.AddPointer(Ptr: Type); |
1080 | } |
1081 | |
1082 | const BinOpInit *BinOpInit::get(BinaryOp Opc, const Init *LHS, const Init *RHS, |
1083 | const RecTy *Type) { |
1084 | FoldingSetNodeID ID; |
1085 | ProfileBinOpInit(ID, Opcode: Opc, LHS, RHS, Type); |
1086 | |
1087 | detail::RecordKeeperImpl &RK = LHS->getRecordKeeper().getImpl(); |
1088 | void *IP = nullptr; |
1089 | if (const BinOpInit *I = RK.TheBinOpInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
1090 | return I; |
1091 | |
1092 | BinOpInit *I = new (RK.Allocator) BinOpInit(Opc, LHS, RHS, Type); |
1093 | RK.TheBinOpInitPool.InsertNode(N: I, InsertPos: IP); |
1094 | return I; |
1095 | } |
1096 | |
1097 | void BinOpInit::Profile(FoldingSetNodeID &ID) const { |
1098 | ProfileBinOpInit(ID, Opcode: getOpcode(), LHS: getLHS(), RHS: getRHS(), Type: getType()); |
1099 | } |
1100 | |
1101 | static const StringInit *ConcatStringInits(const StringInit *I0, |
1102 | const StringInit *I1) { |
1103 | SmallString<80> Concat(I0->getValue()); |
1104 | Concat.append(RHS: I1->getValue()); |
1105 | return StringInit::get( |
1106 | RK&: I0->getRecordKeeper(), V: Concat, |
1107 | Fmt: StringInit::determineFormat(Fmt1: I0->getFormat(), Fmt2: I1->getFormat())); |
1108 | } |
1109 | |
1110 | static const StringInit *interleaveStringList(const ListInit *List, |
1111 | const StringInit *Delim) { |
1112 | if (List->size() == 0) |
1113 | return StringInit::get(RK&: List->getRecordKeeper(), V: "" ); |
1114 | const auto *Element = dyn_cast<StringInit>(Val: List->getElement(Idx: 0)); |
1115 | if (!Element) |
1116 | return nullptr; |
1117 | SmallString<80> Result(Element->getValue()); |
1118 | StringInit::StringFormat Fmt = StringInit::SF_String; |
1119 | |
1120 | for (const Init *Elem : List->getElements().drop_front()) { |
1121 | Result.append(RHS: Delim->getValue()); |
1122 | const auto *Element = dyn_cast<StringInit>(Val: Elem); |
1123 | if (!Element) |
1124 | return nullptr; |
1125 | Result.append(RHS: Element->getValue()); |
1126 | Fmt = StringInit::determineFormat(Fmt1: Fmt, Fmt2: Element->getFormat()); |
1127 | } |
1128 | return StringInit::get(RK&: List->getRecordKeeper(), V: Result, Fmt); |
1129 | } |
1130 | |
1131 | static const StringInit *interleaveIntList(const ListInit *List, |
1132 | const StringInit *Delim) { |
1133 | RecordKeeper &RK = List->getRecordKeeper(); |
1134 | if (List->size() == 0) |
1135 | return StringInit::get(RK, V: "" ); |
1136 | const auto *Element = dyn_cast_or_null<IntInit>( |
1137 | Val: List->getElement(Idx: 0)->convertInitializerTo(Ty: IntRecTy::get(RK))); |
1138 | if (!Element) |
1139 | return nullptr; |
1140 | SmallString<80> Result(Element->getAsString()); |
1141 | |
1142 | for (const Init *Elem : List->getElements().drop_front()) { |
1143 | Result.append(RHS: Delim->getValue()); |
1144 | const auto *Element = dyn_cast_or_null<IntInit>( |
1145 | Val: Elem->convertInitializerTo(Ty: IntRecTy::get(RK))); |
1146 | if (!Element) |
1147 | return nullptr; |
1148 | Result.append(RHS: Element->getAsString()); |
1149 | } |
1150 | return StringInit::get(RK, V: Result); |
1151 | } |
1152 | |
1153 | const Init *BinOpInit::getStrConcat(const Init *I0, const Init *I1) { |
1154 | // Shortcut for the common case of concatenating two strings. |
1155 | if (const auto *I0s = dyn_cast<StringInit>(Val: I0)) |
1156 | if (const auto *I1s = dyn_cast<StringInit>(Val: I1)) |
1157 | return ConcatStringInits(I0: I0s, I1: I1s); |
1158 | return BinOpInit::get(Opc: BinOpInit::STRCONCAT, LHS: I0, RHS: I1, |
1159 | Type: StringRecTy::get(RK&: I0->getRecordKeeper())); |
1160 | } |
1161 | |
1162 | static const ListInit *ConcatListInits(const ListInit *LHS, |
1163 | const ListInit *RHS) { |
1164 | SmallVector<const Init *, 8> Args; |
1165 | llvm::append_range(C&: Args, R: *LHS); |
1166 | llvm::append_range(C&: Args, R: *RHS); |
1167 | return ListInit::get(Elements: Args, EltTy: LHS->getElementType()); |
1168 | } |
1169 | |
1170 | const Init *BinOpInit::getListConcat(const TypedInit *LHS, const Init *RHS) { |
1171 | assert(isa<ListRecTy>(LHS->getType()) && "First arg must be a list" ); |
1172 | |
1173 | // Shortcut for the common case of concatenating two lists. |
1174 | if (const auto *LHSList = dyn_cast<ListInit>(Val: LHS)) |
1175 | if (const auto *RHSList = dyn_cast<ListInit>(Val: RHS)) |
1176 | return ConcatListInits(LHS: LHSList, RHS: RHSList); |
1177 | return BinOpInit::get(Opc: BinOpInit::LISTCONCAT, LHS, RHS, Type: LHS->getType()); |
1178 | } |
1179 | |
1180 | std::optional<bool> BinOpInit::CompareInit(unsigned Opc, const Init *LHS, |
1181 | const Init *RHS) const { |
1182 | // First see if we have two bit, bits, or int. |
1183 | const auto *LHSi = dyn_cast_or_null<IntInit>( |
1184 | Val: LHS->convertInitializerTo(Ty: IntRecTy::get(RK&: getRecordKeeper()))); |
1185 | const auto *RHSi = dyn_cast_or_null<IntInit>( |
1186 | Val: RHS->convertInitializerTo(Ty: IntRecTy::get(RK&: getRecordKeeper()))); |
1187 | |
1188 | if (LHSi && RHSi) { |
1189 | bool Result; |
1190 | switch (Opc) { |
1191 | case EQ: |
1192 | Result = LHSi->getValue() == RHSi->getValue(); |
1193 | break; |
1194 | case NE: |
1195 | Result = LHSi->getValue() != RHSi->getValue(); |
1196 | break; |
1197 | case LE: |
1198 | Result = LHSi->getValue() <= RHSi->getValue(); |
1199 | break; |
1200 | case LT: |
1201 | Result = LHSi->getValue() < RHSi->getValue(); |
1202 | break; |
1203 | case GE: |
1204 | Result = LHSi->getValue() >= RHSi->getValue(); |
1205 | break; |
1206 | case GT: |
1207 | Result = LHSi->getValue() > RHSi->getValue(); |
1208 | break; |
1209 | default: |
1210 | llvm_unreachable("unhandled comparison" ); |
1211 | } |
1212 | return Result; |
1213 | } |
1214 | |
1215 | // Next try strings. |
1216 | const auto *LHSs = dyn_cast<StringInit>(Val: LHS); |
1217 | const auto *RHSs = dyn_cast<StringInit>(Val: RHS); |
1218 | |
1219 | if (LHSs && RHSs) { |
1220 | bool Result; |
1221 | switch (Opc) { |
1222 | case EQ: |
1223 | Result = LHSs->getValue() == RHSs->getValue(); |
1224 | break; |
1225 | case NE: |
1226 | Result = LHSs->getValue() != RHSs->getValue(); |
1227 | break; |
1228 | case LE: |
1229 | Result = LHSs->getValue() <= RHSs->getValue(); |
1230 | break; |
1231 | case LT: |
1232 | Result = LHSs->getValue() < RHSs->getValue(); |
1233 | break; |
1234 | case GE: |
1235 | Result = LHSs->getValue() >= RHSs->getValue(); |
1236 | break; |
1237 | case GT: |
1238 | Result = LHSs->getValue() > RHSs->getValue(); |
1239 | break; |
1240 | default: |
1241 | llvm_unreachable("unhandled comparison" ); |
1242 | } |
1243 | return Result; |
1244 | } |
1245 | |
1246 | // Finally, !eq and !ne can be used with records. |
1247 | if (Opc == EQ || Opc == NE) { |
1248 | const auto *LHSd = dyn_cast<DefInit>(Val: LHS); |
1249 | const auto *RHSd = dyn_cast<DefInit>(Val: RHS); |
1250 | if (LHSd && RHSd) |
1251 | return (Opc == EQ) ? LHSd == RHSd : LHSd != RHSd; |
1252 | } |
1253 | |
1254 | return std::nullopt; |
1255 | } |
1256 | |
1257 | static std::optional<unsigned> |
1258 | getDagArgNoByKey(const DagInit *Dag, const Init *Key, std::string &Error) { |
1259 | // Accessor by index |
1260 | if (const auto *Idx = dyn_cast<IntInit>(Val: Key)) { |
1261 | int64_t Pos = Idx->getValue(); |
1262 | if (Pos < 0) { |
1263 | // The index is negative. |
1264 | Error = |
1265 | (Twine("index " ) + std::to_string(val: Pos) + Twine(" is negative" )).str(); |
1266 | return std::nullopt; |
1267 | } |
1268 | if (Pos >= Dag->getNumArgs()) { |
1269 | // The index is out-of-range. |
1270 | Error = (Twine("index " ) + std::to_string(val: Pos) + |
1271 | " is out of range (dag has " + |
1272 | std::to_string(val: Dag->getNumArgs()) + " arguments)" ) |
1273 | .str(); |
1274 | return std::nullopt; |
1275 | } |
1276 | return Pos; |
1277 | } |
1278 | assert(isa<StringInit>(Key)); |
1279 | // Accessor by name |
1280 | const auto *Name = dyn_cast<StringInit>(Val: Key); |
1281 | auto ArgNo = Dag->getArgNo(Name: Name->getValue()); |
1282 | if (!ArgNo) { |
1283 | // The key is not found. |
1284 | Error = (Twine("key '" ) + Name->getValue() + Twine("' is not found" )).str(); |
1285 | return std::nullopt; |
1286 | } |
1287 | return *ArgNo; |
1288 | } |
1289 | |
1290 | const Init *BinOpInit::Fold(const Record *CurRec) const { |
1291 | switch (getOpcode()) { |
1292 | case CONCAT: { |
1293 | const auto *LHSs = dyn_cast<DagInit>(Val: LHS); |
1294 | const auto *RHSs = dyn_cast<DagInit>(Val: RHS); |
1295 | if (LHSs && RHSs) { |
1296 | const auto *LOp = dyn_cast<DefInit>(Val: LHSs->getOperator()); |
1297 | const auto *ROp = dyn_cast<DefInit>(Val: RHSs->getOperator()); |
1298 | if ((!LOp && !isa<UnsetInit>(Val: LHSs->getOperator())) || |
1299 | (!ROp && !isa<UnsetInit>(Val: RHSs->getOperator()))) |
1300 | break; |
1301 | if (LOp && ROp && LOp->getDef() != ROp->getDef()) { |
1302 | PrintFatalError(Msg: Twine("Concatenated Dag operators do not match: '" ) + |
1303 | LHSs->getAsString() + "' vs. '" + RHSs->getAsString() + |
1304 | "'" ); |
1305 | } |
1306 | const Init *Op = LOp ? LOp : ROp; |
1307 | if (!Op) |
1308 | Op = UnsetInit::get(RK&: getRecordKeeper()); |
1309 | |
1310 | SmallVector<std::pair<const Init *, const StringInit *>, 8> Args; |
1311 | llvm::append_range(C&: Args, R: LHSs->getArgAndNames()); |
1312 | llvm::append_range(C&: Args, R: RHSs->getArgAndNames()); |
1313 | return DagInit::get(V: Op, ArgAndNames: Args); |
1314 | } |
1315 | break; |
1316 | } |
1317 | case MATCH: { |
1318 | const auto *StrInit = dyn_cast<StringInit>(Val: LHS); |
1319 | if (!StrInit) |
1320 | return this; |
1321 | |
1322 | const auto *RegexInit = dyn_cast<StringInit>(Val: RHS); |
1323 | if (!RegexInit) |
1324 | return this; |
1325 | |
1326 | StringRef RegexStr = RegexInit->getValue(); |
1327 | llvm::Regex Matcher(RegexStr); |
1328 | if (!Matcher.isValid()) |
1329 | PrintFatalError(Msg: Twine("invalid regex '" ) + RegexStr + Twine("'" )); |
1330 | |
1331 | return BitInit::get(RK&: LHS->getRecordKeeper(), |
1332 | V: Matcher.match(String: StrInit->getValue())); |
1333 | } |
1334 | case LISTCONCAT: { |
1335 | const auto *LHSs = dyn_cast<ListInit>(Val: LHS); |
1336 | const auto *RHSs = dyn_cast<ListInit>(Val: RHS); |
1337 | if (LHSs && RHSs) { |
1338 | SmallVector<const Init *, 8> Args; |
1339 | llvm::append_range(C&: Args, R: *LHSs); |
1340 | llvm::append_range(C&: Args, R: *RHSs); |
1341 | return ListInit::get(Elements: Args, EltTy: LHSs->getElementType()); |
1342 | } |
1343 | break; |
1344 | } |
1345 | case LISTSPLAT: { |
1346 | const auto *Value = dyn_cast<TypedInit>(Val: LHS); |
1347 | const auto *Size = dyn_cast<IntInit>(Val: RHS); |
1348 | if (Value && Size) { |
1349 | SmallVector<const Init *, 8> Args(Size->getValue(), Value); |
1350 | return ListInit::get(Elements: Args, EltTy: Value->getType()); |
1351 | } |
1352 | break; |
1353 | } |
1354 | case LISTREMOVE: { |
1355 | const auto *LHSs = dyn_cast<ListInit>(Val: LHS); |
1356 | const auto *RHSs = dyn_cast<ListInit>(Val: RHS); |
1357 | if (LHSs && RHSs) { |
1358 | SmallVector<const Init *, 8> Args; |
1359 | for (const Init *EltLHS : *LHSs) { |
1360 | bool Found = false; |
1361 | for (const Init *EltRHS : *RHSs) { |
1362 | if (std::optional<bool> Result = CompareInit(Opc: EQ, LHS: EltLHS, RHS: EltRHS)) { |
1363 | if (*Result) { |
1364 | Found = true; |
1365 | break; |
1366 | } |
1367 | } |
1368 | } |
1369 | if (!Found) |
1370 | Args.push_back(Elt: EltLHS); |
1371 | } |
1372 | return ListInit::get(Elements: Args, EltTy: LHSs->getElementType()); |
1373 | } |
1374 | break; |
1375 | } |
1376 | case LISTELEM: { |
1377 | const auto *TheList = dyn_cast<ListInit>(Val: LHS); |
1378 | const auto *Idx = dyn_cast<IntInit>(Val: RHS); |
1379 | if (!TheList || !Idx) |
1380 | break; |
1381 | auto i = Idx->getValue(); |
1382 | if (i < 0 || i >= (ssize_t)TheList->size()) |
1383 | break; |
1384 | return TheList->getElement(Idx: i); |
1385 | } |
1386 | case LISTSLICE: { |
1387 | const auto *TheList = dyn_cast<ListInit>(Val: LHS); |
1388 | const auto *SliceIdxs = dyn_cast<ListInit>(Val: RHS); |
1389 | if (!TheList || !SliceIdxs) |
1390 | break; |
1391 | SmallVector<const Init *, 8> Args; |
1392 | Args.reserve(N: SliceIdxs->size()); |
1393 | for (auto *I : *SliceIdxs) { |
1394 | auto *II = dyn_cast<IntInit>(Val: I); |
1395 | if (!II) |
1396 | goto unresolved; |
1397 | auto i = II->getValue(); |
1398 | if (i < 0 || i >= (ssize_t)TheList->size()) |
1399 | goto unresolved; |
1400 | Args.push_back(Elt: TheList->getElement(Idx: i)); |
1401 | } |
1402 | return ListInit::get(Elements: Args, EltTy: TheList->getElementType()); |
1403 | } |
1404 | case RANGEC: { |
1405 | const auto *LHSi = dyn_cast<IntInit>(Val: LHS); |
1406 | const auto *RHSi = dyn_cast<IntInit>(Val: RHS); |
1407 | if (!LHSi || !RHSi) |
1408 | break; |
1409 | |
1410 | int64_t Start = LHSi->getValue(); |
1411 | int64_t End = RHSi->getValue(); |
1412 | SmallVector<const Init *, 8> Args; |
1413 | if (getOpcode() == RANGEC) { |
1414 | // Closed interval |
1415 | if (Start <= End) { |
1416 | // Ascending order |
1417 | Args.reserve(N: End - Start + 1); |
1418 | for (auto i = Start; i <= End; ++i) |
1419 | Args.push_back(Elt: IntInit::get(RK&: getRecordKeeper(), V: i)); |
1420 | } else { |
1421 | // Descending order |
1422 | Args.reserve(N: Start - End + 1); |
1423 | for (auto i = Start; i >= End; --i) |
1424 | Args.push_back(Elt: IntInit::get(RK&: getRecordKeeper(), V: i)); |
1425 | } |
1426 | } else if (Start < End) { |
1427 | // Half-open interval (excludes `End`) |
1428 | Args.reserve(N: End - Start); |
1429 | for (auto i = Start; i < End; ++i) |
1430 | Args.push_back(Elt: IntInit::get(RK&: getRecordKeeper(), V: i)); |
1431 | } else { |
1432 | // Empty set |
1433 | } |
1434 | return ListInit::get(Elements: Args, EltTy: LHSi->getType()); |
1435 | } |
1436 | case STRCONCAT: { |
1437 | const auto *LHSs = dyn_cast<StringInit>(Val: LHS); |
1438 | const auto *RHSs = dyn_cast<StringInit>(Val: RHS); |
1439 | if (LHSs && RHSs) |
1440 | return ConcatStringInits(I0: LHSs, I1: RHSs); |
1441 | break; |
1442 | } |
1443 | case INTERLEAVE: { |
1444 | const auto *List = dyn_cast<ListInit>(Val: LHS); |
1445 | const auto *Delim = dyn_cast<StringInit>(Val: RHS); |
1446 | if (List && Delim) { |
1447 | const StringInit *Result; |
1448 | if (isa<StringRecTy>(Val: List->getElementType())) |
1449 | Result = interleaveStringList(List, Delim); |
1450 | else |
1451 | Result = interleaveIntList(List, Delim); |
1452 | if (Result) |
1453 | return Result; |
1454 | } |
1455 | break; |
1456 | } |
1457 | case EQ: |
1458 | case NE: |
1459 | case LE: |
1460 | case LT: |
1461 | case GE: |
1462 | case GT: { |
1463 | if (std::optional<bool> Result = CompareInit(Opc: getOpcode(), LHS, RHS)) |
1464 | return BitInit::get(RK&: getRecordKeeper(), V: *Result); |
1465 | break; |
1466 | } |
1467 | case GETDAGARG: { |
1468 | const auto *Dag = dyn_cast<DagInit>(Val: LHS); |
1469 | if (Dag && isa<IntInit, StringInit>(Val: RHS)) { |
1470 | std::string Error; |
1471 | auto ArgNo = getDagArgNoByKey(Dag, Key: RHS, Error); |
1472 | if (!ArgNo) |
1473 | PrintFatalError(ErrorLoc: CurRec->getLoc(), Msg: "!getdagarg " + Error); |
1474 | |
1475 | assert(*ArgNo < Dag->getNumArgs()); |
1476 | |
1477 | const Init *Arg = Dag->getArg(Num: *ArgNo); |
1478 | if (const auto *TI = dyn_cast<TypedInit>(Val: Arg)) |
1479 | if (!TI->getType()->typeIsConvertibleTo(RHS: getType())) |
1480 | return UnsetInit::get(RK&: Dag->getRecordKeeper()); |
1481 | return Arg; |
1482 | } |
1483 | break; |
1484 | } |
1485 | case GETDAGNAME: { |
1486 | const auto *Dag = dyn_cast<DagInit>(Val: LHS); |
1487 | const auto *Idx = dyn_cast<IntInit>(Val: RHS); |
1488 | if (Dag && Idx) { |
1489 | int64_t Pos = Idx->getValue(); |
1490 | if (Pos < 0 || Pos >= Dag->getNumArgs()) { |
1491 | // The index is out-of-range. |
1492 | PrintError(ErrorLoc: CurRec->getLoc(), |
1493 | Msg: Twine("!getdagname index is out of range 0..." ) + |
1494 | std::to_string(val: Dag->getNumArgs() - 1) + ": " + |
1495 | std::to_string(val: Pos)); |
1496 | } |
1497 | const Init *ArgName = Dag->getArgName(Num: Pos); |
1498 | if (!ArgName) |
1499 | return UnsetInit::get(RK&: getRecordKeeper()); |
1500 | return ArgName; |
1501 | } |
1502 | break; |
1503 | } |
1504 | case SETDAGOP: { |
1505 | const auto *Dag = dyn_cast<DagInit>(Val: LHS); |
1506 | const auto *Op = dyn_cast<DefInit>(Val: RHS); |
1507 | if (Dag && Op) |
1508 | return DagInit::get(V: Op, Args: Dag->getArgs(), ArgNames: Dag->getArgNames()); |
1509 | break; |
1510 | } |
1511 | case ADD: |
1512 | case SUB: |
1513 | case MUL: |
1514 | case DIV: |
1515 | case AND: |
1516 | case OR: |
1517 | case XOR: |
1518 | case SHL: |
1519 | case SRA: |
1520 | case SRL: { |
1521 | const auto *LHSi = dyn_cast_or_null<IntInit>( |
1522 | Val: LHS->convertInitializerTo(Ty: IntRecTy::get(RK&: getRecordKeeper()))); |
1523 | const auto *RHSi = dyn_cast_or_null<IntInit>( |
1524 | Val: RHS->convertInitializerTo(Ty: IntRecTy::get(RK&: getRecordKeeper()))); |
1525 | if (LHSi && RHSi) { |
1526 | int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue(); |
1527 | int64_t Result; |
1528 | switch (getOpcode()) { |
1529 | default: llvm_unreachable("Bad opcode!" ); |
1530 | case ADD: Result = LHSv + RHSv; break; |
1531 | case SUB: Result = LHSv - RHSv; break; |
1532 | case MUL: Result = LHSv * RHSv; break; |
1533 | case DIV: |
1534 | if (RHSv == 0) |
1535 | PrintFatalError(ErrorLoc: CurRec->getLoc(), |
1536 | Msg: "Illegal operation: division by zero" ); |
1537 | else if (LHSv == INT64_MIN && RHSv == -1) |
1538 | PrintFatalError(ErrorLoc: CurRec->getLoc(), |
1539 | Msg: "Illegal operation: INT64_MIN / -1" ); |
1540 | else |
1541 | Result = LHSv / RHSv; |
1542 | break; |
1543 | case AND: Result = LHSv & RHSv; break; |
1544 | case OR: Result = LHSv | RHSv; break; |
1545 | case XOR: Result = LHSv ^ RHSv; break; |
1546 | case SHL: Result = (uint64_t)LHSv << (uint64_t)RHSv; break; |
1547 | case SRA: Result = LHSv >> RHSv; break; |
1548 | case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; |
1549 | } |
1550 | return IntInit::get(RK&: getRecordKeeper(), V: Result); |
1551 | } |
1552 | break; |
1553 | } |
1554 | } |
1555 | unresolved: |
1556 | return this; |
1557 | } |
1558 | |
1559 | const Init *BinOpInit::resolveReferences(Resolver &R) const { |
1560 | const Init *NewLHS = LHS->resolveReferences(R); |
1561 | |
1562 | unsigned Opc = getOpcode(); |
1563 | if (Opc == AND || Opc == OR) { |
1564 | // Short-circuit. Regardless whether this is a logical or bitwise |
1565 | // AND/OR. |
1566 | // Ideally we could also short-circuit `!or(true, ...)`, but it's |
1567 | // difficult to do it right without knowing if rest of the operands |
1568 | // are all `bit` or not. Therefore, we're only implementing a relatively |
1569 | // limited version of short-circuit against all ones (`true` is casted |
1570 | // to 1 rather than all ones before we evaluate `!or`). |
1571 | if (const auto *LHSi = dyn_cast_or_null<IntInit>( |
1572 | Val: NewLHS->convertInitializerTo(Ty: IntRecTy::get(RK&: getRecordKeeper())))) { |
1573 | if ((Opc == AND && !LHSi->getValue()) || |
1574 | (Opc == OR && LHSi->getValue() == -1)) |
1575 | return LHSi; |
1576 | } |
1577 | } |
1578 | |
1579 | const Init *NewRHS = RHS->resolveReferences(R); |
1580 | |
1581 | if (LHS != NewLHS || RHS != NewRHS) |
1582 | return (BinOpInit::get(Opc: getOpcode(), LHS: NewLHS, RHS: NewRHS, Type: getType())) |
1583 | ->Fold(CurRec: R.getCurrentRecord()); |
1584 | return this; |
1585 | } |
1586 | |
1587 | std::string BinOpInit::getAsString() const { |
1588 | std::string Result; |
1589 | switch (getOpcode()) { |
1590 | case LISTELEM: |
1591 | case LISTSLICE: |
1592 | return LHS->getAsString() + "[" + RHS->getAsString() + "]" ; |
1593 | case RANGEC: |
1594 | return LHS->getAsString() + "..." + RHS->getAsString(); |
1595 | case CONCAT: Result = "!con" ; break; |
1596 | case MATCH: |
1597 | Result = "!match" ; |
1598 | break; |
1599 | case ADD: Result = "!add" ; break; |
1600 | case SUB: Result = "!sub" ; break; |
1601 | case MUL: Result = "!mul" ; break; |
1602 | case DIV: Result = "!div" ; break; |
1603 | case AND: Result = "!and" ; break; |
1604 | case OR: Result = "!or" ; break; |
1605 | case XOR: Result = "!xor" ; break; |
1606 | case SHL: Result = "!shl" ; break; |
1607 | case SRA: Result = "!sra" ; break; |
1608 | case SRL: Result = "!srl" ; break; |
1609 | case EQ: Result = "!eq" ; break; |
1610 | case NE: Result = "!ne" ; break; |
1611 | case LE: Result = "!le" ; break; |
1612 | case LT: Result = "!lt" ; break; |
1613 | case GE: Result = "!ge" ; break; |
1614 | case GT: Result = "!gt" ; break; |
1615 | case LISTCONCAT: Result = "!listconcat" ; break; |
1616 | case LISTSPLAT: Result = "!listsplat" ; break; |
1617 | case LISTREMOVE: |
1618 | Result = "!listremove" ; |
1619 | break; |
1620 | case STRCONCAT: Result = "!strconcat" ; break; |
1621 | case INTERLEAVE: Result = "!interleave" ; break; |
1622 | case SETDAGOP: Result = "!setdagop" ; break; |
1623 | case GETDAGARG: |
1624 | Result = "!getdagarg<" + getType()->getAsString() + ">" ; |
1625 | break; |
1626 | case GETDAGNAME: |
1627 | Result = "!getdagname" ; |
1628 | break; |
1629 | } |
1630 | return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")" ; |
1631 | } |
1632 | |
1633 | static void ProfileTernOpInit(FoldingSetNodeID &ID, unsigned Opcode, |
1634 | const Init *LHS, const Init *MHS, const Init *RHS, |
1635 | const RecTy *Type) { |
1636 | ID.AddInteger(I: Opcode); |
1637 | ID.AddPointer(Ptr: LHS); |
1638 | ID.AddPointer(Ptr: MHS); |
1639 | ID.AddPointer(Ptr: RHS); |
1640 | ID.AddPointer(Ptr: Type); |
1641 | } |
1642 | |
1643 | const TernOpInit *TernOpInit::get(TernaryOp Opc, const Init *LHS, |
1644 | const Init *MHS, const Init *RHS, |
1645 | const RecTy *Type) { |
1646 | FoldingSetNodeID ID; |
1647 | ProfileTernOpInit(ID, Opcode: Opc, LHS, MHS, RHS, Type); |
1648 | |
1649 | detail::RecordKeeperImpl &RK = LHS->getRecordKeeper().getImpl(); |
1650 | void *IP = nullptr; |
1651 | if (TernOpInit *I = RK.TheTernOpInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
1652 | return I; |
1653 | |
1654 | TernOpInit *I = new (RK.Allocator) TernOpInit(Opc, LHS, MHS, RHS, Type); |
1655 | RK.TheTernOpInitPool.InsertNode(N: I, InsertPos: IP); |
1656 | return I; |
1657 | } |
1658 | |
1659 | void TernOpInit::Profile(FoldingSetNodeID &ID) const { |
1660 | ProfileTernOpInit(ID, Opcode: getOpcode(), LHS: getLHS(), MHS: getMHS(), RHS: getRHS(), Type: getType()); |
1661 | } |
1662 | |
1663 | static const Init *ItemApply(const Init *LHS, const Init *MHSe, const Init *RHS, |
1664 | const Record *CurRec) { |
1665 | MapResolver R(CurRec); |
1666 | R.set(Key: LHS, Value: MHSe); |
1667 | return RHS->resolveReferences(R); |
1668 | } |
1669 | |
1670 | static const Init *ForeachDagApply(const Init *LHS, const DagInit *MHSd, |
1671 | const Init *RHS, const Record *CurRec) { |
1672 | bool Change = false; |
1673 | const Init *Val = ItemApply(LHS, MHSe: MHSd->getOperator(), RHS, CurRec); |
1674 | if (Val != MHSd->getOperator()) |
1675 | Change = true; |
1676 | |
1677 | SmallVector<std::pair<const Init *, const StringInit *>, 8> NewArgs; |
1678 | for (auto [Arg, ArgName] : MHSd->getArgAndNames()) { |
1679 | const Init *NewArg; |
1680 | |
1681 | if (const auto *Argd = dyn_cast<DagInit>(Val: Arg)) |
1682 | NewArg = ForeachDagApply(LHS, MHSd: Argd, RHS, CurRec); |
1683 | else |
1684 | NewArg = ItemApply(LHS, MHSe: Arg, RHS, CurRec); |
1685 | |
1686 | NewArgs.emplace_back(Args&: NewArg, Args&: ArgName); |
1687 | if (Arg != NewArg) |
1688 | Change = true; |
1689 | } |
1690 | |
1691 | if (Change) |
1692 | return DagInit::get(V: Val, VN: MHSd->getName(), ArgAndNames: NewArgs); |
1693 | return MHSd; |
1694 | } |
1695 | |
1696 | // Applies RHS to all elements of MHS, using LHS as a temp variable. |
1697 | static const Init *ForeachHelper(const Init *LHS, const Init *MHS, |
1698 | const Init *RHS, const RecTy *Type, |
1699 | const Record *CurRec) { |
1700 | if (const auto *MHSd = dyn_cast<DagInit>(Val: MHS)) |
1701 | return ForeachDagApply(LHS, MHSd, RHS, CurRec); |
1702 | |
1703 | if (const auto *MHSl = dyn_cast<ListInit>(Val: MHS)) { |
1704 | SmallVector<const Init *, 8> NewList(MHSl->begin(), MHSl->end()); |
1705 | |
1706 | for (const Init *&Item : NewList) { |
1707 | const Init *NewItem = ItemApply(LHS, MHSe: Item, RHS, CurRec); |
1708 | if (NewItem != Item) |
1709 | Item = NewItem; |
1710 | } |
1711 | return ListInit::get(Elements: NewList, EltTy: cast<ListRecTy>(Val: Type)->getElementType()); |
1712 | } |
1713 | |
1714 | return nullptr; |
1715 | } |
1716 | |
1717 | // Evaluates RHS for all elements of MHS, using LHS as a temp variable. |
1718 | // Creates a new list with the elements that evaluated to true. |
1719 | static const Init *FilterHelper(const Init *LHS, const Init *MHS, |
1720 | const Init *RHS, const RecTy *Type, |
1721 | const Record *CurRec) { |
1722 | if (const auto *MHSl = dyn_cast<ListInit>(Val: MHS)) { |
1723 | SmallVector<const Init *, 8> NewList; |
1724 | |
1725 | for (const Init *Item : MHSl->getElements()) { |
1726 | const Init *Include = ItemApply(LHS, MHSe: Item, RHS, CurRec); |
1727 | if (!Include) |
1728 | return nullptr; |
1729 | if (const auto *IncludeInt = |
1730 | dyn_cast_or_null<IntInit>(Val: Include->convertInitializerTo( |
1731 | Ty: IntRecTy::get(RK&: LHS->getRecordKeeper())))) { |
1732 | if (IncludeInt->getValue()) |
1733 | NewList.push_back(Elt: Item); |
1734 | } else { |
1735 | return nullptr; |
1736 | } |
1737 | } |
1738 | return ListInit::get(Elements: NewList, EltTy: cast<ListRecTy>(Val: Type)->getElementType()); |
1739 | } |
1740 | |
1741 | return nullptr; |
1742 | } |
1743 | |
1744 | const Init *TernOpInit::Fold(const Record *CurRec) const { |
1745 | RecordKeeper &RK = getRecordKeeper(); |
1746 | switch (getOpcode()) { |
1747 | case SUBST: { |
1748 | const auto *LHSd = dyn_cast<DefInit>(Val: LHS); |
1749 | const auto *LHSv = dyn_cast<VarInit>(Val: LHS); |
1750 | const auto *LHSs = dyn_cast<StringInit>(Val: LHS); |
1751 | |
1752 | const auto *MHSd = dyn_cast<DefInit>(Val: MHS); |
1753 | const auto *MHSv = dyn_cast<VarInit>(Val: MHS); |
1754 | const auto *MHSs = dyn_cast<StringInit>(Val: MHS); |
1755 | |
1756 | const auto *RHSd = dyn_cast<DefInit>(Val: RHS); |
1757 | const auto *RHSv = dyn_cast<VarInit>(Val: RHS); |
1758 | const auto *RHSs = dyn_cast<StringInit>(Val: RHS); |
1759 | |
1760 | if (LHSd && MHSd && RHSd) { |
1761 | const Record *Val = RHSd->getDef(); |
1762 | if (LHSd->getAsString() == RHSd->getAsString()) |
1763 | Val = MHSd->getDef(); |
1764 | return Val->getDefInit(); |
1765 | } |
1766 | if (LHSv && MHSv && RHSv) { |
1767 | std::string Val = RHSv->getName().str(); |
1768 | if (LHSv->getAsString() == RHSv->getAsString()) |
1769 | Val = MHSv->getName().str(); |
1770 | return VarInit::get(VN: Val, T: getType()); |
1771 | } |
1772 | if (LHSs && MHSs && RHSs) { |
1773 | std::string Val = RHSs->getValue().str(); |
1774 | |
1775 | std::string::size_type Idx = 0; |
1776 | while (true) { |
1777 | std::string::size_type Found = Val.find(svt: LHSs->getValue(), pos: Idx); |
1778 | if (Found == std::string::npos) |
1779 | break; |
1780 | Val.replace(pos: Found, n: LHSs->getValue().size(), str: MHSs->getValue().str()); |
1781 | Idx = Found + MHSs->getValue().size(); |
1782 | } |
1783 | |
1784 | return StringInit::get(RK, V: Val); |
1785 | } |
1786 | break; |
1787 | } |
1788 | |
1789 | case FOREACH: { |
1790 | if (const Init *Result = ForeachHelper(LHS, MHS, RHS, Type: getType(), CurRec)) |
1791 | return Result; |
1792 | break; |
1793 | } |
1794 | |
1795 | case FILTER: { |
1796 | if (const Init *Result = FilterHelper(LHS, MHS, RHS, Type: getType(), CurRec)) |
1797 | return Result; |
1798 | break; |
1799 | } |
1800 | |
1801 | case IF: { |
1802 | if (const auto *LHSi = dyn_cast_or_null<IntInit>( |
1803 | Val: LHS->convertInitializerTo(Ty: IntRecTy::get(RK)))) { |
1804 | if (LHSi->getValue()) |
1805 | return MHS; |
1806 | return RHS; |
1807 | } |
1808 | break; |
1809 | } |
1810 | |
1811 | case DAG: { |
1812 | const auto *MHSl = dyn_cast<ListInit>(Val: MHS); |
1813 | const auto *RHSl = dyn_cast<ListInit>(Val: RHS); |
1814 | bool MHSok = MHSl || isa<UnsetInit>(Val: MHS); |
1815 | bool RHSok = RHSl || isa<UnsetInit>(Val: RHS); |
1816 | |
1817 | if (isa<UnsetInit>(Val: MHS) && isa<UnsetInit>(Val: RHS)) |
1818 | break; // Typically prevented by the parser, but might happen with template args |
1819 | |
1820 | if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) { |
1821 | SmallVector<std::pair<const Init *, const StringInit *>, 8> Children; |
1822 | unsigned Size = MHSl ? MHSl->size() : RHSl->size(); |
1823 | for (unsigned i = 0; i != Size; ++i) { |
1824 | const Init *Node = MHSl ? MHSl->getElement(Idx: i) : UnsetInit::get(RK); |
1825 | const Init *Name = RHSl ? RHSl->getElement(Idx: i) : UnsetInit::get(RK); |
1826 | if (!isa<StringInit>(Val: Name) && !isa<UnsetInit>(Val: Name)) |
1827 | return this; |
1828 | Children.emplace_back(Args&: Node, Args: dyn_cast<StringInit>(Val: Name)); |
1829 | } |
1830 | return DagInit::get(V: LHS, ArgAndNames: Children); |
1831 | } |
1832 | break; |
1833 | } |
1834 | |
1835 | case RANGE: { |
1836 | const auto *LHSi = dyn_cast<IntInit>(Val: LHS); |
1837 | const auto *MHSi = dyn_cast<IntInit>(Val: MHS); |
1838 | const auto *RHSi = dyn_cast<IntInit>(Val: RHS); |
1839 | if (!LHSi || !MHSi || !RHSi) |
1840 | break; |
1841 | |
1842 | auto Start = LHSi->getValue(); |
1843 | auto End = MHSi->getValue(); |
1844 | auto Step = RHSi->getValue(); |
1845 | if (Step == 0) |
1846 | PrintError(ErrorLoc: CurRec->getLoc(), Msg: "Step of !range can't be 0" ); |
1847 | |
1848 | SmallVector<const Init *, 8> Args; |
1849 | if (Start < End && Step > 0) { |
1850 | Args.reserve(N: (End - Start) / Step); |
1851 | for (auto I = Start; I < End; I += Step) |
1852 | Args.push_back(Elt: IntInit::get(RK&: getRecordKeeper(), V: I)); |
1853 | } else if (Start > End && Step < 0) { |
1854 | Args.reserve(N: (Start - End) / -Step); |
1855 | for (auto I = Start; I > End; I += Step) |
1856 | Args.push_back(Elt: IntInit::get(RK&: getRecordKeeper(), V: I)); |
1857 | } else { |
1858 | // Empty set |
1859 | } |
1860 | return ListInit::get(Elements: Args, EltTy: LHSi->getType()); |
1861 | } |
1862 | |
1863 | case SUBSTR: { |
1864 | const auto *LHSs = dyn_cast<StringInit>(Val: LHS); |
1865 | const auto *MHSi = dyn_cast<IntInit>(Val: MHS); |
1866 | const auto *RHSi = dyn_cast<IntInit>(Val: RHS); |
1867 | if (LHSs && MHSi && RHSi) { |
1868 | int64_t StringSize = LHSs->getValue().size(); |
1869 | int64_t Start = MHSi->getValue(); |
1870 | int64_t Length = RHSi->getValue(); |
1871 | if (Start < 0 || Start > StringSize) |
1872 | PrintError(ErrorLoc: CurRec->getLoc(), |
1873 | Msg: Twine("!substr start position is out of range 0..." ) + |
1874 | std::to_string(val: StringSize) + ": " + |
1875 | std::to_string(val: Start)); |
1876 | if (Length < 0) |
1877 | PrintError(ErrorLoc: CurRec->getLoc(), Msg: "!substr length must be nonnegative" ); |
1878 | return StringInit::get(RK, V: LHSs->getValue().substr(Start, N: Length), |
1879 | Fmt: LHSs->getFormat()); |
1880 | } |
1881 | break; |
1882 | } |
1883 | |
1884 | case FIND: { |
1885 | const auto *LHSs = dyn_cast<StringInit>(Val: LHS); |
1886 | const auto *MHSs = dyn_cast<StringInit>(Val: MHS); |
1887 | const auto *RHSi = dyn_cast<IntInit>(Val: RHS); |
1888 | if (LHSs && MHSs && RHSi) { |
1889 | int64_t SourceSize = LHSs->getValue().size(); |
1890 | int64_t Start = RHSi->getValue(); |
1891 | if (Start < 0 || Start > SourceSize) |
1892 | PrintError(ErrorLoc: CurRec->getLoc(), |
1893 | Msg: Twine("!find start position is out of range 0..." ) + |
1894 | std::to_string(val: SourceSize) + ": " + |
1895 | std::to_string(val: Start)); |
1896 | auto I = LHSs->getValue().find(Str: MHSs->getValue(), From: Start); |
1897 | if (I == std::string::npos) |
1898 | return IntInit::get(RK, V: -1); |
1899 | return IntInit::get(RK, V: I); |
1900 | } |
1901 | break; |
1902 | } |
1903 | |
1904 | case SETDAGARG: { |
1905 | const auto *Dag = dyn_cast<DagInit>(Val: LHS); |
1906 | if (Dag && isa<IntInit, StringInit>(Val: MHS)) { |
1907 | std::string Error; |
1908 | auto ArgNo = getDagArgNoByKey(Dag, Key: MHS, Error); |
1909 | if (!ArgNo) |
1910 | PrintFatalError(ErrorLoc: CurRec->getLoc(), Msg: "!setdagarg " + Error); |
1911 | |
1912 | assert(*ArgNo < Dag->getNumArgs()); |
1913 | |
1914 | SmallVector<const Init *, 8> Args(Dag->getArgs()); |
1915 | Args[*ArgNo] = RHS; |
1916 | return DagInit::get(V: Dag->getOperator(), VN: Dag->getName(), Args, |
1917 | ArgNames: Dag->getArgNames()); |
1918 | } |
1919 | break; |
1920 | } |
1921 | |
1922 | case SETDAGNAME: { |
1923 | const auto *Dag = dyn_cast<DagInit>(Val: LHS); |
1924 | if (Dag && isa<IntInit, StringInit>(Val: MHS)) { |
1925 | std::string Error; |
1926 | auto ArgNo = getDagArgNoByKey(Dag, Key: MHS, Error); |
1927 | if (!ArgNo) |
1928 | PrintFatalError(ErrorLoc: CurRec->getLoc(), Msg: "!setdagname " + Error); |
1929 | |
1930 | assert(*ArgNo < Dag->getNumArgs()); |
1931 | |
1932 | SmallVector<const StringInit *, 8> Names(Dag->getArgNames()); |
1933 | Names[*ArgNo] = dyn_cast<StringInit>(Val: RHS); |
1934 | return DagInit::get(V: Dag->getOperator(), VN: Dag->getName(), Args: Dag->getArgs(), |
1935 | ArgNames: Names); |
1936 | } |
1937 | break; |
1938 | } |
1939 | } |
1940 | |
1941 | return this; |
1942 | } |
1943 | |
1944 | const Init *TernOpInit::resolveReferences(Resolver &R) const { |
1945 | const Init *lhs = LHS->resolveReferences(R); |
1946 | |
1947 | if (getOpcode() == IF && lhs != LHS) { |
1948 | if (const auto *Value = dyn_cast_or_null<IntInit>( |
1949 | Val: lhs->convertInitializerTo(Ty: IntRecTy::get(RK&: getRecordKeeper())))) { |
1950 | // Short-circuit |
1951 | if (Value->getValue()) |
1952 | return MHS->resolveReferences(R); |
1953 | return RHS->resolveReferences(R); |
1954 | } |
1955 | } |
1956 | |
1957 | const Init *mhs = MHS->resolveReferences(R); |
1958 | const Init *rhs; |
1959 | |
1960 | if (getOpcode() == FOREACH || getOpcode() == FILTER) { |
1961 | ShadowResolver SR(R); |
1962 | SR.addShadow(Key: lhs); |
1963 | rhs = RHS->resolveReferences(R&: SR); |
1964 | } else { |
1965 | rhs = RHS->resolveReferences(R); |
1966 | } |
1967 | |
1968 | if (LHS != lhs || MHS != mhs || RHS != rhs) |
1969 | return (TernOpInit::get(Opc: getOpcode(), LHS: lhs, MHS: mhs, RHS: rhs, Type: getType())) |
1970 | ->Fold(CurRec: R.getCurrentRecord()); |
1971 | return this; |
1972 | } |
1973 | |
1974 | std::string TernOpInit::getAsString() const { |
1975 | std::string Result; |
1976 | bool UnquotedLHS = false; |
1977 | switch (getOpcode()) { |
1978 | case DAG: Result = "!dag" ; break; |
1979 | case FILTER: Result = "!filter" ; UnquotedLHS = true; break; |
1980 | case FOREACH: Result = "!foreach" ; UnquotedLHS = true; break; |
1981 | case IF: Result = "!if" ; break; |
1982 | case RANGE: |
1983 | Result = "!range" ; |
1984 | break; |
1985 | case SUBST: Result = "!subst" ; break; |
1986 | case SUBSTR: Result = "!substr" ; break; |
1987 | case FIND: Result = "!find" ; break; |
1988 | case SETDAGARG: |
1989 | Result = "!setdagarg" ; |
1990 | break; |
1991 | case SETDAGNAME: |
1992 | Result = "!setdagname" ; |
1993 | break; |
1994 | } |
1995 | return (Result + "(" + |
1996 | (UnquotedLHS ? LHS->getAsUnquotedString() : LHS->getAsString()) + |
1997 | ", " + MHS->getAsString() + ", " + RHS->getAsString() + ")" ); |
1998 | } |
1999 | |
2000 | static void ProfileFoldOpInit(FoldingSetNodeID &ID, const Init *Start, |
2001 | const Init *List, const Init *A, const Init *B, |
2002 | const Init *Expr, const RecTy *Type) { |
2003 | ID.AddPointer(Ptr: Start); |
2004 | ID.AddPointer(Ptr: List); |
2005 | ID.AddPointer(Ptr: A); |
2006 | ID.AddPointer(Ptr: B); |
2007 | ID.AddPointer(Ptr: Expr); |
2008 | ID.AddPointer(Ptr: Type); |
2009 | } |
2010 | |
2011 | const FoldOpInit *FoldOpInit::get(const Init *Start, const Init *List, |
2012 | const Init *A, const Init *B, |
2013 | const Init *Expr, const RecTy *Type) { |
2014 | FoldingSetNodeID ID; |
2015 | ProfileFoldOpInit(ID, Start, List, A, B, Expr, Type); |
2016 | |
2017 | detail::RecordKeeperImpl &RK = Start->getRecordKeeper().getImpl(); |
2018 | void *IP = nullptr; |
2019 | if (const FoldOpInit *I = RK.TheFoldOpInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
2020 | return I; |
2021 | |
2022 | FoldOpInit *I = new (RK.Allocator) FoldOpInit(Start, List, A, B, Expr, Type); |
2023 | RK.TheFoldOpInitPool.InsertNode(N: I, InsertPos: IP); |
2024 | return I; |
2025 | } |
2026 | |
2027 | void FoldOpInit::Profile(FoldingSetNodeID &ID) const { |
2028 | ProfileFoldOpInit(ID, Start, List, A, B, Expr, Type: getType()); |
2029 | } |
2030 | |
2031 | const Init *FoldOpInit::Fold(const Record *CurRec) const { |
2032 | if (const auto *LI = dyn_cast<ListInit>(Val: List)) { |
2033 | const Init *Accum = Start; |
2034 | for (const Init *Elt : *LI) { |
2035 | MapResolver R(CurRec); |
2036 | R.set(Key: A, Value: Accum); |
2037 | R.set(Key: B, Value: Elt); |
2038 | Accum = Expr->resolveReferences(R); |
2039 | } |
2040 | return Accum; |
2041 | } |
2042 | return this; |
2043 | } |
2044 | |
2045 | const Init *FoldOpInit::resolveReferences(Resolver &R) const { |
2046 | const Init *NewStart = Start->resolveReferences(R); |
2047 | const Init *NewList = List->resolveReferences(R); |
2048 | ShadowResolver SR(R); |
2049 | SR.addShadow(Key: A); |
2050 | SR.addShadow(Key: B); |
2051 | const Init *NewExpr = Expr->resolveReferences(R&: SR); |
2052 | |
2053 | if (Start == NewStart && List == NewList && Expr == NewExpr) |
2054 | return this; |
2055 | |
2056 | return get(Start: NewStart, List: NewList, A, B, Expr: NewExpr, Type: getType()) |
2057 | ->Fold(CurRec: R.getCurrentRecord()); |
2058 | } |
2059 | |
2060 | const Init *FoldOpInit::getBit(unsigned Bit) const { |
2061 | return VarBitInit::get(T: this, B: Bit); |
2062 | } |
2063 | |
2064 | std::string FoldOpInit::getAsString() const { |
2065 | return (Twine("!foldl(" ) + Start->getAsString() + ", " + List->getAsString() + |
2066 | ", " + A->getAsUnquotedString() + ", " + B->getAsUnquotedString() + |
2067 | ", " + Expr->getAsString() + ")" ) |
2068 | .str(); |
2069 | } |
2070 | |
2071 | static void ProfileIsAOpInit(FoldingSetNodeID &ID, const RecTy *CheckType, |
2072 | const Init *Expr) { |
2073 | ID.AddPointer(Ptr: CheckType); |
2074 | ID.AddPointer(Ptr: Expr); |
2075 | } |
2076 | |
2077 | const IsAOpInit *IsAOpInit::get(const RecTy *CheckType, const Init *Expr) { |
2078 | |
2079 | FoldingSetNodeID ID; |
2080 | ProfileIsAOpInit(ID, CheckType, Expr); |
2081 | |
2082 | detail::RecordKeeperImpl &RK = Expr->getRecordKeeper().getImpl(); |
2083 | void *IP = nullptr; |
2084 | if (const IsAOpInit *I = RK.TheIsAOpInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
2085 | return I; |
2086 | |
2087 | IsAOpInit *I = new (RK.Allocator) IsAOpInit(CheckType, Expr); |
2088 | RK.TheIsAOpInitPool.InsertNode(N: I, InsertPos: IP); |
2089 | return I; |
2090 | } |
2091 | |
2092 | void IsAOpInit::Profile(FoldingSetNodeID &ID) const { |
2093 | ProfileIsAOpInit(ID, CheckType, Expr); |
2094 | } |
2095 | |
2096 | const Init *IsAOpInit::Fold() const { |
2097 | if (const auto *TI = dyn_cast<TypedInit>(Val: Expr)) { |
2098 | // Is the expression type known to be (a subclass of) the desired type? |
2099 | if (TI->getType()->typeIsConvertibleTo(RHS: CheckType)) |
2100 | return IntInit::get(RK&: getRecordKeeper(), V: 1); |
2101 | |
2102 | if (isa<RecordRecTy>(Val: CheckType)) { |
2103 | // If the target type is not a subclass of the expression type once the |
2104 | // expression has been made concrete, or if the expression has fully |
2105 | // resolved to a record, we know that it can't be of the required type. |
2106 | if ((!CheckType->typeIsConvertibleTo(RHS: TI->getType()) && |
2107 | Expr->isConcrete()) || |
2108 | isa<DefInit>(Val: Expr)) |
2109 | return IntInit::get(RK&: getRecordKeeper(), V: 0); |
2110 | } else { |
2111 | // We treat non-record types as not castable. |
2112 | return IntInit::get(RK&: getRecordKeeper(), V: 0); |
2113 | } |
2114 | } |
2115 | return this; |
2116 | } |
2117 | |
2118 | const Init *IsAOpInit::resolveReferences(Resolver &R) const { |
2119 | const Init *NewExpr = Expr->resolveReferences(R); |
2120 | if (Expr != NewExpr) |
2121 | return get(CheckType, Expr: NewExpr)->Fold(); |
2122 | return this; |
2123 | } |
2124 | |
2125 | const Init *IsAOpInit::getBit(unsigned Bit) const { |
2126 | return VarBitInit::get(T: this, B: Bit); |
2127 | } |
2128 | |
2129 | std::string IsAOpInit::getAsString() const { |
2130 | return (Twine("!isa<" ) + CheckType->getAsString() + ">(" + |
2131 | Expr->getAsString() + ")" ) |
2132 | .str(); |
2133 | } |
2134 | |
2135 | static void ProfileExistsOpInit(FoldingSetNodeID &ID, const RecTy *CheckType, |
2136 | const Init *Expr) { |
2137 | ID.AddPointer(Ptr: CheckType); |
2138 | ID.AddPointer(Ptr: Expr); |
2139 | } |
2140 | |
2141 | const ExistsOpInit *ExistsOpInit::get(const RecTy *CheckType, |
2142 | const Init *Expr) { |
2143 | FoldingSetNodeID ID; |
2144 | ProfileExistsOpInit(ID, CheckType, Expr); |
2145 | |
2146 | detail::RecordKeeperImpl &RK = Expr->getRecordKeeper().getImpl(); |
2147 | void *IP = nullptr; |
2148 | if (const ExistsOpInit *I = |
2149 | RK.TheExistsOpInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
2150 | return I; |
2151 | |
2152 | ExistsOpInit *I = new (RK.Allocator) ExistsOpInit(CheckType, Expr); |
2153 | RK.TheExistsOpInitPool.InsertNode(N: I, InsertPos: IP); |
2154 | return I; |
2155 | } |
2156 | |
2157 | void ExistsOpInit::Profile(FoldingSetNodeID &ID) const { |
2158 | ProfileExistsOpInit(ID, CheckType, Expr); |
2159 | } |
2160 | |
2161 | const Init *ExistsOpInit::Fold(const Record *CurRec, bool IsFinal) const { |
2162 | if (const auto *Name = dyn_cast<StringInit>(Val: Expr)) { |
2163 | // Look up all defined records to see if we can find one. |
2164 | const Record *D = CheckType->getRecordKeeper().getDef(Name: Name->getValue()); |
2165 | if (D) { |
2166 | // Check if types are compatible. |
2167 | return IntInit::get(RK&: getRecordKeeper(), |
2168 | V: D->getDefInit()->getType()->typeIsA(RHS: CheckType)); |
2169 | } |
2170 | |
2171 | if (CurRec) { |
2172 | // Self-references are allowed, but their resolution is delayed until |
2173 | // the final resolve to ensure that we get the correct type for them. |
2174 | auto *Anonymous = dyn_cast<AnonymousNameInit>(Val: CurRec->getNameInit()); |
2175 | if (Name == CurRec->getNameInit() || |
2176 | (Anonymous && Name == Anonymous->getNameInit())) { |
2177 | if (!IsFinal) |
2178 | return this; |
2179 | |
2180 | // No doubt that there exists a record, so we should check if types are |
2181 | // compatible. |
2182 | return IntInit::get(RK&: getRecordKeeper(), |
2183 | V: CurRec->getType()->typeIsA(RHS: CheckType)); |
2184 | } |
2185 | } |
2186 | |
2187 | if (IsFinal) |
2188 | return IntInit::get(RK&: getRecordKeeper(), V: 0); |
2189 | } |
2190 | return this; |
2191 | } |
2192 | |
2193 | const Init *ExistsOpInit::resolveReferences(Resolver &R) const { |
2194 | const Init *NewExpr = Expr->resolveReferences(R); |
2195 | if (Expr != NewExpr || R.isFinal()) |
2196 | return get(CheckType, Expr: NewExpr)->Fold(CurRec: R.getCurrentRecord(), IsFinal: R.isFinal()); |
2197 | return this; |
2198 | } |
2199 | |
2200 | const Init *ExistsOpInit::getBit(unsigned Bit) const { |
2201 | return VarBitInit::get(T: this, B: Bit); |
2202 | } |
2203 | |
2204 | std::string ExistsOpInit::getAsString() const { |
2205 | return (Twine("!exists<" ) + CheckType->getAsString() + ">(" + |
2206 | Expr->getAsString() + ")" ) |
2207 | .str(); |
2208 | } |
2209 | |
2210 | static void ProfileInstancesOpInit(FoldingSetNodeID &ID, const RecTy *Type, |
2211 | const Init *Regex) { |
2212 | ID.AddPointer(Ptr: Type); |
2213 | ID.AddPointer(Ptr: Regex); |
2214 | } |
2215 | |
2216 | const InstancesOpInit *InstancesOpInit::get(const RecTy *Type, |
2217 | const Init *Regex) { |
2218 | FoldingSetNodeID ID; |
2219 | ProfileInstancesOpInit(ID, Type, Regex); |
2220 | |
2221 | detail::RecordKeeperImpl &RK = Regex->getRecordKeeper().getImpl(); |
2222 | void *IP = nullptr; |
2223 | if (const InstancesOpInit *I = |
2224 | RK.TheInstancesOpInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
2225 | return I; |
2226 | |
2227 | InstancesOpInit *I = new (RK.Allocator) InstancesOpInit(Type, Regex); |
2228 | RK.TheInstancesOpInitPool.InsertNode(N: I, InsertPos: IP); |
2229 | return I; |
2230 | } |
2231 | |
2232 | void InstancesOpInit::Profile(FoldingSetNodeID &ID) const { |
2233 | ProfileInstancesOpInit(ID, Type, Regex); |
2234 | } |
2235 | |
2236 | const Init *InstancesOpInit::Fold(const Record *CurRec, bool IsFinal) const { |
2237 | if (CurRec && !IsFinal) |
2238 | return this; |
2239 | |
2240 | const auto *RegexInit = dyn_cast<StringInit>(Val: Regex); |
2241 | if (!RegexInit) |
2242 | return this; |
2243 | |
2244 | StringRef RegexStr = RegexInit->getValue(); |
2245 | llvm::Regex Matcher(RegexStr); |
2246 | if (!Matcher.isValid()) |
2247 | PrintFatalError(Msg: Twine("invalid regex '" ) + RegexStr + Twine("'" )); |
2248 | |
2249 | const RecordKeeper &RK = Type->getRecordKeeper(); |
2250 | SmallVector<Init *, 8> Selected; |
2251 | for (auto &Def : RK.getAllDerivedDefinitionsIfDefined(ClassName: Type->getAsString())) |
2252 | if (Matcher.match(String: Def->getName())) |
2253 | Selected.push_back(Elt: Def->getDefInit()); |
2254 | |
2255 | return ListInit::get(Elements: Selected, EltTy: Type); |
2256 | } |
2257 | |
2258 | const Init *InstancesOpInit::resolveReferences(Resolver &R) const { |
2259 | const Init *NewRegex = Regex->resolveReferences(R); |
2260 | if (Regex != NewRegex || R.isFinal()) |
2261 | return get(Type, Regex: NewRegex)->Fold(CurRec: R.getCurrentRecord(), IsFinal: R.isFinal()); |
2262 | return this; |
2263 | } |
2264 | |
2265 | const Init *InstancesOpInit::getBit(unsigned Bit) const { |
2266 | return VarBitInit::get(T: this, B: Bit); |
2267 | } |
2268 | |
2269 | std::string InstancesOpInit::getAsString() const { |
2270 | return "!instances<" + Type->getAsString() + ">(" + Regex->getAsString() + |
2271 | ")" ; |
2272 | } |
2273 | |
2274 | const RecTy *TypedInit::getFieldType(const StringInit *FieldName) const { |
2275 | if (const auto *RecordType = dyn_cast<RecordRecTy>(Val: getType())) { |
2276 | for (const Record *Rec : RecordType->getClasses()) { |
2277 | if (const RecordVal *Field = Rec->getValue(Name: FieldName)) |
2278 | return Field->getType(); |
2279 | } |
2280 | } |
2281 | return nullptr; |
2282 | } |
2283 | |
2284 | const Init *TypedInit::convertInitializerTo(const RecTy *Ty) const { |
2285 | if (getType() == Ty || getType()->typeIsA(RHS: Ty)) |
2286 | return this; |
2287 | |
2288 | if (isa<BitRecTy>(Val: getType()) && isa<BitsRecTy>(Val: Ty) && |
2289 | cast<BitsRecTy>(Val: Ty)->getNumBits() == 1) |
2290 | return BitsInit::get(RK&: getRecordKeeper(), Bits: {this}); |
2291 | |
2292 | return nullptr; |
2293 | } |
2294 | |
2295 | const Init * |
2296 | TypedInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const { |
2297 | const auto *T = dyn_cast<BitsRecTy>(Val: getType()); |
2298 | if (!T) return nullptr; // Cannot subscript a non-bits variable. |
2299 | unsigned NumBits = T->getNumBits(); |
2300 | |
2301 | SmallVector<const Init *, 16> NewBits; |
2302 | NewBits.reserve(N: Bits.size()); |
2303 | for (unsigned Bit : Bits) { |
2304 | if (Bit >= NumBits) |
2305 | return nullptr; |
2306 | |
2307 | NewBits.push_back(Elt: VarBitInit::get(T: this, B: Bit)); |
2308 | } |
2309 | return BitsInit::get(RK&: getRecordKeeper(), Bits: NewBits); |
2310 | } |
2311 | |
2312 | const Init *TypedInit::getCastTo(const RecTy *Ty) const { |
2313 | // Handle the common case quickly |
2314 | if (getType() == Ty || getType()->typeIsA(RHS: Ty)) |
2315 | return this; |
2316 | |
2317 | if (const Init *Converted = convertInitializerTo(Ty)) { |
2318 | assert(!isa<TypedInit>(Converted) || |
2319 | cast<TypedInit>(Converted)->getType()->typeIsA(Ty)); |
2320 | return Converted; |
2321 | } |
2322 | |
2323 | if (!getType()->typeIsConvertibleTo(RHS: Ty)) |
2324 | return nullptr; |
2325 | |
2326 | return UnOpInit::get(Opc: UnOpInit::CAST, LHS: this, Type: Ty)->Fold(CurRec: nullptr); |
2327 | } |
2328 | |
2329 | const VarInit *VarInit::get(StringRef VN, const RecTy *T) { |
2330 | const Init *Value = StringInit::get(RK&: T->getRecordKeeper(), V: VN); |
2331 | return VarInit::get(VN: Value, T); |
2332 | } |
2333 | |
2334 | const VarInit *VarInit::get(const Init *VN, const RecTy *T) { |
2335 | detail::RecordKeeperImpl &RK = T->getRecordKeeper().getImpl(); |
2336 | VarInit *&I = RK.TheVarInitPool[{T, VN}]; |
2337 | if (!I) |
2338 | I = new (RK.Allocator) VarInit(VN, T); |
2339 | return I; |
2340 | } |
2341 | |
2342 | StringRef VarInit::getName() const { |
2343 | const auto *NameString = cast<StringInit>(Val: getNameInit()); |
2344 | return NameString->getValue(); |
2345 | } |
2346 | |
2347 | const Init *VarInit::getBit(unsigned Bit) const { |
2348 | if (getType() == BitRecTy::get(RK&: getRecordKeeper())) |
2349 | return this; |
2350 | return VarBitInit::get(T: this, B: Bit); |
2351 | } |
2352 | |
2353 | const Init *VarInit::resolveReferences(Resolver &R) const { |
2354 | if (const Init *Val = R.resolve(VarName)) |
2355 | return Val; |
2356 | return this; |
2357 | } |
2358 | |
2359 | const VarBitInit *VarBitInit::get(const TypedInit *T, unsigned B) { |
2360 | detail::RecordKeeperImpl &RK = T->getRecordKeeper().getImpl(); |
2361 | VarBitInit *&I = RK.TheVarBitInitPool[{T, B}]; |
2362 | if (!I) |
2363 | I = new (RK.Allocator) VarBitInit(T, B); |
2364 | return I; |
2365 | } |
2366 | |
2367 | std::string VarBitInit::getAsString() const { |
2368 | return TI->getAsString() + "{" + utostr(X: Bit) + "}" ; |
2369 | } |
2370 | |
2371 | const Init *VarBitInit::resolveReferences(Resolver &R) const { |
2372 | const Init *I = TI->resolveReferences(R); |
2373 | if (TI != I) |
2374 | return I->getBit(Bit: getBitNum()); |
2375 | |
2376 | return this; |
2377 | } |
2378 | |
2379 | DefInit::DefInit(const Record *D) |
2380 | : TypedInit(IK_DefInit, D->getType()), Def(D) {} |
2381 | |
2382 | const Init *DefInit::convertInitializerTo(const RecTy *Ty) const { |
2383 | if (auto *RRT = dyn_cast<RecordRecTy>(Val: Ty)) |
2384 | if (getType()->typeIsConvertibleTo(RHS: RRT)) |
2385 | return this; |
2386 | return nullptr; |
2387 | } |
2388 | |
2389 | const RecTy *DefInit::getFieldType(const StringInit *FieldName) const { |
2390 | if (const RecordVal *RV = Def->getValue(Name: FieldName)) |
2391 | return RV->getType(); |
2392 | return nullptr; |
2393 | } |
2394 | |
2395 | std::string DefInit::getAsString() const { return Def->getName().str(); } |
2396 | |
2397 | static void ProfileVarDefInit(FoldingSetNodeID &ID, const Record *Class, |
2398 | ArrayRef<const ArgumentInit *> Args) { |
2399 | ID.AddInteger(I: Args.size()); |
2400 | ID.AddPointer(Ptr: Class); |
2401 | |
2402 | for (const Init *I : Args) |
2403 | ID.AddPointer(Ptr: I); |
2404 | } |
2405 | |
2406 | VarDefInit::VarDefInit(SMLoc Loc, const Record *Class, |
2407 | ArrayRef<const ArgumentInit *> Args) |
2408 | : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Loc(Loc), Class(Class), |
2409 | NumArgs(Args.size()) { |
2410 | llvm::uninitialized_copy(Src&: Args, Dst: getTrailingObjects()); |
2411 | } |
2412 | |
2413 | const VarDefInit *VarDefInit::get(SMLoc Loc, const Record *Class, |
2414 | ArrayRef<const ArgumentInit *> Args) { |
2415 | FoldingSetNodeID ID; |
2416 | ProfileVarDefInit(ID, Class, Args); |
2417 | |
2418 | detail::RecordKeeperImpl &RK = Class->getRecords().getImpl(); |
2419 | void *IP = nullptr; |
2420 | if (const VarDefInit *I = RK.TheVarDefInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
2421 | return I; |
2422 | |
2423 | void *Mem = RK.Allocator.Allocate( |
2424 | Size: totalSizeToAlloc<const ArgumentInit *>(Counts: Args.size()), Alignment: alignof(VarDefInit)); |
2425 | VarDefInit *I = new (Mem) VarDefInit(Loc, Class, Args); |
2426 | RK.TheVarDefInitPool.InsertNode(N: I, InsertPos: IP); |
2427 | return I; |
2428 | } |
2429 | |
2430 | void VarDefInit::Profile(FoldingSetNodeID &ID) const { |
2431 | ProfileVarDefInit(ID, Class, Args: args()); |
2432 | } |
2433 | |
2434 | const DefInit *VarDefInit::instantiate() { |
2435 | if (Def) |
2436 | return Def; |
2437 | |
2438 | RecordKeeper &Records = Class->getRecords(); |
2439 | auto NewRecOwner = std::make_unique<Record>( |
2440 | args: Records.getNewAnonymousName(), args&: Loc, args&: Records, args: Record::RK_AnonymousDef); |
2441 | Record *NewRec = NewRecOwner.get(); |
2442 | |
2443 | // Copy values from class to instance |
2444 | for (const RecordVal &Val : Class->getValues()) |
2445 | NewRec->addValue(RV: Val); |
2446 | |
2447 | // Copy assertions from class to instance. |
2448 | NewRec->appendAssertions(Rec: Class); |
2449 | |
2450 | // Copy dumps from class to instance. |
2451 | NewRec->appendDumps(Rec: Class); |
2452 | |
2453 | // Substitute and resolve template arguments |
2454 | ArrayRef<const Init *> TArgs = Class->getTemplateArgs(); |
2455 | MapResolver R(NewRec); |
2456 | |
2457 | for (const Init *Arg : TArgs) { |
2458 | R.set(Key: Arg, Value: NewRec->getValue(Name: Arg)->getValue()); |
2459 | NewRec->removeValue(Name: Arg); |
2460 | } |
2461 | |
2462 | for (auto *Arg : args()) { |
2463 | if (Arg->isPositional()) |
2464 | R.set(Key: TArgs[Arg->getIndex()], Value: Arg->getValue()); |
2465 | if (Arg->isNamed()) |
2466 | R.set(Key: Arg->getName(), Value: Arg->getValue()); |
2467 | } |
2468 | |
2469 | NewRec->resolveReferences(R); |
2470 | |
2471 | // Add superclass. |
2472 | NewRec->addDirectSuperClass( |
2473 | R: Class, Range: SMRange(Class->getLoc().back(), Class->getLoc().back())); |
2474 | |
2475 | // Resolve internal references and store in record keeper |
2476 | NewRec->resolveReferences(); |
2477 | Records.addDef(R: std::move(NewRecOwner)); |
2478 | |
2479 | // Check the assertions. |
2480 | NewRec->checkRecordAssertions(); |
2481 | |
2482 | // Check the assertions. |
2483 | NewRec->emitRecordDumps(); |
2484 | |
2485 | return Def = NewRec->getDefInit(); |
2486 | } |
2487 | |
2488 | const Init *VarDefInit::resolveReferences(Resolver &R) const { |
2489 | TrackUnresolvedResolver UR(&R); |
2490 | bool Changed = false; |
2491 | SmallVector<const ArgumentInit *, 8> NewArgs; |
2492 | NewArgs.reserve(N: args_size()); |
2493 | |
2494 | for (const ArgumentInit *Arg : args()) { |
2495 | const auto *NewArg = cast<ArgumentInit>(Val: Arg->resolveReferences(R&: UR)); |
2496 | NewArgs.push_back(Elt: NewArg); |
2497 | Changed |= NewArg != Arg; |
2498 | } |
2499 | |
2500 | if (Changed) { |
2501 | auto *New = VarDefInit::get(Loc, Class, Args: NewArgs); |
2502 | if (!UR.foundUnresolved()) |
2503 | return const_cast<VarDefInit *>(New)->instantiate(); |
2504 | return New; |
2505 | } |
2506 | return this; |
2507 | } |
2508 | |
2509 | const Init *VarDefInit::Fold() const { |
2510 | if (Def) |
2511 | return Def; |
2512 | |
2513 | TrackUnresolvedResolver R; |
2514 | for (const Init *Arg : args()) |
2515 | Arg->resolveReferences(R); |
2516 | |
2517 | if (!R.foundUnresolved()) |
2518 | return const_cast<VarDefInit *>(this)->instantiate(); |
2519 | return this; |
2520 | } |
2521 | |
2522 | std::string VarDefInit::getAsString() const { |
2523 | std::string Result = Class->getNameInitAsString() + "<" ; |
2524 | ListSeparator LS; |
2525 | for (const Init *Arg : args()) { |
2526 | Result += LS; |
2527 | Result += Arg->getAsString(); |
2528 | } |
2529 | return Result + ">" ; |
2530 | } |
2531 | |
2532 | const FieldInit *FieldInit::get(const Init *R, const StringInit *FN) { |
2533 | detail::RecordKeeperImpl &RK = R->getRecordKeeper().getImpl(); |
2534 | FieldInit *&I = RK.TheFieldInitPool[{R, FN}]; |
2535 | if (!I) |
2536 | I = new (RK.Allocator) FieldInit(R, FN); |
2537 | return I; |
2538 | } |
2539 | |
2540 | const Init *FieldInit::getBit(unsigned Bit) const { |
2541 | if (getType() == BitRecTy::get(RK&: getRecordKeeper())) |
2542 | return this; |
2543 | return VarBitInit::get(T: this, B: Bit); |
2544 | } |
2545 | |
2546 | const Init *FieldInit::resolveReferences(Resolver &R) const { |
2547 | const Init *NewRec = Rec->resolveReferences(R); |
2548 | if (NewRec != Rec) |
2549 | return FieldInit::get(R: NewRec, FN: FieldName)->Fold(CurRec: R.getCurrentRecord()); |
2550 | return this; |
2551 | } |
2552 | |
2553 | const Init *FieldInit::Fold(const Record *CurRec) const { |
2554 | if (const auto *DI = dyn_cast<DefInit>(Val: Rec)) { |
2555 | const Record *Def = DI->getDef(); |
2556 | if (Def == CurRec) |
2557 | PrintFatalError(ErrorLoc: CurRec->getLoc(), |
2558 | Msg: Twine("Attempting to access field '" ) + |
2559 | FieldName->getAsUnquotedString() + "' of '" + |
2560 | Rec->getAsString() + "' is a forbidden self-reference" ); |
2561 | const Init *FieldVal = Def->getValue(Name: FieldName)->getValue(); |
2562 | if (FieldVal->isConcrete()) |
2563 | return FieldVal; |
2564 | } |
2565 | return this; |
2566 | } |
2567 | |
2568 | bool FieldInit::isConcrete() const { |
2569 | if (const auto *DI = dyn_cast<DefInit>(Val: Rec)) { |
2570 | const Init *FieldVal = DI->getDef()->getValue(Name: FieldName)->getValue(); |
2571 | return FieldVal->isConcrete(); |
2572 | } |
2573 | return false; |
2574 | } |
2575 | |
2576 | static void ProfileCondOpInit(FoldingSetNodeID &ID, |
2577 | ArrayRef<const Init *> Conds, |
2578 | ArrayRef<const Init *> Vals, |
2579 | const RecTy *ValType) { |
2580 | assert(Conds.size() == Vals.size() && |
2581 | "Number of conditions and values must match!" ); |
2582 | ID.AddPointer(Ptr: ValType); |
2583 | |
2584 | for (const auto &[Cond, Val] : zip(t&: Conds, u&: Vals)) { |
2585 | ID.AddPointer(Ptr: Cond); |
2586 | ID.AddPointer(Ptr: Val); |
2587 | } |
2588 | } |
2589 | |
2590 | CondOpInit::CondOpInit(ArrayRef<const Init *> Conds, |
2591 | ArrayRef<const Init *> Values, const RecTy *Type) |
2592 | : TypedInit(IK_CondOpInit, Type), NumConds(Conds.size()), ValType(Type) { |
2593 | const Init **TrailingObjects = getTrailingObjects(); |
2594 | llvm::uninitialized_copy(Src&: Conds, Dst: TrailingObjects); |
2595 | llvm::uninitialized_copy(Src&: Values, Dst: TrailingObjects + NumConds); |
2596 | } |
2597 | |
2598 | void CondOpInit::Profile(FoldingSetNodeID &ID) const { |
2599 | ProfileCondOpInit(ID, Conds: getConds(), Vals: getVals(), ValType); |
2600 | } |
2601 | |
2602 | const CondOpInit *CondOpInit::get(ArrayRef<const Init *> Conds, |
2603 | ArrayRef<const Init *> Values, |
2604 | const RecTy *Ty) { |
2605 | assert(Conds.size() == Values.size() && |
2606 | "Number of conditions and values must match!" ); |
2607 | |
2608 | FoldingSetNodeID ID; |
2609 | ProfileCondOpInit(ID, Conds, Vals: Values, ValType: Ty); |
2610 | |
2611 | detail::RecordKeeperImpl &RK = Ty->getRecordKeeper().getImpl(); |
2612 | void *IP = nullptr; |
2613 | if (const CondOpInit *I = RK.TheCondOpInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
2614 | return I; |
2615 | |
2616 | void *Mem = RK.Allocator.Allocate( |
2617 | Size: totalSizeToAlloc<const Init *>(Counts: 2 * Conds.size()), Alignment: alignof(CondOpInit)); |
2618 | CondOpInit *I = new (Mem) CondOpInit(Conds, Values, Ty); |
2619 | RK.TheCondOpInitPool.InsertNode(N: I, InsertPos: IP); |
2620 | return I; |
2621 | } |
2622 | |
2623 | const Init *CondOpInit::resolveReferences(Resolver &R) const { |
2624 | SmallVector<const Init *, 4> NewConds; |
2625 | SmallVector<const Init *, 4> NewVals; |
2626 | |
2627 | bool Changed = false; |
2628 | for (auto [Cond, Val] : getCondAndVals()) { |
2629 | const Init *NewCond = Cond->resolveReferences(R); |
2630 | NewConds.push_back(Elt: NewCond); |
2631 | Changed |= NewCond != Cond; |
2632 | |
2633 | const Init *NewVal = Val->resolveReferences(R); |
2634 | NewVals.push_back(Elt: NewVal); |
2635 | Changed |= NewVal != Val; |
2636 | } |
2637 | |
2638 | if (Changed) |
2639 | return (CondOpInit::get(Conds: NewConds, Values: NewVals, |
2640 | Ty: getValType()))->Fold(CurRec: R.getCurrentRecord()); |
2641 | |
2642 | return this; |
2643 | } |
2644 | |
2645 | const Init *CondOpInit::Fold(const Record *CurRec) const { |
2646 | RecordKeeper &RK = getRecordKeeper(); |
2647 | for (auto [Cond, Val] : getCondAndVals()) { |
2648 | if (const auto *CondI = dyn_cast_or_null<IntInit>( |
2649 | Val: Cond->convertInitializerTo(Ty: IntRecTy::get(RK)))) { |
2650 | if (CondI->getValue()) |
2651 | return Val->convertInitializerTo(Ty: getValType()); |
2652 | } else { |
2653 | return this; |
2654 | } |
2655 | } |
2656 | |
2657 | PrintFatalError(ErrorLoc: CurRec->getLoc(), |
2658 | Msg: CurRec->getNameInitAsString() + |
2659 | " does not have any true condition in:" + |
2660 | this->getAsString()); |
2661 | return nullptr; |
2662 | } |
2663 | |
2664 | bool CondOpInit::isConcrete() const { |
2665 | return all_of(Range: getCondAndVals(), P: [](const auto &Pair) { |
2666 | return std::get<0>(Pair)->isConcrete() && std::get<1>(Pair)->isConcrete(); |
2667 | }); |
2668 | } |
2669 | |
2670 | bool CondOpInit::isComplete() const { |
2671 | return all_of(Range: getCondAndVals(), P: [](const auto &Pair) { |
2672 | return std::get<0>(Pair)->isComplete() && std::get<1>(Pair)->isComplete(); |
2673 | }); |
2674 | } |
2675 | |
2676 | std::string CondOpInit::getAsString() const { |
2677 | std::string Result = "!cond(" ; |
2678 | ListSeparator LS; |
2679 | for (auto [Cond, Val] : getCondAndVals()) { |
2680 | Result += LS; |
2681 | Result += Cond->getAsString() + ": " ; |
2682 | Result += Val->getAsString(); |
2683 | } |
2684 | return Result + ")" ; |
2685 | } |
2686 | |
2687 | const Init *CondOpInit::getBit(unsigned Bit) const { |
2688 | return VarBitInit::get(T: this, B: Bit); |
2689 | } |
2690 | |
2691 | static void ProfileDagInit(FoldingSetNodeID &ID, const Init *V, |
2692 | const StringInit *VN, ArrayRef<const Init *> Args, |
2693 | ArrayRef<const StringInit *> ArgNames) { |
2694 | ID.AddPointer(Ptr: V); |
2695 | ID.AddPointer(Ptr: VN); |
2696 | |
2697 | for (auto [Arg, Name] : zip_equal(t&: Args, u&: ArgNames)) { |
2698 | ID.AddPointer(Ptr: Arg); |
2699 | ID.AddPointer(Ptr: Name); |
2700 | } |
2701 | } |
2702 | |
2703 | DagInit::DagInit(const Init *V, const StringInit *VN, |
2704 | ArrayRef<const Init *> Args, |
2705 | ArrayRef<const StringInit *> ArgNames) |
2706 | : TypedInit(IK_DagInit, DagRecTy::get(RK&: V->getRecordKeeper())), Val(V), |
2707 | ValName(VN), NumArgs(Args.size()) { |
2708 | llvm::uninitialized_copy(Src&: Args, Dst: getTrailingObjects<const Init *>()); |
2709 | llvm::uninitialized_copy(Src&: ArgNames, Dst: getTrailingObjects<const StringInit *>()); |
2710 | } |
2711 | |
2712 | const DagInit *DagInit::get(const Init *V, const StringInit *VN, |
2713 | ArrayRef<const Init *> Args, |
2714 | ArrayRef<const StringInit *> ArgNames) { |
2715 | assert(Args.size() == ArgNames.size() && |
2716 | "Number of DAG args and arg names must match!" ); |
2717 | |
2718 | FoldingSetNodeID ID; |
2719 | ProfileDagInit(ID, V, VN, Args, ArgNames); |
2720 | |
2721 | detail::RecordKeeperImpl &RK = V->getRecordKeeper().getImpl(); |
2722 | void *IP = nullptr; |
2723 | if (const DagInit *I = RK.TheDagInitPool.FindNodeOrInsertPos(ID, InsertPos&: IP)) |
2724 | return I; |
2725 | |
2726 | void *Mem = |
2727 | RK.Allocator.Allocate(Size: totalSizeToAlloc<const Init *, const StringInit *>( |
2728 | Counts: Args.size(), Counts: ArgNames.size()), |
2729 | Alignment: alignof(DagInit)); |
2730 | DagInit *I = new (Mem) DagInit(V, VN, Args, ArgNames); |
2731 | RK.TheDagInitPool.InsertNode(N: I, InsertPos: IP); |
2732 | return I; |
2733 | } |
2734 | |
2735 | const DagInit *DagInit::get( |
2736 | const Init *V, const StringInit *VN, |
2737 | ArrayRef<std::pair<const Init *, const StringInit *>> ArgAndNames) { |
2738 | SmallVector<const Init *, 8> Args(make_first_range(c&: ArgAndNames)); |
2739 | SmallVector<const StringInit *, 8> Names(make_second_range(c&: ArgAndNames)); |
2740 | return DagInit::get(V, VN, Args, ArgNames: Names); |
2741 | } |
2742 | |
2743 | void DagInit::Profile(FoldingSetNodeID &ID) const { |
2744 | ProfileDagInit(ID, V: Val, VN: ValName, Args: getArgs(), ArgNames: getArgNames()); |
2745 | } |
2746 | |
2747 | const Record *DagInit::getOperatorAsDef(ArrayRef<SMLoc> Loc) const { |
2748 | if (const auto *DefI = dyn_cast<DefInit>(Val)) |
2749 | return DefI->getDef(); |
2750 | PrintFatalError(ErrorLoc: Loc, Msg: "Expected record as operator" ); |
2751 | return nullptr; |
2752 | } |
2753 | |
2754 | std::optional<unsigned> DagInit::getArgNo(StringRef Name) const { |
2755 | ArrayRef<const StringInit *> ArgNames = getArgNames(); |
2756 | auto It = llvm::find_if(Range&: ArgNames, P: [Name](const StringInit *ArgName) { |
2757 | return ArgName && ArgName->getValue() == Name; |
2758 | }); |
2759 | if (It == ArgNames.end()) |
2760 | return std::nullopt; |
2761 | return std::distance(first: ArgNames.begin(), last: It); |
2762 | } |
2763 | |
2764 | const Init *DagInit::resolveReferences(Resolver &R) const { |
2765 | SmallVector<const Init *, 8> NewArgs; |
2766 | NewArgs.reserve(N: arg_size()); |
2767 | bool ArgsChanged = false; |
2768 | for (const Init *Arg : getArgs()) { |
2769 | const Init *NewArg = Arg->resolveReferences(R); |
2770 | NewArgs.push_back(Elt: NewArg); |
2771 | ArgsChanged |= NewArg != Arg; |
2772 | } |
2773 | |
2774 | const Init *Op = Val->resolveReferences(R); |
2775 | if (Op != Val || ArgsChanged) |
2776 | return DagInit::get(V: Op, VN: ValName, Args: NewArgs, ArgNames: getArgNames()); |
2777 | |
2778 | return this; |
2779 | } |
2780 | |
2781 | bool DagInit::isConcrete() const { |
2782 | if (!Val->isConcrete()) |
2783 | return false; |
2784 | return all_of(Range: getArgs(), P: [](const Init *Elt) { return Elt->isConcrete(); }); |
2785 | } |
2786 | |
2787 | std::string DagInit::getAsString() const { |
2788 | std::string Result = "(" + Val->getAsString(); |
2789 | if (ValName) |
2790 | Result += ":$" + ValName->getAsUnquotedString(); |
2791 | if (!arg_empty()) { |
2792 | Result += " " ; |
2793 | ListSeparator LS; |
2794 | for (auto [Arg, Name] : getArgAndNames()) { |
2795 | Result += LS; |
2796 | Result += Arg->getAsString(); |
2797 | if (Name) |
2798 | Result += ":$" + Name->getAsUnquotedString(); |
2799 | } |
2800 | } |
2801 | return Result + ")" ; |
2802 | } |
2803 | |
2804 | //===----------------------------------------------------------------------===// |
2805 | // Other implementations |
2806 | //===----------------------------------------------------------------------===// |
2807 | |
2808 | RecordVal::RecordVal(const Init *N, const RecTy *T, FieldKind K) |
2809 | : Name(N), TyAndKind(T, K) { |
2810 | setValue(UnsetInit::get(RK&: N->getRecordKeeper())); |
2811 | assert(Value && "Cannot create unset value for current type!" ); |
2812 | } |
2813 | |
2814 | // This constructor accepts the same arguments as the above, but also |
2815 | // a source location. |
2816 | RecordVal::RecordVal(const Init *N, SMLoc Loc, const RecTy *T, FieldKind K) |
2817 | : Name(N), Loc(Loc), TyAndKind(T, K) { |
2818 | setValue(UnsetInit::get(RK&: N->getRecordKeeper())); |
2819 | assert(Value && "Cannot create unset value for current type!" ); |
2820 | } |
2821 | |
2822 | StringRef RecordVal::getName() const { |
2823 | return cast<StringInit>(Val: getNameInit())->getValue(); |
2824 | } |
2825 | |
2826 | std::string RecordVal::getPrintType() const { |
2827 | if (getType() == StringRecTy::get(RK&: getRecordKeeper())) { |
2828 | if (const auto *StrInit = dyn_cast<StringInit>(Val: Value)) { |
2829 | if (StrInit->hasCodeFormat()) |
2830 | return "code" ; |
2831 | else |
2832 | return "string" ; |
2833 | } else { |
2834 | return "string" ; |
2835 | } |
2836 | } else { |
2837 | return TyAndKind.getPointer()->getAsString(); |
2838 | } |
2839 | } |
2840 | |
2841 | bool RecordVal::setValue(const Init *V) { |
2842 | if (!V) { |
2843 | Value = nullptr; |
2844 | return false; |
2845 | } |
2846 | |
2847 | Value = V->getCastTo(Ty: getType()); |
2848 | if (!Value) |
2849 | return true; |
2850 | |
2851 | assert(!isa<TypedInit>(Value) || |
2852 | cast<TypedInit>(Value)->getType()->typeIsA(getType())); |
2853 | if (const auto *BTy = dyn_cast<BitsRecTy>(Val: getType())) { |
2854 | if (isa<BitsInit>(Val: Value)) |
2855 | return false; |
2856 | SmallVector<const Init *, 64> Bits(BTy->getNumBits()); |
2857 | for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I) |
2858 | Bits[I] = Value->getBit(Bit: I); |
2859 | Value = BitsInit::get(RK&: V->getRecordKeeper(), Bits); |
2860 | } |
2861 | |
2862 | return false; |
2863 | } |
2864 | |
2865 | // This version of setValue takes a source location and resets the |
2866 | // location in the RecordVal. |
2867 | bool RecordVal::setValue(const Init *V, SMLoc NewLoc) { |
2868 | Loc = NewLoc; |
2869 | return setValue(V); |
2870 | } |
2871 | |
2872 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
2873 | LLVM_DUMP_METHOD void RecordVal::dump() const { errs() << *this; } |
2874 | #endif |
2875 | |
2876 | void RecordVal::print(raw_ostream &OS, bool PrintSem) const { |
2877 | if (isNonconcreteOK()) OS << "field " ; |
2878 | OS << getPrintType() << " " << getNameInitAsString(); |
2879 | |
2880 | if (getValue()) |
2881 | OS << " = " << *getValue(); |
2882 | |
2883 | if (PrintSem) OS << ";\n" ; |
2884 | } |
2885 | |
2886 | void Record::updateClassLoc(SMLoc Loc) { |
2887 | assert(Locs.size() == 1); |
2888 | ForwardDeclarationLocs.push_back(Elt: Locs.front()); |
2889 | |
2890 | Locs.clear(); |
2891 | Locs.push_back(Elt: Loc); |
2892 | } |
2893 | |
2894 | void Record::checkName() { |
2895 | // Ensure the record name has string type. |
2896 | const auto *TypedName = cast<const TypedInit>(Val: Name); |
2897 | if (!isa<StringRecTy>(Val: TypedName->getType())) |
2898 | PrintFatalError(ErrorLoc: getLoc(), Msg: Twine("Record name '" ) + Name->getAsString() + |
2899 | "' is not a string!" ); |
2900 | } |
2901 | |
2902 | const RecordRecTy *Record::getType() const { |
2903 | SmallVector<const Record *> DirectSCs( |
2904 | make_first_range(c: getDirectSuperClasses())); |
2905 | return RecordRecTy::get(RK&: TrackedRecords, UnsortedClasses: DirectSCs); |
2906 | } |
2907 | |
2908 | DefInit *Record::getDefInit() const { |
2909 | if (!CorrespondingDefInit) { |
2910 | CorrespondingDefInit = |
2911 | new (TrackedRecords.getImpl().Allocator) DefInit(this); |
2912 | } |
2913 | return CorrespondingDefInit; |
2914 | } |
2915 | |
2916 | unsigned Record::getNewUID(RecordKeeper &RK) { |
2917 | return RK.getImpl().LastRecordID++; |
2918 | } |
2919 | |
2920 | void Record::setName(const Init *NewName) { |
2921 | Name = NewName; |
2922 | checkName(); |
2923 | // DO NOT resolve record values to the name at this point because |
2924 | // there might be default values for arguments of this def. Those |
2925 | // arguments might not have been resolved yet so we don't want to |
2926 | // prematurely assume values for those arguments were not passed to |
2927 | // this def. |
2928 | // |
2929 | // Nonetheless, it may be that some of this Record's values |
2930 | // reference the record name. Indeed, the reason for having the |
2931 | // record name be an Init is to provide this flexibility. The extra |
2932 | // resolve steps after completely instantiating defs takes care of |
2933 | // this. See TGParser::ParseDef and TGParser::ParseDefm. |
2934 | } |
2935 | |
2936 | void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) { |
2937 | const Init *OldName = getNameInit(); |
2938 | const Init *NewName = Name->resolveReferences(R); |
2939 | if (NewName != OldName) { |
2940 | // Re-register with RecordKeeper. |
2941 | setName(NewName); |
2942 | } |
2943 | |
2944 | // Resolve the field values. |
2945 | for (RecordVal &Value : Values) { |
2946 | if (SkipVal == &Value) // Skip resolve the same field as the given one |
2947 | continue; |
2948 | if (const Init *V = Value.getValue()) { |
2949 | const Init *VR = V->resolveReferences(R); |
2950 | if (Value.setValue(VR)) { |
2951 | std::string Type; |
2952 | if (const auto *VRT = dyn_cast<TypedInit>(Val: VR)) |
2953 | Type = |
2954 | (Twine("of type '" ) + VRT->getType()->getAsString() + "' " ).str(); |
2955 | PrintFatalError( |
2956 | ErrorLoc: getLoc(), |
2957 | Msg: Twine("Invalid value " ) + Type + "found when setting field '" + |
2958 | Value.getNameInitAsString() + "' of type '" + |
2959 | Value.getType()->getAsString() + |
2960 | "' after resolving references: " + VR->getAsUnquotedString() + |
2961 | "\n" ); |
2962 | } |
2963 | } |
2964 | } |
2965 | |
2966 | // Resolve the assertion expressions. |
2967 | for (AssertionInfo &Assertion : Assertions) { |
2968 | const Init *Value = Assertion.Condition->resolveReferences(R); |
2969 | Assertion.Condition = Value; |
2970 | Value = Assertion.Message->resolveReferences(R); |
2971 | Assertion.Message = Value; |
2972 | } |
2973 | // Resolve the dump expressions. |
2974 | for (DumpInfo &Dump : Dumps) { |
2975 | const Init *Value = Dump.Message->resolveReferences(R); |
2976 | Dump.Message = Value; |
2977 | } |
2978 | } |
2979 | |
2980 | void Record::resolveReferences(const Init *NewName) { |
2981 | RecordResolver R(*this); |
2982 | R.setName(NewName); |
2983 | R.setFinal(true); |
2984 | resolveReferences(R); |
2985 | } |
2986 | |
2987 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
2988 | LLVM_DUMP_METHOD void Record::dump() const { errs() << *this; } |
2989 | #endif |
2990 | |
2991 | raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { |
2992 | OS << R.getNameInitAsString(); |
2993 | |
2994 | ArrayRef<const Init *> TArgs = R.getTemplateArgs(); |
2995 | if (!TArgs.empty()) { |
2996 | OS << "<" ; |
2997 | ListSeparator LS; |
2998 | for (const Init *TA : TArgs) { |
2999 | const RecordVal *RV = R.getValue(Name: TA); |
3000 | assert(RV && "Template argument record not found??" ); |
3001 | OS << LS; |
3002 | RV->print(OS, PrintSem: false); |
3003 | } |
3004 | OS << ">" ; |
3005 | } |
3006 | |
3007 | OS << " {" ; |
3008 | std::vector<const Record *> SCs = R.getSuperClasses(); |
3009 | if (!SCs.empty()) { |
3010 | OS << "\t//" ; |
3011 | for (const Record *SC : SCs) |
3012 | OS << " " << SC->getNameInitAsString(); |
3013 | } |
3014 | OS << "\n" ; |
3015 | |
3016 | for (const RecordVal &Val : R.getValues()) |
3017 | if (Val.isNonconcreteOK() && !R.isTemplateArg(Name: Val.getNameInit())) |
3018 | OS << Val; |
3019 | for (const RecordVal &Val : R.getValues()) |
3020 | if (!Val.isNonconcreteOK() && !R.isTemplateArg(Name: Val.getNameInit())) |
3021 | OS << Val; |
3022 | |
3023 | return OS << "}\n" ; |
3024 | } |
3025 | |
3026 | SMLoc Record::getFieldLoc(StringRef FieldName) const { |
3027 | const RecordVal *R = getValue(Name: FieldName); |
3028 | if (!R) |
3029 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3030 | "' does not have a field named `" + FieldName + "'!\n" ); |
3031 | return R->getLoc(); |
3032 | } |
3033 | |
3034 | const Init *Record::getValueInit(StringRef FieldName) const { |
3035 | const RecordVal *R = getValue(Name: FieldName); |
3036 | if (!R || !R->getValue()) |
3037 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3038 | "' does not have a field named `" + FieldName + "'!\n" ); |
3039 | return R->getValue(); |
3040 | } |
3041 | |
3042 | StringRef Record::getValueAsString(StringRef FieldName) const { |
3043 | std::optional<StringRef> S = getValueAsOptionalString(FieldName); |
3044 | if (!S) |
3045 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3046 | "' does not have a field named `" + FieldName + "'!\n" ); |
3047 | return *S; |
3048 | } |
3049 | |
3050 | std::optional<StringRef> |
3051 | Record::getValueAsOptionalString(StringRef FieldName) const { |
3052 | const RecordVal *R = getValue(Name: FieldName); |
3053 | if (!R || !R->getValue()) |
3054 | return std::nullopt; |
3055 | if (isa<UnsetInit>(Val: R->getValue())) |
3056 | return std::nullopt; |
3057 | |
3058 | if (const auto *SI = dyn_cast<StringInit>(Val: R->getValue())) |
3059 | return SI->getValue(); |
3060 | |
3061 | PrintFatalError(ErrorLoc: getLoc(), |
3062 | Msg: "Record `" + getName() + "', ` field `" + FieldName + |
3063 | "' exists but does not have a string initializer!" ); |
3064 | } |
3065 | |
3066 | const BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { |
3067 | const RecordVal *R = getValue(Name: FieldName); |
3068 | if (!R || !R->getValue()) |
3069 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3070 | "' does not have a field named `" + FieldName + "'!\n" ); |
3071 | |
3072 | if (const auto *BI = dyn_cast<BitsInit>(Val: R->getValue())) |
3073 | return BI; |
3074 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + "', field `" + FieldName + |
3075 | "' exists but does not have a bits value" ); |
3076 | } |
3077 | |
3078 | const ListInit *Record::getValueAsListInit(StringRef FieldName) const { |
3079 | const RecordVal *R = getValue(Name: FieldName); |
3080 | if (!R || !R->getValue()) |
3081 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3082 | "' does not have a field named `" + FieldName + "'!\n" ); |
3083 | |
3084 | if (const auto *LI = dyn_cast<ListInit>(Val: R->getValue())) |
3085 | return LI; |
3086 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + "', field `" + FieldName + |
3087 | "' exists but does not have a list value" ); |
3088 | } |
3089 | |
3090 | std::vector<const Record *> |
3091 | Record::getValueAsListOfDefs(StringRef FieldName) const { |
3092 | const ListInit *List = getValueAsListInit(FieldName); |
3093 | std::vector<const Record *> Defs; |
3094 | for (const Init *I : List->getElements()) { |
3095 | if (const auto *DI = dyn_cast<DefInit>(Val: I)) |
3096 | Defs.push_back(x: DI->getDef()); |
3097 | else |
3098 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + "', field `" + |
3099 | FieldName + |
3100 | "' list is not entirely DefInit!" ); |
3101 | } |
3102 | return Defs; |
3103 | } |
3104 | |
3105 | int64_t Record::getValueAsInt(StringRef FieldName) const { |
3106 | const RecordVal *R = getValue(Name: FieldName); |
3107 | if (!R || !R->getValue()) |
3108 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3109 | "' does not have a field named `" + FieldName + "'!\n" ); |
3110 | |
3111 | if (const auto *II = dyn_cast<IntInit>(Val: R->getValue())) |
3112 | return II->getValue(); |
3113 | PrintFatalError(ErrorLoc: getLoc(), Msg: Twine("Record `" ) + getName() + "', field `" + |
3114 | FieldName + |
3115 | "' exists but does not have an int value: " + |
3116 | R->getValue()->getAsString()); |
3117 | } |
3118 | |
3119 | std::vector<int64_t> |
3120 | Record::getValueAsListOfInts(StringRef FieldName) const { |
3121 | const ListInit *List = getValueAsListInit(FieldName); |
3122 | std::vector<int64_t> Ints; |
3123 | for (const Init *I : List->getElements()) { |
3124 | if (const auto *II = dyn_cast<IntInit>(Val: I)) |
3125 | Ints.push_back(x: II->getValue()); |
3126 | else |
3127 | PrintFatalError(ErrorLoc: getLoc(), |
3128 | Msg: Twine("Record `" ) + getName() + "', field `" + FieldName + |
3129 | "' exists but does not have a list of ints value: " + |
3130 | I->getAsString()); |
3131 | } |
3132 | return Ints; |
3133 | } |
3134 | |
3135 | std::vector<StringRef> |
3136 | Record::getValueAsListOfStrings(StringRef FieldName) const { |
3137 | const ListInit *List = getValueAsListInit(FieldName); |
3138 | std::vector<StringRef> Strings; |
3139 | for (const Init *I : List->getElements()) { |
3140 | if (const auto *SI = dyn_cast<StringInit>(Val: I)) |
3141 | Strings.push_back(x: SI->getValue()); |
3142 | else |
3143 | PrintFatalError(ErrorLoc: getLoc(), |
3144 | Msg: Twine("Record `" ) + getName() + "', field `" + FieldName + |
3145 | "' exists but does not have a list of strings value: " + |
3146 | I->getAsString()); |
3147 | } |
3148 | return Strings; |
3149 | } |
3150 | |
3151 | const Record *Record::getValueAsDef(StringRef FieldName) const { |
3152 | const RecordVal *R = getValue(Name: FieldName); |
3153 | if (!R || !R->getValue()) |
3154 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3155 | "' does not have a field named `" + FieldName + "'!\n" ); |
3156 | |
3157 | if (const auto *DI = dyn_cast<DefInit>(Val: R->getValue())) |
3158 | return DI->getDef(); |
3159 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + "', field `" + |
3160 | FieldName + "' does not have a def initializer!" ); |
3161 | } |
3162 | |
3163 | const Record *Record::getValueAsOptionalDef(StringRef FieldName) const { |
3164 | const RecordVal *R = getValue(Name: FieldName); |
3165 | if (!R || !R->getValue()) |
3166 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3167 | "' does not have a field named `" + FieldName + "'!\n" ); |
3168 | |
3169 | if (const auto *DI = dyn_cast<DefInit>(Val: R->getValue())) |
3170 | return DI->getDef(); |
3171 | if (isa<UnsetInit>(Val: R->getValue())) |
3172 | return nullptr; |
3173 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + "', field `" + |
3174 | FieldName + "' does not have either a def initializer or '?'!" ); |
3175 | } |
3176 | |
3177 | bool Record::getValueAsBit(StringRef FieldName) const { |
3178 | const RecordVal *R = getValue(Name: FieldName); |
3179 | if (!R || !R->getValue()) |
3180 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3181 | "' does not have a field named `" + FieldName + "'!\n" ); |
3182 | |
3183 | if (const auto *BI = dyn_cast<BitInit>(Val: R->getValue())) |
3184 | return BI->getValue(); |
3185 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + "', field `" + |
3186 | FieldName + "' does not have a bit initializer!" ); |
3187 | } |
3188 | |
3189 | bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const { |
3190 | const RecordVal *R = getValue(Name: FieldName); |
3191 | if (!R || !R->getValue()) |
3192 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3193 | "' does not have a field named `" + FieldName.str() + "'!\n" ); |
3194 | |
3195 | if (isa<UnsetInit>(Val: R->getValue())) { |
3196 | Unset = true; |
3197 | return false; |
3198 | } |
3199 | Unset = false; |
3200 | if (const auto *BI = dyn_cast<BitInit>(Val: R->getValue())) |
3201 | return BI->getValue(); |
3202 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + "', field `" + |
3203 | FieldName + "' does not have a bit initializer!" ); |
3204 | } |
3205 | |
3206 | const DagInit *Record::getValueAsDag(StringRef FieldName) const { |
3207 | const RecordVal *R = getValue(Name: FieldName); |
3208 | if (!R || !R->getValue()) |
3209 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + |
3210 | "' does not have a field named `" + FieldName + "'!\n" ); |
3211 | |
3212 | if (const auto *DI = dyn_cast<DagInit>(Val: R->getValue())) |
3213 | return DI; |
3214 | PrintFatalError(ErrorLoc: getLoc(), Msg: "Record `" + getName() + "', field `" + |
3215 | FieldName + "' does not have a dag initializer!" ); |
3216 | } |
3217 | |
3218 | // Check all record assertions: For each one, resolve the condition |
3219 | // and message, then call CheckAssert(). |
3220 | // Note: The condition and message are probably already resolved, |
3221 | // but resolving again allows calls before records are resolved. |
3222 | void Record::checkRecordAssertions() { |
3223 | RecordResolver R(*this); |
3224 | R.setFinal(true); |
3225 | |
3226 | bool AnyFailed = false; |
3227 | for (const auto &Assertion : getAssertions()) { |
3228 | const Init *Condition = Assertion.Condition->resolveReferences(R); |
3229 | const Init *Message = Assertion.Message->resolveReferences(R); |
3230 | AnyFailed |= CheckAssert(Loc: Assertion.Loc, Condition, Message); |
3231 | } |
3232 | |
3233 | if (!AnyFailed) |
3234 | return; |
3235 | |
3236 | // If any of the record assertions failed, print some context that will |
3237 | // help see where the record that caused these assert failures is defined. |
3238 | PrintError(Rec: this, Msg: "assertion failed in this record" ); |
3239 | } |
3240 | |
3241 | void Record::emitRecordDumps() { |
3242 | RecordResolver R(*this); |
3243 | R.setFinal(true); |
3244 | |
3245 | for (const DumpInfo &Dump : getDumps()) { |
3246 | const Init *Message = Dump.Message->resolveReferences(R); |
3247 | dumpMessage(Loc: Dump.Loc, Message); |
3248 | } |
3249 | } |
3250 | |
3251 | // Report a warning if the record has unused template arguments. |
3252 | void Record::checkUnusedTemplateArgs() { |
3253 | for (const Init *TA : getTemplateArgs()) { |
3254 | const RecordVal *Arg = getValue(Name: TA); |
3255 | if (!Arg->isUsed()) |
3256 | PrintWarning(WarningLoc: Arg->getLoc(), |
3257 | Msg: "unused template argument: " + Twine(Arg->getName())); |
3258 | } |
3259 | } |
3260 | |
3261 | RecordKeeper::RecordKeeper() |
3262 | : Impl(std::make_unique<detail::RecordKeeperImpl>(args&: *this)), |
3263 | Timer(std::make_unique<TGTimer>()) {} |
3264 | |
3265 | RecordKeeper::~RecordKeeper() = default; |
3266 | |
3267 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
3268 | LLVM_DUMP_METHOD void RecordKeeper::dump() const { errs() << *this; } |
3269 | #endif |
3270 | |
3271 | raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) { |
3272 | OS << "------------- Classes -----------------\n" ; |
3273 | for (const auto &[_, C] : RK.getClasses()) |
3274 | OS << "class " << *C; |
3275 | |
3276 | OS << "------------- Defs -----------------\n" ; |
3277 | for (const auto &[_, D] : RK.getDefs()) |
3278 | OS << "def " << *D; |
3279 | return OS; |
3280 | } |
3281 | |
3282 | /// GetNewAnonymousName - Generate a unique anonymous name that can be used as |
3283 | /// an identifier. |
3284 | const Init *RecordKeeper::getNewAnonymousName() { |
3285 | return AnonymousNameInit::get(RK&: *this, V: getImpl().AnonCounter++); |
3286 | } |
3287 | |
3288 | ArrayRef<const Record *> |
3289 | RecordKeeper::getAllDerivedDefinitions(StringRef ClassName) const { |
3290 | // We cache the record vectors for single classes. Many backends request |
3291 | // the same vectors multiple times. |
3292 | auto [Iter, Inserted] = Cache.try_emplace(k: ClassName.str()); |
3293 | if (Inserted) |
3294 | Iter->second = getAllDerivedDefinitions(ClassNames: ArrayRef(ClassName)); |
3295 | return Iter->second; |
3296 | } |
3297 | |
3298 | std::vector<const Record *> |
3299 | RecordKeeper::getAllDerivedDefinitions(ArrayRef<StringRef> ClassNames) const { |
3300 | SmallVector<const Record *, 2> ClassRecs; |
3301 | std::vector<const Record *> Defs; |
3302 | |
3303 | assert(ClassNames.size() > 0 && "At least one class must be passed." ); |
3304 | for (StringRef ClassName : ClassNames) { |
3305 | const Record *Class = getClass(Name: ClassName); |
3306 | if (!Class) |
3307 | PrintFatalError(Msg: "The class '" + ClassName + "' is not defined\n" ); |
3308 | ClassRecs.push_back(Elt: Class); |
3309 | } |
3310 | |
3311 | for (const auto &OneDef : getDefs()) { |
3312 | if (all_of(Range&: ClassRecs, P: [&OneDef](const Record *Class) { |
3313 | return OneDef.second->isSubClassOf(R: Class); |
3314 | })) |
3315 | Defs.push_back(x: OneDef.second.get()); |
3316 | } |
3317 | llvm::sort(C&: Defs, Comp: LessRecord()); |
3318 | return Defs; |
3319 | } |
3320 | |
3321 | ArrayRef<const Record *> |
3322 | RecordKeeper::getAllDerivedDefinitionsIfDefined(StringRef ClassName) const { |
3323 | if (getClass(Name: ClassName)) |
3324 | return getAllDerivedDefinitions(ClassName); |
3325 | return Cache["" ]; |
3326 | } |
3327 | |
3328 | void RecordKeeper::dumpAllocationStats(raw_ostream &OS) const { |
3329 | Impl->dumpAllocationStats(OS); |
3330 | } |
3331 | |
3332 | const Init *MapResolver::resolve(const Init *VarName) { |
3333 | auto It = Map.find(Val: VarName); |
3334 | if (It == Map.end()) |
3335 | return nullptr; |
3336 | |
3337 | const Init *I = It->second.V; |
3338 | |
3339 | if (!It->second.Resolved && Map.size() > 1) { |
3340 | // Resolve mutual references among the mapped variables, but prevent |
3341 | // infinite recursion. |
3342 | Map.erase(I: It); |
3343 | I = I->resolveReferences(R&: *this); |
3344 | Map[VarName] = {I, true}; |
3345 | } |
3346 | |
3347 | return I; |
3348 | } |
3349 | |
3350 | const Init *RecordResolver::resolve(const Init *VarName) { |
3351 | const Init *Val = Cache.lookup(Val: VarName); |
3352 | if (Val) |
3353 | return Val; |
3354 | |
3355 | if (llvm::is_contained(Range&: Stack, Element: VarName)) |
3356 | return nullptr; // prevent infinite recursion |
3357 | |
3358 | if (const RecordVal *RV = getCurrentRecord()->getValue(Name: VarName)) { |
3359 | if (!isa<UnsetInit>(Val: RV->getValue())) { |
3360 | Val = RV->getValue(); |
3361 | Stack.push_back(Elt: VarName); |
3362 | Val = Val->resolveReferences(R&: *this); |
3363 | Stack.pop_back(); |
3364 | } |
3365 | } else if (Name && VarName == getCurrentRecord()->getNameInit()) { |
3366 | Stack.push_back(Elt: VarName); |
3367 | Val = Name->resolveReferences(R&: *this); |
3368 | Stack.pop_back(); |
3369 | } |
3370 | |
3371 | Cache[VarName] = Val; |
3372 | return Val; |
3373 | } |
3374 | |
3375 | const Init *TrackUnresolvedResolver::resolve(const Init *VarName) { |
3376 | const Init *I = nullptr; |
3377 | |
3378 | if (R) { |
3379 | I = R->resolve(VarName); |
3380 | if (I && !FoundUnresolved) { |
3381 | // Do not recurse into the resolved initializer, as that would change |
3382 | // the behavior of the resolver we're delegating, but do check to see |
3383 | // if there are unresolved variables remaining. |
3384 | TrackUnresolvedResolver Sub; |
3385 | I->resolveReferences(R&: Sub); |
3386 | FoundUnresolved |= Sub.FoundUnresolved; |
3387 | } |
3388 | } |
3389 | |
3390 | if (!I) |
3391 | FoundUnresolved = true; |
3392 | return I; |
3393 | } |
3394 | |
3395 | const Init *HasReferenceResolver::resolve(const Init *VarName) { |
3396 | if (VarName == VarNameToTrack) |
3397 | Found = true; |
3398 | return nullptr; |
3399 | } |
3400 | |