LLVM: lib/TableGen/Record.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

22#include "llvm/Config/llvm-config.h"

32#include

33#include

34#include

35#include

36#include

37#include

38#include

39

40using namespace llvm;

41

42#define DEBUG_TYPE "tblgen-records"

43

44

45

46

47

48namespace llvm {

50

51

52

53

61

68

73

95

98

100};

101}

102}

103

105

106 OS << "TheArgumentInitPool size = " << TheArgumentInitPool.size() << '\n';

107 OS << "TheBitsInitPool size = " << TheBitsInitPool.size() << '\n';

108 OS << "TheIntInitPool size = " << TheIntInitPool.size() << '\n';

109 OS << "TheBitsInitPool size = " << TheBitsInitPool.size() << '\n';

110 OS << "TheListInitPool size = " << TheListInitPool.size() << '\n';

111 OS << "TheUnOpInitPool size = " << TheUnOpInitPool.size() << '\n';

112 OS << "TheBinOpInitPool size = " << TheBinOpInitPool.size() << '\n';

113 OS << "TheTernOpInitPool size = " << TheTernOpInitPool.size() << '\n';

114 OS << "TheFoldOpInitPool size = " << TheFoldOpInitPool.size() << '\n';

115 OS << "TheIsAOpInitPool size = " << TheIsAOpInitPool.size() << '\n';

116 OS << "TheExistsOpInitPool size = " << TheExistsOpInitPool.size() << '\n';

117 OS << "TheCondOpInitPool size = " << TheCondOpInitPool.size() << '\n';

118 OS << "TheDagInitPool size = " << TheDagInitPool.size() << '\n';

119 OS << "RecordTypePool size = " << RecordTypePool.size() << '\n';

120 OS << "TheVarInitPool size = " << TheVarInitPool.size() << '\n';

121 OS << "TheVarBitInitPool size = " << TheVarBitInitPool.size() << '\n';

122 OS << "TheVarDefInitPool size = " << TheVarDefInitPool.size() << '\n';

123 OS << "TheFieldInitPool size = " << TheFieldInitPool.size() << '\n';

124 OS << "Bytes allocated = " << Allocator.getBytesAllocated() << '\n';

125 OS << "Total allocator memory = " << Allocator.getTotalMemory() << "\n\n";

126

127 OS << "Number of records instantiated = " << LastRecordID << '\n';

128 OS << "Number of anonymous records = " << AnonCounter << '\n';

129}

130

131

132

133

134

135#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

137#endif

138

140 if (!ListTy)

142 return ListTy;

143}

144

147 return Kind == RHS->getRecTyKind();

148}

149

151

154}

155

158 return true;

159 if (const auto *BitsTy = dyn_cast(RHS))

160 return BitsTy->getNumBits() == 1;

161 return false;

162}

163

169 if (!Ty)

171 return Ty;

172}

173

175 return "bits<" + utostr(Size) + ">";

176}

177

180 return cast(RHS)->Size == Size;

183}

184

187}

188

192}

193

196}

197

199 return "string";

200}

201

205}

206

208 return "list<" + ElementTy->getAsString() + ">";

209}

210

212 if (const auto *ListTy = dyn_cast(RHS))

214 return false;

215}

216

218 if (const auto *RHSl = dyn_cast(RHS))

220 return false;

221}

222

225}

226

228 return "dag";

229}

230

233 ID.AddInteger(Classes.size());

234 for (const Record *R : Classes)

235 ID.AddPointer(R);

236}

237

241 if (UnsortedClasses.empty())

243

245

248 return LHS->getNameInitAsString() < RHS->getNameInitAsString();

249 });

250

253

254 void *IP = nullptr;

256 return Ty;

257

258#ifndef NDEBUG

259

260 for (unsigned i = 0; i < Classes.size(); ++i) {

261 for (unsigned j = 0; j < Classes.size(); ++j) {

263 }

264 assert(&Classes[0]->getRecords() == &Classes[i]->getRecords());

265 }

266#endif

267

269 totalSizeToAlloc<const Record *>(Classes.size()), alignof(RecordRecTy));

271 std::uninitialized_copy(Classes.begin(), Classes.end(),

274 return Ty;

275}

276

278 assert(Class && "unexpected null class");

279 return get(Class->getRecords(), {Class});

280}

281

284}

285

287 if (NumClasses == 1)

288 return getClasses()[0]->getNameInitAsString();

289

290 std::string Str = "{";

291 bool First = true;

294 Str += ", ";

296 Str += R->getNameInitAsString();

297 }

298 Str += "}";

299 return Str;

300}

301

304 return MySuperClass == Class || MySuperClass->isSubClassOf(Class);

305 });

306}

307

309 if (this == RHS)

310 return true;

311

312 const auto *RTy = dyn_cast(RHS);

313 if (!RTy)

314 return false;

315

316 return llvm::all_of(RTy->getClasses(), [this](const Record *TargetClass) {

317 return isSubClassOf(TargetClass);

318 });

319}

320

323}

324

329

330 while (!Stack.empty()) {

331 const Record *R = Stack.pop_back_val();

332

335 } else {

336 R->getDirectSuperClasses(Stack);

337 }

338 }

339

341}

342

344 if (T1 == T2)

345 return T1;

346

347 if (const auto *RecTy1 = dyn_cast(T1)) {

348 if (const auto *RecTy2 = dyn_cast(T2))

350 }

351

352 assert(T1 != nullptr && "Invalid record type");

353 if (T1->typeIsConvertibleTo(T2))

354 return T2;

355

356 assert(T2 != nullptr && "Invalid record type");

358 return T1;

359

360 if (const auto *ListTy1 = dyn_cast(T1)) {

361 if (const auto *ListTy2 = dyn_cast(T2)) {

362 const RecTy *NewType =

363 resolveTypes(ListTy1->getElementType(), ListTy2->getElementType());

364 if (NewType)

366 }

367 }

368

369 return nullptr;

370}

371

372

373

374

375

376void Init::anchor() {}

377

378#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

380#endif

381

383 if (auto *TyInit = dyn_cast(this))

384 return TyInit->getType()->getRecordKeeper();

385 if (auto *ArgInit = dyn_cast(this))

386 return ArgInit->getRecordKeeper();

387 return cast(this)->getRecordKeeper();

388}

389

392}

393

395

397 return this;

398}

399

402 auto I = Aux.index();

403 ID.AddInteger(I);

405 ID.AddInteger(std::getArgumentInit::Positional(Aux));

407 ID.AddPointer(std::getArgumentInit::Named(Aux));

409}

410

413}

414

418

421 void *IP = nullptr;

424 return I;

425

428 return I;

429}

430

432 const Init *NewValue = Value->resolveReferences(R);

433 if (NewValue != Value)

435

436 return this;

437}

438

441}

442

444 if (isa(Ty))

445 return this;

446

447 if (isa(Ty))

449

450 if (auto *BRT = dyn_cast(Ty)) {

451

452 if (BRT->getNumBits() == 1)

454 }

455

456 return nullptr;

457}

458

461 ID.AddInteger(Range.size());

462

464 ID.AddPointer(I);

465}

466

470

472 void *IP = nullptr;

474 return I;

475

477 totalSizeToAlloc<const Init *>(Range.size()), alignof(BitsInit));

479 std::uninitialized_copy(Range.begin(), Range.end(),

480 I->getTrailingObjects<const Init *>());

482 return I;

483}

484

487}

488

490 if (isa(Ty)) {

491 if (getNumBits() != 1) return nullptr;

493 }

494

495 if (auto *BRT = dyn_cast(Ty)) {

496

497

498 if (getNumBits() != BRT->getNumBits()) return nullptr;

499 return this;

500 }

501

502 if (isa(Ty)) {

504 if (Result)

506 }

507

508 return nullptr;

509}

510

512 int64_t Result = 0;

513 for (unsigned i = 0, e = getNumBits(); i != e; ++i)

514 if (auto *Bit = dyn_cast(getBit(i)))

515 Result |= static_cast<int64_t>(Bit->getValue()) << i;

516 else

517 return std::nullopt;

518 return Result;

519}

520

524

525 for (unsigned i = 0, e = Bits.size(); i != e; ++i) {

527 return nullptr;

528 NewBits[i] = getBit(Bits[i]);

529 }

531}

532

534 for (unsigned i = 0, e = getNumBits(); i != e; ++i) {

536 return false;

537 }

538 return true;

539}

540

542 std::string Result = "{ ";

543 for (unsigned i = 0, e = getNumBits(); i != e; ++i) {

544 if (i) Result += ", ";

545 if (const Init *Bit = getBit(e - i - 1))

546 Result += Bit->getAsString();

547 else

548 Result += "*";

549 }

550 return Result + " }";

551}

552

553

554

556 bool Changed = false;

558

559 const Init *CachedBitVarRef = nullptr;

560 const Init *CachedBitVarResolved = nullptr;

561

562 for (unsigned i = 0, e = getNumBits(); i != e; ++i) {

564 const Init *NewBit = CurBit;

565

566 if (const auto *CurBitVar = dyn_cast(CurBit)) {

567 if (CurBitVar->getBitVar() != CachedBitVarRef) {

568 CachedBitVarRef = CurBitVar->getBitVar();

570 }

571 assert(CachedBitVarResolved && "Unresolved bitvar reference");

572 NewBit = CachedBitVarResolved->getBit(CurBitVar->getBitNum());

573 } else {

574

576 }

577

578 if (isa(NewBit) && R.keepUnsetBits())

579 NewBit = CurBit;

580 NewBits[i] = NewBit;

581 Changed |= CurBit != NewBit;

582 }

583

584 if (Changed)

586

587 return this;

588}

589

592 if (I)

594 return I;

595}

596

598 return itostr(Value);

599}

600

602

603 return (NumBits >= sizeof(Value) * 8) ||

604 (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1);

605}

606

608 if (isa(Ty))

609 return this;

610

611 if (isa(Ty)) {

613 if (Val != 0 && Val != 1) return nullptr;

615 }

616

617 if (const auto *BRT = dyn_cast(Ty)) {

619

621 return nullptr;

622

624 for (unsigned i = 0; i != BRT->getNumBits(); ++i)

625 NewBits[i] =

627

629 }

630

631 return nullptr;

632}

633

636

637 for (unsigned i = 0, e = Bits.size(); i != e; ++i) {

638 if (Bits[i] >= 64)

639 return nullptr;

640

641 NewBits[i] =

643 }

645}

646

649}

650

653}

654

656 return "anonymous_" + utostr(Value);

657}

658

660 auto *Old = this;

661 auto *New = R.resolve(Old);

662 New = New ? New : Old;

663 if (R.isFinal())

664 if (const auto *Anonymous = dyn_cast(New))

665 return Anonymous->getNameInit();

666 return New;

667}

668

674 auto &Entry = *InitMap.try_emplace(V, nullptr).first;

675 if (!Entry.second)

676 Entry.second = new (RKImpl.Allocator) StringInit(RK, Entry.getKey(), Fmt);

677 return Entry.second;

678}

679

681 if (isa(Ty))

682 return this;

683

684 return nullptr;

685}

686

688 const RecTy *EltTy) {

689 ID.AddInteger(Range.size());

690 ID.AddPointer(EltTy);

691

693 ID.AddPointer(I);

694}

695

697 const RecTy *EltTy) {

700

702 void *IP = nullptr;

704 return I;

705

707 cast(Range[0])->getType()->typeIsConvertibleTo(EltTy));

708

710 totalSizeToAlloc<const Init *>(Range.size()), alignof(ListInit));

712 std::uninitialized_copy(Range.begin(), Range.end(),

713 I->getTrailingObjects<const Init *>());

715 return I;

716}

717

719 const RecTy *EltTy = cast(getType())->getElementType();

720

722}

723

726 return this;

727

728 if (const auto *LRT = dyn_cast(Ty)) {

731

732

733

734 bool Changed = false;

735 const RecTy *ElementType = LRT->getElementType();

737 if (const Init *CI = I->convertInitializerTo(ElementType)) {

738 Elements.push_back(CI);

739 if (CI != I)

740 Changed = true;

741 } else

742 return nullptr;

743

744 if (!Changed)

745 return this;

747 }

748

749 return nullptr;

750}

751

753 assert(i < NumValues && "List element index out of range!");

754 const auto *DI = dyn_cast(getElement(i));

755 if (!DI)

757 return DI->getDef();

758}

759

762 Resolved.reserve(size());

763 bool Changed = false;

764

767 Changed |= E != CurElt;

768 Resolved.push_back(E);

769 }

770

771 if (Changed)

773 return this;

774}

775

777 for (const Init *Element : *this) {

779 return false;

780 }

781 return true;

782}

783

785 for (const Init *Element : *this) {

787 return false;

788 }

789 return true;

790}

791

793 std::string Result = "[";

794 const char *sep = "";

795 for (const Init *Element : *this) {

796 Result += sep;

797 sep = ", ";

799 }

800 return Result + "]";

801}

802

805 return this;

807}

808

811 ID.AddInteger(Opcode);

812 ID.AddPointer(Op);

814}

815

819

821 void *IP = nullptr;

823 return I;

824

827 return I;

828}

829

832}

833

839

840 if (const auto *Def = dyn_cast(LHS)) {

841 std::string S;

843 OS << *Def->getDef();

845 } else {

846

847

848

849

850

852 }

853 }

854 break;

856 if (const auto *LHSs = dyn_cast(LHS))

858 break;

860 if (const auto *LHSs = dyn_cast(LHS))

862 break;

864 if (isa(getType())) {

865 if (const auto *LHSs = dyn_cast(LHS))

866 return LHSs;

867

868 if (const auto *LHSd = dyn_cast(LHS))

870

871 if (const auto *LHSi = dyn_cast_or_null(

874

875 } else if (isa(getType())) {

876 if (const auto *Name = dyn_cast(LHS)) {

878 if (D && CurRec) {

879

880

881 auto *Anonymous = dyn_cast(CurRec->getNameInit());

883 (Anonymous && Name == Anonymous->getNameInit())) {

884 if (!IsFinal)

885 break;

886 D = CurRec;

887 }

888 }

889

890 auto PrintFatalErrorHelper = [CurRec](const Twine &T) {

891 if (CurRec)

893 else

895 };

896

897 if (D) {

898 if (IsFinal) {

899 PrintFatalErrorHelper(Twine("Undefined reference to record: '") +

900 Name->getValue() + "'\n");

901 }

902 break;

903 }

904

905 DefInit *DI = D->getDefInit();

907 PrintFatalErrorHelper(Twine("Expected type '") +

911 }

912 return DI;

913 }

914 }

915

917 return NewInit;

918 break;

919

921 if (isa(LHS))

925 break;

926

927 case NOT:

928 if (const auto *LHSi = dyn_cast_or_null(

930 return IntInit::get(RK, LHSi->getValue() ? 0 : 1);

931 break;

932

934 if (const auto *LHSl = dyn_cast(LHS)) {

935 assert(!LHSl->empty() && "Empty list in head");

936 return LHSl->getElement(0);

937 }

938 break;

939

941 if (const auto *LHSl = dyn_cast(LHS)) {

942 assert(!LHSl->empty() && "Empty list in tail");

943

944

945 return ListInit::get(LHSl->getValues().slice(1), LHSl->getElementType());

946 }

947 break;

948

950 if (const auto *LHSl = dyn_cast(LHS))

952 if (const auto *LHSd = dyn_cast(LHS))

954 if (const auto *LHSs = dyn_cast(LHS))

955 return IntInit::get(RK, LHSs->getValue().size());

956 break;

957

959 if (const auto *LHSl = dyn_cast(LHS))

961 if (const auto *LHSd = dyn_cast(LHS))

963 if (const auto *LHSs = dyn_cast(LHS))

964 return IntInit::get(RK, LHSs->getValue().empty());

965 break;

966

968 if (const auto *Dag = dyn_cast(LHS)) {

969

970

971 auto *TI = cast(Dag->getOperator());

972 if (!TI->getType()->typeIsA(getType())) {

975 "', got '" + TI->getType()->getAsString() +

977 } else {

978 return Dag->getOperator();

979 }

980 }

981 break;

982

984 if (const auto *LHSi = dyn_cast_or_null(

986 int64_t LHSv = LHSi->getValue();

987 if (LHSv <= 0) {

989 "Illegal operation: logtwo is undefined "

990 "on arguments less than or equal to 0");

991 } else {

994 "Log of an int64_t must be smaller than INT64_MAX");

995 return IntInit::get(RK, static_cast<int64_t>(Log));

996 }

997 }

998 break;

999

1001 if (const auto *LHSList = dyn_cast(LHS)) {

1002 const auto *InnerListTy = dyn_cast(LHSList->getElementType());

1003

1004 if (!InnerListTy)

1005 return LHS;

1006

1007 auto Flatten =

1008 [](const ListInit *List) -> std::optional<std::vector<const Init *>> {

1009 std::vector<const Init *> Flattened;

1010

1011 for (const Init *InnerInit : List->getValues()) {

1012 const auto *InnerList = dyn_cast(InnerInit);

1013 if (!InnerList)

1014 return std::nullopt;

1015 for (const Init *InnerElem : InnerList->getValues())

1016 Flattened.push_back(InnerElem);

1017 };

1018 return Flattened;

1019 };

1020

1021 auto Flattened = Flatten(LHSList);

1022 if (Flattened)

1023 return ListInit::get(*Flattened, InnerListTy->getElementType());

1024 }

1025 break;

1026 }

1027 return this;

1028}

1029

1032

1033 if (LHS != lhs || (R.isFinal() && getOpcode() == CAST))

1035 ->Fold(R.getCurrentRecord(), R.isFinal());

1036 return this;

1037}

1038

1040 std::string Result;

1043 case NOT: Result = "!not"; break;

1044 case HEAD: Result = "!head"; break;

1045 case TAIL: Result = "!tail"; break;

1046 case SIZE: Result = "!size"; break;

1047 case EMPTY: Result = "!empty"; break;

1048 case GETDAGOP: Result = "!getdagop"; break;

1049 case LOG2 : Result = "!logtwo"; break;

1051 Result = "!listflatten";

1052 break;

1054 Result = "!repr";

1055 break;

1057 Result = "!tolower";

1058 break;

1060 Result = "!toupper";

1061 break;

1063 Result = "!initialized";

1064 break;

1065 }

1066 return Result + "(" + LHS->getAsString() + ")";

1067}

1068

1070 const Init *LHS, const Init *RHS,

1072 ID.AddInteger(Opcode);

1073 ID.AddPointer(LHS);

1074 ID.AddPointer(RHS);

1075 ID.AddPointer(Type);

1076}

1077

1082

1084 void *IP = nullptr;

1086 return I;

1087

1090 return I;

1091}

1092

1095}

1096

1100 Concat.append(I1->getValue());

1104}

1105

1108 if (List->size() == 0)

1110 const auto *Element = dyn_cast(List->getElement(0));

1111 if (!Element)

1112 return nullptr;

1115

1116 for (unsigned I = 1, E = List->size(); I < E; ++I) {

1117 Result.append(Delim->getValue());

1118 const auto *Element = dyn_cast(List->getElement(I));

1119 if (!Element)

1120 return nullptr;

1121 Result.append(Element->getValue());

1123 }

1125}

1126

1130 if (List->size() == 0)

1132 const auto *Element = dyn_cast_or_null(

1134 if (!Element)

1135 return nullptr;

1137

1138 for (unsigned I = 1, E = List->size(); I < E; ++I) {

1139 Result.append(Delim->getValue());

1140 const auto *Element = dyn_cast_or_null(

1142 if (!Element)

1143 return nullptr;

1144 Result.append(Element->getAsString());

1145 }

1147}

1148

1150

1151 if (const auto *I0s = dyn_cast(I0))

1152 if (const auto *I1s = dyn_cast(I1))

1156}

1157

1164}

1165

1167 assert(isa(LHS->getType()) && "First arg must be a list");

1168

1169

1170 if (const auto *LHSList = dyn_cast(LHS))

1171 if (const auto *RHSList = dyn_cast(RHS))

1174}

1175

1177 const Init *RHS) const {

1178

1179 const auto *LHSi = dyn_cast_or_null(

1181 const auto *RHSi = dyn_cast_or_null(

1183

1184 if (LHSi && RHSi) {

1185 bool Result;

1186 switch (Opc) {

1187 case EQ:

1188 Result = LHSi->getValue() == RHSi->getValue();

1189 break;

1190 case NE:

1191 Result = LHSi->getValue() != RHSi->getValue();

1192 break;

1193 case LE:

1194 Result = LHSi->getValue() <= RHSi->getValue();

1195 break;

1196 case LT:

1197 Result = LHSi->getValue() < RHSi->getValue();

1198 break;

1199 case GE:

1200 Result = LHSi->getValue() >= RHSi->getValue();

1201 break;

1202 case GT:

1203 Result = LHSi->getValue() > RHSi->getValue();

1204 break;

1205 default:

1207 }

1208 return Result;

1209 }

1210

1211

1212 const auto *LHSs = dyn_cast(LHS);

1213 const auto *RHSs = dyn_cast(RHS);

1214

1215 if (LHSs && RHSs) {

1216 bool Result;

1217 switch (Opc) {

1218 case EQ:

1219 Result = LHSs->getValue() == RHSs->getValue();

1220 break;

1221 case NE:

1222 Result = LHSs->getValue() != RHSs->getValue();

1223 break;

1224 case LE:

1225 Result = LHSs->getValue() <= RHSs->getValue();

1226 break;

1227 case LT:

1228 Result = LHSs->getValue() < RHSs->getValue();

1229 break;

1230 case GE:

1231 Result = LHSs->getValue() >= RHSs->getValue();

1232 break;

1233 case GT:

1234 Result = LHSs->getValue() > RHSs->getValue();

1235 break;

1236 default:

1238 }

1239 return Result;

1240 }

1241

1242

1244 const auto *LHSd = dyn_cast(LHS);

1245 const auto *RHSd = dyn_cast(RHS);

1246 if (LHSd && RHSd)

1247 return (Opc == EQ) ? LHSd == RHSd : LHSd != RHSd;

1248 }

1249

1250 return std::nullopt;

1251}

1252

1253static std::optional

1255

1256 if (const auto *Idx = dyn_cast(Key)) {

1257 int64_t Pos = Idx->getValue();

1258 if (Pos < 0) {

1259

1261 (Twine("index ") + std::to_string(Pos) + Twine(" is negative")).str();

1262 return std::nullopt;

1263 }

1264 if (Pos >= Dag->getNumArgs()) {

1265

1266 Error = (Twine("index ") + std::to_string(Pos) +

1267 " is out of range (dag has " +

1268 std::to_string(Dag->getNumArgs()) + " arguments)")

1269 .str();

1270 return std::nullopt;

1271 }

1272 return Pos;

1273 }

1274 assert(isa(Key));

1275

1276 const auto *Name = dyn_cast(Key);

1277 auto ArgNo = Dag->getArgNo(Name->getValue());

1278 if (!ArgNo) {

1279

1280 Error = (Twine("key '") + Name->getValue() + Twine("' is not found")).str();

1281 return std::nullopt;

1282 }

1283 return *ArgNo;

1284}

1285

1289 const auto *LHSs = dyn_cast(LHS);

1290 const auto *RHSs = dyn_cast(RHS);

1291 if (LHSs && RHSs) {

1292 const auto *LOp = dyn_cast(LHSs->getOperator());

1293 const auto *ROp = dyn_cast(RHSs->getOperator());

1294 if ((!LOp && !isa(LHSs->getOperator())) ||

1295 (!ROp && !isa(RHSs->getOperator())))

1296 break;

1297 if (LOp && ROp && LOp->getDef() != ROp->getDef()) {

1299 LHSs->getAsString() + "' vs. '" + RHSs->getAsString() +

1300 "'");

1301 }

1302 const Init *Op = LOp ? LOp : ROp;

1303 if (Op)

1305

1308 for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) {

1309 Args.push_back(LHSs->getArg(i));

1310 ArgNames.push_back(LHSs->getArgName(i));

1311 }

1312 for (unsigned i = 0, e = RHSs->getNumArgs(); i != e; ++i) {

1313 Args.push_back(RHSs->getArg(i));

1314 ArgNames.push_back(RHSs->getArgName(i));

1315 }

1317 }

1318 break;

1319 }

1321 const auto *LHSs = dyn_cast(LHS);

1322 const auto *RHSs = dyn_cast(RHS);

1323 if (LHSs && RHSs) {

1327 return ListInit::get(Args, LHSs->getElementType());

1328 }

1329 break;

1330 }

1332 const auto *Value = dyn_cast(LHS);

1333 const auto *Size = dyn_cast(RHS);

1337 }

1338 break;

1339 }

1341 const auto *LHSs = dyn_cast(LHS);

1342 const auto *RHSs = dyn_cast(RHS);

1343 if (LHSs && RHSs) {

1345 for (const Init *EltLHS : *LHSs) {

1346 bool Found = false;

1347 for (const Init *EltRHS : *RHSs) {

1348 if (std::optional Result = CompareInit(EQ, EltLHS, EltRHS)) {

1349 if (*Result) {

1350 Found = true;

1351 break;

1352 }

1353 }

1354 }

1355 if (!Found)

1356 Args.push_back(EltLHS);

1357 }

1358 return ListInit::get(Args, LHSs->getElementType());

1359 }

1360 break;

1361 }

1363 const auto *TheList = dyn_cast(LHS);

1364 const auto *Idx = dyn_cast(RHS);

1365 if (!TheList || Idx)

1366 break;

1367 auto i = Idx->getValue();

1368 if (i < 0 || i >= (ssize_t)TheList->size())

1369 break;

1370 return TheList->getElement(i);

1371 }

1373 const auto *TheList = dyn_cast(LHS);

1374 const auto *SliceIdxs = dyn_cast(RHS);

1375 if (!TheList || !SliceIdxs)

1376 break;

1378 Args.reserve(SliceIdxs->size());

1379 for (auto *I : *SliceIdxs) {

1380 auto *II = dyn_cast(I);

1381 if (II)

1382 goto unresolved;

1383 auto i = II->getValue();

1384 if (i < 0 || i >= (ssize_t)TheList->size())

1385 goto unresolved;

1386 Args.push_back(TheList->getElement(i));

1387 }

1388 return ListInit::get(Args, TheList->getElementType());

1389 }

1391 const auto *LHSi = dyn_cast(LHS);

1392 const auto *RHSi = dyn_cast(RHS);

1393 if (!LHSi || !RHSi)

1394 break;

1395

1396 auto Start = LHSi->getValue();

1397 auto End = RHSi->getValue();

1400

1401 if (Start <= End) {

1402

1403 Args.reserve(End - Start + 1);

1404 for (auto i = Start; i <= End; ++i)

1406 } else {

1407

1408 Args.reserve(Start - End + 1);

1409 for (auto i = Start; i >= End; --i)

1411 }

1412 } else if (Start < End) {

1413

1414 Args.reserve(End - Start);

1415 for (auto i = Start; i < End; ++i)

1417 } else {

1418

1419 }

1421 }

1423 const auto *LHSs = dyn_cast(LHS);

1424 const auto *RHSs = dyn_cast(RHS);

1425 if (LHSs && RHSs)

1427 break;

1428 }

1430 const auto *List = dyn_cast(LHS);

1431 const auto *Delim = dyn_cast(RHS);

1432 if (List && Delim) {

1434 if (isa(List->getElementType()))

1436 else

1438 if (Result)

1439 return Result;

1440 }

1441 break;

1442 }

1443 case EQ:

1444 case NE:

1445 case LE:

1446 case LT:

1447 case GE:

1448 case GT: {

1451 break;

1452 }

1454 const auto *Dag = dyn_cast(LHS);

1455 if (Dag && isa<IntInit, StringInit>(RHS)) {

1456 std::string Error;

1458 if (!ArgNo)

1460

1461 assert(*ArgNo < Dag->getNumArgs());

1462

1463 const Init *Arg = Dag->getArg(*ArgNo);

1464 if (const auto *TI = dyn_cast(Arg))

1465 if (!TI->getType()->typeIsConvertibleTo(getType()))

1467 return Arg;

1468 }

1469 break;

1470 }

1472 const auto *Dag = dyn_cast(LHS);

1473 const auto *Idx = dyn_cast(RHS);

1474 if (Dag && Idx) {

1475 int64_t Pos = Idx->getValue();

1476 if (Pos < 0 || Pos >= Dag->getNumArgs()) {

1477

1479 Twine("!getdagname index is out of range 0...") +

1480 std::to_string(Dag->getNumArgs() - 1) + ": " +

1481 std::to_string(Pos));

1482 }

1483 const Init *ArgName = Dag->getArgName(Pos);

1484 if (!ArgName)

1486 return ArgName;

1487 }

1488 break;

1489 }

1491 const auto *Dag = dyn_cast(LHS);

1492 const auto *Op = dyn_cast(RHS);

1493 if (Dag && Op) {

1496 for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {

1497 Args.push_back(Dag->getArg(i));

1498 ArgNames.push_back(Dag->getArgName(i));

1499 }

1501 }

1502 break;

1503 }

1504 case ADD:

1505 case SUB:

1506 case MUL:

1507 case DIV:

1508 case AND:

1509 case OR:

1510 case XOR:

1511 case SHL:

1512 case SRA:

1513 case SRL: {

1514 const auto *LHSi = dyn_cast_or_null(

1516 const auto *RHSi = dyn_cast_or_null(

1518 if (LHSi && RHSi) {

1519 int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();

1520 int64_t Result;

1523 case ADD: Result = LHSv + RHSv; break;

1524 case SUB: Result = LHSv - RHSv; break;

1525 case MUL: Result = LHSv * RHSv; break;

1526 case DIV:

1527 if (RHSv == 0)

1529 "Illegal operation: division by zero");

1530 else if (LHSv == INT64_MIN && RHSv == -1)

1532 "Illegal operation: INT64_MIN / -1");

1533 else

1534 Result = LHSv / RHSv;

1535 break;

1536 case AND: Result = LHSv & RHSv; break;

1537 case OR: Result = LHSv | RHSv; break;

1538 case XOR: Result = LHSv ^ RHSv; break;

1540 case SRA: Result = LHSv >> RHSv; break;

1542 }

1544 }

1545 break;

1546 }

1547 }

1548unresolved:

1549 return this;

1550}

1551

1555

1558

1559

1560

1561

1562

1563

1564

1565 if (const auto *LHSi = dyn_cast_or_null(

1567 if ((Opc == AND && !LHSi->getValue()) ||

1568 (Opc == OR && LHSi->getValue() == -1))

1569 return LHSi;

1570 }

1571 }

1572

1573 if (LHS != lhs || RHS != rhs)

1575 ->Fold(R.getCurrentRecord());

1576 return this;

1577}

1578

1580 std::string Result;

1587 case CONCAT: Result = "!con"; break;

1588 case ADD: Result = "!add"; break;

1589 case SUB: Result = "!sub"; break;

1590 case MUL: Result = "!mul"; break;

1591 case DIV: Result = "!div"; break;

1592 case AND: Result = "!and"; break;

1593 case OR: Result = "!or"; break;

1594 case XOR: Result = "!xor"; break;

1595 case SHL: Result = "!shl"; break;

1596 case SRA: Result = "!sra"; break;

1597 case SRL: Result = "!srl"; break;

1598 case EQ: Result = "!eq"; break;

1599 case NE: Result = "!ne"; break;

1600 case LE: Result = "!le"; break;

1601 case LT: Result = "!lt"; break;

1602 case GE: Result = "!ge"; break;

1603 case GT: Result = "!gt"; break;

1604 case LISTCONCAT: Result = "!listconcat"; break;

1605 case LISTSPLAT: Result = "!listsplat"; break;

1607 Result = "!listremove";

1608 break;

1609 case STRCONCAT: Result = "!strconcat"; break;

1610 case INTERLEAVE: Result = "!interleave"; break;

1611 case SETDAGOP: Result = "!setdagop"; break;

1614 break;

1616 Result = "!getdagname";

1617 break;

1618 }

1620}

1621

1623 const Init *LHS, const Init *MHS, const Init *RHS,

1625 ID.AddInteger(Opcode);

1626 ID.AddPointer(LHS);

1627 ID.AddPointer(MHS);

1628 ID.AddPointer(RHS);

1629 ID.AddPointer(Type);

1630}

1631

1633 const Init *MHS, const Init *RHS,

1637

1639 void *IP = nullptr;

1641 return I;

1642

1645 return I;

1646}

1647

1650}

1651

1653 const Record *CurRec) {

1655 R.set(LHS, MHSe);

1656 return RHS->resolveReferences(R);

1657}

1658

1660 const Init *RHS, const Record *CurRec) {

1661 bool Change = false;

1664 Change = true;

1665

1667 for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {

1669 const Init *NewArg;

1671

1672 if (const auto *Argd = dyn_cast(Arg))

1674 else

1676

1678 if (Arg != NewArg)

1679 Change = true;

1680 }

1681

1682 if (Change)

1684 return MHSd;

1685}

1686

1687

1690 const Record *CurRec) {

1691 if (const auto *MHSd = dyn_cast(MHS))

1693

1694 if (const auto *MHSl = dyn_cast(MHS)) {

1696

1697 for (const Init *&Item : NewList) {

1699 if (NewItem != Item)

1700 Item = NewItem;

1701 }

1702 return ListInit::get(NewList, cast(Type)->getElementType());

1703 }

1704

1705 return nullptr;

1706}

1707

1708

1709

1712 const Record *CurRec) {

1713 if (const auto *MHSl = dyn_cast(MHS)) {

1715

1716 for (const Init *Item : MHSl->getValues()) {

1719 return nullptr;

1720 if (const auto *IncludeInt =

1721 dyn_cast_or_null(Include->convertInitializerTo(

1723 if (IncludeInt->getValue())

1725 } else {

1726 return nullptr;

1727 }

1728 }

1729 return ListInit::get(NewList, cast(Type)->getElementType());

1730 }

1731

1732 return nullptr;

1733}

1734

1739 const auto *LHSd = dyn_cast(LHS);

1740 const auto *LHSv = dyn_cast(LHS);

1741 const auto *LHSs = dyn_cast(LHS);

1742

1743 const auto *MHSd = dyn_cast(MHS);

1744 const auto *MHSv = dyn_cast(MHS);

1745 const auto *MHSs = dyn_cast(MHS);

1746

1747 const auto *RHSd = dyn_cast(RHS);

1748 const auto *RHSv = dyn_cast(RHS);

1749 const auto *RHSs = dyn_cast(RHS);

1750

1751 if (LHSd && MHSd && RHSd) {

1752 const Record *Val = RHSd->getDef();

1753 if (LHSd->getAsString() == RHSd->getAsString())

1754 Val = MHSd->getDef();

1756 }

1757 if (LHSv && MHSv && RHSv) {

1758 std::string Val = std::string(RHSv->getName());

1759 if (LHSv->getAsString() == RHSv->getAsString())

1760 Val = std::string(MHSv->getName());

1762 }

1763 if (LHSs && MHSs && RHSs) {

1764 std::string Val = std::string(RHSs->getValue());

1765

1766 std:🧵:size_type found;

1767 std:🧵:size_type idx = 0;

1768 while (true) {

1769 found = Val.find(std::string(LHSs->getValue()), idx);

1770 if (found == std:🧵:npos)

1771 break;

1772 Val.replace(found, LHSs->getValue().size(),

1773 std::string(MHSs->getValue()));

1774 idx = found + MHSs->getValue().size();

1775 }

1776

1778 }

1779 break;

1780 }

1781

1784 return Result;

1785 break;

1786 }

1787

1790 return Result;

1791 break;

1792 }

1793

1794 case IF: {

1795 if (const auto *LHSi = dyn_cast_or_null(

1797 if (LHSi->getValue())

1798 return MHS;

1799 return RHS;

1800 }

1801 break;

1802 }

1803

1804 case DAG: {

1805 const auto *MHSl = dyn_cast(MHS);

1806 const auto *RHSl = dyn_cast(RHS);

1807 bool MHSok = MHSl || isa(MHS);

1808 bool RHSok = RHSl || isa(RHS);

1809

1810 if (isa(MHS) && isa(RHS))

1811 break;

1812

1813 if (MHSok && RHSok && (!MHSl || !RHSl || MHSl->size() == RHSl->size())) {

1815 unsigned Size = MHSl ? MHSl->size() : RHSl->size();

1816 for (unsigned i = 0; i != Size; ++i) {

1819 if (!isa(Name) && !isa(Name))

1820 return this;

1821 Children.emplace_back(Node, dyn_cast(Name));

1822 }

1823 return DagInit::get(LHS, nullptr, Children);

1824 }

1825 break;

1826 }

1827

1829 const auto *LHSi = dyn_cast(LHS);

1830 const auto *MHSi = dyn_cast(MHS);

1831 const auto *RHSi = dyn_cast(RHS);

1832 if (!LHSi || !MHSi || !RHSi)

1833 break;

1834

1835 auto Start = LHSi->getValue();

1836 auto End = MHSi->getValue();

1837 auto Step = RHSi->getValue();

1838 if (Step == 0)

1840

1842 if (Start < End && Step > 0) {

1843 Args.reserve((End - Start) / Step);

1844 for (auto I = Start; I < End; I += Step)

1846 } else if (Start > End && Step < 0) {

1847 Args.reserve((Start - End) / -Step);

1848 for (auto I = Start; I > End; I += Step)

1850 } else {

1851

1852 }

1854 }

1855

1857 const auto *LHSs = dyn_cast(LHS);

1858 const auto *MHSi = dyn_cast(MHS);

1859 const auto *RHSi = dyn_cast(RHS);

1860 if (LHSs && MHSi && RHSi) {

1861 int64_t StringSize = LHSs->getValue().size();

1862 int64_t Start = MHSi->getValue();

1863 int64_t Length = RHSi->getValue();

1864 if (Start < 0 || Start > StringSize)

1866 Twine("!substr start position is out of range 0...") +

1867 std::to_string(StringSize) + ": " +

1868 std::to_string(Start));

1870 PrintError(CurRec->getLoc(), "!substr length must be nonnegative");

1872 LHSs->getFormat());

1873 }

1874 break;

1875 }

1876

1877 case FIND: {

1878 const auto *LHSs = dyn_cast(LHS);

1879 const auto *MHSs = dyn_cast(MHS);

1880 const auto *RHSi = dyn_cast(RHS);

1881 if (LHSs && MHSs && RHSi) {

1882 int64_t SourceSize = LHSs->getValue().size();

1883 int64_t Start = RHSi->getValue();

1884 if (Start < 0 || Start > SourceSize)

1886 Twine("!find start position is out of range 0...") +

1887 std::to_string(SourceSize) + ": " +

1888 std::to_string(Start));

1889 auto I = LHSs->getValue().find(MHSs->getValue(), Start);

1890 if (I == std:🧵:npos)

1893 }

1894 break;

1895 }

1896

1898 const auto *Dag = dyn_cast(LHS);

1899 if (Dag && isa<IntInit, StringInit>(MHS)) {

1900 std::string Error;

1902 if (!ArgNo)

1904

1905 assert(*ArgNo < Dag->getNumArgs());

1906

1909 Args[*ArgNo] = RHS;

1910 return DagInit::get(Dag->getOperator(), Dag->getName(), Args, Names);

1911 }

1912 break;

1913 }

1914

1916 const auto *Dag = dyn_cast(LHS);

1917 if (Dag && isa<IntInit, StringInit>(MHS)) {

1918 std::string Error;

1920 if (!ArgNo)

1922

1923 assert(*ArgNo < Dag->getNumArgs());

1924

1927 Names[*ArgNo] = dyn_cast(RHS);

1928 return DagInit::get(Dag->getOperator(), Dag->getName(), Args, Names);

1929 }

1930 break;

1931 }

1932 }

1933

1934 return this;

1935}

1936

1939

1941 if (const auto *Value = dyn_cast_or_null(

1943

1944 if (Value->getValue())

1947 }

1948 }

1949

1951 const Init *rhs;

1952

1957 } else {

1959 }

1960

1961 if (LHS != lhs || MHS != mhs || RHS != rhs)

1963 ->Fold(R.getCurrentRecord());

1964 return this;

1965}

1966

1968 std::string Result;

1969 bool UnquotedLHS = false;

1971 case DAG: Result = "!dag"; break;

1972 case FILTER: Result = "!filter"; UnquotedLHS = true; break;

1973 case FOREACH: Result = "!foreach"; UnquotedLHS = true; break;

1974 case IF: Result = "!if"; break;

1976 Result = "!range";

1977 break;

1978 case SUBST: Result = "!subst"; break;

1979 case SUBSTR: Result = "!substr"; break;

1980 case FIND: Result = "!find"; break;

1982 Result = "!setdagarg";

1983 break;

1985 Result = "!setdagname";

1986 break;

1987 }

1988 return (Result + "(" +

1991}

1992

1996 ID.AddPointer(Start);

1997 ID.AddPointer(List);

1998 ID.AddPointer(A);

1999 ID.AddPointer(B);

2000 ID.AddPointer(Expr);

2001 ID.AddPointer(Type);

2002}

2003

2009

2011 void *IP = nullptr;

2013 return I;

2014

2017 return I;

2018}

2019

2022}

2023

2025 if (const auto *LI = dyn_cast(List)) {

2026 const Init *Accum = Start;

2027 for (const Init *Elt : *LI) {

2029 R.set(A, Accum);

2030 R.set(B, Elt);

2032 }

2033 return Accum;

2034 }

2035 return this;

2036}

2037

2045

2046 if (Start == NewStart && List == NewList && Expr == NewExpr)

2047 return this;

2048

2050 ->Fold(R.getCurrentRecord());

2051}

2052

2055}

2056

2061 .str();

2062}

2063

2065 const Init *Expr) {

2067 ID.AddPointer(Expr);

2068}

2069

2071

2074

2076 void *IP = nullptr;

2078 return I;

2079

2082 return I;

2083}

2084

2087}

2088

2090 if (const auto *TI = dyn_cast(Expr)) {

2091

2092 if (TI->getType()->typeIsConvertibleTo(CheckType))

2094

2095 if (isa(CheckType)) {

2096

2097

2098

2099 if (!CheckType->typeIsConvertibleTo(TI->getType()) || isa(Expr))

2101 } else {

2102

2104 }

2105 }

2106 return this;

2107}

2108

2113 return this;

2114}

2115

2118}

2119

2123 .str();

2124}

2125

2127 const Init *Expr) {

2129 ID.AddPointer(Expr);

2130}

2131

2133 const Init *Expr) {

2136

2138 void *IP = nullptr;

2141 return I;

2142

2145 return I;

2146}

2147

2150}

2151

2153 if (const auto *Name = dyn_cast(Expr)) {

2154

2156 if (D) {

2157

2159 D->getDefInit()->getType()->typeIsA(CheckType));

2160 }

2161

2162 if (CurRec) {

2163

2164

2165 auto *Anonymous = dyn_cast(CurRec->getNameInit());

2167 (Anonymous && Name == Anonymous->getNameInit())) {

2168 if (!IsFinal)

2169 return this;

2170

2171

2172

2175 }

2176 }

2177

2178 if (IsFinal)

2180 }

2181 return this;

2182}

2183

2186 if (Expr != NewExpr || R.isFinal())

2187 return get(CheckType, NewExpr)->Fold(R.getCurrentRecord(), R.isFinal());

2188 return this;

2189}

2190

2193}

2194

2196 return (Twine("!exists<") + CheckType->getAsString() + ">(" +

2198 .str();

2199}

2200

2202 if (const auto *RecordType = dyn_cast(getType())) {

2204 if (const RecordVal *Field = Rec->getValue(FieldName))

2205 return Field->getType();

2206 }

2207 }

2208 return nullptr;

2209}

2210

2213 return this;

2214

2215 if (isa(getType()) && isa(Ty) &&

2216 cast(Ty)->getNumBits() == 1)

2218

2219 return nullptr;

2220}

2221

2224 const auto *T = dyn_cast(getType());

2225 if (T) return nullptr;

2226 unsigned NumBits = T->getNumBits();

2227

2229 NewBits.reserve(Bits.size());

2230 for (unsigned Bit : Bits) {

2231 if (Bit >= NumBits)

2232 return nullptr;

2233

2235 }

2237}

2238

2240

2242 return this;

2243

2245 assert(!isa(Converted) ||

2246 cast(Converted)->getType()->typeIsA(Ty));

2247 return Converted;

2248 }

2249

2250 if (getType()->typeIsConvertibleTo(Ty))

2251 return nullptr;

2252

2254}

2255

2259}

2260

2264 if (I)

2266 return I;

2267}

2268

2270 const auto *NameString = cast(getNameInit());

2271 return NameString->getValue();

2272}

2273

2276 return this;

2278}

2279

2281 if (const Init *Val = R.resolve(VarName))

2282 return Val;

2283 return this;

2284}

2285

2289 if (I)

2291 return I;

2292}

2293

2295 return TI->getAsString() + "{" + utostr(Bit) + "}";

2296}

2297

2300 if (TI != I)

2302

2303 return this;

2304}

2305

2306DefInit::DefInit(const Record *D)

2308

2310 if (auto *RRT = dyn_cast(Ty))

2311 if (getType()->typeIsConvertibleTo(RRT))

2312 return this;

2313 return nullptr;

2314}

2315

2318 return RV->getType();

2319 return nullptr;

2320}

2321

2323

2326 ID.AddInteger(Args.size());

2327 ID.AddPointer(Class);

2328

2329 for (const Init *I : Args)

2330 ID.AddPointer(I);

2331}

2332

2333VarDefInit::VarDefInit(SMLoc Loc, const Record *Class, unsigned N)

2335 NumArgs(N) {}

2336

2341

2343 void *IP = nullptr;

2345 return I;

2346

2348 totalSizeToAlloc<const ArgumentInit *>(Args.size()), alignof(VarDefInit));

2350 std::uninitialized_copy(Args.begin(), Args.end(),

2353 return I;

2354}

2355

2358}

2359

2360const DefInit *VarDefInit::instantiate() {

2361 if (Def)

2362 return Def;

2363

2365 auto NewRecOwner = std::make_unique(

2367 Record *NewRec = NewRecOwner.get();

2368

2369

2372

2373

2375

2376

2378

2379

2382

2383 for (const Init *Arg : TArgs) {

2386 }

2387

2388 for (auto *Arg : args()) {

2389 if (Arg->isPositional())

2390 R.set(TArgs[Arg->getIndex()], Arg->getValue());

2391 if (Arg->isNamed())

2392 R.set(Arg->getName(), Arg->getValue());

2393 }

2394

2396

2397

2400

2403

2404

2406 Records.addDef(std::move(NewRecOwner));

2407

2408

2410

2411

2413

2415}

2416

2419 bool Changed = false;

2422

2424 const auto *NewArg = cast(Arg->resolveReferences(UR));

2426 Changed |= NewArg != Arg;

2427 }

2428

2429 if (Changed) {

2432 return const_cast<VarDefInit *>(New)->instantiate();

2433 return New;

2434 }

2435 return this;

2436}

2437

2439 if (Def)

2440 return Def;

2441

2443 for (const Init *Arg : args())

2444 Arg->resolveReferences(R);

2445

2446 if (!R.foundUnresolved())

2447 return const_cast<VarDefInit *>(this)->instantiate();

2448 return this;

2449}

2450

2453 const char *sep = "";

2454 for (const Init *Arg : args()) {

2455 Result += sep;

2456 sep = ", ";

2457 Result += Arg->getAsString();

2458 }

2459 return Result + ">";

2460}

2461

2465 if (I)

2467 return I;

2468}

2469

2472 return this;

2474}

2475

2478 if (NewRec != Rec)

2479 return FieldInit::get(NewRec, FieldName)->Fold(R.getCurrentRecord());

2480 return this;

2481}

2482

2484 if (const auto *DI = dyn_cast(Rec)) {

2485 const Record *Def = DI->getDef();

2486 if (Def == CurRec)

2488 Twine("Attempting to access field '") +

2490 Rec->getAsString() + "' is a forbidden self-reference");

2491 const Init *FieldVal = Def->getValue(FieldName)->getValue();

2493 return FieldVal;

2494 }

2495 return this;

2496}

2497

2499 if (const auto *DI = dyn_cast(Rec)) {

2500 const Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();

2502 }

2503 return false;

2504}

2505

2509 const RecTy *ValType) {

2511 "Number of conditions and values must match!");

2512 ID.AddPointer(ValType);

2515

2516 while (Case != CondRange.end()) {

2517 ID.AddPointer(*Case++);

2518 ID.AddPointer(*Val++);

2519 }

2520}

2521

2524 ID, ArrayRef(getTrailingObjects<const Init *>(), NumConds),

2525 ArrayRef(getTrailingObjects<const Init *>() + NumConds, NumConds),

2526 ValType);

2527}

2528

2531 const RecTy *Ty) {

2533 "Number of conditions and values must match!");

2534

2537

2539 void *IP = nullptr;

2541 return I;

2542

2544 totalSizeToAlloc<const Init *>(2 * CondRange.size()), alignof(BitsInit));

2546

2547 std::uninitialized_copy(CondRange.begin(), CondRange.end(),

2548 I->getTrailingObjects<const Init *>());

2549 std::uninitialized_copy(ValRange.begin(), ValRange.end(),

2550 I->getTrailingObjects<const Init *>() +

2551 CondRange.size());

2553 return I;

2554}

2555

2558 bool Changed = false;

2562 Changed |= NewCase != Case;

2563 }

2564

2569 Changed |= NewVal != Val;

2570 }

2571

2572 if (Changed)

2574 getValType()))->Fold(R.getCurrentRecord());

2575

2576 return this;

2577}

2578

2581 for (unsigned i = 0; i < NumConds; ++i) {

2584

2585 if (const auto *CondI = dyn_cast_or_null(

2587 if (CondI->getValue())

2589 } else {

2590 return this;

2591 }

2592 }

2593

2596 " does not have any true condition in:" +

2597 this->getAsString());

2598 return nullptr;

2599}

2600

2603 if (!Case->isConcrete())

2604 return false;

2605

2607 if (!Val->isConcrete())

2608 return false;

2609

2610 return true;

2611}

2612

2615 if (!Case->isComplete())

2616 return false;

2617

2619 if (!Val->isConcrete())

2620 return false;

2621

2622 return true;

2623}

2624

2626 std::string Result = "!cond(";

2627 for (unsigned i = 0; i < getNumConds(); i++) {

2631 Result += ", ";

2632 }

2633 return Result + ")";

2634}

2635

2638}

2639

2644 ID.AddPointer(V);

2645 ID.AddPointer(VN);

2646

2649 while (Arg != ArgRange.end()) {

2650 assert(Name != NameRange.end() && "Arg name underflow!");

2651 ID.AddPointer(*Arg++);

2652 ID.AddPointer(*Name++);

2653 }

2654 assert(Name == NameRange.end() && "Arg name overflow!");

2655}

2656

2663

2665 void *IP = nullptr;

2667 return I;

2668

2669 void *Mem =

2670 RK.Allocator.Allocate(totalSizeToAlloc<const Init *, const StringInit *>(

2671 ArgRange.size(), NameRange.size()),

2674 std::uninitialized_copy(ArgRange.begin(), ArgRange.end(),

2675 I->getTrailingObjects<const Init *>());

2676 std::uninitialized_copy(NameRange.begin(), NameRange.end(),

2677 I->getTrailingObjects<const StringInit *>());

2679 return I;

2680}

2681

2684 ArrayRef<std::pair<const Init *, const StringInit *>> args) {

2687

2688 for (const auto &Arg : args) {

2689 Args.push_back(Arg.first);

2691 }

2692

2694}

2695

2698 ID, Val, ValName, ArrayRef(getTrailingObjects<const Init *>(), NumArgs),

2699 ArrayRef(getTrailingObjects<const StringInit *>(), NumArgNames));

2700}

2701

2703 if (const auto *DefI = dyn_cast(Val))

2704 return DefI->getDef();

2706 return nullptr;

2707}

2708

2710 for (unsigned i = 0, e = getNumArgs(); i < e; ++i) {

2713 return i;

2714 }

2715 return std::nullopt;

2716}

2717

2721 bool ArgsChanged = false;

2725 ArgsChanged |= NewArg != Arg;

2726 }

2727

2729 if (Op != Val || ArgsChanged)

2731

2732 return this;

2733}

2734

2737 return false;

2739 if (!Elt->isConcrete())

2740 return false;

2741 }

2742 return true;

2743}

2744

2746 std::string Result = "(" + Val->getAsString();

2747 if (ValName)

2752 for (unsigned i = 1, e = getNumArgs(); i != e; ++i) {

2755 }

2756 }

2757 return Result + ")";

2758}

2759

2760

2761

2762

2763

2765 : Name(N), TyAndKind(T, K) {

2767 assert(Value && "Cannot create unset value for current type!");

2768}

2769

2770

2771

2773 : Name(N), Loc(Loc), TyAndKind(T, K) {

2775 assert(Value && "Cannot create unset value for current type!");

2776}

2777

2779 return cast(getNameInit())->getValue();

2780}

2781

2784 if (const auto *StrInit = dyn_cast(Value)) {

2785 if (StrInit->hasCodeFormat())

2786 return "code";

2787 else

2788 return "string";

2789 } else {

2790 return "string";

2791 }

2792 } else {

2793 return TyAndKind.getPointer()->getAsString();

2794 }

2795}

2796

2798 if (V) {

2803 if (const auto *BTy = dyn_cast(getType())) {

2804 if (!isa(Value)) {

2806 Bits.reserve(BTy->getNumBits());

2807 for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I)

2808 Bits.push_back(Value->getBit(I));

2810 }

2811 }

2812 }

2813 return Value == nullptr;

2814 }

2815 Value = nullptr;

2816 return false;

2817}

2818

2819

2820

2822 Loc = NewLoc;

2823 if (V) {

2828 if (const auto *BTy = dyn_cast(getType())) {

2829 if (!isa(Value)) {

2831 Bits.reserve(BTy->getNumBits());

2832 for (unsigned I = 0, E = BTy->getNumBits(); I < E; ++I)

2833 Bits.push_back(Value->getBit(I));

2835 }

2836 }

2837 }

2838 return Value == nullptr;

2839 }

2840 Value = nullptr;

2841 return false;

2842}

2843

2844#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

2847#endif

2848

2852

2855

2856 if (PrintSem) OS << ";\n";

2857}

2858

2860 assert(Locs.size() == 1);

2861 ForwardDeclarationLocs.push_back(Locs.front());

2862

2863 Locs.clear();

2864 Locs.push_back(Loc);

2865}

2866

2867void Record::checkName() {

2868

2869 const auto *TypedName = cast(Name);

2870 if (!isa(TypedName->getType()))

2872 "' is not a string!");

2873}

2874

2879}

2880

2882 if (!CorrespondingDefInit) {

2883 CorrespondingDefInit =

2885 }

2886 return CorrespondingDefInit;

2887}

2888

2891}

2892

2894 Name = NewName;

2895 checkName();

2896

2897

2898

2899

2900

2901

2902

2903

2904

2905

2906

2907}

2908

2909

2910

2911

2912

2913

2916

2917 for (int I = SCs.size() - 1; I >= 0; --I) {

2918 const Record *SC = SCs[I].first;

2919 if (SC == Superclass)

2920 return true;

2921 I -= SC->getSuperClasses().size();

2922 }

2923

2924 return false;

2925}

2926

2930

2931 while (!SCs.empty()) {

2932 const Record *SC = SCs.back().first;

2933 SCs = SCs.drop_back(1 + SC->getSuperClasses().size());

2935 }

2936}

2937

2941 if (NewName != OldName) {

2942

2944 }

2945

2946

2948 if (SkipVal == &Value)

2949 continue;

2950 if (const Init *V = Value.getValue()) {

2951 const Init *VR = V->resolveReferences(R);

2952 if (Value.setValue(VR)) {

2953 std::string Type;

2954 if (const auto *VRT = dyn_cast(VR))

2956 (Twine("of type '") + VRT->getType()->getAsString() + "' ").str();

2959 Twine("Invalid value ") + Type + "found when setting field '" +

2960 Value.getNameInitAsString() + "' of type '" +

2963 "\n");

2964 }

2965 }

2966 }

2967

2968

2969 for (auto &Assertion : Assertions) {

2970 const Init *Value = Assertion.Condition->resolveReferences(R);

2971 Assertion.Condition = Value;

2972 Value = Assertion.Message->resolveReferences(R);

2973 Assertion.Message = Value;

2974 }

2975

2976 for (auto &Dump : Dumps) {

2977 const Init *Value = Dump.Message->resolveReferences(R);

2978 Dump.Message = Value;

2979 }

2980}

2981

2984 R.setName(NewName);

2985 R.setFinal(true);

2987}

2988

2989#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

2991#endif

2992

2994 OS << R.getNameInitAsString();

2995

2997 if (!TArgs.empty()) {

2998 OS << "<";

2999 bool NeedComma = false;

3000 for (const Init *TA : TArgs) {

3001 if (NeedComma) OS << ", ";

3002 NeedComma = true;

3003 const RecordVal *RV = R.getValue(TA);

3004 assert(RV && "Template argument record not found??");

3006 }

3007 OS << ">";

3008 }

3009

3010 OS << " {";

3012 if (!SC.empty()) {

3013 OS << "\t//";

3014 for (const auto &[SC, _] : SC)

3015 OS << " " << SC->getNameInitAsString();

3016 }

3017 OS << "\n";

3018

3019 for (const RecordVal &Val : R.getValues())

3020 if (Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))

3021 OS << Val;

3022 for (const RecordVal &Val : R.getValues())

3023 if (!Val.isNonconcreteOK() && !R.isTemplateArg(Val.getNameInit()))

3024 OS << Val;

3025

3026 return OS << "}\n";

3027}

3028

3031 if (!R)

3033 "' does not have a field named `" + FieldName + "'!\n");

3034 return R->getLoc();

3035}

3036

3039 if (!R || !R->getValue())

3041 "' does not have a field named `" + FieldName + "'!\n");

3042 return R->getValue();

3043}

3044

3047 if (!S)

3049 "' does not have a field named `" + FieldName + "'!\n");

3050 return *S;

3051}

3052

3053std::optional

3056 if (!R || !R->getValue())

3057 return std::nullopt;

3058 if (isa(R->getValue()))

3059 return std::nullopt;

3060

3061 if (const auto *SI = dyn_cast(R->getValue()))

3062 return SI->getValue();

3063

3065 "Record `" + getName() + "', ` field `" + FieldName +

3066 "' exists but does not have a string initializer!");

3067}

3068

3071 if (!R || !R->getValue())

3073 "' does not have a field named `" + FieldName + "'!\n");

3074

3075 if (const auto *BI = dyn_cast(R->getValue()))

3076 return BI;

3078 "' exists but does not have a bits value");

3079}

3080

3083 if (!R || !R->getValue())

3085 "' does not have a field named `" + FieldName + "'!\n");

3086

3087 if (const auto *LI = dyn_cast(R->getValue()))

3088 return LI;

3090 "' exists but does not have a list value");

3091}

3092

3093std::vector<const Record *>

3096 std::vector<const Record *> Defs;

3097 for (const Init *I : List->getValues()) {

3098 if (const auto *DI = dyn_cast(I))

3099 Defs.push_back(DI->getDef());

3100 else

3102 FieldName +

3103 "' list is not entirely DefInit!");

3104 }

3105 return Defs;

3106}

3107

3110 if (!R || !R->getValue())

3112 "' does not have a field named `" + FieldName + "'!\n");

3113

3114 if (const auto *II = dyn_cast(R->getValue()))

3115 return II->getValue();

3117 FieldName +

3118 "' exists but does not have an int value: " +

3119 R->getValue()->getAsString());

3120}

3121

3122std::vector<int64_t>

3125 std::vector<int64_t> Ints;

3126 for (const Init *I : List->getValues()) {

3127 if (const auto *II = dyn_cast(I))

3128 Ints.push_back(II->getValue());

3129 else

3131 Twine("Record `") + getName() + "', field `" + FieldName +

3132 "' exists but does not have a list of ints value: " +

3133 I->getAsString());

3134 }

3135 return Ints;

3136}

3137

3138std::vector

3141 std::vector Strings;

3142 for (const Init *I : List->getValues()) {

3143 if (const auto *SI = dyn_cast(I))

3144 Strings.push_back(SI->getValue());

3145 else

3147 Twine("Record `") + getName() + "', field `" + FieldName +

3148 "' exists but does not have a list of strings value: " +

3149 I->getAsString());

3150 }

3151 return Strings;

3152}

3153

3156 if (!R || !R->getValue())

3158 "' does not have a field named `" + FieldName + "'!\n");

3159

3160 if (const auto *DI = dyn_cast(R->getValue()))

3161 return DI->getDef();

3163 FieldName + "' does not have a def initializer!");

3164}

3165

3168 if (!R || !R->getValue())

3170 "' does not have a field named `" + FieldName + "'!\n");

3171

3172 if (const auto *DI = dyn_cast(R->getValue()))

3173 return DI->getDef();

3174 if (isa(R->getValue()))

3175 return nullptr;

3177 FieldName + "' does not have either a def initializer or '?'!");

3178}

3179

3182 if (!R || !R->getValue())

3184 "' does not have a field named `" + FieldName + "'!\n");

3185

3186 if (const auto *BI = dyn_cast(R->getValue()))

3187 return BI->getValue();

3189 FieldName + "' does not have a bit initializer!");

3190}

3191

3194 if (!R || !R->getValue())

3196 "' does not have a field named `" + FieldName.str() + "'!\n");

3197

3198 if (isa(R->getValue())) {

3199 Unset = true;

3200 return false;

3201 }

3202 Unset = false;

3203 if (const auto *BI = dyn_cast(R->getValue()))

3204 return BI->getValue();

3206 FieldName + "' does not have a bit initializer!");

3207}

3208

3211 if (!R || !R->getValue())

3213 "' does not have a field named `" + FieldName + "'!\n");

3214

3215 if (const auto *DI = dyn_cast(R->getValue()))

3216 return DI;

3218 FieldName + "' does not have a dag initializer!");

3219}

3220

3221

3222

3223

3224

3227 R.setFinal(true);

3228

3229 bool AnyFailed = false;

3233 AnyFailed |= CheckAssert(Assertion.Loc, Condition, Message);

3234 }

3235

3236 if (!AnyFailed)

3237 return;

3238

3239

3240

3241 PrintError(this, "assertion failed in this record");

3242}

3243

3246 R.setFinal(true);

3247

3248 for (const auto &Dump : getDumps()) {

3249 const Init *Message = Dump.Message->resolveReferences(R);

3251 }

3252}

3253

3254

3260 "unused template argument: " + Twine(Arg->getName()));

3261 }

3262}

3263

3265 : Impl(std::make_unique<detail::RecordKeeperImpl>(*this)),

3267

3269

3270#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

3272#endif

3273

3275 OS << "------------- Classes -----------------\n";

3277 OS << "class " << *C.second;

3278

3279 OS << "------------- Defs -----------------\n";

3280 for (const auto &D : RK.getDefs())

3281 OS << "def " << *D.second;

3282 return OS;

3283}

3284

3285

3286

3289}

3290

3293

3294

3295 auto [Iter, Inserted] = Cache.try_emplace(ClassName.str());

3296 if (Inserted)

3298 return Iter->second;

3299}

3300

3301std::vector<const Record *>

3304 std::vector<const Record *> Defs;

3305

3306 assert(ClassNames.size() > 0 && "At least one class must be passed.");

3307 for (const auto &ClassName : ClassNames) {

3309 if (!Class)

3310 PrintFatalError("The class '" + ClassName + "' is not defined\n");

3312 }

3313

3314 for (const auto &OneDef : getDefs()) {

3315 if (all_of(ClassRecs, [&OneDef](const Record *Class) {

3316 return OneDef.second->isSubClassOf(Class);

3317 }))

3318 Defs.push_back(OneDef.second.get());

3319 }

3321 return Defs;

3322}

3323

3328 return Cache[""];

3329}

3330

3332 Impl->dumpAllocationStats(OS);

3333}

3334

3336 auto It = Map.find(VarName);

3337 if (It == Map.end())

3338 return nullptr;

3339

3340 const Init *I = It->second.V;

3341

3342 if (!It->second.Resolved && Map.size() > 1) {

3343

3344

3345 Map.erase(It);

3346 I = I->resolveReferences(*this);

3347 Map[VarName] = {I, true};

3348 }

3349

3350 return I;

3351}

3352

3354 const Init *Val = Cache.lookup(VarName);

3355 if (Val)

3356 return Val;

3357

3359 return nullptr;

3360

3362 if (!isa(RV->getValue())) {

3363 Val = RV->getValue();

3364 Stack.push_back(VarName);

3366 Stack.pop_back();

3367 }

3368 } else if (Name && VarName == getCurrentRecord()->getNameInit()) {

3369 Stack.push_back(VarName);

3371 Stack.pop_back();

3372 }

3373

3374 Cache[VarName] = Val;

3375 return Val;

3376}

3377

3379 const Init *I = nullptr;

3380

3381 if (R) {

3383 if (I && !FoundUnresolved) {

3384

3385

3386

3388 I->resolveReferences(Sub);

3389 FoundUnresolved |= Sub.FoundUnresolved;

3390 }

3391 }

3392

3393 if (I)

3394 FoundUnresolved = true;

3395 return I;

3396}

3397

3399 if (VarName == VarNameToTrack)

3400 Found = true;

3401 return nullptr;

3402}

This file defines the StringMap class.

This file defines the BumpPtrAllocator interface.

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

This file defines the DenseMap class.

This file defines a hash set that can be used to remove duplication of nodes in a graph.

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

uint64_t IntrinsicInst * II

const SmallVectorImpl< MachineOperand > & Cond

static void ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef< const Init * > Range)

static bool canFitInBitfield(int64_t Value, unsigned NumBits)

static std::optional< unsigned > getDagArgNoByKey(const DagInit *Dag, const Init *Key, std::string &Error)

static void ProfileBinOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *LHS, const Init *RHS, const RecTy *Type)

static const StringInit * ConcatStringInits(const StringInit *I0, const StringInit *I1)

static void ProfileTernOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type)

static void ProfileExistsOpInit(FoldingSetNodeID &ID, const RecTy *CheckType, const Init *Expr)

static const ListInit * ConcatListInits(const ListInit *LHS, const ListInit *RHS)

static void ProfileCondOpInit(FoldingSetNodeID &ID, ArrayRef< const Init * > CondRange, ArrayRef< const Init * > ValRange, const RecTy *ValType)

static const StringInit * interleaveStringList(const ListInit *List, const StringInit *Delim)

static void ProfileFoldOpInit(FoldingSetNodeID &ID, const Init *Start, const Init *List, const Init *A, const Init *B, const Init *Expr, const RecTy *Type)

static void ProfileUnOpInit(FoldingSetNodeID &ID, unsigned Opcode, const Init *Op, const RecTy *Type)

static void ProfileArgumentInit(FoldingSetNodeID &ID, const Init *Value, ArgAuxType Aux)

static const Init * ForeachDagApply(const Init *LHS, const DagInit *MHSd, const Init *RHS, const Record *CurRec)

static const Init * FilterHelper(const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type, const Record *CurRec)

static const Init * ItemApply(const Init *LHS, const Init *MHSe, const Init *RHS, const Record *CurRec)

static const RecordRecTy * resolveRecordTypes(const RecordRecTy *T1, const RecordRecTy *T2)

static void ProfileRecordRecTy(FoldingSetNodeID &ID, ArrayRef< const Record * > Classes)

static const Init * ForeachHelper(const Init *LHS, const Init *MHS, const Init *RHS, const RecTy *Type, const Record *CurRec)

static void ProfileDagInit(FoldingSetNodeID &ID, const Init *V, const StringInit *VN, ArrayRef< const Init * > ArgRange, ArrayRef< const StringInit * > NameRange)

static void ProfileVarDefInit(FoldingSetNodeID &ID, const Record *Class, ArrayRef< const ArgumentInit * > Args)

static void ProfileIsAOpInit(FoldingSetNodeID &ID, const RecTy *CheckType, const Init *Expr)

static const StringInit * interleaveIntList(const ListInit *List, const StringInit *Delim)

static void ProfileListInit(FoldingSetNodeID &ID, ArrayRef< const Init * > Range, const RecTy *EltTy)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

static LLVM_ATTRIBUTE_ALWAYS_INLINE bool CheckType(MVT::SimpleValueType VT, SDValue N, const TargetLowering *TLI, const DataLayout &DL)

This file defines the SmallString class.

This file defines the SmallVector class.

static SymbolRef::Type getType(const Symbol *Sym)

static constexpr int Concat[]

"anonymous_n" - Represent an anonymous record name

static AnonymousNameInit * get(RecordKeeper &RK, unsigned)

const StringInit * getNameInit() const

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

std::string getAsString() const override

Convert this value to a literal form.

const ArgumentInit * cloneWithValue(const Init *Value) const

void Profile(FoldingSetNodeID &ID) const

static const ArgumentInit * get(const Init *Value, ArgAuxType Aux)

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

const T & back() const

back - Get the last element.

size_t size() const

size - Get the array size.

ArrayRef< T > drop_back(size_t N=1) const

Drop the last N elements of the array.

bool empty() const

empty - Check if the array is empty.

!op (X, Y) - Combine two inits.

static const BinOpInit * get(BinaryOp opc, const Init *lhs, const Init *rhs, const RecTy *Type)

void Profile(FoldingSetNodeID &ID) const

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

static const Init * getStrConcat(const Init *lhs, const Init *rhs)

std::string getAsString() const override

Convert this value to a literal form.

BinaryOp getOpcode() const

const Init * getRHS() const

std::optional< bool > CompareInit(unsigned Opc, const Init *LHS, const Init *RHS) const

const Init * getLHS() const

static const Init * getListConcat(const TypedInit *lhs, const Init *rhs)

const Init * Fold(const Record *CurRec) const

'true'/'false' - Represent a concrete initializer for a bit.

static BitInit * get(RecordKeeper &RK, bool V)

const Init * convertInitializerTo(const RecTy *Ty) const override

Convert to a value whose type is Ty, or return null if this is not possible.

'bit' - Represent a single bit

static const BitRecTy * get(RecordKeeper &RK)

bool typeIsConvertibleTo(const RecTy *RHS) const override

Return true if all values of 'this' type can be converted to the specified type.

'{ a, b, c }' - Represents an initializer for a BitsRecTy value.

void Profile(FoldingSetNodeID &ID) const

std::string getAsString() const override

Convert this value to a literal form.

unsigned getNumBits() const

std::optional< int64_t > convertInitializerToInt() const

const Init * getBit(unsigned Bit) const override

Get the Init value of the specified bit.

const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override

This function is used to implement the bit range selection operator.

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

const Init * convertInitializerTo(const RecTy *Ty) const override

Convert to a value whose type is Ty, or return null if this is not possible.

static BitsInit * get(RecordKeeper &RK, ArrayRef< const Init * > Range)

bool isConcrete() const override

Is this a concrete and fully resolved value without any references or stuck operations?...

'bits' - Represent a fixed number of bits

bool typeIsConvertibleTo(const RecTy *RHS) const override

Return true if all values of 'this' type can be converted to the specified type.

static const BitsRecTy * get(RecordKeeper &RK, unsigned Sz)

std::string getAsString() const override

Allocate memory in an ever growing pool, as if by bump-pointer.

LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)

Allocate space at the specified alignment.

!cond(condition_1: value1, ... , condition_n: value) Selects the first value for which condition is t...

static const CondOpInit * get(ArrayRef< const Init * > C, ArrayRef< const Init * > V, const RecTy *Type)

const Init * Fold(const Record *CurRec) const

ArrayRef< const Init * > getVals() const

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

const Init * getBit(unsigned Bit) const override

Get the Init value of the specified bit.

const Init * getCond(unsigned Num) const

bool isConcrete() const override

Is this a concrete and fully resolved value without any references or stuck operations?...

void Profile(FoldingSetNodeID &ID) const

std::string getAsString() const override

Convert this value to a literal form.

unsigned getNumConds() const

const RecTy * getValType() const

bool isComplete() const override

Is this a complete value with no unset (uninitialized) subvalues?

const Init * getVal(unsigned Num) const

ArrayRef< const Init * > getConds() const

This class represents an Operation in the Expression.

(v a, b) - Represent a DAG tree value.

bool isConcrete() const override

Is this a concrete and fully resolved value without any references or stuck operations?...

unsigned getNumArgs() const

const StringInit * getArgName(unsigned Num) const

std::optional< unsigned > getArgNo(StringRef Name) const

This method looks up the specified argument name and returns its argument number or std::nullopt if t...

void Profile(FoldingSetNodeID &ID) const

const Init * getOperator() const

static const DagInit * get(const Init *V, const StringInit *VN, ArrayRef< const Init * > ArgRange, ArrayRef< const StringInit * > NameRange)

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

ArrayRef< const StringInit * > getArgNames() const

const Record * getOperatorAsDef(ArrayRef< SMLoc > Loc) const

const Init * getArg(unsigned Num) const

ArrayRef< const Init * > getArgs() const

std::string getAsString() const override

Convert this value to a literal form.

'dag' - Represent a dag fragment

std::string getAsString() const override

static const DagRecTy * get(RecordKeeper &RK)

AL - Represent a reference to a 'def' in the description.

std::string getAsString() const override

Convert this value to a literal form.

const RecTy * getFieldType(const StringInit *FieldName) const override

This method is used to implement the FieldInit class.

const Init * convertInitializerTo(const RecTy *Ty) const override

Convert to a value whose type is Ty, or return null if this is not possible.

Lightweight error class with error context and mandatory checking.

!exists(expr) - Dynamically determine if a record of type named expr exists.

void Profile(FoldingSetNodeID &ID) const

static const ExistsOpInit * get(const RecTy *CheckType, const Init *Expr)

std::string getAsString() const override

Convert this value to a literal form.

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

const Init * Fold(const Record *CurRec, bool IsFinal=false) const

const Init * getBit(unsigned Bit) const override

Get the Init value of the specified bit.

X.Y - Represent a reference to a subfield of a variable.

const Init * Fold(const Record *CurRec) const

const Init * getBit(unsigned Bit) const override

Get the Init value of the specified bit.

static const FieldInit * get(const Init *R, const StringInit *FN)

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

bool isConcrete() const override

Is this a concrete and fully resolved value without any references or stuck operations?...

!foldl (a, b, expr, start, lst) - Fold over a list.

const Init * Fold(const Record *CurRec) const

std::string getAsString() const override

Convert this value to a literal form.

static const FoldOpInit * get(const Init *Start, const Init *List, const Init *A, const Init *B, const Init *Expr, const RecTy *Type)

const Init * getBit(unsigned Bit) const override

Get the Init value of the specified bit.

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

void Profile(FoldingSetNodeID &ID) const

void InsertNode(T *N, void *InsertPos)

InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...

T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)

FindNodeOrInsertPos - Look up the node specified by ID.

FoldingSetNodeID - This class is used to gather all the unique data bits of a node.

FoldingSet - This template class is used to instantiate a specialized implementation of the folding s...

const Init * resolve(const Init *VarName) override

Return the initializer for the given variable name (should normally be a StringInit),...

virtual const Init * resolveReferences(Resolver &R) const

This function is used by classes that refer to other variables which may not be defined at the time t...

virtual std::string getAsUnquotedString() const

Convert this value to a literal form, without adding quotes around a string.

void dump() const

Debugging method that may be called through a debugger; just invokes print on stderr.

void print(raw_ostream &OS) const

Print this value.

virtual std::string getAsString() const =0

Convert this value to a literal form.

virtual bool isConcrete() const

Is this a concrete and fully resolved value without any references or stuck operations?...

virtual bool isComplete() const

Is this a complete value with no unset (uninitialized) subvalues?

virtual const Init * getBit(unsigned Bit) const =0

Get the Init value of the specified bit.

virtual const Init * convertInitializerTo(const RecTy *Ty) const =0

Convert to a value whose type is Ty, or return null if this is not possible.

RecordKeeper & getRecordKeeper() const

Get the record keeper that initialized this Init.

'7' - Represent an initialization by a literal integer value.

static IntInit * get(RecordKeeper &RK, int64_t V)

const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override

This function is used to implement the bit range selection operator.

std::string getAsString() const override

Convert this value to a literal form.

const Init * convertInitializerTo(const RecTy *Ty) const override

Convert to a value whose type is Ty, or return null if this is not possible.

'int' - Represent an integer value of no particular size

static const IntRecTy * get(RecordKeeper &RK)

bool typeIsConvertibleTo(const RecTy *RHS) const override

Return true if all values of 'this' type can be converted to the specified type.

!isa(expr) - Dynamically determine the type of an expression.

static const IsAOpInit * get(const RecTy *CheckType, const Init *Expr)

void Profile(FoldingSetNodeID &ID) const

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

std::string getAsString() const override

Convert this value to a literal form.

const Init * getBit(unsigned Bit) const override

Get the Init value of the specified bit.

const Init * Fold() const

[AL, AH, CL] - Represent a list of defs

std::string getAsString() const override

Convert this value to a literal form.

const RecTy * getElementType() const

const Record * getElementAsRecord(unsigned i) const

static const ListInit * get(ArrayRef< const Init * > Range, const RecTy *EltTy)

bool isConcrete() const override

Is this a concrete and fully resolved value without any references or stuck operations?...

bool isComplete() const override

Is this a complete value with no unset (uninitialized) subvalues?

const Init * resolveReferences(Resolver &R) const override

This method is used by classes that refer to other variables which may not be defined at the time the...

const Init * getElement(unsigned i) const

const Init * convertInitializerTo(const RecTy *Ty) const override

Convert to a value whose type is Ty, or return null if this is not possible.

void Profile(FoldingSetNodeID &ID) const

ArrayRef< const Init * > getValues() const

'list' - Represent a list of element values, all of which must be of the specified type.

const RecTy * getElementType() const

bool typeIsA(const RecTy *RHS) const override

Return true if 'this' type is equal to or a subtype of RHS.

std::string getAsString() const override

bool typeIsConvertibleTo(const RecTy *RHS) const override

Return true if all values of 'this' type can be converted to the specified type.

Resolve arbitrary mappings.

const Init * resolve(const Init *VarName) override

Return the initializer for the given variable name (should normally be a StringInit),...

const Init * getBit(unsigned Bit) const final

Get the Init value of the specified bit.

RecordKeeper & getRecordKeeper() const

Return the RecordKeeper that uniqued this Type.

virtual bool typeIsA(const RecTy *RHS) const

Return true if 'this' type is equal to or a subtype of RHS.

virtual bool typeIsConvertibleTo(const RecTy *RHS) const

Return true if all values of 'this' type can be converted to the specified type.

RecTyKind

Subclass discriminator (for dyn_cast<> et al.)

virtual std::string getAsString() const =0

const ListRecTy * getListTy() const

Returns the type representing list.

void print(raw_ostream &OS) const

const Record * getClass(StringRef Name) const

Get the class with the specified name.

const RecordMap & getClasses() const

Get the map of classes.

const Init * getNewAnonymousName()

GetNewAnonymousName - Generate a unique anonymous name that can be used as an identifier.

const RecordMap & getDefs() const

Get the map of records (defs).

detail::RecordKeeperImpl & getImpl()

Return the internal implementation of the RecordKeeper.

void dumpAllocationStats(raw_ostream &OS) const

ArrayRef< const Record * > getAllDerivedDefinitionsIfDefined(StringRef ClassName) const

Get all the concrete records that inherit from specified class, if the class is defined.

const Record * getDef(StringRef Name) const

Get the concrete record with the specified name.

ArrayRef< const Record * > getAllDerivedDefinitions(StringRef ClassName) const

Get all the concrete records that inherit from the one specified class.

'[classname]' - Type of record values that have zero or more superclasses.

bool typeIsConvertibleTo(const RecTy *RHS) const override

Return true if all values of 'this' type can be converted to the specified type.

bool isSubClassOf(const Record *Class) const

ArrayRef< const Record * > getClasses() const

void Profile(FoldingSetNodeID &ID) const

std::string getAsString() const override

bool typeIsA(const RecTy *RHS) const override

Return true if 'this' type is equal to or a subtype of RHS.

static const RecordRecTy * get(RecordKeeper &RK, ArrayRef< const Record * > Classes)

Get the record type with the given non-redundant list of superclasses.

Resolve all variables from a record except for unset variables.

const Init * resolve(const Init *VarName) override

Return the initializer for the given variable name (should normally be a StringInit),...

This class represents a field in a record, including its name, type, value, and source location.

std::string getNameInitAsString() const

Get the name of the field as a std::string.

bool isNonconcreteOK() const

Is this a field where nonconcrete values are okay?

bool setValue(const Init *V)

Set the value of the field from an Init.

RecordKeeper & getRecordKeeper() const

Get the record keeper used to unique this value.

const SMLoc & getLoc() const

Get the source location of the point where the field was defined.

const Init * getValue() const

Get the value of the field as an Init.

StringRef getName() const

Get the name of the field as a StringRef.

void print(raw_ostream &OS, bool PrintSem=true) const

Print the value to an output stream, possibly with a semicolon.

RecordVal(const Init *N, const RecTy *T, FieldKind K)

const Init * getNameInit() const

Get the name of the field as an Init.

std::string getPrintType() const

Get the type of the field for printing purposes.

const RecTy * getType() const

Get the type of the field value as a RecTy.

std::vector< int64_t > getValueAsListOfInts(StringRef FieldName) const

This method looks up the specified field and returns its value as a vector of integers,...

const RecordRecTy * getType() const

const Init * getValueInit(StringRef FieldName) const

Return the initializer for a value with the specified name, or throw an exception if the field does n...

bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const

This method looks up the specified field and returns its value as a bit.

bool getValueAsBit(StringRef FieldName) const

This method looks up the specified field and returns its value as a bit, throwing an exception if the...

ArrayRef< std::pair< const Record *, SMRange > > getSuperClasses() const

static unsigned getNewUID(RecordKeeper &RK)

ArrayRef< SMLoc > getLoc() const

void checkUnusedTemplateArgs()

ArrayRef< DumpInfo > getDumps() const

std::vector< const Record * > getValueAsListOfDefs(StringRef FieldName) const

This method looks up the specified field and returns its value as a vector of records,...

ArrayRef< AssertionInfo > getAssertions() const

std::string getNameInitAsString() const

const Record * getValueAsDef(StringRef FieldName) const

This method looks up the specified field and returns its value as a Record, throwing an exception if ...

RecordKeeper & getRecords() const

const DagInit * getValueAsDag(StringRef FieldName) const

This method looks up the specified field and returns its value as an Dag, throwing an exception if th...

std::vector< StringRef > getValueAsListOfStrings(StringRef FieldName) const

This method looks up the specified field and returns its value as a vector of strings,...

const RecordVal * getValue(const Init *Name) const

void addValue(const RecordVal &RV)

const Record * getValueAsOptionalDef(StringRef FieldName) const

This method looks up the specified field and returns its value as a Record, returning null if the fie...

bool hasDirectSuperClass(const Record *SuperClass) const

Determine whether this record has the specified direct superclass.

StringRef getName() const

void setName(const Init *Name)

const ListInit * getValueAsListInit(StringRef FieldName) const

This method looks up the specified field and returns its value as a ListInit, throwing an exception i...

void appendDumps(const Record *Rec)

bool isSubClassOf(const Record *R) const

DefInit * getDefInit() const

get the corresponding DefInit.

ArrayRef< RecordVal > getValues() const

SMLoc getFieldLoc(StringRef FieldName) const

Return the source location for the named field.

void resolveReferences(const Init *NewName=nullptr)

If there are any field references that refer to fields that have been filled in, we can propagate the...

std::optional< StringRef > getValueAsOptionalString(StringRef FieldName) const

This method looks up the specified field and returns its value as a string, throwing an exception if ...

void removeValue(const Init *Name)

ArrayRef< const Init * > getTemplateArgs() const

void updateClassLoc(SMLoc Loc)

const BitsInit * getValueAsBitsInit(StringRef FieldName) const

This method looks up the specified field and returns its value as a BitsInit, throwing an exception i...

void getDirectSuperClasses(SmallVectorImpl< const Record * > &Classes) const

Append the direct superclasses of this record to Classes.

void appendAssertions(const Record *Rec)

const Init * getNameInit() const

int64_t getValueAsInt(StringRef FieldName) const

This method looks up the specified field and returns its value as an int64_t, throwing an exception i...

void addSuperClass(const Record *R, SMRange Range)

void checkRecordAssertions()

StringRef getValueAsString(StringRef FieldName) const

This method looks up the specified field and returns its value as a string, throwing an exception if ...

Interface for looking up the initializer for a variable name, used by Init::resolveReferences.

const Record * getCurrentRecord() const

virtual const Init * resolve(const Init *VarName)=0

Return the initializer for the given variable name (should normally be a StringInit),...

Represents a location in source code.

Represents a range in source code.

Delegate resolving to a sub-resolver, but shadow some variable names.

void addShadow(const Init *Key)

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

void reserve(size_type N)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

"foo" - Represent an initialization by a string value.

static const StringInit * get(RecordKeeper &RK, StringRef, StringFormat Fmt=SF_String)

StringFormat getFormat() const

StringRef getValue() const

static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2)

std::string getAsUnquotedString() const override

Convert this value to a literal form, without adding quotes around a string.

const Init * convertInitializerTo(const RecTy *Ty) const override

Convert to a value whose type is Ty, or return null if this is not possible.

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

'string' - Represent an string value

std::string getAsString() const override

static const StringRecTy * get(RecordKeeper &RK)

bool typeIsConvertibleTo(const RecTy *RHS) const override

Return true if all values of 'this' type can be converted to the specified type.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

!op (X, Y, Z) - Combine two inits.

const Init * Fold(const Record *CurRec) const

const Init * getLHS() const

void Profile(FoldingSetNodeID &ID) const

const Init * getMHS() const

const Init * getRHS() const

static const TernOpInit * get(TernaryOp opc, const Init *lhs, const Init *mhs, const Init *rhs, const RecTy *Type)

std::string getAsString() const override

Convert this value to a literal form.

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

TernaryOp getOpcode() const

This class is used to track the amount of time spent between invocations of its startTimer()/stopTime...

(Optionally) delegate resolving to a sub-resolver, and keep track whether there were unresolved refer...

const Init * resolve(const Init *VarName) override

Return the initializer for the given variable name (should normally be a StringInit),...

bool foundUnresolved() const

const T * getTrailingObjects() const

Returns a pointer to the trailing object array of the given type (which must be one of those specifie...

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

This is the common superclass of types that have a specific, explicit type, stored in ValueTy.

const RecTy * getFieldType(const StringInit *FieldName) const override

This method is used to implement the FieldInit class.

const Init * convertInitializerBitRange(ArrayRef< unsigned > Bits) const override

This function is used to implement the bit range selection operator.

RecordKeeper & getRecordKeeper() const

Get the record keeper that initialized this Init.

const Init * getCastTo(const RecTy *Ty) const override

If this value is convertible to type Ty, return a value whose type is Ty, generating a !...

const Init * convertInitializerTo(const RecTy *Ty) const override

Convert to a value whose type is Ty, or return null if this is not possible.

const RecTy * getType() const

Get the type of the Init as a RecTy.

!op (X) - Transform an init.

const Init * getOperand() const

UnaryOp getOpcode() const

static const UnOpInit * get(UnaryOp opc, const Init *lhs, const RecTy *Type)

void Profile(FoldingSetNodeID &ID) const

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

std::string getAsString() const override

Convert this value to a literal form.

const Init * Fold(const Record *CurRec, bool IsFinal=false) const

'?' - Represents an uninitialized value.

const Init * getCastTo(const RecTy *Ty) const override

If this value is convertible to type Ty, return a value whose type is Ty, generating a !...

const Init * convertInitializerTo(const RecTy *Ty) const override

Convert to a value whose type is Ty, or return null if this is not possible.

static UnsetInit * get(RecordKeeper &RK)

Get the singleton unset Init.

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

Opcode{0} - Represent access to one bit of a variable or field.

static const VarBitInit * get(const TypedInit *T, unsigned B)

unsigned getBitNum() const

std::string getAsString() const override

Convert this value to a literal form.

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

classname<targs...> - Represent an uninstantiated anonymous class instantiation.

ArrayRef< const ArgumentInit * > args() const

static const VarDefInit * get(SMLoc Loc, const Record *Class, ArrayRef< const ArgumentInit * > Args)

const Init * resolveReferences(Resolver &R) const override

This function is used by classes that refer to other variables which may not be defined at the time t...

const Init * Fold() const

void Profile(FoldingSetNodeID &ID) const

std::string getAsString() const override

Convert this value to a literal form.

'Opcode' - Represent a reference to an entire variable object.

static const VarInit * get(StringRef VN, const RecTy *T)

const Init * getBit(unsigned Bit) const override

Get the Init value of the specified bit.

StringRef getName() const

const Init * getNameInit() const

const Init * resolveReferences(Resolver &R) const override

This method is used by classes that refer to other variables which may not be defined at the time the...

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an std::string.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ C

The default llvm calling convention, compatible with C.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

void PrintFatalError(const Twine &Msg)

void PrintError(const Twine &Msg)

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

unsigned Log2_64(uint64_t Value)

Return the floor log base 2 of the specified value, -1 if the value is zero.

bool CheckAssert(SMLoc Loc, const Init *Condition, const Init *Message)

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

void PrintWarning(const Twine &Msg)

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

void sort(IteratorTy Start, IteratorTy End)

raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

std::variant< unsigned, const Init * > ArgAuxType

void dumpMessage(SMLoc Loc, const Init *Message)

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

const RecTy * resolveTypes(const RecTy *T1, const RecTy *T2)

Find a common type that T1 and T2 convert to.

Implement std::hash so that hash_code can be used in STL containers.

Helper object to track which of three possible relocation mechanisms are used for a particular value ...

Sorting predicate to sort record pointers by name.

This class represents the internal implementation of the RecordKeeper.

FoldingSet< BitsInit > TheBitsInitPool

std::map< int64_t, IntInit * > TheIntInitPool

FoldingSet< FoldOpInit > TheFoldOpInitPool

DenseMap< std::pair< const RecTy *, const Init * >, VarInit * > TheVarInitPool

FoldingSet< IsAOpInit > TheIsAOpInitPool

FoldingSet< DagInit > TheDagInitPool

FoldingSet< CondOpInit > TheCondOpInitPool

FoldingSet< BinOpInit > TheBinOpInitPool

FoldingSet< ArgumentInit > TheArgumentInitPool

StringRecTy SharedStringRecTy

FoldingSet< RecordRecTy > RecordTypePool

FoldingSet< VarDefInit > TheVarDefInitPool

StringMap< const StringInit *, BumpPtrAllocator & > StringInitCodePool

DenseMap< std::pair< const TypedInit *, unsigned >, VarBitInit * > TheVarBitInitPool

std::vector< BitsRecTy * > SharedBitsRecTys

FoldingSet< UnOpInit > TheUnOpInitPool

void dumpAllocationStats(raw_ostream &OS) const

DenseMap< std::pair< const Init *, const StringInit * >, FieldInit * > TheFieldInitPool

FoldingSet< TernOpInit > TheTernOpInitPool

BumpPtrAllocator Allocator

FoldingSet< ExistsOpInit > TheExistsOpInitPool

StringMap< const StringInit *, BumpPtrAllocator & > StringInitStringPool

FoldingSet< ListInit > TheListInitPool

RecordKeeperImpl(RecordKeeper &RK)