184c287e3SPeter Collingbourne //===- TGParser.cpp - Parser for TableGen Files ---------------------------===//
284c287e3SPeter Collingbourne //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
684c287e3SPeter Collingbourne //
784c287e3SPeter Collingbourne //===----------------------------------------------------------------------===//
884c287e3SPeter Collingbourne //
984c287e3SPeter Collingbourne // Implement the Parser for TableGen.
1084c287e3SPeter Collingbourne //
1184c287e3SPeter Collingbourne //===----------------------------------------------------------------------===//
1284c287e3SPeter Collingbourne
1384c287e3SPeter Collingbourne #include "TGParser.h"
1492f49b89Sserge-sans-paille #include "llvm/ADT/DenseMapInfo.h"
1533d7b762SEugene Zelenko #include "llvm/ADT/None.h"
16ed0881b2SChandler Carruth #include "llvm/ADT/SmallVector.h"
1784c287e3SPeter Collingbourne #include "llvm/ADT/StringExtras.h"
18df91a0f7SSimon Pilgrim #include "llvm/ADT/Twine.h"
19432a3883SNico Weber #include "llvm/Config/llvm-config.h"
2033d7b762SEugene Zelenko #include "llvm/Support/Casting.h"
2133d7b762SEugene Zelenko #include "llvm/Support/Compiler.h"
2233d7b762SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
2333d7b762SEugene Zelenko #include "llvm/Support/raw_ostream.h"
2484c287e3SPeter Collingbourne #include <algorithm>
2533d7b762SEugene Zelenko #include <cassert>
2633d7b762SEugene Zelenko #include <cstdint>
27e122a71aSPaul C. Anagnostopoulos #include <limits>
2833d7b762SEugene Zelenko
2984c287e3SPeter Collingbourne using namespace llvm;
3084c287e3SPeter Collingbourne
3184c287e3SPeter Collingbourne //===----------------------------------------------------------------------===//
3284c287e3SPeter Collingbourne // Support Code for the Semantic Actions.
3384c287e3SPeter Collingbourne //===----------------------------------------------------------------------===//
3484c287e3SPeter Collingbourne
3584c287e3SPeter Collingbourne namespace llvm {
3633d7b762SEugene Zelenko
3784c287e3SPeter Collingbourne struct SubClassReference {
38f12e8a93SJordan Rose SMRange RefRange;
3984c287e3SPeter Collingbourne Record *Rec;
40c66e7557SMatthias Braun SmallVector<Init*, 4> TemplateArgs;
4133d7b762SEugene Zelenko
SubClassReferencellvm::SubClassReference42011817a0SCraig Topper SubClassReference() : Rec(nullptr) {}
4384c287e3SPeter Collingbourne
isInvalidllvm::SubClassReference44011817a0SCraig Topper bool isInvalid() const { return Rec == nullptr; }
4584c287e3SPeter Collingbourne };
4684c287e3SPeter Collingbourne
4784c287e3SPeter Collingbourne struct SubMultiClassReference {
48f12e8a93SJordan Rose SMRange RefRange;
4984c287e3SPeter Collingbourne MultiClass *MC;
50c66e7557SMatthias Braun SmallVector<Init*, 4> TemplateArgs;
5133d7b762SEugene Zelenko
SubMultiClassReferencellvm::SubMultiClassReference52011817a0SCraig Topper SubMultiClassReference() : MC(nullptr) {}
5384c287e3SPeter Collingbourne
isInvalidllvm::SubMultiClassReference54011817a0SCraig Topper bool isInvalid() const { return MC == nullptr; }
5584c287e3SPeter Collingbourne void dump() const;
5684c287e3SPeter Collingbourne };
5784c287e3SPeter Collingbourne
58615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const59eb2a2546SYaron Keren LLVM_DUMP_METHOD void SubMultiClassReference::dump() const {
6084c287e3SPeter Collingbourne errs() << "Multiclass:\n";
6184c287e3SPeter Collingbourne
6284c287e3SPeter Collingbourne MC->dump();
6384c287e3SPeter Collingbourne
6484c287e3SPeter Collingbourne errs() << "Template args:\n";
65a9642b4eSCraig Topper for (Init *TA : TemplateArgs)
66eb4d7c6bSCraig Topper TA->dump();
6784c287e3SPeter Collingbourne }
6825bcaba5SMatthias Braun #endif
6984c287e3SPeter Collingbourne
7084c287e3SPeter Collingbourne } // end namespace llvm
7184c287e3SPeter Collingbourne
checkBitsConcrete(Record & R,const RecordVal & RV)720f529885SNicolai Haehnle static bool checkBitsConcrete(Record &R, const RecordVal &RV) {
730f529885SNicolai Haehnle BitsInit *BV = cast<BitsInit>(RV.getValue());
740f529885SNicolai Haehnle for (unsigned i = 0, e = BV->getNumBits(); i != e; ++i) {
750f529885SNicolai Haehnle Init *Bit = BV->getBit(i);
760f529885SNicolai Haehnle bool IsReference = false;
770f529885SNicolai Haehnle if (auto VBI = dyn_cast<VarBitInit>(Bit)) {
780f529885SNicolai Haehnle if (auto VI = dyn_cast<VarInit>(VBI->getBitVar())) {
790f529885SNicolai Haehnle if (R.getValue(VI->getName()))
800f529885SNicolai Haehnle IsReference = true;
810f529885SNicolai Haehnle }
820f529885SNicolai Haehnle } else if (isa<VarInit>(Bit)) {
830f529885SNicolai Haehnle IsReference = true;
840f529885SNicolai Haehnle }
850f529885SNicolai Haehnle if (!(IsReference || Bit->isConcrete()))
860f529885SNicolai Haehnle return false;
870f529885SNicolai Haehnle }
880f529885SNicolai Haehnle return true;
890f529885SNicolai Haehnle }
900f529885SNicolai Haehnle
checkConcrete(Record & R)910f529885SNicolai Haehnle static void checkConcrete(Record &R) {
920f529885SNicolai Haehnle for (const RecordVal &RV : R.getValues()) {
930f529885SNicolai Haehnle // HACK: Disable this check for variables declared with 'field'. This is
940f529885SNicolai Haehnle // done merely because existing targets have legitimate cases of
950f529885SNicolai Haehnle // non-concrete variables in helper defs. Ideally, we'd introduce a
960f529885SNicolai Haehnle // 'maybe' or 'optional' modifier instead of this.
97aa7968a8SPaul C. Anagnostopoulos if (RV.isNonconcreteOK())
980f529885SNicolai Haehnle continue;
990f529885SNicolai Haehnle
1000f529885SNicolai Haehnle if (Init *V = RV.getValue()) {
1010f529885SNicolai Haehnle bool Ok = isa<BitsInit>(V) ? checkBitsConcrete(R, RV) : V->isConcrete();
1020f529885SNicolai Haehnle if (!Ok) {
1030f529885SNicolai Haehnle PrintError(R.getLoc(),
1040f529885SNicolai Haehnle Twine("Initializer of '") + RV.getNameInitAsString() +
1050f529885SNicolai Haehnle "' in '" + R.getNameInitAsString() +
1060f529885SNicolai Haehnle "' could not be fully resolved: " +
1070f529885SNicolai Haehnle RV.getValue()->getAsString());
1080f529885SNicolai Haehnle }
1090f529885SNicolai Haehnle }
1100f529885SNicolai Haehnle }
1110f529885SNicolai Haehnle }
1120f529885SNicolai Haehnle
1137d69e0f3SNicolai Haehnle /// Return an Init with a qualifier prefix referring
1147d69e0f3SNicolai Haehnle /// to CurRec's name.
QualifyName(Record & CurRec,MultiClass * CurMultiClass,Init * Name,StringRef Scoper)1152ac3cd20SRiver Riddle static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass, Init *Name,
1162ac3cd20SRiver Riddle StringRef Scoper) {
1172ac3cd20SRiver Riddle RecordKeeper &RK = CurRec.getRecords();
1182ac3cd20SRiver Riddle Init *NewName = BinOpInit::getStrConcat(CurRec.getNameInit(),
1192ac3cd20SRiver Riddle StringInit::get(RK, Scoper));
1207d69e0f3SNicolai Haehnle NewName = BinOpInit::getStrConcat(NewName, Name);
1217d69e0f3SNicolai Haehnle if (CurMultiClass && Scoper != "::") {
1227d69e0f3SNicolai Haehnle Init *Prefix = BinOpInit::getStrConcat(CurMultiClass->Rec.getNameInit(),
1232ac3cd20SRiver Riddle StringInit::get(RK, "::"));
1247d69e0f3SNicolai Haehnle NewName = BinOpInit::getStrConcat(Prefix, NewName);
1257d69e0f3SNicolai Haehnle }
1267d69e0f3SNicolai Haehnle
1277d69e0f3SNicolai Haehnle if (BinOpInit *BinOp = dyn_cast<BinOpInit>(NewName))
1287d69e0f3SNicolai Haehnle NewName = BinOp->Fold(&CurRec);
1297d69e0f3SNicolai Haehnle return NewName;
1307d69e0f3SNicolai Haehnle }
1317d69e0f3SNicolai Haehnle
13201d261f1SNicolai Haehnle /// Return the qualified version of the implicit 'NAME' template argument.
QualifiedNameOfImplicitName(Record & Rec,MultiClass * MC=nullptr)13301d261f1SNicolai Haehnle static Init *QualifiedNameOfImplicitName(Record &Rec,
13401d261f1SNicolai Haehnle MultiClass *MC = nullptr) {
1352ac3cd20SRiver Riddle return QualifyName(Rec, MC, StringInit::get(Rec.getRecords(), "NAME"),
1362ac3cd20SRiver Riddle MC ? "::" : ":");
13701d261f1SNicolai Haehnle }
13801d261f1SNicolai Haehnle
QualifiedNameOfImplicitName(MultiClass * MC)13901d261f1SNicolai Haehnle static Init *QualifiedNameOfImplicitName(MultiClass *MC) {
14001d261f1SNicolai Haehnle return QualifiedNameOfImplicitName(MC->Rec, MC);
14101d261f1SNicolai Haehnle }
14201d261f1SNicolai Haehnle
AddValue(Record * CurRec,SMLoc Loc,const RecordVal & RV)14384c287e3SPeter Collingbourne bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
144011817a0SCraig Topper if (!CurRec)
14584c287e3SPeter Collingbourne CurRec = &CurMultiClass->Rec;
14684c287e3SPeter Collingbourne
1479d1c5eebSJakob Stoklund Olesen if (RecordVal *ERV = CurRec->getValue(RV.getNameInit())) {
14884c287e3SPeter Collingbourne // The value already exists in the class, treat this as a set.
14984c287e3SPeter Collingbourne if (ERV->setValue(RV.getValue()))
15084c287e3SPeter Collingbourne return Error(Loc, "New definition of '" + RV.getName() + "' of type '" +
15184c287e3SPeter Collingbourne RV.getType()->getAsString() + "' is incompatible with " +
15284c287e3SPeter Collingbourne "previous definition of type '" +
15384c287e3SPeter Collingbourne ERV->getType()->getAsString() + "'");
15484c287e3SPeter Collingbourne } else {
15584c287e3SPeter Collingbourne CurRec->addValue(RV);
15684c287e3SPeter Collingbourne }
15784c287e3SPeter Collingbourne return false;
15884c287e3SPeter Collingbourne }
15984c287e3SPeter Collingbourne
16084c287e3SPeter Collingbourne /// SetValue -
16184c287e3SPeter Collingbourne /// Return true on error, false on success.
SetValue(Record * CurRec,SMLoc Loc,Init * ValName,ArrayRef<unsigned> BitList,Init * V,bool AllowSelfAssignment)1623ca42126SDavid Greene bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
163cfd81733SCraig Topper ArrayRef<unsigned> BitList, Init *V,
1641e23ed9eSCraig Topper bool AllowSelfAssignment) {
16584c287e3SPeter Collingbourne if (!V) return false;
16684c287e3SPeter Collingbourne
167011817a0SCraig Topper if (!CurRec) CurRec = &CurMultiClass->Rec;
16884c287e3SPeter Collingbourne
16984c287e3SPeter Collingbourne RecordVal *RV = CurRec->getValue(ValName);
170011817a0SCraig Topper if (!RV)
17185c07007SCraig Topper return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
17285c07007SCraig Topper "' unknown!");
17384c287e3SPeter Collingbourne
17484c287e3SPeter Collingbourne // Do not allow assignments like 'X = X'. This will just cause infinite loops
17584c287e3SPeter Collingbourne // in the resolution machinery.
17684c287e3SPeter Collingbourne if (BitList.empty())
177fb509ed1SSean Silva if (VarInit *VI = dyn_cast<VarInit>(V))
1781e23ed9eSCraig Topper if (VI->getNameInit() == ValName && !AllowSelfAssignment)
179f19083d1SNicolai Haehnle return Error(Loc, "Recursion / self-assignment forbidden");
18084c287e3SPeter Collingbourne
18184c287e3SPeter Collingbourne // If we are assigning to a subset of the bits in the value... then we must be
18284c287e3SPeter Collingbourne // assigning to a field of BitsRecTy, which must have a BitsInit
18384c287e3SPeter Collingbourne // initializer.
18484c287e3SPeter Collingbourne //
18584c287e3SPeter Collingbourne if (!BitList.empty()) {
186fb509ed1SSean Silva BitsInit *CurVal = dyn_cast<BitsInit>(RV->getValue());
187011817a0SCraig Topper if (!CurVal)
18885c07007SCraig Topper return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
18985c07007SCraig Topper "' is not a bits type");
19084c287e3SPeter Collingbourne
19184c287e3SPeter Collingbourne // Convert the incoming value to a bits type of the appropriate size...
1922ac3cd20SRiver Riddle Init *BI = V->getCastTo(BitsRecTy::get(Records, BitList.size()));
193a9642b4eSCraig Topper if (!BI)
19484c287e3SPeter Collingbourne return Error(Loc, "Initializer is not compatible with bit range");
19584c287e3SPeter Collingbourne
19684c287e3SPeter Collingbourne SmallVector<Init *, 16> NewBits(CurVal->getNumBits());
19784c287e3SPeter Collingbourne
19884c287e3SPeter Collingbourne // Loop over bits, assigning values as appropriate.
19984c287e3SPeter Collingbourne for (unsigned i = 0, e = BitList.size(); i != e; ++i) {
20084c287e3SPeter Collingbourne unsigned Bit = BitList[i];
20184c287e3SPeter Collingbourne if (NewBits[Bit])
202dba7ee90SBenjamin Kramer return Error(Loc, "Cannot set bit #" + Twine(Bit) + " of value '" +
2033ca42126SDavid Greene ValName->getAsUnquotedString() + "' more than once");
204dfda9dccSNicolai Haehnle NewBits[Bit] = BI->getBit(i);
20584c287e3SPeter Collingbourne }
20684c287e3SPeter Collingbourne
20784c287e3SPeter Collingbourne for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
208011817a0SCraig Topper if (!NewBits[i])
20984c287e3SPeter Collingbourne NewBits[i] = CurVal->getBit(i);
21084c287e3SPeter Collingbourne
2112ac3cd20SRiver Riddle V = BitsInit::get(Records, NewBits);
21284c287e3SPeter Collingbourne }
21384c287e3SPeter Collingbourne
214b3931188SPaul C. Anagnostopoulos if (RV->setValue(V, Loc)) {
21533d7b762SEugene Zelenko std::string InitType;
216a9642b4eSCraig Topper if (BitsInit *BI = dyn_cast<BitsInit>(V))
217040c6a67SPete Cooper InitType = (Twine("' of type bit initializer with length ") +
218040c6a67SPete Cooper Twine(BI->getNumBits())).str();
219f19083d1SNicolai Haehnle else if (TypedInit *TI = dyn_cast<TypedInit>(V))
220f19083d1SNicolai Haehnle InitType = (Twine("' of type '") + TI->getType()->getAsString()).str();
221b3931188SPaul C. Anagnostopoulos return Error(Loc, "Field '" + ValName->getAsUnquotedString() +
22285c07007SCraig Topper "' of type '" + RV->getType()->getAsString() +
223b3931188SPaul C. Anagnostopoulos "' is incompatible with value '" +
224f19083d1SNicolai Haehnle V->getAsString() + InitType + "'");
225040c6a67SPete Cooper }
22684c287e3SPeter Collingbourne return false;
22784c287e3SPeter Collingbourne }
22884c287e3SPeter Collingbourne
22984c287e3SPeter Collingbourne /// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template
23084c287e3SPeter Collingbourne /// args as SubClass's template arguments.
AddSubClass(Record * CurRec,SubClassReference & SubClass)23184c287e3SPeter Collingbourne bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
23284c287e3SPeter Collingbourne Record *SC = SubClass.Rec;
23349d663d5SPaul C. Anagnostopoulos MapResolver R(CurRec);
23449d663d5SPaul C. Anagnostopoulos
235a9fc44c5SPaul C. Anagnostopoulos // Loop over all the subclass record's fields. Add template arguments
236a9fc44c5SPaul C. Anagnostopoulos // to the resolver map. Add regular fields to the new record.
237a9fc44c5SPaul C. Anagnostopoulos for (const RecordVal &Field : SC->getValues()) {
238a9fc44c5SPaul C. Anagnostopoulos if (Field.isTemplateArg()) {
239a9fc44c5SPaul C. Anagnostopoulos R.set(Field.getNameInit(), Field.getValue());
240a9fc44c5SPaul C. Anagnostopoulos } else {
241a9fc44c5SPaul C. Anagnostopoulos if (AddValue(CurRec, SubClass.RefRange.Start, Field))
24249d663d5SPaul C. Anagnostopoulos return true;
243a9fc44c5SPaul C. Anagnostopoulos }
24449d663d5SPaul C. Anagnostopoulos }
24549d663d5SPaul C. Anagnostopoulos
246a9fc44c5SPaul C. Anagnostopoulos ArrayRef<Init *> TArgs = SC->getTemplateArgs();
247a9fc44c5SPaul C. Anagnostopoulos assert(SubClass.TemplateArgs.size() <= TArgs.size() &&
248a9fc44c5SPaul C. Anagnostopoulos "Too many template arguments allowed");
24949d663d5SPaul C. Anagnostopoulos
250a9fc44c5SPaul C. Anagnostopoulos // Loop over the template argument names. If a value was specified,
251a9fc44c5SPaul C. Anagnostopoulos // reset the map value. If not and there was no default, complain.
252a9fc44c5SPaul C. Anagnostopoulos for (unsigned I = 0, E = TArgs.size(); I != E; ++I) {
253a9fc44c5SPaul C. Anagnostopoulos if (I < SubClass.TemplateArgs.size())
254a9fc44c5SPaul C. Anagnostopoulos R.set(TArgs[I], SubClass.TemplateArgs[I]);
255a9fc44c5SPaul C. Anagnostopoulos else if (!R.isComplete(TArgs[I]))
256a9fc44c5SPaul C. Anagnostopoulos return Error(SubClass.RefRange.Start,
257a9fc44c5SPaul C. Anagnostopoulos "Value not specified for template argument '" +
258a9fc44c5SPaul C. Anagnostopoulos TArgs[I]->getAsUnquotedString() + "' (#" + Twine(I) +
259a9fc44c5SPaul C. Anagnostopoulos ") of parent class '" + SC->getNameInitAsString() + "'");
26084c287e3SPeter Collingbourne }
26184c287e3SPeter Collingbourne
2625f473a04SPaul C. Anagnostopoulos // Copy the subclass record's assertions to the new record.
2635f473a04SPaul C. Anagnostopoulos CurRec->appendAssertions(SC);
2645f473a04SPaul C. Anagnostopoulos
26501d261f1SNicolai Haehnle Init *Name;
26601d261f1SNicolai Haehnle if (CurRec->isClass())
2672ac3cd20SRiver Riddle Name = VarInit::get(QualifiedNameOfImplicitName(*CurRec),
2682ac3cd20SRiver Riddle StringRecTy::get(Records));
26901d261f1SNicolai Haehnle else
27001d261f1SNicolai Haehnle Name = CurRec->getNameInit();
27101d261f1SNicolai Haehnle R.set(QualifiedNameOfImplicitName(*SC), Name);
27201d261f1SNicolai Haehnle
273b0cf9e93SNicolai Haehnle CurRec->resolveReferences(R);
274b0cf9e93SNicolai Haehnle
27584c287e3SPeter Collingbourne // Since everything went well, we can now set the "superclass" list for the
27684c287e3SPeter Collingbourne // current record.
2770e41d0b9SCraig Topper ArrayRef<std::pair<Record *, SMRange>> SCs = SC->getSuperClasses();
2780e41d0b9SCraig Topper for (const auto &SCPair : SCs) {
2790e41d0b9SCraig Topper if (CurRec->isSubClassOf(SCPair.first))
280f12e8a93SJordan Rose return Error(SubClass.RefRange.Start,
2810e41d0b9SCraig Topper "Already subclass of '" + SCPair.first->getName() + "'!\n");
2820e41d0b9SCraig Topper CurRec->addSuperClass(SCPair.first, SCPair.second);
28384c287e3SPeter Collingbourne }
284c10570f7SNicolai Haehnle
285c10570f7SNicolai Haehnle if (CurRec->isSubClassOf(SC))
286c10570f7SNicolai Haehnle return Error(SubClass.RefRange.Start,
287c10570f7SNicolai Haehnle "Already subclass of '" + SC->getName() + "'!\n");
288c10570f7SNicolai Haehnle CurRec->addSuperClass(SC, SubClass.RefRange);
28984c287e3SPeter Collingbourne return false;
29084c287e3SPeter Collingbourne }
29184c287e3SPeter Collingbourne
AddSubClass(RecordsEntry & Entry,SubClassReference & SubClass)2927d69e0f3SNicolai Haehnle bool TGParser::AddSubClass(RecordsEntry &Entry, SubClassReference &SubClass) {
2937d69e0f3SNicolai Haehnle if (Entry.Rec)
2947d69e0f3SNicolai Haehnle return AddSubClass(Entry.Rec.get(), SubClass);
2957d69e0f3SNicolai Haehnle
296985ab6e1SPaul C. Anagnostopoulos if (Entry.Assertion)
297985ab6e1SPaul C. Anagnostopoulos return false;
298985ab6e1SPaul C. Anagnostopoulos
2997d69e0f3SNicolai Haehnle for (auto &E : Entry.Loop->Entries) {
3007d69e0f3SNicolai Haehnle if (AddSubClass(E, SubClass))
3017d69e0f3SNicolai Haehnle return true;
3027d69e0f3SNicolai Haehnle }
3037d69e0f3SNicolai Haehnle
3047d69e0f3SNicolai Haehnle return false;
3057d69e0f3SNicolai Haehnle }
3067d69e0f3SNicolai Haehnle
30784c287e3SPeter Collingbourne /// AddSubMultiClass - Add SubMultiClass as a subclass to
30884c287e3SPeter Collingbourne /// CurMC, resolving its template args as SubMultiClass's
30984c287e3SPeter Collingbourne /// template arguments.
AddSubMultiClass(MultiClass * CurMC,SubMultiClassReference & SubMultiClass)31084c287e3SPeter Collingbourne bool TGParser::AddSubMultiClass(MultiClass *CurMC,
31184c287e3SPeter Collingbourne SubMultiClassReference &SubMultiClass) {
31284c287e3SPeter Collingbourne MultiClass *SMC = SubMultiClass.MC;
31384c287e3SPeter Collingbourne
3147ecf8c22SBenjamin Kramer ArrayRef<Init *> SMCTArgs = SMC->Rec.getTemplateArgs();
31584c287e3SPeter Collingbourne if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size())
316f12e8a93SJordan Rose return Error(SubMultiClass.RefRange.Start,
31784c287e3SPeter Collingbourne "More template args specified than expected");
31884c287e3SPeter Collingbourne
31901d261f1SNicolai Haehnle // Prepare the mapping of template argument name to value, filling in default
32001d261f1SNicolai Haehnle // values if necessary.
3217d69e0f3SNicolai Haehnle SubstStack TemplateArgs;
32284c287e3SPeter Collingbourne for (unsigned i = 0, e = SMCTArgs.size(); i != e; ++i) {
32384c287e3SPeter Collingbourne if (i < SubMultiClass.TemplateArgs.size()) {
32401d261f1SNicolai Haehnle TemplateArgs.emplace_back(SMCTArgs[i], SubMultiClass.TemplateArgs[i]);
32501d261f1SNicolai Haehnle } else {
32601d261f1SNicolai Haehnle Init *Default = SMC->Rec.getValue(SMCTArgs[i])->getValue();
32701d261f1SNicolai Haehnle if (!Default->isComplete()) {
328f12e8a93SJordan Rose return Error(SubMultiClass.RefRange.Start,
32901d261f1SNicolai Haehnle "value not specified for template argument #" + Twine(i) +
33001d261f1SNicolai Haehnle " (" + SMCTArgs[i]->getAsUnquotedString() +
33101d261f1SNicolai Haehnle ") of multiclass '" + SMC->Rec.getNameInitAsString() +
33201d261f1SNicolai Haehnle "'");
33301d261f1SNicolai Haehnle }
33401d261f1SNicolai Haehnle TemplateArgs.emplace_back(SMCTArgs[i], Default);
33501d261f1SNicolai Haehnle }
33684c287e3SPeter Collingbourne }
3371faf8689SNicolai Haehnle
3382ac3cd20SRiver Riddle TemplateArgs.emplace_back(QualifiedNameOfImplicitName(SMC),
3392ac3cd20SRiver Riddle VarInit::get(QualifiedNameOfImplicitName(CurMC),
3402ac3cd20SRiver Riddle StringRecTy::get(Records)));
3411faf8689SNicolai Haehnle
34201d261f1SNicolai Haehnle // Add all of the defs in the subclass into the current multiclass.
3437d69e0f3SNicolai Haehnle return resolve(SMC->Entries, TemplateArgs, false, &CurMC->Entries);
34484c287e3SPeter Collingbourne }
34584c287e3SPeter Collingbourne
346a5aaec8fSPaul C. Anagnostopoulos /// Add a record, foreach loop, or assertion to the current context.
addEntry(RecordsEntry E)3477d69e0f3SNicolai Haehnle bool TGParser::addEntry(RecordsEntry E) {
348a5aaec8fSPaul C. Anagnostopoulos assert((!!E.Rec + !!E.Loop + !!E.Assertion) == 1 &&
349a5aaec8fSPaul C. Anagnostopoulos "RecordsEntry has invalid number of items");
3507d69e0f3SNicolai Haehnle
351a5aaec8fSPaul C. Anagnostopoulos // If we are parsing a loop, add it to the loop's entries.
3527d69e0f3SNicolai Haehnle if (!Loops.empty()) {
3537d69e0f3SNicolai Haehnle Loops.back()->Entries.push_back(std::move(E));
35484c287e3SPeter Collingbourne return false;
35584c287e3SPeter Collingbourne }
35684c287e3SPeter Collingbourne
357a5aaec8fSPaul C. Anagnostopoulos // If it is a loop, then resolve and perform the loop.
3587d69e0f3SNicolai Haehnle if (E.Loop) {
3597d69e0f3SNicolai Haehnle SubstStack Stack;
3607d69e0f3SNicolai Haehnle return resolve(*E.Loop, Stack, CurMultiClass == nullptr,
3617d69e0f3SNicolai Haehnle CurMultiClass ? &CurMultiClass->Entries : nullptr);
362fb927af2SDavid Greene }
363fb927af2SDavid Greene
364a5aaec8fSPaul C. Anagnostopoulos // If we are parsing a multiclass, add it to the multiclass's entries.
365420e28c7SNicolai Haehnle if (CurMultiClass) {
3667d69e0f3SNicolai Haehnle CurMultiClass->Entries.push_back(std::move(E));
367420e28c7SNicolai Haehnle return false;
368420e28c7SNicolai Haehnle }
369420e28c7SNicolai Haehnle
370a5aaec8fSPaul C. Anagnostopoulos // If it is an assertion, then it's a top-level one, so check it.
371a5aaec8fSPaul C. Anagnostopoulos if (E.Assertion) {
3722d4c4d3cSPaul C. Anagnostopoulos CheckAssert(E.Assertion->Loc, E.Assertion->Condition, E.Assertion->Message);
373a5aaec8fSPaul C. Anagnostopoulos return false;
374a5aaec8fSPaul C. Anagnostopoulos }
375a5aaec8fSPaul C. Anagnostopoulos
376a5aaec8fSPaul C. Anagnostopoulos // It must be a record, so finish it off.
3777d69e0f3SNicolai Haehnle return addDefOne(std::move(E.Rec));
3787d69e0f3SNicolai Haehnle }
3797d69e0f3SNicolai Haehnle
3807d69e0f3SNicolai Haehnle /// Resolve the entries in \p Loop, going over inner loops recursively
3817d69e0f3SNicolai Haehnle /// and making the given subsitutions of (name, value) pairs.
3827d69e0f3SNicolai Haehnle ///
3837d69e0f3SNicolai Haehnle /// The resulting records are stored in \p Dest if non-null. Otherwise, they
3847d69e0f3SNicolai Haehnle /// are added to the global record keeper.
resolve(const ForeachLoop & Loop,SubstStack & Substs,bool Final,std::vector<RecordsEntry> * Dest,SMLoc * Loc)3857d69e0f3SNicolai Haehnle bool TGParser::resolve(const ForeachLoop &Loop, SubstStack &Substs,
3867d69e0f3SNicolai Haehnle bool Final, std::vector<RecordsEntry> *Dest,
3877d69e0f3SNicolai Haehnle SMLoc *Loc) {
3887d69e0f3SNicolai Haehnle MapResolver R;
3897d69e0f3SNicolai Haehnle for (const auto &S : Substs)
3907d69e0f3SNicolai Haehnle R.set(S.first, S.second);
3917d69e0f3SNicolai Haehnle Init *List = Loop.ListValue->resolveReferences(R);
3927d69e0f3SNicolai Haehnle auto LI = dyn_cast<ListInit>(List);
3937d69e0f3SNicolai Haehnle if (!LI) {
3947d69e0f3SNicolai Haehnle if (!Final) {
3950eaee545SJonas Devlieghere Dest->emplace_back(std::make_unique<ForeachLoop>(Loop.Loc, Loop.IterVar,
3967d69e0f3SNicolai Haehnle List));
3977d69e0f3SNicolai Haehnle return resolve(Loop.Entries, Substs, Final, &Dest->back().Loop->Entries,
3987d69e0f3SNicolai Haehnle Loc);
3997d69e0f3SNicolai Haehnle }
4007d69e0f3SNicolai Haehnle
4017d69e0f3SNicolai Haehnle PrintError(Loop.Loc, Twine("attempting to loop over '") +
4027d69e0f3SNicolai Haehnle List->getAsString() + "', expected a list");
4037d69e0f3SNicolai Haehnle return true;
4047d69e0f3SNicolai Haehnle }
4057d69e0f3SNicolai Haehnle
4067d69e0f3SNicolai Haehnle bool Error = false;
4077d69e0f3SNicolai Haehnle for (auto Elt : *LI) {
408ddbc0b1eSSimon Tatham if (Loop.IterVar)
4097d69e0f3SNicolai Haehnle Substs.emplace_back(Loop.IterVar->getNameInit(), Elt);
4107d69e0f3SNicolai Haehnle Error = resolve(Loop.Entries, Substs, Final, Dest);
411ddbc0b1eSSimon Tatham if (Loop.IterVar)
4127d69e0f3SNicolai Haehnle Substs.pop_back();
4137d69e0f3SNicolai Haehnle if (Error)
4147d69e0f3SNicolai Haehnle break;
4157d69e0f3SNicolai Haehnle }
4167d69e0f3SNicolai Haehnle return Error;
4177d69e0f3SNicolai Haehnle }
4187d69e0f3SNicolai Haehnle
4197d69e0f3SNicolai Haehnle /// Resolve the entries in \p Source, going over loops recursively and
4207d69e0f3SNicolai Haehnle /// making the given substitutions of (name, value) pairs.
4217d69e0f3SNicolai Haehnle ///
4227d69e0f3SNicolai Haehnle /// The resulting records are stored in \p Dest if non-null. Otherwise, they
4237d69e0f3SNicolai Haehnle /// are added to the global record keeper.
resolve(const std::vector<RecordsEntry> & Source,SubstStack & Substs,bool Final,std::vector<RecordsEntry> * Dest,SMLoc * Loc)4247d69e0f3SNicolai Haehnle bool TGParser::resolve(const std::vector<RecordsEntry> &Source,
4257d69e0f3SNicolai Haehnle SubstStack &Substs, bool Final,
4267d69e0f3SNicolai Haehnle std::vector<RecordsEntry> *Dest, SMLoc *Loc) {
4277d69e0f3SNicolai Haehnle bool Error = false;
4287d69e0f3SNicolai Haehnle for (auto &E : Source) {
4297d69e0f3SNicolai Haehnle if (E.Loop) {
4307d69e0f3SNicolai Haehnle Error = resolve(*E.Loop, Substs, Final, Dest);
431a5aaec8fSPaul C. Anagnostopoulos
432a5aaec8fSPaul C. Anagnostopoulos } else if (E.Assertion) {
433a5aaec8fSPaul C. Anagnostopoulos MapResolver R;
434a5aaec8fSPaul C. Anagnostopoulos for (const auto &S : Substs)
435a5aaec8fSPaul C. Anagnostopoulos R.set(S.first, S.second);
4362d4c4d3cSPaul C. Anagnostopoulos Init *Condition = E.Assertion->Condition->resolveReferences(R);
4372d4c4d3cSPaul C. Anagnostopoulos Init *Message = E.Assertion->Message->resolveReferences(R);
438a5aaec8fSPaul C. Anagnostopoulos
4392d4c4d3cSPaul C. Anagnostopoulos if (Dest)
4402d4c4d3cSPaul C. Anagnostopoulos Dest->push_back(std::make_unique<Record::AssertionInfo>(
4412d4c4d3cSPaul C. Anagnostopoulos E.Assertion->Loc, Condition, Message));
4422d4c4d3cSPaul C. Anagnostopoulos else
4432d4c4d3cSPaul C. Anagnostopoulos CheckAssert(E.Assertion->Loc, Condition, Message);
444a5aaec8fSPaul C. Anagnostopoulos
4457d69e0f3SNicolai Haehnle } else {
4460eaee545SJonas Devlieghere auto Rec = std::make_unique<Record>(*E.Rec);
4477d69e0f3SNicolai Haehnle if (Loc)
4487d69e0f3SNicolai Haehnle Rec->appendLoc(*Loc);
4497d69e0f3SNicolai Haehnle
4507d69e0f3SNicolai Haehnle MapResolver R(Rec.get());
4517d69e0f3SNicolai Haehnle for (const auto &S : Substs)
4527d69e0f3SNicolai Haehnle R.set(S.first, S.second);
4537d69e0f3SNicolai Haehnle Rec->resolveReferences(R);
4547d69e0f3SNicolai Haehnle
4557d69e0f3SNicolai Haehnle if (Dest)
4567d69e0f3SNicolai Haehnle Dest->push_back(std::move(Rec));
4577d69e0f3SNicolai Haehnle else
4587d69e0f3SNicolai Haehnle Error = addDefOne(std::move(Rec));
4597d69e0f3SNicolai Haehnle }
4607d69e0f3SNicolai Haehnle if (Error)
4617d69e0f3SNicolai Haehnle break;
4627d69e0f3SNicolai Haehnle }
4637d69e0f3SNicolai Haehnle return Error;
4647d69e0f3SNicolai Haehnle }
4657d69e0f3SNicolai Haehnle
4667d69e0f3SNicolai Haehnle /// Resolve the record fully and add it to the record keeper.
addDefOne(std::unique_ptr<Record> Rec)4677d69e0f3SNicolai Haehnle bool TGParser::addDefOne(std::unique_ptr<Record> Rec) {
468267b573bSJ-Y You Init *NewName = nullptr;
469420e28c7SNicolai Haehnle if (Record *Prev = Records.getDef(Rec->getNameInitAsString())) {
470420e28c7SNicolai Haehnle if (!Rec->isAnonymous()) {
471420e28c7SNicolai Haehnle PrintError(Rec->getLoc(),
472420e28c7SNicolai Haehnle "def already exists: " + Rec->getNameInitAsString());
473420e28c7SNicolai Haehnle PrintNote(Prev->getLoc(), "location of previous definition");
474420e28c7SNicolai Haehnle return true;
475420e28c7SNicolai Haehnle }
476267b573bSJ-Y You NewName = Records.getNewAnonymousName();
477420e28c7SNicolai Haehnle }
478420e28c7SNicolai Haehnle
479267b573bSJ-Y You Rec->resolveReferences(NewName);
480420e28c7SNicolai Haehnle checkConcrete(*Rec);
481420e28c7SNicolai Haehnle
482e7ae0f48SNicolai Haehnle if (!isa<StringInit>(Rec->getNameInit())) {
483e7ae0f48SNicolai Haehnle PrintError(Rec->getLoc(), Twine("record name '") +
484e7ae0f48SNicolai Haehnle Rec->getNameInit()->getAsString() +
485e7ae0f48SNicolai Haehnle "' could not be fully resolved");
486e7ae0f48SNicolai Haehnle return true;
487e7ae0f48SNicolai Haehnle }
488e7ae0f48SNicolai Haehnle
4895f473a04SPaul C. Anagnostopoulos // Check the assertions.
490a5aaec8fSPaul C. Anagnostopoulos Rec->checkRecordAssertions();
4915f473a04SPaul C. Anagnostopoulos
492420e28c7SNicolai Haehnle // If ObjectBody has template arguments, it's an error.
493420e28c7SNicolai Haehnle assert(Rec->getTemplateArgs().empty() && "How'd this get template args?");
494420e28c7SNicolai Haehnle
495420e28c7SNicolai Haehnle for (DefsetRecord *Defset : Defsets) {
496420e28c7SNicolai Haehnle DefInit *I = Rec->getDefInit();
497420e28c7SNicolai Haehnle if (!I->getType()->typeIsA(Defset->EltTy)) {
498420e28c7SNicolai Haehnle PrintError(Rec->getLoc(), Twine("adding record of incompatible type '") +
499420e28c7SNicolai Haehnle I->getType()->getAsString() +
500420e28c7SNicolai Haehnle "' to defset");
501420e28c7SNicolai Haehnle PrintNote(Defset->Loc, "location of defset declaration");
502420e28c7SNicolai Haehnle return true;
503420e28c7SNicolai Haehnle }
504420e28c7SNicolai Haehnle Defset->Elements.push_back(I);
505420e28c7SNicolai Haehnle }
506420e28c7SNicolai Haehnle
507420e28c7SNicolai Haehnle Records.addDef(std::move(Rec));
508fb927af2SDavid Greene return false;
509fb927af2SDavid Greene }
510fb927af2SDavid Greene
51184c287e3SPeter Collingbourne //===----------------------------------------------------------------------===//
51284c287e3SPeter Collingbourne // Parser Code
51384c287e3SPeter Collingbourne //===----------------------------------------------------------------------===//
51484c287e3SPeter Collingbourne
5156e2b6351SPaul C. Anagnostopoulos /// isObjectStart - Return true if this is a valid first token for a statement.
isObjectStart(tgtok::TokKind K)51684c287e3SPeter Collingbourne static bool isObjectStart(tgtok::TokKind K) {
5176e2b6351SPaul C. Anagnostopoulos return K == tgtok::Assert || K == tgtok::Class || K == tgtok::Def ||
5186e2b6351SPaul C. Anagnostopoulos K == tgtok::Defm || K == tgtok::Defset || K == tgtok::Defvar ||
5196e2b6351SPaul C. Anagnostopoulos K == tgtok::Foreach || K == tgtok::If || K == tgtok::Let ||
5206e2b6351SPaul C. Anagnostopoulos K == tgtok::MultiClass;
52184c287e3SPeter Collingbourne }
52284c287e3SPeter Collingbourne
consume(tgtok::TokKind K)523e69605bfSFangrui Song bool TGParser::consume(tgtok::TokKind K) {
524e69605bfSFangrui Song if (Lex.getCode() == K) {
525e69605bfSFangrui Song Lex.Lex();
526e69605bfSFangrui Song return true;
527e69605bfSFangrui Song }
528e69605bfSFangrui Song return false;
529e69605bfSFangrui Song }
530e69605bfSFangrui Song
531420e28c7SNicolai Haehnle /// ParseObjectName - If a valid object name is specified, return it. If no
532420e28c7SNicolai Haehnle /// name is specified, return the unset initializer. Return nullptr on parse
533420e28c7SNicolai Haehnle /// error.
5342affd67bSDavid Greene /// ObjectName ::= Value [ '#' Value ]*
53584c287e3SPeter Collingbourne /// ObjectName ::= /*empty*/
53684c287e3SPeter Collingbourne ///
ParseObjectName(MultiClass * CurMultiClass)5372affd67bSDavid Greene Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) {
5382affd67bSDavid Greene switch (Lex.getCode()) {
5392affd67bSDavid Greene case tgtok::colon:
5402affd67bSDavid Greene case tgtok::semi:
5412affd67bSDavid Greene case tgtok::l_brace:
5422affd67bSDavid Greene // These are all of the tokens that can begin an object body.
5432affd67bSDavid Greene // Some of these can also begin values but we disallow those cases
5442affd67bSDavid Greene // because they are unlikely to be useful.
5452ac3cd20SRiver Riddle return UnsetInit::get(Records);
5462affd67bSDavid Greene default:
5472affd67bSDavid Greene break;
54884c287e3SPeter Collingbourne }
54984c287e3SPeter Collingbourne
550011817a0SCraig Topper Record *CurRec = nullptr;
5512affd67bSDavid Greene if (CurMultiClass)
5522affd67bSDavid Greene CurRec = &CurMultiClass->Rec;
5532affd67bSDavid Greene
5542ac3cd20SRiver Riddle Init *Name = ParseValue(CurRec, StringRecTy::get(Records), ParseNameMode);
55501d261f1SNicolai Haehnle if (!Name)
55601d261f1SNicolai Haehnle return nullptr;
55701d261f1SNicolai Haehnle
55801d261f1SNicolai Haehnle if (CurMultiClass) {
55901d261f1SNicolai Haehnle Init *NameStr = QualifiedNameOfImplicitName(CurMultiClass);
56001d261f1SNicolai Haehnle HasReferenceResolver R(NameStr);
56101d261f1SNicolai Haehnle Name->resolveReferences(R);
56201d261f1SNicolai Haehnle if (!R.found())
5632ac3cd20SRiver Riddle Name = BinOpInit::getStrConcat(
5642ac3cd20SRiver Riddle VarInit::get(NameStr, StringRecTy::get(Records)), Name);
56501d261f1SNicolai Haehnle }
56601d261f1SNicolai Haehnle
56701d261f1SNicolai Haehnle return Name;
5682affd67bSDavid Greene }
56984c287e3SPeter Collingbourne
57084c287e3SPeter Collingbourne /// ParseClassID - Parse and resolve a reference to a class name. This returns
57184c287e3SPeter Collingbourne /// null on error.
57284c287e3SPeter Collingbourne ///
57384c287e3SPeter Collingbourne /// ClassID ::= ID
57484c287e3SPeter Collingbourne ///
ParseClassID()57584c287e3SPeter Collingbourne Record *TGParser::ParseClassID() {
57684c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::Id) {
57784c287e3SPeter Collingbourne TokError("expected name for ClassID");
578011817a0SCraig Topper return nullptr;
57984c287e3SPeter Collingbourne }
58084c287e3SPeter Collingbourne
58184c287e3SPeter Collingbourne Record *Result = Records.getClass(Lex.getCurStrVal());
58233888ff6SJaved Absar if (!Result) {
58333888ff6SJaved Absar std::string Msg("Couldn't find class '" + Lex.getCurStrVal() + "'");
58433888ff6SJaved Absar if (MultiClasses[Lex.getCurStrVal()].get())
58533888ff6SJaved Absar TokError(Msg + ". Use 'defm' if you meant to use multiclass '" +
58633888ff6SJaved Absar Lex.getCurStrVal() + "'");
58733888ff6SJaved Absar else
58833888ff6SJaved Absar TokError(Msg);
58933888ff6SJaved Absar }
59084c287e3SPeter Collingbourne
59184c287e3SPeter Collingbourne Lex.Lex();
59284c287e3SPeter Collingbourne return Result;
59384c287e3SPeter Collingbourne }
59484c287e3SPeter Collingbourne
59584c287e3SPeter Collingbourne /// ParseMultiClassID - Parse and resolve a reference to a multiclass name.
59684c287e3SPeter Collingbourne /// This returns null on error.
59784c287e3SPeter Collingbourne ///
59884c287e3SPeter Collingbourne /// MultiClassID ::= ID
59984c287e3SPeter Collingbourne ///
ParseMultiClassID()60084c287e3SPeter Collingbourne MultiClass *TGParser::ParseMultiClassID() {
60184c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::Id) {
602710c3ae5SSean Silva TokError("expected name for MultiClassID");
603011817a0SCraig Topper return nullptr;
60484c287e3SPeter Collingbourne }
60584c287e3SPeter Collingbourne
6067adf2bf7SCraig Topper MultiClass *Result = MultiClasses[Lex.getCurStrVal()].get();
6074ca4001dSCraig Topper if (!Result)
608710c3ae5SSean Silva TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
60984c287e3SPeter Collingbourne
61084c287e3SPeter Collingbourne Lex.Lex();
6114ca4001dSCraig Topper return Result;
61284c287e3SPeter Collingbourne }
61384c287e3SPeter Collingbourne
614a9fc44c5SPaul C. Anagnostopoulos /// ParseSubClassReference - Parse a reference to a subclass or a
615a9fc44c5SPaul C. Anagnostopoulos /// multiclass. This returns a SubClassRefTy with a null Record* on error.
61684c287e3SPeter Collingbourne ///
61784c287e3SPeter Collingbourne /// SubClassRef ::= ClassID
61884c287e3SPeter Collingbourne /// SubClassRef ::= ClassID '<' ValueList '>'
61984c287e3SPeter Collingbourne ///
62084c287e3SPeter Collingbourne SubClassReference TGParser::
ParseSubClassReference(Record * CurRec,bool isDefm)62184c287e3SPeter Collingbourne ParseSubClassReference(Record *CurRec, bool isDefm) {
62284c287e3SPeter Collingbourne SubClassReference Result;
623f12e8a93SJordan Rose Result.RefRange.Start = Lex.getLoc();
62484c287e3SPeter Collingbourne
6250657b40bSSean Silva if (isDefm) {
6260657b40bSSean Silva if (MultiClass *MC = ParseMultiClassID())
6270657b40bSSean Silva Result.Rec = &MC->Rec;
6280657b40bSSean Silva } else {
62984c287e3SPeter Collingbourne Result.Rec = ParseClassID();
6300657b40bSSean Silva }
631011817a0SCraig Topper if (!Result.Rec) return Result;
63284c287e3SPeter Collingbourne
63384c287e3SPeter Collingbourne // If there is no template arg list, we're done.
634e69605bfSFangrui Song if (!consume(tgtok::less)) {
635f12e8a93SJordan Rose Result.RefRange.End = Lex.getLoc();
63684c287e3SPeter Collingbourne return Result;
637f12e8a93SJordan Rose }
63884c287e3SPeter Collingbourne
639a9fc44c5SPaul C. Anagnostopoulos if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec)) {
640011817a0SCraig Topper Result.Rec = nullptr; // Error parsing value list.
64184c287e3SPeter Collingbourne return Result;
64284c287e3SPeter Collingbourne }
64384c287e3SPeter Collingbourne
644a9fc44c5SPaul C. Anagnostopoulos if (CheckTemplateArgValues(Result.TemplateArgs, Result.RefRange.Start,
645a9fc44c5SPaul C. Anagnostopoulos Result.Rec)) {
646a9fc44c5SPaul C. Anagnostopoulos Result.Rec = nullptr; // Error checking value list.
64784c287e3SPeter Collingbourne return Result;
64884c287e3SPeter Collingbourne }
64949d663d5SPaul C. Anagnostopoulos
650a9fc44c5SPaul C. Anagnostopoulos Result.RefRange.End = Lex.getLoc();
65184c287e3SPeter Collingbourne return Result;
65284c287e3SPeter Collingbourne }
65384c287e3SPeter Collingbourne
65484c287e3SPeter Collingbourne /// ParseSubMultiClassReference - Parse a reference to a subclass or to a
65584c287e3SPeter Collingbourne /// templated submulticlass. This returns a SubMultiClassRefTy with a null
65684c287e3SPeter Collingbourne /// Record* on error.
65784c287e3SPeter Collingbourne ///
65884c287e3SPeter Collingbourne /// SubMultiClassRef ::= MultiClassID
65984c287e3SPeter Collingbourne /// SubMultiClassRef ::= MultiClassID '<' ValueList '>'
66084c287e3SPeter Collingbourne ///
66184c287e3SPeter Collingbourne SubMultiClassReference TGParser::
ParseSubMultiClassReference(MultiClass * CurMC)66284c287e3SPeter Collingbourne ParseSubMultiClassReference(MultiClass *CurMC) {
66384c287e3SPeter Collingbourne SubMultiClassReference Result;
664f12e8a93SJordan Rose Result.RefRange.Start = Lex.getLoc();
66584c287e3SPeter Collingbourne
66684c287e3SPeter Collingbourne Result.MC = ParseMultiClassID();
667011817a0SCraig Topper if (!Result.MC) return Result;
66884c287e3SPeter Collingbourne
66984c287e3SPeter Collingbourne // If there is no template arg list, we're done.
670e69605bfSFangrui Song if (!consume(tgtok::less)) {
671f12e8a93SJordan Rose Result.RefRange.End = Lex.getLoc();
67284c287e3SPeter Collingbourne return Result;
673f12e8a93SJordan Rose }
67484c287e3SPeter Collingbourne
675a9fc44c5SPaul C. Anagnostopoulos if (ParseTemplateArgValueList(Result.TemplateArgs, &CurMC->Rec,
676a9fc44c5SPaul C. Anagnostopoulos &Result.MC->Rec)) {
677011817a0SCraig Topper Result.MC = nullptr; // Error parsing value list.
67884c287e3SPeter Collingbourne return Result;
67984c287e3SPeter Collingbourne }
68084c287e3SPeter Collingbourne
681f12e8a93SJordan Rose Result.RefRange.End = Lex.getLoc();
68284c287e3SPeter Collingbourne
68384c287e3SPeter Collingbourne return Result;
68484c287e3SPeter Collingbourne }
68584c287e3SPeter Collingbourne
68684c287e3SPeter Collingbourne /// ParseRangePiece - Parse a bit/value range.
68784c287e3SPeter Collingbourne /// RangePiece ::= INTVAL
688196e6f9fSPaul C. Anagnostopoulos /// RangePiece ::= INTVAL '...' INTVAL
68984c287e3SPeter Collingbourne /// RangePiece ::= INTVAL '-' INTVAL
69084c287e3SPeter Collingbourne /// RangePiece ::= INTVAL INTVAL
691196e6f9fSPaul C. Anagnostopoulos // The last two forms are deprecated.
ParseRangePiece(SmallVectorImpl<unsigned> & Ranges,TypedInit * FirstItem)692b79a25b1SMatt Arsenault bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges,
693b79a25b1SMatt Arsenault TypedInit *FirstItem) {
694b79a25b1SMatt Arsenault Init *CurVal = FirstItem;
695b79a25b1SMatt Arsenault if (!CurVal)
696b79a25b1SMatt Arsenault CurVal = ParseValue(nullptr);
697b79a25b1SMatt Arsenault
698b79a25b1SMatt Arsenault IntInit *II = dyn_cast_or_null<IntInit>(CurVal);
699b79a25b1SMatt Arsenault if (!II)
700b79a25b1SMatt Arsenault return TokError("expected integer or bitrange");
701b79a25b1SMatt Arsenault
702b79a25b1SMatt Arsenault int64_t Start = II->getValue();
70384c287e3SPeter Collingbourne int64_t End;
70484c287e3SPeter Collingbourne
70584c287e3SPeter Collingbourne if (Start < 0)
70684c287e3SPeter Collingbourne return TokError("invalid range, cannot be negative");
70784c287e3SPeter Collingbourne
708b79a25b1SMatt Arsenault switch (Lex.getCode()) {
70984c287e3SPeter Collingbourne default:
71084c287e3SPeter Collingbourne Ranges.push_back(Start);
71184c287e3SPeter Collingbourne return false;
712196e6f9fSPaul C. Anagnostopoulos
713196e6f9fSPaul C. Anagnostopoulos case tgtok::dotdotdot:
714b79a25b1SMatt Arsenault case tgtok::minus: {
715b79a25b1SMatt Arsenault Lex.Lex(); // eat
716b79a25b1SMatt Arsenault
717b79a25b1SMatt Arsenault Init *I_End = ParseValue(nullptr);
718b79a25b1SMatt Arsenault IntInit *II_End = dyn_cast_or_null<IntInit>(I_End);
719b79a25b1SMatt Arsenault if (!II_End) {
72084c287e3SPeter Collingbourne TokError("expected integer value as end of range");
72184c287e3SPeter Collingbourne return true;
72284c287e3SPeter Collingbourne }
723b79a25b1SMatt Arsenault
724b79a25b1SMatt Arsenault End = II_End->getValue();
72584c287e3SPeter Collingbourne break;
726b79a25b1SMatt Arsenault }
727b79a25b1SMatt Arsenault case tgtok::IntVal: {
72884c287e3SPeter Collingbourne End = -Lex.getCurIntVal();
729b79a25b1SMatt Arsenault Lex.Lex();
73084c287e3SPeter Collingbourne break;
73184c287e3SPeter Collingbourne }
732b79a25b1SMatt Arsenault }
73384c287e3SPeter Collingbourne if (End < 0)
73484c287e3SPeter Collingbourne return TokError("invalid range, cannot be negative");
73584c287e3SPeter Collingbourne
73684c287e3SPeter Collingbourne // Add to the range.
737a9642b4eSCraig Topper if (Start < End)
73884c287e3SPeter Collingbourne for (; Start <= End; ++Start)
73984c287e3SPeter Collingbourne Ranges.push_back(Start);
740a9642b4eSCraig Topper else
74184c287e3SPeter Collingbourne for (; Start >= End; --Start)
74284c287e3SPeter Collingbourne Ranges.push_back(Start);
74384c287e3SPeter Collingbourne return false;
74484c287e3SPeter Collingbourne }
74584c287e3SPeter Collingbourne
74684c287e3SPeter Collingbourne /// ParseRangeList - Parse a list of scalars and ranges into scalar values.
74784c287e3SPeter Collingbourne ///
74884c287e3SPeter Collingbourne /// RangeList ::= RangePiece (',' RangePiece)*
74984c287e3SPeter Collingbourne ///
ParseRangeList(SmallVectorImpl<unsigned> & Result)750c66e7557SMatthias Braun void TGParser::ParseRangeList(SmallVectorImpl<unsigned> &Result) {
75184c287e3SPeter Collingbourne // Parse the first piece.
752c66e7557SMatthias Braun if (ParseRangePiece(Result)) {
753c66e7557SMatthias Braun Result.clear();
754c66e7557SMatthias Braun return;
755c66e7557SMatthias Braun }
756e69605bfSFangrui Song while (consume(tgtok::comma))
75784c287e3SPeter Collingbourne // Parse the next range piece.
758c66e7557SMatthias Braun if (ParseRangePiece(Result)) {
759c66e7557SMatthias Braun Result.clear();
760c66e7557SMatthias Braun return;
76184c287e3SPeter Collingbourne }
762c66e7557SMatthias Braun }
76384c287e3SPeter Collingbourne
76484c287e3SPeter Collingbourne /// ParseOptionalRangeList - Parse either a range list in <>'s or nothing.
76584c287e3SPeter Collingbourne /// OptionalRangeList ::= '<' RangeList '>'
76684c287e3SPeter Collingbourne /// OptionalRangeList ::= /*empty*/
ParseOptionalRangeList(SmallVectorImpl<unsigned> & Ranges)767c66e7557SMatthias Braun bool TGParser::ParseOptionalRangeList(SmallVectorImpl<unsigned> &Ranges) {
76884c287e3SPeter Collingbourne SMLoc StartLoc = Lex.getLoc();
769e69605bfSFangrui Song if (!consume(tgtok::less))
770e69605bfSFangrui Song return false;
77184c287e3SPeter Collingbourne
77284c287e3SPeter Collingbourne // Parse the range list.
773c66e7557SMatthias Braun ParseRangeList(Ranges);
77484c287e3SPeter Collingbourne if (Ranges.empty()) return true;
77584c287e3SPeter Collingbourne
776e69605bfSFangrui Song if (!consume(tgtok::greater)) {
77784c287e3SPeter Collingbourne TokError("expected '>' at end of range list");
77884c287e3SPeter Collingbourne return Error(StartLoc, "to match this '<'");
77984c287e3SPeter Collingbourne }
78084c287e3SPeter Collingbourne return false;
78184c287e3SPeter Collingbourne }
78284c287e3SPeter Collingbourne
78384c287e3SPeter Collingbourne /// ParseOptionalBitList - Parse either a bit list in {}'s or nothing.
78484c287e3SPeter Collingbourne /// OptionalBitList ::= '{' RangeList '}'
78584c287e3SPeter Collingbourne /// OptionalBitList ::= /*empty*/
ParseOptionalBitList(SmallVectorImpl<unsigned> & Ranges)786c66e7557SMatthias Braun bool TGParser::ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges) {
78784c287e3SPeter Collingbourne SMLoc StartLoc = Lex.getLoc();
788e69605bfSFangrui Song if (!consume(tgtok::l_brace))
789e69605bfSFangrui Song return false;
79084c287e3SPeter Collingbourne
79184c287e3SPeter Collingbourne // Parse the range list.
792c66e7557SMatthias Braun ParseRangeList(Ranges);
79384c287e3SPeter Collingbourne if (Ranges.empty()) return true;
79484c287e3SPeter Collingbourne
795e69605bfSFangrui Song if (!consume(tgtok::r_brace)) {
79684c287e3SPeter Collingbourne TokError("expected '}' at end of bit list");
79784c287e3SPeter Collingbourne return Error(StartLoc, "to match this '{'");
79884c287e3SPeter Collingbourne }
79984c287e3SPeter Collingbourne return false;
80084c287e3SPeter Collingbourne }
80184c287e3SPeter Collingbourne
80284c287e3SPeter Collingbourne /// ParseType - Parse and return a tblgen type. This returns null on error.
80384c287e3SPeter Collingbourne ///
80484c287e3SPeter Collingbourne /// Type ::= STRING // string type
805dd8fbf57SJakob Stoklund Olesen /// Type ::= CODE // code type
80684c287e3SPeter Collingbourne /// Type ::= BIT // bit type
80784c287e3SPeter Collingbourne /// Type ::= BITS '<' INTVAL '>' // bits<x> type
80884c287e3SPeter Collingbourne /// Type ::= INT // int type
80984c287e3SPeter Collingbourne /// Type ::= LIST '<' Type '>' // list<x> type
81084c287e3SPeter Collingbourne /// Type ::= DAG // dag type
81184c287e3SPeter Collingbourne /// Type ::= ClassID // Record Type
81284c287e3SPeter Collingbourne ///
ParseType()81384c287e3SPeter Collingbourne RecTy *TGParser::ParseType() {
81484c287e3SPeter Collingbourne switch (Lex.getCode()) {
815011817a0SCraig Topper default: TokError("Unknown token when expecting a type"); return nullptr;
816415fab6fSPaul C. Anagnostopoulos case tgtok::String:
8172ac3cd20SRiver Riddle case tgtok::Code:
8182ac3cd20SRiver Riddle Lex.Lex();
8192ac3cd20SRiver Riddle return StringRecTy::get(Records);
8202ac3cd20SRiver Riddle case tgtok::Bit:
8212ac3cd20SRiver Riddle Lex.Lex();
8222ac3cd20SRiver Riddle return BitRecTy::get(Records);
8232ac3cd20SRiver Riddle case tgtok::Int:
8242ac3cd20SRiver Riddle Lex.Lex();
8252ac3cd20SRiver Riddle return IntRecTy::get(Records);
8262ac3cd20SRiver Riddle case tgtok::Dag:
8272ac3cd20SRiver Riddle Lex.Lex();
8282ac3cd20SRiver Riddle return DagRecTy::get(Records);
82984c287e3SPeter Collingbourne case tgtok::Id:
8302ac3cd20SRiver Riddle if (Record *R = ParseClassID())
8312ac3cd20SRiver Riddle return RecordRecTy::get(R);
832fcd6525aSNicolai Haehnle TokError("unknown class name");
833011817a0SCraig Topper return nullptr;
83484c287e3SPeter Collingbourne case tgtok::Bits: {
83584c287e3SPeter Collingbourne if (Lex.Lex() != tgtok::less) { // Eat 'bits'
83684c287e3SPeter Collingbourne TokError("expected '<' after bits type");
837011817a0SCraig Topper return nullptr;
83884c287e3SPeter Collingbourne }
83984c287e3SPeter Collingbourne if (Lex.Lex() != tgtok::IntVal) { // Eat '<'
84084c287e3SPeter Collingbourne TokError("expected integer in bits<n> type");
841011817a0SCraig Topper return nullptr;
84284c287e3SPeter Collingbourne }
84384c287e3SPeter Collingbourne uint64_t Val = Lex.getCurIntVal();
84484c287e3SPeter Collingbourne if (Lex.Lex() != tgtok::greater) { // Eat count.
84584c287e3SPeter Collingbourne TokError("expected '>' at end of bits<n> type");
846011817a0SCraig Topper return nullptr;
84784c287e3SPeter Collingbourne }
84884c287e3SPeter Collingbourne Lex.Lex(); // Eat '>'
8492ac3cd20SRiver Riddle return BitsRecTy::get(Records, Val);
85084c287e3SPeter Collingbourne }
85184c287e3SPeter Collingbourne case tgtok::List: {
85284c287e3SPeter Collingbourne if (Lex.Lex() != tgtok::less) { // Eat 'bits'
85384c287e3SPeter Collingbourne TokError("expected '<' after list type");
854011817a0SCraig Topper return nullptr;
85584c287e3SPeter Collingbourne }
85684c287e3SPeter Collingbourne Lex.Lex(); // Eat '<'
85784c287e3SPeter Collingbourne RecTy *SubType = ParseType();
858011817a0SCraig Topper if (!SubType) return nullptr;
85984c287e3SPeter Collingbourne
860e69605bfSFangrui Song if (!consume(tgtok::greater)) {
86184c287e3SPeter Collingbourne TokError("expected '>' at end of list<ty> type");
862011817a0SCraig Topper return nullptr;
86384c287e3SPeter Collingbourne }
86484c287e3SPeter Collingbourne return ListRecTy::get(SubType);
86584c287e3SPeter Collingbourne }
86684c287e3SPeter Collingbourne }
86784c287e3SPeter Collingbourne }
86884c287e3SPeter Collingbourne
8696e2b6351SPaul C. Anagnostopoulos /// ParseIDValue
ParseIDValue(Record * CurRec,StringInit * Name,SMLoc NameLoc,IDParseMode Mode)870215ff84bSMatthias Braun Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
871d4263a6aSDavid Greene IDParseMode Mode) {
87284c287e3SPeter Collingbourne if (CurRec) {
87384c287e3SPeter Collingbourne if (const RecordVal *RV = CurRec->getValue(Name))
87484c287e3SPeter Collingbourne return VarInit::get(Name, RV->getType());
87501d261f1SNicolai Haehnle }
87684c287e3SPeter Collingbourne
87701d261f1SNicolai Haehnle if ((CurRec && CurRec->isClass()) || CurMultiClass) {
87801d261f1SNicolai Haehnle Init *TemplateArgName;
87901d261f1SNicolai Haehnle if (CurMultiClass) {
88001d261f1SNicolai Haehnle TemplateArgName =
88101d261f1SNicolai Haehnle QualifyName(CurMultiClass->Rec, CurMultiClass, Name, "::");
88201d261f1SNicolai Haehnle } else
88301d261f1SNicolai Haehnle TemplateArgName = QualifyName(*CurRec, CurMultiClass, Name, ":");
884db10e691SDavid Greene
88501d261f1SNicolai Haehnle Record *TemplateRec = CurMultiClass ? &CurMultiClass->Rec : CurRec;
88601d261f1SNicolai Haehnle if (TemplateRec->isTemplateArg(TemplateArgName)) {
887d968b173SCullen Rhodes RecordVal *RV = TemplateRec->getValue(TemplateArgName);
88884c287e3SPeter Collingbourne assert(RV && "Template arg doesn't exist??");
889d968b173SCullen Rhodes RV->setUsed(true);
89084c287e3SPeter Collingbourne return VarInit::get(TemplateArgName, RV->getType());
89101d261f1SNicolai Haehnle } else if (Name->getValue() == "NAME") {
8922ac3cd20SRiver Riddle return VarInit::get(TemplateArgName, StringRecTy::get(Records));
89384c287e3SPeter Collingbourne }
89484c287e3SPeter Collingbourne }
89584c287e3SPeter Collingbourne
8963388b0f5SSimon Tatham if (CurLocalScope)
8973388b0f5SSimon Tatham if (Init *I = CurLocalScope->getVar(Name->getValue()))
8983388b0f5SSimon Tatham return I;
8993388b0f5SSimon Tatham
900fb927af2SDavid Greene // If this is in a foreach loop, make sure it's not a loop iterator
901eb4d7c6bSCraig Topper for (const auto &L : Loops) {
902ddbc0b1eSSimon Tatham if (L->IterVar) {
9037d69e0f3SNicolai Haehnle VarInit *IterVar = dyn_cast<VarInit>(L->IterVar);
904215ff84bSMatthias Braun if (IterVar && IterVar->getNameInit() == Name)
905fb927af2SDavid Greene return IterVar;
906fb927af2SDavid Greene }
907ddbc0b1eSSimon Tatham }
908fb927af2SDavid Greene
909232bd601SDavid Greene if (Mode == ParseNameMode)
910215ff84bSMatthias Braun return Name;
911232bd601SDavid Greene
912fcd6525aSNicolai Haehnle if (Init *I = Records.getGlobal(Name->getValue()))
913fcd6525aSNicolai Haehnle return I;
91484c287e3SPeter Collingbourne
915420e28c7SNicolai Haehnle // Allow self-references of concrete defs, but delay the lookup so that we
916420e28c7SNicolai Haehnle // get the correct type.
91701d261f1SNicolai Haehnle if (CurRec && !CurRec->isClass() && !CurMultiClass &&
91801d261f1SNicolai Haehnle CurRec->getNameInit() == Name)
919420e28c7SNicolai Haehnle return UnOpInit::get(UnOpInit::CAST, Name, CurRec->getType());
920420e28c7SNicolai Haehnle
921215ff84bSMatthias Braun Error(NameLoc, "Variable not defined: '" + Name->getValue() + "'");
922011817a0SCraig Topper return nullptr;
92384c287e3SPeter Collingbourne }
92484c287e3SPeter Collingbourne
92584c287e3SPeter Collingbourne /// ParseOperation - Parse an operator. This returns null on error.
92684c287e3SPeter Collingbourne ///
92784c287e3SPeter Collingbourne /// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
92884c287e3SPeter Collingbourne ///
ParseOperation(Record * CurRec,RecTy * ItemType)929a73fd935SMatt Arsenault Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
93084c287e3SPeter Collingbourne switch (Lex.getCode()) {
93184c287e3SPeter Collingbourne default:
932d56cd429SPaul C. Anagnostopoulos TokError("unknown bang operator");
933011817a0SCraig Topper return nullptr;
9344767bb2cSPaul C. Anagnostopoulos case tgtok::XNOT:
93584c287e3SPeter Collingbourne case tgtok::XHead:
93684c287e3SPeter Collingbourne case tgtok::XTail:
9370243aaf4SNicolai Haehnle case tgtok::XSize:
93884c287e3SPeter Collingbourne case tgtok::XEmpty:
9391fed9a0cSSimon Tatham case tgtok::XCast:
940876af264SPaul C. Anagnostopoulos case tgtok::XGetDagOp: { // Value ::= !unop '(' Value ')'
94184c287e3SPeter Collingbourne UnOpInit::UnaryOp Code;
942011817a0SCraig Topper RecTy *Type = nullptr;
94384c287e3SPeter Collingbourne
94484c287e3SPeter Collingbourne switch (Lex.getCode()) {
945a2886c21SCraig Topper default: llvm_unreachable("Unhandled code!");
94684c287e3SPeter Collingbourne case tgtok::XCast:
94784c287e3SPeter Collingbourne Lex.Lex(); // eat the operation
94884c287e3SPeter Collingbourne Code = UnOpInit::CAST;
94984c287e3SPeter Collingbourne
95084c287e3SPeter Collingbourne Type = ParseOperatorType();
95184c287e3SPeter Collingbourne
952011817a0SCraig Topper if (!Type) {
95384c287e3SPeter Collingbourne TokError("did not get type for unary operator");
954011817a0SCraig Topper return nullptr;
95584c287e3SPeter Collingbourne }
95684c287e3SPeter Collingbourne
95784c287e3SPeter Collingbourne break;
9584767bb2cSPaul C. Anagnostopoulos case tgtok::XNOT:
9594767bb2cSPaul C. Anagnostopoulos Lex.Lex(); // eat the operation
9604767bb2cSPaul C. Anagnostopoulos Code = UnOpInit::NOT;
9612ac3cd20SRiver Riddle Type = IntRecTy::get(Records);
9624767bb2cSPaul C. Anagnostopoulos break;
96384c287e3SPeter Collingbourne case tgtok::XHead:
96484c287e3SPeter Collingbourne Lex.Lex(); // eat the operation
96584c287e3SPeter Collingbourne Code = UnOpInit::HEAD;
96684c287e3SPeter Collingbourne break;
96784c287e3SPeter Collingbourne case tgtok::XTail:
96884c287e3SPeter Collingbourne Lex.Lex(); // eat the operation
96984c287e3SPeter Collingbourne Code = UnOpInit::TAIL;
97084c287e3SPeter Collingbourne break;
9710243aaf4SNicolai Haehnle case tgtok::XSize:
9720243aaf4SNicolai Haehnle Lex.Lex();
9730243aaf4SNicolai Haehnle Code = UnOpInit::SIZE;
9742ac3cd20SRiver Riddle Type = IntRecTy::get(Records);
9750243aaf4SNicolai Haehnle break;
97684c287e3SPeter Collingbourne case tgtok::XEmpty:
97784c287e3SPeter Collingbourne Lex.Lex(); // eat the operation
97884c287e3SPeter Collingbourne Code = UnOpInit::EMPTY;
9792ac3cd20SRiver Riddle Type = IntRecTy::get(Records);
98084c287e3SPeter Collingbourne break;
981876af264SPaul C. Anagnostopoulos case tgtok::XGetDagOp:
9821fed9a0cSSimon Tatham Lex.Lex(); // eat the operation
9831fed9a0cSSimon Tatham if (Lex.getCode() == tgtok::less) {
9841fed9a0cSSimon Tatham // Parse an optional type suffix, so that you can say
985876af264SPaul C. Anagnostopoulos // !getdagop<BaseClass>(someDag) as a shorthand for
986876af264SPaul C. Anagnostopoulos // !cast<BaseClass>(!getdagop(someDag)).
9871fed9a0cSSimon Tatham Type = ParseOperatorType();
9881fed9a0cSSimon Tatham
9891fed9a0cSSimon Tatham if (!Type) {
9901fed9a0cSSimon Tatham TokError("did not get type for unary operator");
9911fed9a0cSSimon Tatham return nullptr;
9921fed9a0cSSimon Tatham }
9931fed9a0cSSimon Tatham
9941fed9a0cSSimon Tatham if (!isa<RecordRecTy>(Type)) {
995876af264SPaul C. Anagnostopoulos TokError("type for !getdagop must be a record type");
9961fed9a0cSSimon Tatham // but keep parsing, to consume the operand
9971fed9a0cSSimon Tatham }
9981fed9a0cSSimon Tatham } else {
9992ac3cd20SRiver Riddle Type = RecordRecTy::get(Records, {});
10001fed9a0cSSimon Tatham }
1001876af264SPaul C. Anagnostopoulos Code = UnOpInit::GETDAGOP;
10021fed9a0cSSimon Tatham break;
100384c287e3SPeter Collingbourne }
1004e69605bfSFangrui Song if (!consume(tgtok::l_paren)) {
100584c287e3SPeter Collingbourne TokError("expected '(' after unary operator");
1006011817a0SCraig Topper return nullptr;
100784c287e3SPeter Collingbourne }
100884c287e3SPeter Collingbourne
100984c287e3SPeter Collingbourne Init *LHS = ParseValue(CurRec);
1010011817a0SCraig Topper if (!LHS) return nullptr;
101184c287e3SPeter Collingbourne
1012dc5d6632SPaul C. Anagnostopoulos if (Code == UnOpInit::EMPTY || Code == UnOpInit::SIZE) {
1013fb509ed1SSean Silva ListInit *LHSl = dyn_cast<ListInit>(LHS);
1014fb509ed1SSean Silva StringInit *LHSs = dyn_cast<StringInit>(LHS);
1015dc5d6632SPaul C. Anagnostopoulos DagInit *LHSd = dyn_cast<DagInit>(LHS);
1016fb509ed1SSean Silva TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
1017dc5d6632SPaul C. Anagnostopoulos if (!LHSl && !LHSs && !LHSd && !LHSt) {
1018dc5d6632SPaul C. Anagnostopoulos TokError("expected string, list, or dag type argument in unary operator");
1019011817a0SCraig Topper return nullptr;
102084c287e3SPeter Collingbourne }
102184c287e3SPeter Collingbourne if (LHSt) {
102298c61711SSean Silva ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
102398c61711SSean Silva StringRecTy *SType = dyn_cast<StringRecTy>(LHSt->getType());
1024dc5d6632SPaul C. Anagnostopoulos DagRecTy *DType = dyn_cast<DagRecTy>(LHSt->getType());
1025dc5d6632SPaul C. Anagnostopoulos if (!LType && !SType && !DType) {
1026dc5d6632SPaul C. Anagnostopoulos TokError("expected string, list, or dag type argument in unary operator");
1027011817a0SCraig Topper return nullptr;
102884c287e3SPeter Collingbourne }
102984c287e3SPeter Collingbourne }
1030dc5d6632SPaul C. Anagnostopoulos }
103184c287e3SPeter Collingbourne
1032dc5d6632SPaul C. Anagnostopoulos if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) {
1033dc5d6632SPaul C. Anagnostopoulos ListInit *LHSl = dyn_cast<ListInit>(LHS);
1034dc5d6632SPaul C. Anagnostopoulos TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
1035011817a0SCraig Topper if (!LHSl && !LHSt) {
10360757607dSMatt Arsenault TokError("expected list type argument in unary operator");
1037011817a0SCraig Topper return nullptr;
103884c287e3SPeter Collingbourne }
1039dc5d6632SPaul C. Anagnostopoulos if (LHSt) {
1040dc5d6632SPaul C. Anagnostopoulos ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
1041dc5d6632SPaul C. Anagnostopoulos if (!LType) {
1042dc5d6632SPaul C. Anagnostopoulos TokError("expected list type argument in unary operator");
1043dc5d6632SPaul C. Anagnostopoulos return nullptr;
1044dc5d6632SPaul C. Anagnostopoulos }
10450243aaf4SNicolai Haehnle }
104684c287e3SPeter Collingbourne
1047ec9072d6SCraig Topper if (LHSl && LHSl->empty()) {
104884c287e3SPeter Collingbourne TokError("empty list argument in unary operator");
1049011817a0SCraig Topper return nullptr;
105084c287e3SPeter Collingbourne }
105184c287e3SPeter Collingbourne if (LHSl) {
105284c287e3SPeter Collingbourne Init *Item = LHSl->getElement(0);
1053fb509ed1SSean Silva TypedInit *Itemt = dyn_cast<TypedInit>(Item);
1054011817a0SCraig Topper if (!Itemt) {
105584c287e3SPeter Collingbourne TokError("untyped list element in unary operator");
1056011817a0SCraig Topper return nullptr;
105784c287e3SPeter Collingbourne }
1058a9642b4eSCraig Topper Type = (Code == UnOpInit::HEAD) ? Itemt->getType()
1059a9642b4eSCraig Topper : ListRecTy::get(Itemt->getType());
106084c287e3SPeter Collingbourne } else {
106184c287e3SPeter Collingbourne assert(LHSt && "expected list type argument in unary operator");
106298c61711SSean Silva ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
1063a9642b4eSCraig Topper Type = (Code == UnOpInit::HEAD) ? LType->getElementType() : LType;
106484c287e3SPeter Collingbourne }
106584c287e3SPeter Collingbourne }
106684c287e3SPeter Collingbourne
1067e69605bfSFangrui Song if (!consume(tgtok::r_paren)) {
106884c287e3SPeter Collingbourne TokError("expected ')' in unary operator");
1069011817a0SCraig Topper return nullptr;
107084c287e3SPeter Collingbourne }
1071c47fe129SNicolai Haehnle return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec);
107284c287e3SPeter Collingbourne }
107384c287e3SPeter Collingbourne
1074b5376059SNicolai Haehnle case tgtok::XIsA: {
1075b5376059SNicolai Haehnle // Value ::= !isa '<' Type '>' '(' Value ')'
1076b5376059SNicolai Haehnle Lex.Lex(); // eat the operation
1077b5376059SNicolai Haehnle
1078b5376059SNicolai Haehnle RecTy *Type = ParseOperatorType();
1079b5376059SNicolai Haehnle if (!Type)
1080b5376059SNicolai Haehnle return nullptr;
1081b5376059SNicolai Haehnle
1082e69605bfSFangrui Song if (!consume(tgtok::l_paren)) {
1083b5376059SNicolai Haehnle TokError("expected '(' after type of !isa");
1084b5376059SNicolai Haehnle return nullptr;
1085b5376059SNicolai Haehnle }
1086b5376059SNicolai Haehnle
1087b5376059SNicolai Haehnle Init *LHS = ParseValue(CurRec);
1088b5376059SNicolai Haehnle if (!LHS)
1089b5376059SNicolai Haehnle return nullptr;
1090b5376059SNicolai Haehnle
1091e69605bfSFangrui Song if (!consume(tgtok::r_paren)) {
1092b5376059SNicolai Haehnle TokError("expected ')' in !isa");
1093b5376059SNicolai Haehnle return nullptr;
1094b5376059SNicolai Haehnle }
1095b5376059SNicolai Haehnle
1096b5376059SNicolai Haehnle return (IsAOpInit::get(Type, LHS))->Fold();
1097b5376059SNicolai Haehnle }
1098b5376059SNicolai Haehnle
109963448488Swangpc case tgtok::XExists: {
110063448488Swangpc // Value ::= !exists '<' Type '>' '(' Value ')'
110163448488Swangpc Lex.Lex(); // eat the operation
110263448488Swangpc
110363448488Swangpc RecTy *Type = ParseOperatorType();
110463448488Swangpc if (!Type)
110563448488Swangpc return nullptr;
110663448488Swangpc
110763448488Swangpc if (!consume(tgtok::l_paren)) {
110863448488Swangpc TokError("expected '(' after type of !exists");
110963448488Swangpc return nullptr;
111063448488Swangpc }
111163448488Swangpc
111263448488Swangpc SMLoc ExprLoc = Lex.getLoc();
111363448488Swangpc Init *Expr = ParseValue(CurRec);
111463448488Swangpc if (!Expr)
111563448488Swangpc return nullptr;
111663448488Swangpc
111763448488Swangpc TypedInit *ExprType = dyn_cast<TypedInit>(Expr);
111863448488Swangpc if (!ExprType) {
111963448488Swangpc Error(ExprLoc, "expected string type argument in !exists operator");
112063448488Swangpc return nullptr;
112163448488Swangpc }
112263448488Swangpc
112363448488Swangpc RecordRecTy *RecType = dyn_cast<RecordRecTy>(ExprType->getType());
112463448488Swangpc if (RecType) {
112563448488Swangpc Error(ExprLoc,
112663448488Swangpc "expected string type argument in !exists operator, please "
112763448488Swangpc "use !isa instead");
112863448488Swangpc return nullptr;
112963448488Swangpc }
113063448488Swangpc
113163448488Swangpc StringRecTy *SType = dyn_cast<StringRecTy>(ExprType->getType());
113263448488Swangpc if (!SType) {
113363448488Swangpc Error(ExprLoc, "expected string type argument in !exists operator");
113463448488Swangpc return nullptr;
113563448488Swangpc }
113663448488Swangpc
113763448488Swangpc if (!consume(tgtok::r_paren)) {
113863448488Swangpc TokError("expected ')' in !exists");
113963448488Swangpc return nullptr;
114063448488Swangpc }
114163448488Swangpc
114263448488Swangpc return (ExistsOpInit::get(Type, Expr))->Fold(CurRec);
114363448488Swangpc }
114463448488Swangpc
114584c287e3SPeter Collingbourne case tgtok::XConcat:
1146c7d4dc13SHal Finkel case tgtok::XADD:
11479d72065cSPaul C. Anagnostopoulos case tgtok::XSUB:
1148a8967569SNicola Zaghen case tgtok::XMUL:
11496b41a990SJoerg Sonnenberger case tgtok::XAND:
11501c8d9338SMatt Arsenault case tgtok::XOR:
11514767bb2cSPaul C. Anagnostopoulos case tgtok::XXOR:
115284c287e3SPeter Collingbourne case tgtok::XSRA:
115384c287e3SPeter Collingbourne case tgtok::XSRL:
115484c287e3SPeter Collingbourne case tgtok::XSHL:
115584c287e3SPeter Collingbourne case tgtok::XEq:
1156aa9ca691SNicolai Haehnle case tgtok::XNe:
1157aa9ca691SNicolai Haehnle case tgtok::XLe:
1158aa9ca691SNicolai Haehnle case tgtok::XLt:
1159aa9ca691SNicolai Haehnle case tgtok::XGe:
1160aa9ca691SNicolai Haehnle case tgtok::XGt:
1161314e80e5SDaniel Sanders case tgtok::XListConcat:
11625d9f656bSRoman Lebedev case tgtok::XListSplat:
11631fed9a0cSSimon Tatham case tgtok::XStrConcat:
1164d56cd429SPaul C. Anagnostopoulos case tgtok::XInterleave:
1165876af264SPaul C. Anagnostopoulos case tgtok::XSetDagOp: { // Value ::= !binop '(' Value ',' Value ')'
116684c287e3SPeter Collingbourne tgtok::TokKind OpTok = Lex.getCode();
116784c287e3SPeter Collingbourne SMLoc OpLoc = Lex.getLoc();
116884c287e3SPeter Collingbourne Lex.Lex(); // eat the operation
116984c287e3SPeter Collingbourne
117084c287e3SPeter Collingbourne BinOpInit::BinaryOp Code;
117184c287e3SPeter Collingbourne switch (OpTok) {
1172a2886c21SCraig Topper default: llvm_unreachable("Unhandled code!");
117377841b15SNicolai Haehnle case tgtok::XConcat: Code = BinOpInit::CONCAT; break;
117477841b15SNicolai Haehnle case tgtok::XADD: Code = BinOpInit::ADD; break;
11759d72065cSPaul C. Anagnostopoulos case tgtok::XSUB: Code = BinOpInit::SUB; break;
1176a8967569SNicola Zaghen case tgtok::XMUL: Code = BinOpInit::MUL; break;
117777841b15SNicolai Haehnle case tgtok::XAND: Code = BinOpInit::AND; break;
117877841b15SNicolai Haehnle case tgtok::XOR: Code = BinOpInit::OR; break;
11794767bb2cSPaul C. Anagnostopoulos case tgtok::XXOR: Code = BinOpInit::XOR; break;
118077841b15SNicolai Haehnle case tgtok::XSRA: Code = BinOpInit::SRA; break;
118177841b15SNicolai Haehnle case tgtok::XSRL: Code = BinOpInit::SRL; break;
118277841b15SNicolai Haehnle case tgtok::XSHL: Code = BinOpInit::SHL; break;
118377841b15SNicolai Haehnle case tgtok::XEq: Code = BinOpInit::EQ; break;
1184aa9ca691SNicolai Haehnle case tgtok::XNe: Code = BinOpInit::NE; break;
1185aa9ca691SNicolai Haehnle case tgtok::XLe: Code = BinOpInit::LE; break;
1186aa9ca691SNicolai Haehnle case tgtok::XLt: Code = BinOpInit::LT; break;
1187aa9ca691SNicolai Haehnle case tgtok::XGe: Code = BinOpInit::GE; break;
1188aa9ca691SNicolai Haehnle case tgtok::XGt: Code = BinOpInit::GT; break;
118977841b15SNicolai Haehnle case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break;
11905d9f656bSRoman Lebedev case tgtok::XListSplat: Code = BinOpInit::LISTSPLAT; break;
119177841b15SNicolai Haehnle case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;
1192d56cd429SPaul C. Anagnostopoulos case tgtok::XInterleave: Code = BinOpInit::INTERLEAVE; break;
1193876af264SPaul C. Anagnostopoulos case tgtok::XSetDagOp: Code = BinOpInit::SETDAGOP; break;
119477841b15SNicolai Haehnle }
119577841b15SNicolai Haehnle
119677841b15SNicolai Haehnle RecTy *Type = nullptr;
119777841b15SNicolai Haehnle RecTy *ArgType = nullptr;
119877841b15SNicolai Haehnle switch (OpTok) {
119977841b15SNicolai Haehnle default:
120077841b15SNicolai Haehnle llvm_unreachable("Unhandled code!");
120177841b15SNicolai Haehnle case tgtok::XConcat:
1202876af264SPaul C. Anagnostopoulos case tgtok::XSetDagOp:
12032ac3cd20SRiver Riddle Type = DagRecTy::get(Records);
12042ac3cd20SRiver Riddle ArgType = DagRecTy::get(Records);
120577841b15SNicolai Haehnle break;
120677841b15SNicolai Haehnle case tgtok::XAND:
120777841b15SNicolai Haehnle case tgtok::XOR:
12084767bb2cSPaul C. Anagnostopoulos case tgtok::XXOR:
120977841b15SNicolai Haehnle case tgtok::XSRA:
121077841b15SNicolai Haehnle case tgtok::XSRL:
121177841b15SNicolai Haehnle case tgtok::XSHL:
121277841b15SNicolai Haehnle case tgtok::XADD:
12139d72065cSPaul C. Anagnostopoulos case tgtok::XSUB:
1214a8967569SNicola Zaghen case tgtok::XMUL:
12152ac3cd20SRiver Riddle Type = IntRecTy::get(Records);
12162ac3cd20SRiver Riddle ArgType = IntRecTy::get(Records);
121777841b15SNicolai Haehnle break;
121877841b15SNicolai Haehnle case tgtok::XEq:
1219aa9ca691SNicolai Haehnle case tgtok::XNe:
1220aa9ca691SNicolai Haehnle case tgtok::XLe:
1221aa9ca691SNicolai Haehnle case tgtok::XLt:
1222aa9ca691SNicolai Haehnle case tgtok::XGe:
1223aa9ca691SNicolai Haehnle case tgtok::XGt:
12242ac3cd20SRiver Riddle Type = BitRecTy::get(Records);
1225641428f9SPaul C. Anagnostopoulos // ArgType for the comparison operators is not yet known.
122677841b15SNicolai Haehnle break;
1227314e80e5SDaniel Sanders case tgtok::XListConcat:
1228314e80e5SDaniel Sanders // We don't know the list type until we parse the first argument
122977841b15SNicolai Haehnle ArgType = ItemType;
1230314e80e5SDaniel Sanders break;
12315d9f656bSRoman Lebedev case tgtok::XListSplat:
12325d9f656bSRoman Lebedev // Can't do any typechecking until we parse the first argument.
12335d9f656bSRoman Lebedev break;
123484c287e3SPeter Collingbourne case tgtok::XStrConcat:
12352ac3cd20SRiver Riddle Type = StringRecTy::get(Records);
12362ac3cd20SRiver Riddle ArgType = StringRecTy::get(Records);
123784c287e3SPeter Collingbourne break;
1238d56cd429SPaul C. Anagnostopoulos case tgtok::XInterleave:
12392ac3cd20SRiver Riddle Type = StringRecTy::get(Records);
1240d56cd429SPaul C. Anagnostopoulos // The first argument type is not yet known.
124184c287e3SPeter Collingbourne }
124284c287e3SPeter Collingbourne
124377841b15SNicolai Haehnle if (Type && ItemType && !Type->typeIsConvertibleTo(ItemType)) {
124477841b15SNicolai Haehnle Error(OpLoc, Twine("expected value of type '") +
124577841b15SNicolai Haehnle ItemType->getAsString() + "', got '" +
124677841b15SNicolai Haehnle Type->getAsString() + "'");
124777841b15SNicolai Haehnle return nullptr;
124877841b15SNicolai Haehnle }
124977841b15SNicolai Haehnle
1250e69605bfSFangrui Song if (!consume(tgtok::l_paren)) {
125184c287e3SPeter Collingbourne TokError("expected '(' after binary operator");
1252011817a0SCraig Topper return nullptr;
125384c287e3SPeter Collingbourne }
125484c287e3SPeter Collingbourne
125584c287e3SPeter Collingbourne SmallVector<Init*, 2> InitList;
125684c287e3SPeter Collingbourne
1257d56cd429SPaul C. Anagnostopoulos // Note that this loop consumes an arbitrary number of arguments.
1258d56cd429SPaul C. Anagnostopoulos // The actual count is checked later.
125977841b15SNicolai Haehnle for (;;) {
126077841b15SNicolai Haehnle SMLoc InitLoc = Lex.getLoc();
126177841b15SNicolai Haehnle InitList.push_back(ParseValue(CurRec, ArgType));
1262011817a0SCraig Topper if (!InitList.back()) return nullptr;
126384c287e3SPeter Collingbourne
12642c8ee532SDaniel Sanders TypedInit *InitListBack = dyn_cast<TypedInit>(InitList.back());
12652c8ee532SDaniel Sanders if (!InitListBack) {
12662c8ee532SDaniel Sanders Error(OpLoc, Twine("expected value to be a typed value, got '" +
12672c8ee532SDaniel Sanders InitList.back()->getAsString() + "'"));
12682c8ee532SDaniel Sanders return nullptr;
12692c8ee532SDaniel Sanders }
12702c8ee532SDaniel Sanders RecTy *ListType = InitListBack->getType();
1271d56cd429SPaul C. Anagnostopoulos
127277841b15SNicolai Haehnle if (!ArgType) {
1273d56cd429SPaul C. Anagnostopoulos // Argument type must be determined from the argument itself.
12745c6ea055SSimon Pilgrim ArgType = ListType;
127577841b15SNicolai Haehnle
127677841b15SNicolai Haehnle switch (Code) {
127777841b15SNicolai Haehnle case BinOpInit::LISTCONCAT:
127877841b15SNicolai Haehnle if (!isa<ListRecTy>(ArgType)) {
127977841b15SNicolai Haehnle Error(InitLoc, Twine("expected a list, got value of type '") +
128077841b15SNicolai Haehnle ArgType->getAsString() + "'");
128177841b15SNicolai Haehnle return nullptr;
128277841b15SNicolai Haehnle }
128377841b15SNicolai Haehnle break;
12845d9f656bSRoman Lebedev case BinOpInit::LISTSPLAT:
12855d9f656bSRoman Lebedev if (ItemType && InitList.size() == 1) {
12865d9f656bSRoman Lebedev if (!isa<ListRecTy>(ItemType)) {
12875d9f656bSRoman Lebedev Error(OpLoc,
12885d9f656bSRoman Lebedev Twine("expected output type to be a list, got type '") +
12895d9f656bSRoman Lebedev ItemType->getAsString() + "'");
12905d9f656bSRoman Lebedev return nullptr;
12915d9f656bSRoman Lebedev }
12925d9f656bSRoman Lebedev if (!ArgType->getListTy()->typeIsConvertibleTo(ItemType)) {
12935d9f656bSRoman Lebedev Error(OpLoc, Twine("expected first arg type to be '") +
12945d9f656bSRoman Lebedev ArgType->getAsString() +
12955d9f656bSRoman Lebedev "', got value of type '" +
12965d9f656bSRoman Lebedev cast<ListRecTy>(ItemType)
12975d9f656bSRoman Lebedev ->getElementType()
12985d9f656bSRoman Lebedev ->getAsString() +
12995d9f656bSRoman Lebedev "'");
13005d9f656bSRoman Lebedev return nullptr;
13015d9f656bSRoman Lebedev }
13025d9f656bSRoman Lebedev }
13035d9f656bSRoman Lebedev if (InitList.size() == 2 && !isa<IntRecTy>(ArgType)) {
13045d9f656bSRoman Lebedev Error(InitLoc, Twine("expected second parameter to be an int, got "
13055d9f656bSRoman Lebedev "value of type '") +
13065d9f656bSRoman Lebedev ArgType->getAsString() + "'");
13075d9f656bSRoman Lebedev return nullptr;
13085d9f656bSRoman Lebedev }
13095d9f656bSRoman Lebedev ArgType = nullptr; // Broken invariant: types not identical.
13105d9f656bSRoman Lebedev break;
131177841b15SNicolai Haehnle case BinOpInit::EQ:
1312aa9ca691SNicolai Haehnle case BinOpInit::NE:
13132ac3cd20SRiver Riddle if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&
13142ac3cd20SRiver Riddle !ArgType->typeIsConvertibleTo(StringRecTy::get(Records)) &&
13152ac3cd20SRiver Riddle !ArgType->typeIsConvertibleTo(RecordRecTy::get(Records, {}))) {
1316641428f9SPaul C. Anagnostopoulos Error(InitLoc, Twine("expected bit, bits, int, string, or record; "
1317641428f9SPaul C. Anagnostopoulos "got value of type '") + ArgType->getAsString() +
1318641428f9SPaul C. Anagnostopoulos "'");
1319641428f9SPaul C. Anagnostopoulos return nullptr;
1320641428f9SPaul C. Anagnostopoulos }
1321641428f9SPaul C. Anagnostopoulos break;
1322641428f9SPaul C. Anagnostopoulos case BinOpInit::LE:
1323641428f9SPaul C. Anagnostopoulos case BinOpInit::LT:
1324641428f9SPaul C. Anagnostopoulos case BinOpInit::GE:
1325641428f9SPaul C. Anagnostopoulos case BinOpInit::GT:
13262ac3cd20SRiver Riddle if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&
13272ac3cd20SRiver Riddle !ArgType->typeIsConvertibleTo(StringRecTy::get(Records))) {
1328641428f9SPaul C. Anagnostopoulos Error(InitLoc, Twine("expected bit, bits, int, or string; "
1329641428f9SPaul C. Anagnostopoulos "got value of type '") + ArgType->getAsString() +
1330641428f9SPaul C. Anagnostopoulos "'");
133177841b15SNicolai Haehnle return nullptr;
133277841b15SNicolai Haehnle }
133377841b15SNicolai Haehnle break;
1334d56cd429SPaul C. Anagnostopoulos case BinOpInit::INTERLEAVE:
1335d56cd429SPaul C. Anagnostopoulos switch (InitList.size()) {
1336d56cd429SPaul C. Anagnostopoulos case 1: // First argument must be a list of strings or integers.
13372ac3cd20SRiver Riddle if (ArgType != StringRecTy::get(Records)->getListTy() &&
13382ac3cd20SRiver Riddle !ArgType->typeIsConvertibleTo(
13392ac3cd20SRiver Riddle IntRecTy::get(Records)->getListTy())) {
1340d56cd429SPaul C. Anagnostopoulos Error(InitLoc, Twine("expected list of string, int, bits, or bit; "
1341d56cd429SPaul C. Anagnostopoulos "got value of type '") +
1342d56cd429SPaul C. Anagnostopoulos ArgType->getAsString() + "'");
1343d56cd429SPaul C. Anagnostopoulos return nullptr;
1344d56cd429SPaul C. Anagnostopoulos }
1345d56cd429SPaul C. Anagnostopoulos break;
1346d56cd429SPaul C. Anagnostopoulos case 2: // Second argument must be a string.
1347d56cd429SPaul C. Anagnostopoulos if (!isa<StringRecTy>(ArgType)) {
1348d56cd429SPaul C. Anagnostopoulos Error(InitLoc, Twine("expected second argument to be a string, "
1349d56cd429SPaul C. Anagnostopoulos "got value of type '") +
1350d56cd429SPaul C. Anagnostopoulos ArgType->getAsString() + "'");
1351d56cd429SPaul C. Anagnostopoulos return nullptr;
1352d56cd429SPaul C. Anagnostopoulos }
1353d56cd429SPaul C. Anagnostopoulos break;
1354d56cd429SPaul C. Anagnostopoulos default: ;
1355d56cd429SPaul C. Anagnostopoulos }
1356d56cd429SPaul C. Anagnostopoulos ArgType = nullptr; // Broken invariant: types not identical.
1357d56cd429SPaul C. Anagnostopoulos break;
135877841b15SNicolai Haehnle default: llvm_unreachable("other ops have fixed argument types");
135977841b15SNicolai Haehnle }
1360d56cd429SPaul C. Anagnostopoulos
136177841b15SNicolai Haehnle } else {
1362d56cd429SPaul C. Anagnostopoulos // Desired argument type is a known and in ArgType.
13635c6ea055SSimon Pilgrim RecTy *Resolved = resolveTypes(ArgType, ListType);
136477841b15SNicolai Haehnle if (!Resolved) {
136577841b15SNicolai Haehnle Error(InitLoc, Twine("expected value of type '") +
136677841b15SNicolai Haehnle ArgType->getAsString() + "', got '" +
13675c6ea055SSimon Pilgrim ListType->getAsString() + "'");
136877841b15SNicolai Haehnle return nullptr;
136977841b15SNicolai Haehnle }
13709d72065cSPaul C. Anagnostopoulos if (Code != BinOpInit::ADD && Code != BinOpInit::SUB &&
13719d72065cSPaul C. Anagnostopoulos Code != BinOpInit::AND && Code != BinOpInit::OR &&
13729d72065cSPaul C. Anagnostopoulos Code != BinOpInit::XOR && Code != BinOpInit::SRA &&
13739d72065cSPaul C. Anagnostopoulos Code != BinOpInit::SRL && Code != BinOpInit::SHL &&
13749d72065cSPaul C. Anagnostopoulos Code != BinOpInit::MUL)
137577841b15SNicolai Haehnle ArgType = Resolved;
137677841b15SNicolai Haehnle }
137777841b15SNicolai Haehnle
13781fed9a0cSSimon Tatham // Deal with BinOps whose arguments have different types, by
13791fed9a0cSSimon Tatham // rewriting ArgType in between them.
13801fed9a0cSSimon Tatham switch (Code) {
1381876af264SPaul C. Anagnostopoulos case BinOpInit::SETDAGOP:
13821fed9a0cSSimon Tatham // After parsing the first dag argument, switch to expecting
13831fed9a0cSSimon Tatham // a record, with no restriction on its superclasses.
13842ac3cd20SRiver Riddle ArgType = RecordRecTy::get(Records, {});
13851fed9a0cSSimon Tatham break;
13861fed9a0cSSimon Tatham default:
13871fed9a0cSSimon Tatham break;
13881fed9a0cSSimon Tatham }
13891fed9a0cSSimon Tatham
1390e69605bfSFangrui Song if (!consume(tgtok::comma))
139177841b15SNicolai Haehnle break;
139284c287e3SPeter Collingbourne }
139384c287e3SPeter Collingbourne
1394e69605bfSFangrui Song if (!consume(tgtok::r_paren)) {
139584c287e3SPeter Collingbourne TokError("expected ')' in operator");
1396011817a0SCraig Topper return nullptr;
139784c287e3SPeter Collingbourne }
139884c287e3SPeter Collingbourne
13995d9f656bSRoman Lebedev // listconcat returns a list with type of the argument.
140077841b15SNicolai Haehnle if (Code == BinOpInit::LISTCONCAT)
140177841b15SNicolai Haehnle Type = ArgType;
14025d9f656bSRoman Lebedev // listsplat returns a list of type of the *first* argument.
14035d9f656bSRoman Lebedev if (Code == BinOpInit::LISTSPLAT)
14045d9f656bSRoman Lebedev Type = cast<TypedInit>(InitList.front())->getType()->getListTy();
1405314e80e5SDaniel Sanders
140684c287e3SPeter Collingbourne // We allow multiple operands to associative operators like !strconcat as
140784c287e3SPeter Collingbourne // shorthand for nesting them.
140877841b15SNicolai Haehnle if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT ||
140977841b15SNicolai Haehnle Code == BinOpInit::CONCAT || Code == BinOpInit::ADD ||
1410a8967569SNicola Zaghen Code == BinOpInit::AND || Code == BinOpInit::OR ||
14114767bb2cSPaul C. Anagnostopoulos Code == BinOpInit::XOR || Code == BinOpInit::MUL) {
141284c287e3SPeter Collingbourne while (InitList.size() > 2) {
141384c287e3SPeter Collingbourne Init *RHS = InitList.pop_back_val();
1414c47fe129SNicolai Haehnle RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec);
141584c287e3SPeter Collingbourne InitList.back() = RHS;
141684c287e3SPeter Collingbourne }
141784c287e3SPeter Collingbourne }
141884c287e3SPeter Collingbourne
141984c287e3SPeter Collingbourne if (InitList.size() == 2)
142084c287e3SPeter Collingbourne return (BinOpInit::get(Code, InitList[0], InitList[1], Type))
1421c47fe129SNicolai Haehnle ->Fold(CurRec);
142284c287e3SPeter Collingbourne
142384c287e3SPeter Collingbourne Error(OpLoc, "expected two operands to operator");
1424011817a0SCraig Topper return nullptr;
142584c287e3SPeter Collingbourne }
142684c287e3SPeter Collingbourne
142791d2e5c8SPaul C. Anagnostopoulos case tgtok::XForEach:
142891d2e5c8SPaul C. Anagnostopoulos case tgtok::XFilter: {
142991d2e5c8SPaul C. Anagnostopoulos return ParseOperationForEachFilter(CurRec, ItemType);
14308ebf7e4dSNicolai Haehnle }
14318ebf7e4dSNicolai Haehnle
14326c118656SNicolai Haehnle case tgtok::XDag:
143384c287e3SPeter Collingbourne case tgtok::XIf:
143484c287e3SPeter Collingbourne case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
143584c287e3SPeter Collingbourne TernOpInit::TernaryOp Code;
1436011817a0SCraig Topper RecTy *Type = nullptr;
143784c287e3SPeter Collingbourne
143884c287e3SPeter Collingbourne tgtok::TokKind LexCode = Lex.getCode();
143984c287e3SPeter Collingbourne Lex.Lex(); // eat the operation
144084c287e3SPeter Collingbourne switch (LexCode) {
1441a2886c21SCraig Topper default: llvm_unreachable("Unhandled code!");
14426c118656SNicolai Haehnle case tgtok::XDag:
14436c118656SNicolai Haehnle Code = TernOpInit::DAG;
14442ac3cd20SRiver Riddle Type = DagRecTy::get(Records);
14456c118656SNicolai Haehnle ItemType = nullptr;
14466c118656SNicolai Haehnle break;
144784c287e3SPeter Collingbourne case tgtok::XIf:
144884c287e3SPeter Collingbourne Code = TernOpInit::IF;
144984c287e3SPeter Collingbourne break;
145084c287e3SPeter Collingbourne case tgtok::XSubst:
145184c287e3SPeter Collingbourne Code = TernOpInit::SUBST;
145284c287e3SPeter Collingbourne break;
145384c287e3SPeter Collingbourne }
1454e69605bfSFangrui Song if (!consume(tgtok::l_paren)) {
145584c287e3SPeter Collingbourne TokError("expected '(' after ternary operator");
1456011817a0SCraig Topper return nullptr;
145784c287e3SPeter Collingbourne }
145884c287e3SPeter Collingbourne
145984c287e3SPeter Collingbourne Init *LHS = ParseValue(CurRec);
1460011817a0SCraig Topper if (!LHS) return nullptr;
146184c287e3SPeter Collingbourne
1462e69605bfSFangrui Song if (!consume(tgtok::comma)) {
146384c287e3SPeter Collingbourne TokError("expected ',' in ternary operator");
1464011817a0SCraig Topper return nullptr;
146584c287e3SPeter Collingbourne }
146684c287e3SPeter Collingbourne
14676c118656SNicolai Haehnle SMLoc MHSLoc = Lex.getLoc();
1468a73fd935SMatt Arsenault Init *MHS = ParseValue(CurRec, ItemType);
1469a73fd935SMatt Arsenault if (!MHS)
1470a73fd935SMatt Arsenault return nullptr;
147184c287e3SPeter Collingbourne
1472e69605bfSFangrui Song if (!consume(tgtok::comma)) {
147384c287e3SPeter Collingbourne TokError("expected ',' in ternary operator");
1474011817a0SCraig Topper return nullptr;
147584c287e3SPeter Collingbourne }
147684c287e3SPeter Collingbourne
14776c118656SNicolai Haehnle SMLoc RHSLoc = Lex.getLoc();
1478a73fd935SMatt Arsenault Init *RHS = ParseValue(CurRec, ItemType);
1479a73fd935SMatt Arsenault if (!RHS)
1480a73fd935SMatt Arsenault return nullptr;
148184c287e3SPeter Collingbourne
1482e69605bfSFangrui Song if (!consume(tgtok::r_paren)) {
148384c287e3SPeter Collingbourne TokError("expected ')' in binary operator");
1484011817a0SCraig Topper return nullptr;
148584c287e3SPeter Collingbourne }
148684c287e3SPeter Collingbourne
148784c287e3SPeter Collingbourne switch (LexCode) {
1488a2886c21SCraig Topper default: llvm_unreachable("Unhandled code!");
14896c118656SNicolai Haehnle case tgtok::XDag: {
14906c118656SNicolai Haehnle TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
14916c118656SNicolai Haehnle if (!MHSt && !isa<UnsetInit>(MHS)) {
14926c118656SNicolai Haehnle Error(MHSLoc, "could not determine type of the child list in !dag");
14936c118656SNicolai Haehnle return nullptr;
14946c118656SNicolai Haehnle }
14956c118656SNicolai Haehnle if (MHSt && !isa<ListRecTy>(MHSt->getType())) {
14966c118656SNicolai Haehnle Error(MHSLoc, Twine("expected list of children, got type '") +
14976c118656SNicolai Haehnle MHSt->getType()->getAsString() + "'");
14986c118656SNicolai Haehnle return nullptr;
14996c118656SNicolai Haehnle }
15006c118656SNicolai Haehnle
15016c118656SNicolai Haehnle TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
15026c118656SNicolai Haehnle if (!RHSt && !isa<UnsetInit>(RHS)) {
15036c118656SNicolai Haehnle Error(RHSLoc, "could not determine type of the name list in !dag");
15046c118656SNicolai Haehnle return nullptr;
15056c118656SNicolai Haehnle }
15062ac3cd20SRiver Riddle if (RHSt && StringRecTy::get(Records)->getListTy() != RHSt->getType()) {
15076c118656SNicolai Haehnle Error(RHSLoc, Twine("expected list<string>, got type '") +
15086c118656SNicolai Haehnle RHSt->getType()->getAsString() + "'");
15096c118656SNicolai Haehnle return nullptr;
15106c118656SNicolai Haehnle }
15116c118656SNicolai Haehnle
15126c118656SNicolai Haehnle if (!MHSt && !RHSt) {
15136c118656SNicolai Haehnle Error(MHSLoc,
15146c118656SNicolai Haehnle "cannot have both unset children and unset names in !dag");
15156c118656SNicolai Haehnle return nullptr;
15166c118656SNicolai Haehnle }
15176c118656SNicolai Haehnle break;
15186c118656SNicolai Haehnle }
151984c287e3SPeter Collingbourne case tgtok::XIf: {
1520011817a0SCraig Topper RecTy *MHSTy = nullptr;
1521011817a0SCraig Topper RecTy *RHSTy = nullptr;
152284c287e3SPeter Collingbourne
1523fb509ed1SSean Silva if (TypedInit *MHSt = dyn_cast<TypedInit>(MHS))
152484c287e3SPeter Collingbourne MHSTy = MHSt->getType();
1525fb509ed1SSean Silva if (BitsInit *MHSbits = dyn_cast<BitsInit>(MHS))
15262ac3cd20SRiver Riddle MHSTy = BitsRecTy::get(Records, MHSbits->getNumBits());
152788eb8dd4SSean Silva if (isa<BitInit>(MHS))
15282ac3cd20SRiver Riddle MHSTy = BitRecTy::get(Records);
1529026f8333SMichael Liao
1530fb509ed1SSean Silva if (TypedInit *RHSt = dyn_cast<TypedInit>(RHS))
153184c287e3SPeter Collingbourne RHSTy = RHSt->getType();
1532fb509ed1SSean Silva if (BitsInit *RHSbits = dyn_cast<BitsInit>(RHS))
15332ac3cd20SRiver Riddle RHSTy = BitsRecTy::get(Records, RHSbits->getNumBits());
153488eb8dd4SSean Silva if (isa<BitInit>(RHS))
15352ac3cd20SRiver Riddle RHSTy = BitRecTy::get(Records);
1536026f8333SMichael Liao
1537026f8333SMichael Liao // For UnsetInit, it's typed from the other hand.
153888eb8dd4SSean Silva if (isa<UnsetInit>(MHS))
1539026f8333SMichael Liao MHSTy = RHSTy;
154088eb8dd4SSean Silva if (isa<UnsetInit>(RHS))
1541026f8333SMichael Liao RHSTy = MHSTy;
154284c287e3SPeter Collingbourne
154384c287e3SPeter Collingbourne if (!MHSTy || !RHSTy) {
154484c287e3SPeter Collingbourne TokError("could not get type for !if");
1545011817a0SCraig Topper return nullptr;
154684c287e3SPeter Collingbourne }
154784c287e3SPeter Collingbourne
154813080fd1SNicolai Haehnle Type = resolveTypes(MHSTy, RHSTy);
154913080fd1SNicolai Haehnle if (!Type) {
155013080fd1SNicolai Haehnle TokError(Twine("inconsistent types '") + MHSTy->getAsString() +
155113080fd1SNicolai Haehnle "' and '" + RHSTy->getAsString() + "' for !if");
1552011817a0SCraig Topper return nullptr;
155384c287e3SPeter Collingbourne }
155484c287e3SPeter Collingbourne break;
155584c287e3SPeter Collingbourne }
155684c287e3SPeter Collingbourne case tgtok::XSubst: {
1557fb509ed1SSean Silva TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
1558011817a0SCraig Topper if (!RHSt) {
155984c287e3SPeter Collingbourne TokError("could not get type for !subst");
1560011817a0SCraig Topper return nullptr;
156184c287e3SPeter Collingbourne }
156284c287e3SPeter Collingbourne Type = RHSt->getType();
156384c287e3SPeter Collingbourne break;
156484c287e3SPeter Collingbourne }
156584c287e3SPeter Collingbourne }
1566c47fe129SNicolai Haehnle return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);
156784c287e3SPeter Collingbourne }
1568d34f6843SNicolai Haehnle
1569e122a71aSPaul C. Anagnostopoulos case tgtok::XSubstr:
1570e122a71aSPaul C. Anagnostopoulos return ParseOperationSubstr(CurRec, ItemType);
1571e122a71aSPaul C. Anagnostopoulos
1572952c6dddSPaul C. Anagnostopoulos case tgtok::XFind:
1573952c6dddSPaul C. Anagnostopoulos return ParseOperationFind(CurRec, ItemType);
1574952c6dddSPaul C. Anagnostopoulos
1575a3e3d852SJaved Absar case tgtok::XCond:
1576a3e3d852SJaved Absar return ParseOperationCond(CurRec, ItemType);
1577a3e3d852SJaved Absar
1578d34f6843SNicolai Haehnle case tgtok::XFoldl: {
1579b3931188SPaul C. Anagnostopoulos // Value ::= !foldl '(' Value ',' Value ',' Id ',' Id ',' Expr ')'
1580d34f6843SNicolai Haehnle Lex.Lex(); // eat the operation
1581e69605bfSFangrui Song if (!consume(tgtok::l_paren)) {
1582d34f6843SNicolai Haehnle TokError("expected '(' after !foldl");
1583d34f6843SNicolai Haehnle return nullptr;
1584d34f6843SNicolai Haehnle }
1585d34f6843SNicolai Haehnle
1586d34f6843SNicolai Haehnle Init *StartUntyped = ParseValue(CurRec);
1587d34f6843SNicolai Haehnle if (!StartUntyped)
1588d34f6843SNicolai Haehnle return nullptr;
1589d34f6843SNicolai Haehnle
1590d34f6843SNicolai Haehnle TypedInit *Start = dyn_cast<TypedInit>(StartUntyped);
1591d34f6843SNicolai Haehnle if (!Start) {
1592d34f6843SNicolai Haehnle TokError(Twine("could not get type of !foldl start: '") +
1593d34f6843SNicolai Haehnle StartUntyped->getAsString() + "'");
1594d34f6843SNicolai Haehnle return nullptr;
1595d34f6843SNicolai Haehnle }
1596d34f6843SNicolai Haehnle
1597e69605bfSFangrui Song if (!consume(tgtok::comma)) {
1598d34f6843SNicolai Haehnle TokError("expected ',' in !foldl");
1599d34f6843SNicolai Haehnle return nullptr;
1600d34f6843SNicolai Haehnle }
1601d34f6843SNicolai Haehnle
1602d34f6843SNicolai Haehnle Init *ListUntyped = ParseValue(CurRec);
1603d34f6843SNicolai Haehnle if (!ListUntyped)
1604d34f6843SNicolai Haehnle return nullptr;
1605d34f6843SNicolai Haehnle
1606d34f6843SNicolai Haehnle TypedInit *List = dyn_cast<TypedInit>(ListUntyped);
1607d34f6843SNicolai Haehnle if (!List) {
1608d34f6843SNicolai Haehnle TokError(Twine("could not get type of !foldl list: '") +
1609d34f6843SNicolai Haehnle ListUntyped->getAsString() + "'");
1610d34f6843SNicolai Haehnle return nullptr;
1611d34f6843SNicolai Haehnle }
1612d34f6843SNicolai Haehnle
1613d34f6843SNicolai Haehnle ListRecTy *ListType = dyn_cast<ListRecTy>(List->getType());
1614d34f6843SNicolai Haehnle if (!ListType) {
1615d34f6843SNicolai Haehnle TokError(Twine("!foldl list must be a list, but is of type '") +
1616d34f6843SNicolai Haehnle List->getType()->getAsString());
1617d34f6843SNicolai Haehnle return nullptr;
1618d34f6843SNicolai Haehnle }
1619d34f6843SNicolai Haehnle
1620d34f6843SNicolai Haehnle if (Lex.getCode() != tgtok::comma) {
1621d34f6843SNicolai Haehnle TokError("expected ',' in !foldl");
1622d34f6843SNicolai Haehnle return nullptr;
1623d34f6843SNicolai Haehnle }
1624d34f6843SNicolai Haehnle
1625d34f6843SNicolai Haehnle if (Lex.Lex() != tgtok::Id) { // eat the ','
1626d34f6843SNicolai Haehnle TokError("third argument of !foldl must be an identifier");
1627d34f6843SNicolai Haehnle return nullptr;
1628d34f6843SNicolai Haehnle }
1629d34f6843SNicolai Haehnle
16302ac3cd20SRiver Riddle Init *A = StringInit::get(Records, Lex.getCurStrVal());
16317d69e0f3SNicolai Haehnle if (CurRec && CurRec->getValue(A)) {
1632d34f6843SNicolai Haehnle TokError((Twine("left !foldl variable '") + A->getAsString() +
1633d34f6843SNicolai Haehnle "' already defined")
1634d34f6843SNicolai Haehnle .str());
1635d34f6843SNicolai Haehnle return nullptr;
1636d34f6843SNicolai Haehnle }
1637d34f6843SNicolai Haehnle
1638d34f6843SNicolai Haehnle if (Lex.Lex() != tgtok::comma) { // eat the id
1639d34f6843SNicolai Haehnle TokError("expected ',' in !foldl");
1640d34f6843SNicolai Haehnle return nullptr;
1641d34f6843SNicolai Haehnle }
1642d34f6843SNicolai Haehnle
1643d34f6843SNicolai Haehnle if (Lex.Lex() != tgtok::Id) { // eat the ','
1644d34f6843SNicolai Haehnle TokError("fourth argument of !foldl must be an identifier");
1645d34f6843SNicolai Haehnle return nullptr;
1646d34f6843SNicolai Haehnle }
1647d34f6843SNicolai Haehnle
16482ac3cd20SRiver Riddle Init *B = StringInit::get(Records, Lex.getCurStrVal());
16497d69e0f3SNicolai Haehnle if (CurRec && CurRec->getValue(B)) {
1650d34f6843SNicolai Haehnle TokError((Twine("right !foldl variable '") + B->getAsString() +
1651d34f6843SNicolai Haehnle "' already defined")
1652d34f6843SNicolai Haehnle .str());
1653d34f6843SNicolai Haehnle return nullptr;
1654d34f6843SNicolai Haehnle }
1655d34f6843SNicolai Haehnle
1656d34f6843SNicolai Haehnle if (Lex.Lex() != tgtok::comma) { // eat the id
1657d34f6843SNicolai Haehnle TokError("expected ',' in !foldl");
1658d34f6843SNicolai Haehnle return nullptr;
1659d34f6843SNicolai Haehnle }
1660d34f6843SNicolai Haehnle Lex.Lex(); // eat the ','
1661d34f6843SNicolai Haehnle
1662b3931188SPaul C. Anagnostopoulos // We need to create a temporary record to provide a scope for the
1663b3931188SPaul C. Anagnostopoulos // two variables.
16647d69e0f3SNicolai Haehnle std::unique_ptr<Record> ParseRecTmp;
16657d69e0f3SNicolai Haehnle Record *ParseRec = CurRec;
16667d69e0f3SNicolai Haehnle if (!ParseRec) {
16670eaee545SJonas Devlieghere ParseRecTmp = std::make_unique<Record>(".parse", ArrayRef<SMLoc>{}, Records);
16687d69e0f3SNicolai Haehnle ParseRec = ParseRecTmp.get();
16697d69e0f3SNicolai Haehnle }
16707d69e0f3SNicolai Haehnle
1671aa7968a8SPaul C. Anagnostopoulos ParseRec->addValue(RecordVal(A, Start->getType(), RecordVal::FK_Normal));
1672aa7968a8SPaul C. Anagnostopoulos ParseRec->addValue(RecordVal(B, ListType->getElementType(),
1673aa7968a8SPaul C. Anagnostopoulos RecordVal::FK_Normal));
16747d69e0f3SNicolai Haehnle Init *ExprUntyped = ParseValue(ParseRec);
16757d69e0f3SNicolai Haehnle ParseRec->removeValue(A);
16767d69e0f3SNicolai Haehnle ParseRec->removeValue(B);
1677d34f6843SNicolai Haehnle if (!ExprUntyped)
1678d34f6843SNicolai Haehnle return nullptr;
1679d34f6843SNicolai Haehnle
1680d34f6843SNicolai Haehnle TypedInit *Expr = dyn_cast<TypedInit>(ExprUntyped);
1681d34f6843SNicolai Haehnle if (!Expr) {
1682d34f6843SNicolai Haehnle TokError("could not get type of !foldl expression");
1683d34f6843SNicolai Haehnle return nullptr;
1684d34f6843SNicolai Haehnle }
1685d34f6843SNicolai Haehnle
1686d34f6843SNicolai Haehnle if (Expr->getType() != Start->getType()) {
1687d34f6843SNicolai Haehnle TokError(Twine("!foldl expression must be of same type as start (") +
1688d34f6843SNicolai Haehnle Start->getType()->getAsString() + "), but is of type " +
1689d34f6843SNicolai Haehnle Expr->getType()->getAsString());
1690d34f6843SNicolai Haehnle return nullptr;
1691d34f6843SNicolai Haehnle }
1692d34f6843SNicolai Haehnle
1693e69605bfSFangrui Song if (!consume(tgtok::r_paren)) {
1694d34f6843SNicolai Haehnle TokError("expected ')' in fold operator");
1695d34f6843SNicolai Haehnle return nullptr;
1696d34f6843SNicolai Haehnle }
1697d34f6843SNicolai Haehnle
1698d34f6843SNicolai Haehnle return FoldOpInit::get(Start, List, A, B, Expr, Start->getType())
1699d34f6843SNicolai Haehnle ->Fold(CurRec);
1700d34f6843SNicolai Haehnle }
170184c287e3SPeter Collingbourne }
170284c287e3SPeter Collingbourne }
170384c287e3SPeter Collingbourne
170484c287e3SPeter Collingbourne /// ParseOperatorType - Parse a type for an operator. This returns
170584c287e3SPeter Collingbourne /// null on error.
170684c287e3SPeter Collingbourne ///
170784c287e3SPeter Collingbourne /// OperatorType ::= '<' Type '>'
170884c287e3SPeter Collingbourne ///
ParseOperatorType()170984c287e3SPeter Collingbourne RecTy *TGParser::ParseOperatorType() {
1710011817a0SCraig Topper RecTy *Type = nullptr;
171184c287e3SPeter Collingbourne
1712e69605bfSFangrui Song if (!consume(tgtok::less)) {
171384c287e3SPeter Collingbourne TokError("expected type name for operator");
1714011817a0SCraig Topper return nullptr;
171584c287e3SPeter Collingbourne }
171684c287e3SPeter Collingbourne
1717415fab6fSPaul C. Anagnostopoulos if (Lex.getCode() == tgtok::Code)
1718415fab6fSPaul C. Anagnostopoulos TokError("the 'code' type is not allowed in bang operators; use 'string'");
1719415fab6fSPaul C. Anagnostopoulos
172084c287e3SPeter Collingbourne Type = ParseType();
172184c287e3SPeter Collingbourne
1722011817a0SCraig Topper if (!Type) {
172384c287e3SPeter Collingbourne TokError("expected type name for operator");
1724011817a0SCraig Topper return nullptr;
172584c287e3SPeter Collingbourne }
172684c287e3SPeter Collingbourne
1727e69605bfSFangrui Song if (!consume(tgtok::greater)) {
172884c287e3SPeter Collingbourne TokError("expected type name for operator");
1729011817a0SCraig Topper return nullptr;
173084c287e3SPeter Collingbourne }
173184c287e3SPeter Collingbourne
173284c287e3SPeter Collingbourne return Type;
173384c287e3SPeter Collingbourne }
173484c287e3SPeter Collingbourne
1735e122a71aSPaul C. Anagnostopoulos /// Parse the !substr operation. Return null on error.
1736e122a71aSPaul C. Anagnostopoulos ///
1737e122a71aSPaul C. Anagnostopoulos /// Substr ::= !substr(string, start-int [, length-int]) => string
ParseOperationSubstr(Record * CurRec,RecTy * ItemType)1738e122a71aSPaul C. Anagnostopoulos Init *TGParser::ParseOperationSubstr(Record *CurRec, RecTy *ItemType) {
1739e122a71aSPaul C. Anagnostopoulos TernOpInit::TernaryOp Code = TernOpInit::SUBSTR;
17402ac3cd20SRiver Riddle RecTy *Type = StringRecTy::get(Records);
1741e122a71aSPaul C. Anagnostopoulos
1742e122a71aSPaul C. Anagnostopoulos Lex.Lex(); // eat the operation
1743e122a71aSPaul C. Anagnostopoulos
1744e122a71aSPaul C. Anagnostopoulos if (!consume(tgtok::l_paren)) {
1745e122a71aSPaul C. Anagnostopoulos TokError("expected '(' after !substr operator");
1746e122a71aSPaul C. Anagnostopoulos return nullptr;
1747e122a71aSPaul C. Anagnostopoulos }
1748e122a71aSPaul C. Anagnostopoulos
1749e122a71aSPaul C. Anagnostopoulos Init *LHS = ParseValue(CurRec);
1750e122a71aSPaul C. Anagnostopoulos if (!LHS)
1751e122a71aSPaul C. Anagnostopoulos return nullptr;
1752e122a71aSPaul C. Anagnostopoulos
1753e122a71aSPaul C. Anagnostopoulos if (!consume(tgtok::comma)) {
1754e122a71aSPaul C. Anagnostopoulos TokError("expected ',' in !substr operator");
1755e122a71aSPaul C. Anagnostopoulos return nullptr;
1756e122a71aSPaul C. Anagnostopoulos }
1757e122a71aSPaul C. Anagnostopoulos
1758e122a71aSPaul C. Anagnostopoulos SMLoc MHSLoc = Lex.getLoc();
1759e122a71aSPaul C. Anagnostopoulos Init *MHS = ParseValue(CurRec);
1760e122a71aSPaul C. Anagnostopoulos if (!MHS)
1761e122a71aSPaul C. Anagnostopoulos return nullptr;
1762e122a71aSPaul C. Anagnostopoulos
1763e122a71aSPaul C. Anagnostopoulos SMLoc RHSLoc = Lex.getLoc();
1764e122a71aSPaul C. Anagnostopoulos Init *RHS;
1765e122a71aSPaul C. Anagnostopoulos if (consume(tgtok::comma)) {
1766e122a71aSPaul C. Anagnostopoulos RHSLoc = Lex.getLoc();
1767e122a71aSPaul C. Anagnostopoulos RHS = ParseValue(CurRec);
1768e122a71aSPaul C. Anagnostopoulos if (!RHS)
1769e122a71aSPaul C. Anagnostopoulos return nullptr;
1770e122a71aSPaul C. Anagnostopoulos } else {
17712ac3cd20SRiver Riddle RHS = IntInit::get(Records, std::numeric_limits<int64_t>::max());
1772e122a71aSPaul C. Anagnostopoulos }
1773e122a71aSPaul C. Anagnostopoulos
1774e122a71aSPaul C. Anagnostopoulos if (!consume(tgtok::r_paren)) {
1775e122a71aSPaul C. Anagnostopoulos TokError("expected ')' in !substr operator");
1776e122a71aSPaul C. Anagnostopoulos return nullptr;
1777e122a71aSPaul C. Anagnostopoulos }
1778e122a71aSPaul C. Anagnostopoulos
1779e122a71aSPaul C. Anagnostopoulos if (ItemType && !Type->typeIsConvertibleTo(ItemType)) {
1780e122a71aSPaul C. Anagnostopoulos Error(RHSLoc, Twine("expected value of type '") +
1781e122a71aSPaul C. Anagnostopoulos ItemType->getAsString() + "', got '" +
1782e122a71aSPaul C. Anagnostopoulos Type->getAsString() + "'");
1783e122a71aSPaul C. Anagnostopoulos }
1784e122a71aSPaul C. Anagnostopoulos
1785e122a71aSPaul C. Anagnostopoulos TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
1786e122a71aSPaul C. Anagnostopoulos if (!LHSt && !isa<UnsetInit>(LHS)) {
1787e122a71aSPaul C. Anagnostopoulos TokError("could not determine type of the string in !substr");
1788e122a71aSPaul C. Anagnostopoulos return nullptr;
1789e122a71aSPaul C. Anagnostopoulos }
1790e122a71aSPaul C. Anagnostopoulos if (LHSt && !isa<StringRecTy>(LHSt->getType())) {
1791e122a71aSPaul C. Anagnostopoulos TokError(Twine("expected string, got type '") +
1792e122a71aSPaul C. Anagnostopoulos LHSt->getType()->getAsString() + "'");
1793e122a71aSPaul C. Anagnostopoulos return nullptr;
1794e122a71aSPaul C. Anagnostopoulos }
1795e122a71aSPaul C. Anagnostopoulos
1796e122a71aSPaul C. Anagnostopoulos TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
1797e122a71aSPaul C. Anagnostopoulos if (!MHSt && !isa<UnsetInit>(MHS)) {
1798e122a71aSPaul C. Anagnostopoulos TokError("could not determine type of the start position in !substr");
1799e122a71aSPaul C. Anagnostopoulos return nullptr;
1800e122a71aSPaul C. Anagnostopoulos }
1801e122a71aSPaul C. Anagnostopoulos if (MHSt && !isa<IntRecTy>(MHSt->getType())) {
1802e122a71aSPaul C. Anagnostopoulos Error(MHSLoc, Twine("expected int, got type '") +
1803e122a71aSPaul C. Anagnostopoulos MHSt->getType()->getAsString() + "'");
1804e122a71aSPaul C. Anagnostopoulos return nullptr;
1805e122a71aSPaul C. Anagnostopoulos }
1806e122a71aSPaul C. Anagnostopoulos
1807e122a71aSPaul C. Anagnostopoulos if (RHS) {
1808e122a71aSPaul C. Anagnostopoulos TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
1809e122a71aSPaul C. Anagnostopoulos if (!RHSt && !isa<UnsetInit>(RHS)) {
1810e122a71aSPaul C. Anagnostopoulos TokError("could not determine type of the length in !substr");
1811e122a71aSPaul C. Anagnostopoulos return nullptr;
1812e122a71aSPaul C. Anagnostopoulos }
1813e122a71aSPaul C. Anagnostopoulos if (RHSt && !isa<IntRecTy>(RHSt->getType())) {
1814e122a71aSPaul C. Anagnostopoulos TokError(Twine("expected int, got type '") +
1815e122a71aSPaul C. Anagnostopoulos RHSt->getType()->getAsString() + "'");
1816e122a71aSPaul C. Anagnostopoulos return nullptr;
1817e122a71aSPaul C. Anagnostopoulos }
1818e122a71aSPaul C. Anagnostopoulos }
1819e122a71aSPaul C. Anagnostopoulos
1820e122a71aSPaul C. Anagnostopoulos return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);
1821e122a71aSPaul C. Anagnostopoulos }
1822e122a71aSPaul C. Anagnostopoulos
1823952c6dddSPaul C. Anagnostopoulos /// Parse the !find operation. Return null on error.
1824952c6dddSPaul C. Anagnostopoulos ///
1825952c6dddSPaul C. Anagnostopoulos /// Substr ::= !find(string, string [, start-int]) => int
ParseOperationFind(Record * CurRec,RecTy * ItemType)1826952c6dddSPaul C. Anagnostopoulos Init *TGParser::ParseOperationFind(Record *CurRec, RecTy *ItemType) {
1827952c6dddSPaul C. Anagnostopoulos TernOpInit::TernaryOp Code = TernOpInit::FIND;
18282ac3cd20SRiver Riddle RecTy *Type = IntRecTy::get(Records);
1829952c6dddSPaul C. Anagnostopoulos
1830952c6dddSPaul C. Anagnostopoulos Lex.Lex(); // eat the operation
1831952c6dddSPaul C. Anagnostopoulos
1832952c6dddSPaul C. Anagnostopoulos if (!consume(tgtok::l_paren)) {
1833952c6dddSPaul C. Anagnostopoulos TokError("expected '(' after !find operator");
1834952c6dddSPaul C. Anagnostopoulos return nullptr;
1835952c6dddSPaul C. Anagnostopoulos }
1836952c6dddSPaul C. Anagnostopoulos
1837952c6dddSPaul C. Anagnostopoulos Init *LHS = ParseValue(CurRec);
1838952c6dddSPaul C. Anagnostopoulos if (!LHS)
1839952c6dddSPaul C. Anagnostopoulos return nullptr;
1840952c6dddSPaul C. Anagnostopoulos
1841952c6dddSPaul C. Anagnostopoulos if (!consume(tgtok::comma)) {
1842952c6dddSPaul C. Anagnostopoulos TokError("expected ',' in !find operator");
1843952c6dddSPaul C. Anagnostopoulos return nullptr;
1844952c6dddSPaul C. Anagnostopoulos }
1845952c6dddSPaul C. Anagnostopoulos
1846952c6dddSPaul C. Anagnostopoulos SMLoc MHSLoc = Lex.getLoc();
1847952c6dddSPaul C. Anagnostopoulos Init *MHS = ParseValue(CurRec);
1848952c6dddSPaul C. Anagnostopoulos if (!MHS)
1849952c6dddSPaul C. Anagnostopoulos return nullptr;
1850952c6dddSPaul C. Anagnostopoulos
1851952c6dddSPaul C. Anagnostopoulos SMLoc RHSLoc = Lex.getLoc();
1852952c6dddSPaul C. Anagnostopoulos Init *RHS;
1853952c6dddSPaul C. Anagnostopoulos if (consume(tgtok::comma)) {
1854952c6dddSPaul C. Anagnostopoulos RHSLoc = Lex.getLoc();
1855952c6dddSPaul C. Anagnostopoulos RHS = ParseValue(CurRec);
1856952c6dddSPaul C. Anagnostopoulos if (!RHS)
1857952c6dddSPaul C. Anagnostopoulos return nullptr;
1858952c6dddSPaul C. Anagnostopoulos } else {
18592ac3cd20SRiver Riddle RHS = IntInit::get(Records, 0);
1860952c6dddSPaul C. Anagnostopoulos }
1861952c6dddSPaul C. Anagnostopoulos
1862952c6dddSPaul C. Anagnostopoulos if (!consume(tgtok::r_paren)) {
1863952c6dddSPaul C. Anagnostopoulos TokError("expected ')' in !find operator");
1864952c6dddSPaul C. Anagnostopoulos return nullptr;
1865952c6dddSPaul C. Anagnostopoulos }
1866952c6dddSPaul C. Anagnostopoulos
1867952c6dddSPaul C. Anagnostopoulos if (ItemType && !Type->typeIsConvertibleTo(ItemType)) {
1868952c6dddSPaul C. Anagnostopoulos Error(RHSLoc, Twine("expected value of type '") +
1869952c6dddSPaul C. Anagnostopoulos ItemType->getAsString() + "', got '" +
1870952c6dddSPaul C. Anagnostopoulos Type->getAsString() + "'");
1871952c6dddSPaul C. Anagnostopoulos }
1872952c6dddSPaul C. Anagnostopoulos
1873952c6dddSPaul C. Anagnostopoulos TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
1874952c6dddSPaul C. Anagnostopoulos if (!LHSt && !isa<UnsetInit>(LHS)) {
1875952c6dddSPaul C. Anagnostopoulos TokError("could not determine type of the source string in !find");
1876952c6dddSPaul C. Anagnostopoulos return nullptr;
1877952c6dddSPaul C. Anagnostopoulos }
1878952c6dddSPaul C. Anagnostopoulos if (LHSt && !isa<StringRecTy>(LHSt->getType())) {
1879952c6dddSPaul C. Anagnostopoulos TokError(Twine("expected string, got type '") +
1880952c6dddSPaul C. Anagnostopoulos LHSt->getType()->getAsString() + "'");
1881952c6dddSPaul C. Anagnostopoulos return nullptr;
1882952c6dddSPaul C. Anagnostopoulos }
1883952c6dddSPaul C. Anagnostopoulos
1884952c6dddSPaul C. Anagnostopoulos TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
1885952c6dddSPaul C. Anagnostopoulos if (!MHSt && !isa<UnsetInit>(MHS)) {
1886952c6dddSPaul C. Anagnostopoulos TokError("could not determine type of the target string in !find");
1887952c6dddSPaul C. Anagnostopoulos return nullptr;
1888952c6dddSPaul C. Anagnostopoulos }
1889952c6dddSPaul C. Anagnostopoulos if (MHSt && !isa<StringRecTy>(MHSt->getType())) {
1890952c6dddSPaul C. Anagnostopoulos Error(MHSLoc, Twine("expected string, got type '") +
1891952c6dddSPaul C. Anagnostopoulos MHSt->getType()->getAsString() + "'");
1892952c6dddSPaul C. Anagnostopoulos return nullptr;
1893952c6dddSPaul C. Anagnostopoulos }
1894952c6dddSPaul C. Anagnostopoulos
1895952c6dddSPaul C. Anagnostopoulos if (RHS) {
1896952c6dddSPaul C. Anagnostopoulos TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
1897952c6dddSPaul C. Anagnostopoulos if (!RHSt && !isa<UnsetInit>(RHS)) {
1898952c6dddSPaul C. Anagnostopoulos TokError("could not determine type of the start position in !find");
1899952c6dddSPaul C. Anagnostopoulos return nullptr;
1900952c6dddSPaul C. Anagnostopoulos }
1901952c6dddSPaul C. Anagnostopoulos if (RHSt && !isa<IntRecTy>(RHSt->getType())) {
1902952c6dddSPaul C. Anagnostopoulos TokError(Twine("expected int, got type '") +
1903952c6dddSPaul C. Anagnostopoulos RHSt->getType()->getAsString() + "'");
1904952c6dddSPaul C. Anagnostopoulos return nullptr;
1905952c6dddSPaul C. Anagnostopoulos }
1906952c6dddSPaul C. Anagnostopoulos }
1907952c6dddSPaul C. Anagnostopoulos
1908952c6dddSPaul C. Anagnostopoulos return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);
1909952c6dddSPaul C. Anagnostopoulos }
1910952c6dddSPaul C. Anagnostopoulos
191191d2e5c8SPaul C. Anagnostopoulos /// Parse the !foreach and !filter operations. Return null on error.
191291d2e5c8SPaul C. Anagnostopoulos ///
191391d2e5c8SPaul C. Anagnostopoulos /// ForEach ::= !foreach(ID, list-or-dag, expr) => list<expr type>
191491d2e5c8SPaul C. Anagnostopoulos /// Filter ::= !foreach(ID, list, predicate) ==> list<list type>
ParseOperationForEachFilter(Record * CurRec,RecTy * ItemType)191591d2e5c8SPaul C. Anagnostopoulos Init *TGParser::ParseOperationForEachFilter(Record *CurRec, RecTy *ItemType) {
191691d2e5c8SPaul C. Anagnostopoulos SMLoc OpLoc = Lex.getLoc();
191791d2e5c8SPaul C. Anagnostopoulos tgtok::TokKind Operation = Lex.getCode();
191891d2e5c8SPaul C. Anagnostopoulos Lex.Lex(); // eat the operation
191991d2e5c8SPaul C. Anagnostopoulos if (Lex.getCode() != tgtok::l_paren) {
192091d2e5c8SPaul C. Anagnostopoulos TokError("expected '(' after !foreach/!filter");
192191d2e5c8SPaul C. Anagnostopoulos return nullptr;
192291d2e5c8SPaul C. Anagnostopoulos }
192391d2e5c8SPaul C. Anagnostopoulos
192491d2e5c8SPaul C. Anagnostopoulos if (Lex.Lex() != tgtok::Id) { // eat the '('
192591d2e5c8SPaul C. Anagnostopoulos TokError("first argument of !foreach/!filter must be an identifier");
192691d2e5c8SPaul C. Anagnostopoulos return nullptr;
192791d2e5c8SPaul C. Anagnostopoulos }
192891d2e5c8SPaul C. Anagnostopoulos
19292ac3cd20SRiver Riddle Init *LHS = StringInit::get(Records, Lex.getCurStrVal());
193091d2e5c8SPaul C. Anagnostopoulos Lex.Lex(); // eat the ID.
193191d2e5c8SPaul C. Anagnostopoulos
193291d2e5c8SPaul C. Anagnostopoulos if (CurRec && CurRec->getValue(LHS)) {
193391d2e5c8SPaul C. Anagnostopoulos TokError((Twine("iteration variable '") + LHS->getAsString() +
193491d2e5c8SPaul C. Anagnostopoulos "' is already defined")
193591d2e5c8SPaul C. Anagnostopoulos .str());
193691d2e5c8SPaul C. Anagnostopoulos return nullptr;
193791d2e5c8SPaul C. Anagnostopoulos }
193891d2e5c8SPaul C. Anagnostopoulos
193991d2e5c8SPaul C. Anagnostopoulos if (!consume(tgtok::comma)) {
194091d2e5c8SPaul C. Anagnostopoulos TokError("expected ',' in !foreach/!filter");
194191d2e5c8SPaul C. Anagnostopoulos return nullptr;
194291d2e5c8SPaul C. Anagnostopoulos }
194391d2e5c8SPaul C. Anagnostopoulos
194491d2e5c8SPaul C. Anagnostopoulos Init *MHS = ParseValue(CurRec);
194591d2e5c8SPaul C. Anagnostopoulos if (!MHS)
194691d2e5c8SPaul C. Anagnostopoulos return nullptr;
194791d2e5c8SPaul C. Anagnostopoulos
194891d2e5c8SPaul C. Anagnostopoulos if (!consume(tgtok::comma)) {
194991d2e5c8SPaul C. Anagnostopoulos TokError("expected ',' in !foreach/!filter");
195091d2e5c8SPaul C. Anagnostopoulos return nullptr;
195191d2e5c8SPaul C. Anagnostopoulos }
195291d2e5c8SPaul C. Anagnostopoulos
195391d2e5c8SPaul C. Anagnostopoulos TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
195491d2e5c8SPaul C. Anagnostopoulos if (!MHSt) {
195591d2e5c8SPaul C. Anagnostopoulos TokError("could not get type of !foreach/!filter list or dag");
195691d2e5c8SPaul C. Anagnostopoulos return nullptr;
195791d2e5c8SPaul C. Anagnostopoulos }
195891d2e5c8SPaul C. Anagnostopoulos
195991d2e5c8SPaul C. Anagnostopoulos RecTy *InEltType = nullptr;
196091d2e5c8SPaul C. Anagnostopoulos RecTy *ExprEltType = nullptr;
196191d2e5c8SPaul C. Anagnostopoulos bool IsDAG = false;
196291d2e5c8SPaul C. Anagnostopoulos
196391d2e5c8SPaul C. Anagnostopoulos if (ListRecTy *InListTy = dyn_cast<ListRecTy>(MHSt->getType())) {
196491d2e5c8SPaul C. Anagnostopoulos InEltType = InListTy->getElementType();
196591d2e5c8SPaul C. Anagnostopoulos if (ItemType) {
196691d2e5c8SPaul C. Anagnostopoulos if (ListRecTy *OutListTy = dyn_cast<ListRecTy>(ItemType)) {
196791d2e5c8SPaul C. Anagnostopoulos ExprEltType = (Operation == tgtok::XForEach)
196891d2e5c8SPaul C. Anagnostopoulos ? OutListTy->getElementType()
19692ac3cd20SRiver Riddle : IntRecTy::get(Records);
197091d2e5c8SPaul C. Anagnostopoulos } else {
197191d2e5c8SPaul C. Anagnostopoulos Error(OpLoc,
197291d2e5c8SPaul C. Anagnostopoulos "expected value of type '" +
197391d2e5c8SPaul C. Anagnostopoulos Twine(ItemType->getAsString()) +
197491d2e5c8SPaul C. Anagnostopoulos "', but got list type");
197591d2e5c8SPaul C. Anagnostopoulos return nullptr;
197691d2e5c8SPaul C. Anagnostopoulos }
197791d2e5c8SPaul C. Anagnostopoulos }
197891d2e5c8SPaul C. Anagnostopoulos } else if (DagRecTy *InDagTy = dyn_cast<DagRecTy>(MHSt->getType())) {
197991d2e5c8SPaul C. Anagnostopoulos if (Operation == tgtok::XFilter) {
198091d2e5c8SPaul C. Anagnostopoulos TokError("!filter must have a list argument");
198191d2e5c8SPaul C. Anagnostopoulos return nullptr;
198291d2e5c8SPaul C. Anagnostopoulos }
198391d2e5c8SPaul C. Anagnostopoulos InEltType = InDagTy;
198491d2e5c8SPaul C. Anagnostopoulos if (ItemType && !isa<DagRecTy>(ItemType)) {
198591d2e5c8SPaul C. Anagnostopoulos Error(OpLoc,
198691d2e5c8SPaul C. Anagnostopoulos "expected value of type '" + Twine(ItemType->getAsString()) +
198791d2e5c8SPaul C. Anagnostopoulos "', but got dag type");
198891d2e5c8SPaul C. Anagnostopoulos return nullptr;
198991d2e5c8SPaul C. Anagnostopoulos }
199091d2e5c8SPaul C. Anagnostopoulos IsDAG = true;
199191d2e5c8SPaul C. Anagnostopoulos } else {
199291d2e5c8SPaul C. Anagnostopoulos if (Operation == tgtok::XForEach)
199391d2e5c8SPaul C. Anagnostopoulos TokError("!foreach must have a list or dag argument");
199491d2e5c8SPaul C. Anagnostopoulos else
199591d2e5c8SPaul C. Anagnostopoulos TokError("!filter must have a list argument");
199691d2e5c8SPaul C. Anagnostopoulos return nullptr;
199791d2e5c8SPaul C. Anagnostopoulos }
199891d2e5c8SPaul C. Anagnostopoulos
199991d2e5c8SPaul C. Anagnostopoulos // We need to create a temporary record to provide a scope for the
200091d2e5c8SPaul C. Anagnostopoulos // iteration variable.
200191d2e5c8SPaul C. Anagnostopoulos std::unique_ptr<Record> ParseRecTmp;
200291d2e5c8SPaul C. Anagnostopoulos Record *ParseRec = CurRec;
200391d2e5c8SPaul C. Anagnostopoulos if (!ParseRec) {
200491d2e5c8SPaul C. Anagnostopoulos ParseRecTmp =
200591d2e5c8SPaul C. Anagnostopoulos std::make_unique<Record>(".parse", ArrayRef<SMLoc>{}, Records);
200691d2e5c8SPaul C. Anagnostopoulos ParseRec = ParseRecTmp.get();
200791d2e5c8SPaul C. Anagnostopoulos }
200891d2e5c8SPaul C. Anagnostopoulos
2009aa7968a8SPaul C. Anagnostopoulos ParseRec->addValue(RecordVal(LHS, InEltType, RecordVal::FK_Normal));
201091d2e5c8SPaul C. Anagnostopoulos Init *RHS = ParseValue(ParseRec, ExprEltType);
201191d2e5c8SPaul C. Anagnostopoulos ParseRec->removeValue(LHS);
201291d2e5c8SPaul C. Anagnostopoulos if (!RHS)
201391d2e5c8SPaul C. Anagnostopoulos return nullptr;
201491d2e5c8SPaul C. Anagnostopoulos
201591d2e5c8SPaul C. Anagnostopoulos if (!consume(tgtok::r_paren)) {
201691d2e5c8SPaul C. Anagnostopoulos TokError("expected ')' in !foreach/!filter");
201791d2e5c8SPaul C. Anagnostopoulos return nullptr;
201891d2e5c8SPaul C. Anagnostopoulos }
201991d2e5c8SPaul C. Anagnostopoulos
202091d2e5c8SPaul C. Anagnostopoulos RecTy *OutType = InEltType;
202191d2e5c8SPaul C. Anagnostopoulos if (Operation == tgtok::XForEach && !IsDAG) {
202291d2e5c8SPaul C. Anagnostopoulos TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
202391d2e5c8SPaul C. Anagnostopoulos if (!RHSt) {
202491d2e5c8SPaul C. Anagnostopoulos TokError("could not get type of !foreach result expression");
202591d2e5c8SPaul C. Anagnostopoulos return nullptr;
202691d2e5c8SPaul C. Anagnostopoulos }
202791d2e5c8SPaul C. Anagnostopoulos OutType = RHSt->getType()->getListTy();
202891d2e5c8SPaul C. Anagnostopoulos } else if (Operation == tgtok::XFilter) {
202991d2e5c8SPaul C. Anagnostopoulos OutType = InEltType->getListTy();
203091d2e5c8SPaul C. Anagnostopoulos }
203191d2e5c8SPaul C. Anagnostopoulos
203291d2e5c8SPaul C. Anagnostopoulos return (TernOpInit::get((Operation == tgtok::XForEach) ? TernOpInit::FOREACH
203391d2e5c8SPaul C. Anagnostopoulos : TernOpInit::FILTER,
203491d2e5c8SPaul C. Anagnostopoulos LHS, MHS, RHS, OutType))
203591d2e5c8SPaul C. Anagnostopoulos ->Fold(CurRec);
203691d2e5c8SPaul C. Anagnostopoulos }
203791d2e5c8SPaul C. Anagnostopoulos
ParseOperationCond(Record * CurRec,RecTy * ItemType)2038a3e3d852SJaved Absar Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) {
2039a3e3d852SJaved Absar Lex.Lex(); // eat the operation 'cond'
2040a3e3d852SJaved Absar
2041e69605bfSFangrui Song if (!consume(tgtok::l_paren)) {
2042a3e3d852SJaved Absar TokError("expected '(' after !cond operator");
2043a3e3d852SJaved Absar return nullptr;
2044a3e3d852SJaved Absar }
2045a3e3d852SJaved Absar
2046a3e3d852SJaved Absar // Parse through '[Case: Val,]+'
2047a3e3d852SJaved Absar SmallVector<Init *, 4> Case;
2048a3e3d852SJaved Absar SmallVector<Init *, 4> Val;
2049a3e3d852SJaved Absar while (true) {
2050e69605bfSFangrui Song if (consume(tgtok::r_paren))
2051a3e3d852SJaved Absar break;
2052a3e3d852SJaved Absar
2053a3e3d852SJaved Absar Init *V = ParseValue(CurRec);
2054a3e3d852SJaved Absar if (!V)
2055a3e3d852SJaved Absar return nullptr;
2056a3e3d852SJaved Absar Case.push_back(V);
2057a3e3d852SJaved Absar
2058e69605bfSFangrui Song if (!consume(tgtok::colon)) {
2059a3e3d852SJaved Absar TokError("expected ':' following a condition in !cond operator");
2060a3e3d852SJaved Absar return nullptr;
2061a3e3d852SJaved Absar }
2062a3e3d852SJaved Absar
2063a3e3d852SJaved Absar V = ParseValue(CurRec, ItemType);
2064a3e3d852SJaved Absar if (!V)
2065a3e3d852SJaved Absar return nullptr;
2066a3e3d852SJaved Absar Val.push_back(V);
2067a3e3d852SJaved Absar
2068e69605bfSFangrui Song if (consume(tgtok::r_paren))
2069a3e3d852SJaved Absar break;
2070a3e3d852SJaved Absar
2071e69605bfSFangrui Song if (!consume(tgtok::comma)) {
2072a3e3d852SJaved Absar TokError("expected ',' or ')' following a value in !cond operator");
2073a3e3d852SJaved Absar return nullptr;
2074a3e3d852SJaved Absar }
2075a3e3d852SJaved Absar }
2076a3e3d852SJaved Absar
2077a3e3d852SJaved Absar if (Case.size() < 1) {
2078a3e3d852SJaved Absar TokError("there should be at least 1 'condition : value' in the !cond operator");
2079a3e3d852SJaved Absar return nullptr;
2080a3e3d852SJaved Absar }
2081a3e3d852SJaved Absar
2082a3e3d852SJaved Absar // resolve type
2083a3e3d852SJaved Absar RecTy *Type = nullptr;
2084a3e3d852SJaved Absar for (Init *V : Val) {
2085a3e3d852SJaved Absar RecTy *VTy = nullptr;
2086a3e3d852SJaved Absar if (TypedInit *Vt = dyn_cast<TypedInit>(V))
2087a3e3d852SJaved Absar VTy = Vt->getType();
2088a3e3d852SJaved Absar if (BitsInit *Vbits = dyn_cast<BitsInit>(V))
20892ac3cd20SRiver Riddle VTy = BitsRecTy::get(Records, Vbits->getNumBits());
2090a3e3d852SJaved Absar if (isa<BitInit>(V))
20912ac3cd20SRiver Riddle VTy = BitRecTy::get(Records);
2092a3e3d852SJaved Absar
2093a3e3d852SJaved Absar if (Type == nullptr) {
2094a3e3d852SJaved Absar if (!isa<UnsetInit>(V))
2095a3e3d852SJaved Absar Type = VTy;
2096a3e3d852SJaved Absar } else {
2097a3e3d852SJaved Absar if (!isa<UnsetInit>(V)) {
2098a3e3d852SJaved Absar RecTy *RType = resolveTypes(Type, VTy);
2099a3e3d852SJaved Absar if (!RType) {
2100a3e3d852SJaved Absar TokError(Twine("inconsistent types '") + Type->getAsString() +
2101a3e3d852SJaved Absar "' and '" + VTy->getAsString() + "' for !cond");
2102a3e3d852SJaved Absar return nullptr;
2103a3e3d852SJaved Absar }
2104a3e3d852SJaved Absar Type = RType;
2105a3e3d852SJaved Absar }
2106a3e3d852SJaved Absar }
2107a3e3d852SJaved Absar }
2108a3e3d852SJaved Absar
2109a3e3d852SJaved Absar if (!Type) {
2110a3e3d852SJaved Absar TokError("could not determine type for !cond from its arguments");
2111a3e3d852SJaved Absar return nullptr;
2112a3e3d852SJaved Absar }
2113a3e3d852SJaved Absar return CondOpInit::get(Case, Val, Type)->Fold(CurRec);
2114a3e3d852SJaved Absar }
2115a3e3d852SJaved Absar
211684c287e3SPeter Collingbourne /// ParseSimpleValue - Parse a tblgen value. This returns null on error.
211784c287e3SPeter Collingbourne ///
211884c287e3SPeter Collingbourne /// SimpleValue ::= IDValue
211984c287e3SPeter Collingbourne /// SimpleValue ::= INTVAL
212084c287e3SPeter Collingbourne /// SimpleValue ::= STRVAL+
212184c287e3SPeter Collingbourne /// SimpleValue ::= CODEFRAGMENT
212284c287e3SPeter Collingbourne /// SimpleValue ::= '?'
212384c287e3SPeter Collingbourne /// SimpleValue ::= '{' ValueList '}'
212484c287e3SPeter Collingbourne /// SimpleValue ::= ID '<' ValueListNE '>'
212584c287e3SPeter Collingbourne /// SimpleValue ::= '[' ValueList ']'
212684c287e3SPeter Collingbourne /// SimpleValue ::= '(' IDValue DagArgList ')'
212784c287e3SPeter Collingbourne /// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'
2128c7d4dc13SHal Finkel /// SimpleValue ::= ADDTOK '(' Value ',' Value ')'
21299d72065cSPaul C. Anagnostopoulos /// SimpleValue ::= SUBTOK '(' Value ',' Value ')'
213084c287e3SPeter Collingbourne /// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
213184c287e3SPeter Collingbourne /// SimpleValue ::= SRATOK '(' Value ',' Value ')'
213284c287e3SPeter Collingbourne /// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
2133314e80e5SDaniel Sanders /// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'
21345d9f656bSRoman Lebedev /// SimpleValue ::= LISTSPLATTOK '(' Value ',' Value ')'
213584c287e3SPeter Collingbourne /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
2136a3e3d852SJaved Absar /// SimpleValue ::= COND '(' [Value ':' Value,]+ ')'
213784c287e3SPeter Collingbourne ///
ParseSimpleValue(Record * CurRec,RecTy * ItemType,IDParseMode Mode)2138d4263a6aSDavid Greene Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
2139d4263a6aSDavid Greene IDParseMode Mode) {
2140011817a0SCraig Topper Init *R = nullptr;
214184c287e3SPeter Collingbourne switch (Lex.getCode()) {
2142ae2cb4f4SPaul C. Anagnostopoulos default: TokError("Unknown or reserved token when parsing a value"); break;
2143ae2cb4f4SPaul C. Anagnostopoulos
2144ae2cb4f4SPaul C. Anagnostopoulos case tgtok::TrueVal:
21452ac3cd20SRiver Riddle R = IntInit::get(Records, 1);
2146ae2cb4f4SPaul C. Anagnostopoulos Lex.Lex();
2147ae2cb4f4SPaul C. Anagnostopoulos break;
2148ae2cb4f4SPaul C. Anagnostopoulos case tgtok::FalseVal:
21492ac3cd20SRiver Riddle R = IntInit::get(Records, 0);
2150ae2cb4f4SPaul C. Anagnostopoulos Lex.Lex();
2151ae2cb4f4SPaul C. Anagnostopoulos break;
2152ae2cb4f4SPaul C. Anagnostopoulos case tgtok::IntVal:
21532ac3cd20SRiver Riddle R = IntInit::get(Records, Lex.getCurIntVal());
2154ae2cb4f4SPaul C. Anagnostopoulos Lex.Lex();
2155ae2cb4f4SPaul C. Anagnostopoulos break;
21562597764aSPete Cooper case tgtok::BinaryIntVal: {
21572597764aSPete Cooper auto BinaryVal = Lex.getCurBinaryIntVal();
21582597764aSPete Cooper SmallVector<Init*, 16> Bits(BinaryVal.second);
21592597764aSPete Cooper for (unsigned i = 0, e = BinaryVal.second; i != e; ++i)
21602ac3cd20SRiver Riddle Bits[i] = BitInit::get(Records, BinaryVal.first & (1LL << i));
21612ac3cd20SRiver Riddle R = BitsInit::get(Records, Bits);
21622597764aSPete Cooper Lex.Lex();
21632597764aSPete Cooper break;
21642597764aSPete Cooper }
216584c287e3SPeter Collingbourne case tgtok::StrVal: {
216684c287e3SPeter Collingbourne std::string Val = Lex.getCurStrVal();
216784c287e3SPeter Collingbourne Lex.Lex();
216884c287e3SPeter Collingbourne
216984c287e3SPeter Collingbourne // Handle multiple consecutive concatenated strings.
217084c287e3SPeter Collingbourne while (Lex.getCode() == tgtok::StrVal) {
217184c287e3SPeter Collingbourne Val += Lex.getCurStrVal();
217284c287e3SPeter Collingbourne Lex.Lex();
217384c287e3SPeter Collingbourne }
217484c287e3SPeter Collingbourne
21752ac3cd20SRiver Riddle R = StringInit::get(Records, Val);
217684c287e3SPeter Collingbourne break;
217784c287e3SPeter Collingbourne }
217884c287e3SPeter Collingbourne case tgtok::CodeFragment:
21792ac3cd20SRiver Riddle R = StringInit::get(Records, Lex.getCurStrVal(), StringInit::SF_Code);
218084c287e3SPeter Collingbourne Lex.Lex();
218184c287e3SPeter Collingbourne break;
218284c287e3SPeter Collingbourne case tgtok::question:
21832ac3cd20SRiver Riddle R = UnsetInit::get(Records);
218484c287e3SPeter Collingbourne Lex.Lex();
218584c287e3SPeter Collingbourne break;
218684c287e3SPeter Collingbourne case tgtok::Id: {
218784c287e3SPeter Collingbourne SMLoc NameLoc = Lex.getLoc();
21882ac3cd20SRiver Riddle StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());
218984c287e3SPeter Collingbourne if (Lex.Lex() != tgtok::less) // consume the Id.
2190d4263a6aSDavid Greene return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue
219184c287e3SPeter Collingbourne
2192a9fc44c5SPaul C. Anagnostopoulos // Value ::= CLASSID '<' ValueListNE '>' (CLASSID has been consumed)
2193a9fc44c5SPaul C. Anagnostopoulos // This is supposed to synthesize a new anonymous definition, deriving
2194a9fc44c5SPaul C. Anagnostopoulos // from the class with the template arguments, but no body.
2195215ff84bSMatthias Braun Record *Class = Records.getClass(Name->getValue());
219684c287e3SPeter Collingbourne if (!Class) {
2197215ff84bSMatthias Braun Error(NameLoc, "Expected a class name, got '" + Name->getValue() + "'");
2198011817a0SCraig Topper return nullptr;
219984c287e3SPeter Collingbourne }
220084c287e3SPeter Collingbourne
2201d4c0a5d0SNicolai Haehnle SmallVector<Init *, 8> Args;
2202a9fc44c5SPaul C. Anagnostopoulos Lex.Lex(); // consume the <
2203a9fc44c5SPaul C. Anagnostopoulos if (ParseTemplateArgValueList(Args, CurRec, Class))
2204a9fc44c5SPaul C. Anagnostopoulos return nullptr; // Error parsing value list.
220584c287e3SPeter Collingbourne
2206a9fc44c5SPaul C. Anagnostopoulos if (CheckTemplateArgValues(Args, NameLoc, Class))
2207a9fc44c5SPaul C. Anagnostopoulos return nullptr; // Error checking template argument values.
220884c287e3SPeter Collingbourne
2209a9fc44c5SPaul C. Anagnostopoulos // Loop through the arguments that were not specified and make sure
2210a9fc44c5SPaul C. Anagnostopoulos // they have a complete value.
2211a9fc44c5SPaul C. Anagnostopoulos ArrayRef<Init *> TArgs = Class->getTemplateArgs();
2212a9fc44c5SPaul C. Anagnostopoulos for (unsigned I = Args.size(), E = TArgs.size(); I < E; ++I) {
2213a9fc44c5SPaul C. Anagnostopoulos RecordVal *Arg = Class->getValue(TArgs[I]);
2214a9fc44c5SPaul C. Anagnostopoulos if (!Arg->getValue()->isComplete())
2215a9fc44c5SPaul C. Anagnostopoulos Error(NameLoc, "Value not specified for template argument '" +
2216a9fc44c5SPaul C. Anagnostopoulos TArgs[I]->getAsUnquotedString() + "' (#" + Twine(I) +
2217a9fc44c5SPaul C. Anagnostopoulos ") of parent class '" +
2218a9fc44c5SPaul C. Anagnostopoulos Class->getNameInitAsString() + "'");
2219a8c1f467SHal Finkel
2220a8c1f467SHal Finkel }
222184c287e3SPeter Collingbourne
2222d4c0a5d0SNicolai Haehnle return VarDefInit::get(Class, Args)->Fold();
222384c287e3SPeter Collingbourne }
222484c287e3SPeter Collingbourne case tgtok::l_brace: { // Value ::= '{' ValueList '}'
222584c287e3SPeter Collingbourne SMLoc BraceLoc = Lex.getLoc();
222684c287e3SPeter Collingbourne Lex.Lex(); // eat the '{'
2227c66e7557SMatthias Braun SmallVector<Init*, 16> Vals;
222884c287e3SPeter Collingbourne
222984c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::r_brace) {
2230c66e7557SMatthias Braun ParseValueList(Vals, CurRec);
2231011817a0SCraig Topper if (Vals.empty()) return nullptr;
223284c287e3SPeter Collingbourne }
22338ba36497SFangrui Song if (!consume(tgtok::r_brace)) {
223484c287e3SPeter Collingbourne TokError("expected '}' at end of bit list value");
2235011817a0SCraig Topper return nullptr;
223684c287e3SPeter Collingbourne }
223784c287e3SPeter Collingbourne
22380bf1ea72SPete Cooper SmallVector<Init *, 16> NewBits;
223984c287e3SPeter Collingbourne
22400bf1ea72SPete Cooper // As we parse { a, b, ... }, 'a' is the highest bit, but we parse it
22410bf1ea72SPete Cooper // first. We'll first read everything in to a vector, then we can reverse
22420bf1ea72SPete Cooper // it to get the bits in the correct order for the BitsInit value.
224384c287e3SPeter Collingbourne for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
224497bfbb84SJean-Luc Duprat // FIXME: The following two loops would not be duplicated
224597bfbb84SJean-Luc Duprat // if the API was a little more orthogonal.
224697bfbb84SJean-Luc Duprat
22470bf1ea72SPete Cooper // bits<n> values are allowed to initialize n bits.
22480bf1ea72SPete Cooper if (BitsInit *BI = dyn_cast<BitsInit>(Vals[i])) {
22490bf1ea72SPete Cooper for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
22500bf1ea72SPete Cooper NewBits.push_back(BI->getBit((e - i) - 1));
22510bf1ea72SPete Cooper continue;
22520bf1ea72SPete Cooper }
22536d7b4561SJean-Luc Duprat // bits<n> can also come from variable initializers.
22546d7b4561SJean-Luc Duprat if (VarInit *VI = dyn_cast<VarInit>(Vals[i])) {
22556d7b4561SJean-Luc Duprat if (BitsRecTy *BitsRec = dyn_cast<BitsRecTy>(VI->getType())) {
22566d7b4561SJean-Luc Duprat for (unsigned i = 0, e = BitsRec->getNumBits(); i != e; ++i)
22576d7b4561SJean-Luc Duprat NewBits.push_back(VI->getBit((e - i) - 1));
22586d7b4561SJean-Luc Duprat continue;
22596d7b4561SJean-Luc Duprat }
22606d7b4561SJean-Luc Duprat // Fallthrough to try convert this to a bit.
22616d7b4561SJean-Luc Duprat }
22620bf1ea72SPete Cooper // All other values must be convertible to just a single bit.
22632ac3cd20SRiver Riddle Init *Bit = Vals[i]->getCastTo(BitRecTy::get(Records));
2264011817a0SCraig Topper if (!Bit) {
2265dba7ee90SBenjamin Kramer Error(BraceLoc, "Element #" + Twine(i) + " (" + Vals[i]->getAsString() +
226684c287e3SPeter Collingbourne ") is not convertable to a bit");
2267011817a0SCraig Topper return nullptr;
226884c287e3SPeter Collingbourne }
22690bf1ea72SPete Cooper NewBits.push_back(Bit);
227084c287e3SPeter Collingbourne }
22710bf1ea72SPete Cooper std::reverse(NewBits.begin(), NewBits.end());
22722ac3cd20SRiver Riddle return BitsInit::get(Records, NewBits);
227384c287e3SPeter Collingbourne }
227484c287e3SPeter Collingbourne case tgtok::l_square: { // Value ::= '[' ValueList ']'
227584c287e3SPeter Collingbourne Lex.Lex(); // eat the '['
2276c66e7557SMatthias Braun SmallVector<Init*, 16> Vals;
227784c287e3SPeter Collingbourne
2278011817a0SCraig Topper RecTy *DeducedEltTy = nullptr;
2279011817a0SCraig Topper ListRecTy *GivenListTy = nullptr;
228084c287e3SPeter Collingbourne
2281011817a0SCraig Topper if (ItemType) {
228298c61711SSean Silva ListRecTy *ListType = dyn_cast<ListRecTy>(ItemType);
2283011817a0SCraig Topper if (!ListType) {
2284473f8ae6SPaul C. Anagnostopoulos TokError(Twine("Encountered a list when expecting a ") +
2285dba7ee90SBenjamin Kramer ItemType->getAsString());
2286011817a0SCraig Topper return nullptr;
228784c287e3SPeter Collingbourne }
228884c287e3SPeter Collingbourne GivenListTy = ListType;
228984c287e3SPeter Collingbourne }
229084c287e3SPeter Collingbourne
229184c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::r_square) {
2292a9fc44c5SPaul C. Anagnostopoulos ParseValueList(Vals, CurRec,
2293011817a0SCraig Topper GivenListTy ? GivenListTy->getElementType() : nullptr);
2294011817a0SCraig Topper if (Vals.empty()) return nullptr;
229584c287e3SPeter Collingbourne }
2296e69605bfSFangrui Song if (!consume(tgtok::r_square)) {
229784c287e3SPeter Collingbourne TokError("expected ']' at end of list value");
2298011817a0SCraig Topper return nullptr;
229984c287e3SPeter Collingbourne }
230084c287e3SPeter Collingbourne
2301011817a0SCraig Topper RecTy *GivenEltTy = nullptr;
2302e69605bfSFangrui Song if (consume(tgtok::less)) {
230384c287e3SPeter Collingbourne // Optional list element type
230484c287e3SPeter Collingbourne GivenEltTy = ParseType();
2305011817a0SCraig Topper if (!GivenEltTy) {
230684c287e3SPeter Collingbourne // Couldn't parse element type
2307011817a0SCraig Topper return nullptr;
230884c287e3SPeter Collingbourne }
230984c287e3SPeter Collingbourne
2310e69605bfSFangrui Song if (!consume(tgtok::greater)) {
231184c287e3SPeter Collingbourne TokError("expected '>' at end of list element type");
2312011817a0SCraig Topper return nullptr;
231384c287e3SPeter Collingbourne }
231484c287e3SPeter Collingbourne }
231584c287e3SPeter Collingbourne
231684c287e3SPeter Collingbourne // Check elements
2317011817a0SCraig Topper RecTy *EltTy = nullptr;
2318eb4d7c6bSCraig Topper for (Init *V : Vals) {
2319eb4d7c6bSCraig Topper TypedInit *TArg = dyn_cast<TypedInit>(V);
2320ef60a268SNicolai Haehnle if (TArg) {
2321011817a0SCraig Topper if (EltTy) {
232284c287e3SPeter Collingbourne EltTy = resolveTypes(EltTy, TArg->getType());
2323011817a0SCraig Topper if (!EltTy) {
232484c287e3SPeter Collingbourne TokError("Incompatible types in list elements");
2325011817a0SCraig Topper return nullptr;
232684c287e3SPeter Collingbourne }
232784c287e3SPeter Collingbourne } else {
232884c287e3SPeter Collingbourne EltTy = TArg->getType();
232984c287e3SPeter Collingbourne }
233084c287e3SPeter Collingbourne }
2331ef60a268SNicolai Haehnle }
233284c287e3SPeter Collingbourne
2333011817a0SCraig Topper if (GivenEltTy) {
2334011817a0SCraig Topper if (EltTy) {
233584c287e3SPeter Collingbourne // Verify consistency
233684c287e3SPeter Collingbourne if (!EltTy->typeIsConvertibleTo(GivenEltTy)) {
233784c287e3SPeter Collingbourne TokError("Incompatible types in list elements");
2338011817a0SCraig Topper return nullptr;
233984c287e3SPeter Collingbourne }
234084c287e3SPeter Collingbourne }
234184c287e3SPeter Collingbourne EltTy = GivenEltTy;
234284c287e3SPeter Collingbourne }
234384c287e3SPeter Collingbourne
2344011817a0SCraig Topper if (!EltTy) {
2345011817a0SCraig Topper if (!ItemType) {
234684c287e3SPeter Collingbourne TokError("No type for list");
2347011817a0SCraig Topper return nullptr;
234884c287e3SPeter Collingbourne }
234984c287e3SPeter Collingbourne DeducedEltTy = GivenListTy->getElementType();
235084c287e3SPeter Collingbourne } else {
235184c287e3SPeter Collingbourne // Make sure the deduced type is compatible with the given type
235284c287e3SPeter Collingbourne if (GivenListTy) {
235384c287e3SPeter Collingbourne if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) {
2354f19083d1SNicolai Haehnle TokError(Twine("Element type mismatch for list: element type '") +
2355f19083d1SNicolai Haehnle EltTy->getAsString() + "' not convertible to '" +
2356f19083d1SNicolai Haehnle GivenListTy->getElementType()->getAsString());
2357011817a0SCraig Topper return nullptr;
235884c287e3SPeter Collingbourne }
235984c287e3SPeter Collingbourne }
236084c287e3SPeter Collingbourne DeducedEltTy = EltTy;
236184c287e3SPeter Collingbourne }
236284c287e3SPeter Collingbourne
236384c287e3SPeter Collingbourne return ListInit::get(Vals, DeducedEltTy);
236484c287e3SPeter Collingbourne }
236584c287e3SPeter Collingbourne case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
236684c287e3SPeter Collingbourne Lex.Lex(); // eat the '('
23670e894edeSSimon Tatham if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast &&
2368876af264SPaul C. Anagnostopoulos Lex.getCode() != tgtok::question && Lex.getCode() != tgtok::XGetDagOp) {
236984c287e3SPeter Collingbourne TokError("expected identifier in dag init");
2370011817a0SCraig Topper return nullptr;
237184c287e3SPeter Collingbourne }
237284c287e3SPeter Collingbourne
237384c287e3SPeter Collingbourne Init *Operator = ParseValue(CurRec);
2374011817a0SCraig Topper if (!Operator) return nullptr;
237584c287e3SPeter Collingbourne
237684c287e3SPeter Collingbourne // If the operator name is present, parse it.
23777cf3b112SMatthias Braun StringInit *OperatorName = nullptr;
2378e69605bfSFangrui Song if (consume(tgtok::colon)) {
2379e69605bfSFangrui Song if (Lex.getCode() != tgtok::VarName) { // eat the ':'
238084c287e3SPeter Collingbourne TokError("expected variable name in dag operator");
2381011817a0SCraig Topper return nullptr;
238284c287e3SPeter Collingbourne }
23832ac3cd20SRiver Riddle OperatorName = StringInit::get(Records, Lex.getCurStrVal());
238484c287e3SPeter Collingbourne Lex.Lex(); // eat the VarName.
238584c287e3SPeter Collingbourne }
238684c287e3SPeter Collingbourne
23871ddb78cdSMatthias Braun SmallVector<std::pair<llvm::Init*, StringInit*>, 8> DagArgs;
238884c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::r_paren) {
23891ddb78cdSMatthias Braun ParseDagArgList(DagArgs, CurRec);
2390011817a0SCraig Topper if (DagArgs.empty()) return nullptr;
239184c287e3SPeter Collingbourne }
239284c287e3SPeter Collingbourne
2393e69605bfSFangrui Song if (!consume(tgtok::r_paren)) {
239484c287e3SPeter Collingbourne TokError("expected ')' in dag init");
2395011817a0SCraig Topper return nullptr;
239684c287e3SPeter Collingbourne }
239784c287e3SPeter Collingbourne
239884c287e3SPeter Collingbourne return DagInit::get(Operator, OperatorName, DagArgs);
239984c287e3SPeter Collingbourne }
240084c287e3SPeter Collingbourne
240184c287e3SPeter Collingbourne case tgtok::XHead:
240284c287e3SPeter Collingbourne case tgtok::XTail:
24030243aaf4SNicolai Haehnle case tgtok::XSize:
240484c287e3SPeter Collingbourne case tgtok::XEmpty:
24051fed9a0cSSimon Tatham case tgtok::XCast:
2406876af264SPaul C. Anagnostopoulos case tgtok::XGetDagOp: // Value ::= !unop '(' Value ')'
240763448488Swangpc case tgtok::XExists:
2408b5376059SNicolai Haehnle case tgtok::XIsA:
240984c287e3SPeter Collingbourne case tgtok::XConcat:
24106c118656SNicolai Haehnle case tgtok::XDag:
2411c7d4dc13SHal Finkel case tgtok::XADD:
24129d72065cSPaul C. Anagnostopoulos case tgtok::XSUB:
2413a8967569SNicola Zaghen case tgtok::XMUL:
24144767bb2cSPaul C. Anagnostopoulos case tgtok::XNOT:
24156b41a990SJoerg Sonnenberger case tgtok::XAND:
24161c8d9338SMatt Arsenault case tgtok::XOR:
24174767bb2cSPaul C. Anagnostopoulos case tgtok::XXOR:
241884c287e3SPeter Collingbourne case tgtok::XSRA:
241984c287e3SPeter Collingbourne case tgtok::XSRL:
242084c287e3SPeter Collingbourne case tgtok::XSHL:
242184c287e3SPeter Collingbourne case tgtok::XEq:
2422aa9ca691SNicolai Haehnle case tgtok::XNe:
2423aa9ca691SNicolai Haehnle case tgtok::XLe:
2424aa9ca691SNicolai Haehnle case tgtok::XLt:
2425aa9ca691SNicolai Haehnle case tgtok::XGe:
2426aa9ca691SNicolai Haehnle case tgtok::XGt:
2427314e80e5SDaniel Sanders case tgtok::XListConcat:
24285d9f656bSRoman Lebedev case tgtok::XListSplat:
24291fed9a0cSSimon Tatham case tgtok::XStrConcat:
2430d56cd429SPaul C. Anagnostopoulos case tgtok::XInterleave:
2431876af264SPaul C. Anagnostopoulos case tgtok::XSetDagOp: // Value ::= !binop '(' Value ',' Value ')'
243284c287e3SPeter Collingbourne case tgtok::XIf:
2433a3e3d852SJaved Absar case tgtok::XCond:
2434d34f6843SNicolai Haehnle case tgtok::XFoldl:
243584c287e3SPeter Collingbourne case tgtok::XForEach:
243691d2e5c8SPaul C. Anagnostopoulos case tgtok::XFilter:
2437e122a71aSPaul C. Anagnostopoulos case tgtok::XSubst:
2438952c6dddSPaul C. Anagnostopoulos case tgtok::XSubstr:
2439952c6dddSPaul C. Anagnostopoulos case tgtok::XFind: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
2440a73fd935SMatt Arsenault return ParseOperation(CurRec, ItemType);
244184c287e3SPeter Collingbourne }
244284c287e3SPeter Collingbourne }
244384c287e3SPeter Collingbourne
244484c287e3SPeter Collingbourne return R;
244584c287e3SPeter Collingbourne }
244684c287e3SPeter Collingbourne
24476e2b6351SPaul C. Anagnostopoulos /// ParseValue - Parse a TableGen value. This returns null on error.
244884c287e3SPeter Collingbourne ///
244984c287e3SPeter Collingbourne /// Value ::= SimpleValue ValueSuffix*
245084c287e3SPeter Collingbourne /// ValueSuffix ::= '{' BitList '}'
245184c287e3SPeter Collingbourne /// ValueSuffix ::= '[' BitList ']'
245284c287e3SPeter Collingbourne /// ValueSuffix ::= '.' ID
245384c287e3SPeter Collingbourne ///
ParseValue(Record * CurRec,RecTy * ItemType,IDParseMode Mode)2454d4263a6aSDavid Greene Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
2455d4263a6aSDavid Greene Init *Result = ParseSimpleValue(CurRec, ItemType, Mode);
2456011817a0SCraig Topper if (!Result) return nullptr;
245784c287e3SPeter Collingbourne
245884c287e3SPeter Collingbourne // Parse the suffixes now if present.
245933d7b762SEugene Zelenko while (true) {
246084c287e3SPeter Collingbourne switch (Lex.getCode()) {
246184c287e3SPeter Collingbourne default: return Result;
246284c287e3SPeter Collingbourne case tgtok::l_brace: {
24632435855aSNicolai Haehnle if (Mode == ParseNameMode)
2464b8a7c9d0SDavid Greene // This is the beginning of the object body.
2465b8a7c9d0SDavid Greene return Result;
2466b8a7c9d0SDavid Greene
246784c287e3SPeter Collingbourne SMLoc CurlyLoc = Lex.getLoc();
246884c287e3SPeter Collingbourne Lex.Lex(); // eat the '{'
2469c66e7557SMatthias Braun SmallVector<unsigned, 16> Ranges;
2470c66e7557SMatthias Braun ParseRangeList(Ranges);
2471011817a0SCraig Topper if (Ranges.empty()) return nullptr;
247284c287e3SPeter Collingbourne
247384c287e3SPeter Collingbourne // Reverse the bitlist.
247484c287e3SPeter Collingbourne std::reverse(Ranges.begin(), Ranges.end());
247584c287e3SPeter Collingbourne Result = Result->convertInitializerBitRange(Ranges);
2476011817a0SCraig Topper if (!Result) {
247784c287e3SPeter Collingbourne Error(CurlyLoc, "Invalid bit range for value");
2478011817a0SCraig Topper return nullptr;
247984c287e3SPeter Collingbourne }
248084c287e3SPeter Collingbourne
248184c287e3SPeter Collingbourne // Eat the '}'.
2482e69605bfSFangrui Song if (!consume(tgtok::r_brace)) {
248384c287e3SPeter Collingbourne TokError("expected '}' at end of bit range list");
2484011817a0SCraig Topper return nullptr;
248584c287e3SPeter Collingbourne }
248684c287e3SPeter Collingbourne break;
248784c287e3SPeter Collingbourne }
248884c287e3SPeter Collingbourne case tgtok::l_square: {
248984c287e3SPeter Collingbourne SMLoc SquareLoc = Lex.getLoc();
249084c287e3SPeter Collingbourne Lex.Lex(); // eat the '['
2491c66e7557SMatthias Braun SmallVector<unsigned, 16> Ranges;
2492c66e7557SMatthias Braun ParseRangeList(Ranges);
2493011817a0SCraig Topper if (Ranges.empty()) return nullptr;
249484c287e3SPeter Collingbourne
249584c287e3SPeter Collingbourne Result = Result->convertInitListSlice(Ranges);
2496011817a0SCraig Topper if (!Result) {
249784c287e3SPeter Collingbourne Error(SquareLoc, "Invalid range for list slice");
2498011817a0SCraig Topper return nullptr;
249984c287e3SPeter Collingbourne }
250084c287e3SPeter Collingbourne
250184c287e3SPeter Collingbourne // Eat the ']'.
2502e69605bfSFangrui Song if (!consume(tgtok::r_square)) {
250384c287e3SPeter Collingbourne TokError("expected ']' at end of list slice");
2504011817a0SCraig Topper return nullptr;
250584c287e3SPeter Collingbourne }
250684c287e3SPeter Collingbourne break;
250784c287e3SPeter Collingbourne }
2508196e6f9fSPaul C. Anagnostopoulos case tgtok::dot: {
250984c287e3SPeter Collingbourne if (Lex.Lex() != tgtok::Id) { // eat the .
251084c287e3SPeter Collingbourne TokError("expected field identifier after '.'");
2511011817a0SCraig Topper return nullptr;
251284c287e3SPeter Collingbourne }
25132ac3cd20SRiver Riddle StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());
25146a441839SMatthias Braun if (!Result->getFieldType(FieldName)) {
251584c287e3SPeter Collingbourne TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
251684c287e3SPeter Collingbourne Result->getAsString() + "'");
2517011817a0SCraig Topper return nullptr;
251884c287e3SPeter Collingbourne }
25192ad19016SNicolai Haehnle Result = FieldInit::get(Result, FieldName)->Fold(CurRec);
252084c287e3SPeter Collingbourne Lex.Lex(); // eat field name
252184c287e3SPeter Collingbourne break;
25226a441839SMatthias Braun }
25238e85b480SDavid Greene
25248e85b480SDavid Greene case tgtok::paste:
25258e85b480SDavid Greene SMLoc PasteLoc = Lex.getLoc();
2526fb509ed1SSean Silva TypedInit *LHS = dyn_cast<TypedInit>(Result);
25278e85b480SDavid Greene if (!LHS) {
25288e85b480SDavid Greene Error(PasteLoc, "LHS of paste is not typed!");
2529011817a0SCraig Topper return nullptr;
25308e85b480SDavid Greene }
25318e85b480SDavid Greene
253234d3b80dSJaved Absar // Check if it's a 'listA # listB'
253334d3b80dSJaved Absar if (isa<ListRecTy>(LHS->getType())) {
253434d3b80dSJaved Absar Lex.Lex(); // Eat the '#'.
253534d3b80dSJaved Absar
2536473f8ae6SPaul C. Anagnostopoulos assert(Mode == ParseValueMode && "encountered paste of lists in name");
2537473f8ae6SPaul C. Anagnostopoulos
253834d3b80dSJaved Absar switch (Lex.getCode()) {
253934d3b80dSJaved Absar case tgtok::colon:
254034d3b80dSJaved Absar case tgtok::semi:
254134d3b80dSJaved Absar case tgtok::l_brace:
254234d3b80dSJaved Absar Result = LHS; // trailing paste, ignore.
254334d3b80dSJaved Absar break;
254434d3b80dSJaved Absar default:
2545473f8ae6SPaul C. Anagnostopoulos Init *RHSResult = ParseValue(CurRec, ItemType, ParseValueMode);
254617cd3440SNicolai Hähnle if (!RHSResult)
254717cd3440SNicolai Hähnle return nullptr;
254834d3b80dSJaved Absar Result = BinOpInit::getListConcat(LHS, RHSResult);
2549ae2cb4f4SPaul C. Anagnostopoulos break;
255034d3b80dSJaved Absar }
255134d3b80dSJaved Absar break;
255234d3b80dSJaved Absar }
255334d3b80dSJaved Absar
255434d3b80dSJaved Absar // Create a !strconcat() operation, first casting each operand to
255534d3b80dSJaved Absar // a string if necessary.
25562ac3cd20SRiver Riddle if (LHS->getType() != StringRecTy::get(Records)) {
2557123e04b8SSimon Pilgrim auto CastLHS = dyn_cast<TypedInit>(
25582ac3cd20SRiver Riddle UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get(Records))
2559335c70f5SNicolai Haehnle ->Fold(CurRec));
2560123e04b8SSimon Pilgrim if (!CastLHS) {
2561123e04b8SSimon Pilgrim Error(PasteLoc,
2562123e04b8SSimon Pilgrim Twine("can't cast '") + LHS->getAsString() + "' to string");
2563335c70f5SNicolai Haehnle return nullptr;
2564335c70f5SNicolai Haehnle }
2565123e04b8SSimon Pilgrim LHS = CastLHS;
25668e85b480SDavid Greene }
25678e85b480SDavid Greene
2568011817a0SCraig Topper TypedInit *RHS = nullptr;
25698e85b480SDavid Greene
25708e85b480SDavid Greene Lex.Lex(); // Eat the '#'.
25718e85b480SDavid Greene switch (Lex.getCode()) {
25728e85b480SDavid Greene case tgtok::colon:
25738e85b480SDavid Greene case tgtok::semi:
25748e85b480SDavid Greene case tgtok::l_brace:
25758e85b480SDavid Greene // These are all of the tokens that can begin an object body.
25768e85b480SDavid Greene // Some of these can also begin values but we disallow those cases
25778e85b480SDavid Greene // because they are unlikely to be useful.
25788e85b480SDavid Greene
25798e85b480SDavid Greene // Trailing paste, concat with an empty string.
25802ac3cd20SRiver Riddle RHS = StringInit::get(Records, "");
25818e85b480SDavid Greene break;
25828e85b480SDavid Greene
25838e85b480SDavid Greene default:
258477841b15SNicolai Haehnle Init *RHSResult = ParseValue(CurRec, nullptr, ParseNameMode);
258517cd3440SNicolai Hähnle if (!RHSResult)
258617cd3440SNicolai Hähnle return nullptr;
2587fb509ed1SSean Silva RHS = dyn_cast<TypedInit>(RHSResult);
25888e85b480SDavid Greene if (!RHS) {
25898e85b480SDavid Greene Error(PasteLoc, "RHS of paste is not typed!");
2590011817a0SCraig Topper return nullptr;
25918e85b480SDavid Greene }
25928e85b480SDavid Greene
25932ac3cd20SRiver Riddle if (RHS->getType() != StringRecTy::get(Records)) {
2594123e04b8SSimon Pilgrim auto CastRHS = dyn_cast<TypedInit>(
25952ac3cd20SRiver Riddle UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get(Records))
2596335c70f5SNicolai Haehnle ->Fold(CurRec));
2597123e04b8SSimon Pilgrim if (!CastRHS) {
2598123e04b8SSimon Pilgrim Error(PasteLoc,
2599123e04b8SSimon Pilgrim Twine("can't cast '") + RHS->getAsString() + "' to string");
2600335c70f5SNicolai Haehnle return nullptr;
2601335c70f5SNicolai Haehnle }
2602123e04b8SSimon Pilgrim RHS = CastRHS;
26038e85b480SDavid Greene }
26048e85b480SDavid Greene
26058e85b480SDavid Greene break;
26068e85b480SDavid Greene }
26078e85b480SDavid Greene
26081eaebc62SNicolai Haehnle Result = BinOpInit::getStrConcat(LHS, RHS);
26098e85b480SDavid Greene break;
261084c287e3SPeter Collingbourne }
261184c287e3SPeter Collingbourne }
261284c287e3SPeter Collingbourne }
261384c287e3SPeter Collingbourne
261484c287e3SPeter Collingbourne /// ParseDagArgList - Parse the argument list for a dag literal expression.
261584c287e3SPeter Collingbourne ///
261691a5848cSJakob Stoklund Olesen /// DagArg ::= Value (':' VARNAME)?
261791a5848cSJakob Stoklund Olesen /// DagArg ::= VARNAME
261891a5848cSJakob Stoklund Olesen /// DagArgList ::= DagArg
261991a5848cSJakob Stoklund Olesen /// DagArgList ::= DagArgList ',' DagArg
ParseDagArgList(SmallVectorImpl<std::pair<llvm::Init *,StringInit * >> & Result,Record * CurRec)26201ddb78cdSMatthias Braun void TGParser::ParseDagArgList(
26211ddb78cdSMatthias Braun SmallVectorImpl<std::pair<llvm::Init*, StringInit*>> &Result,
26221ddb78cdSMatthias Braun Record *CurRec) {
262384c287e3SPeter Collingbourne
262433d7b762SEugene Zelenko while (true) {
262591a5848cSJakob Stoklund Olesen // DagArg ::= VARNAME
262691a5848cSJakob Stoklund Olesen if (Lex.getCode() == tgtok::VarName) {
262791a5848cSJakob Stoklund Olesen // A missing value is treated like '?'.
26282ac3cd20SRiver Riddle StringInit *VarName = StringInit::get(Records, Lex.getCurStrVal());
26292ac3cd20SRiver Riddle Result.emplace_back(UnsetInit::get(Records), VarName);
263091a5848cSJakob Stoklund Olesen Lex.Lex();
263191a5848cSJakob Stoklund Olesen } else {
263291a5848cSJakob Stoklund Olesen // DagArg ::= Value (':' VARNAME)?
263384c287e3SPeter Collingbourne Init *Val = ParseValue(CurRec);
26341ddb78cdSMatthias Braun if (!Val) {
26351ddb78cdSMatthias Braun Result.clear();
26361ddb78cdSMatthias Braun return;
26371ddb78cdSMatthias Braun }
263884c287e3SPeter Collingbourne
263984c287e3SPeter Collingbourne // If the variable name is present, add it.
2640bb053164SMatthias Braun StringInit *VarName = nullptr;
264184c287e3SPeter Collingbourne if (Lex.getCode() == tgtok::colon) {
264284c287e3SPeter Collingbourne if (Lex.Lex() != tgtok::VarName) { // eat the ':'
264384c287e3SPeter Collingbourne TokError("expected variable name in dag literal");
26441ddb78cdSMatthias Braun Result.clear();
26451ddb78cdSMatthias Braun return;
264684c287e3SPeter Collingbourne }
26472ac3cd20SRiver Riddle VarName = StringInit::get(Records, Lex.getCurStrVal());
264884c287e3SPeter Collingbourne Lex.Lex(); // eat the VarName.
264984c287e3SPeter Collingbourne }
265084c287e3SPeter Collingbourne
265184c287e3SPeter Collingbourne Result.push_back(std::make_pair(Val, VarName));
265291a5848cSJakob Stoklund Olesen }
2653e69605bfSFangrui Song if (!consume(tgtok::comma))
2654e69605bfSFangrui Song break;
265584c287e3SPeter Collingbourne }
265684c287e3SPeter Collingbourne }
265784c287e3SPeter Collingbourne
2658a9fc44c5SPaul C. Anagnostopoulos /// ParseValueList - Parse a comma separated list of values, returning them
2659a9fc44c5SPaul C. Anagnostopoulos /// in a vector. Note that this always expects to be able to parse at least one
266084c287e3SPeter Collingbourne /// value. It returns an empty list if this is not possible.
266184c287e3SPeter Collingbourne ///
266284c287e3SPeter Collingbourne /// ValueList ::= Value (',' Value)
266384c287e3SPeter Collingbourne ///
ParseValueList(SmallVectorImpl<Init * > & Result,Record * CurRec,RecTy * ItemType)2664c66e7557SMatthias Braun void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec,
2665a9fc44c5SPaul C. Anagnostopoulos RecTy *ItemType) {
2666a9fc44c5SPaul C. Anagnostopoulos
266784c287e3SPeter Collingbourne Result.push_back(ParseValue(CurRec, ItemType));
2668c66e7557SMatthias Braun if (!Result.back()) {
2669c66e7557SMatthias Braun Result.clear();
2670c66e7557SMatthias Braun return;
2671c66e7557SMatthias Braun }
267284c287e3SPeter Collingbourne
2673e69605bfSFangrui Song while (consume(tgtok::comma)) {
2674c85cb2fbSJaved Absar // ignore trailing comma for lists
2675c85cb2fbSJaved Absar if (Lex.getCode() == tgtok::r_square)
2676c85cb2fbSJaved Absar return;
267784c287e3SPeter Collingbourne Result.push_back(ParseValue(CurRec, ItemType));
2678c66e7557SMatthias Braun if (!Result.back()) {
2679c66e7557SMatthias Braun Result.clear();
2680c66e7557SMatthias Braun return;
268184c287e3SPeter Collingbourne }
2682c66e7557SMatthias Braun }
268384c287e3SPeter Collingbourne }
268484c287e3SPeter Collingbourne
2685a9fc44c5SPaul C. Anagnostopoulos // ParseTemplateArgValueList - Parse a template argument list with the syntax
2686a9fc44c5SPaul C. Anagnostopoulos // shown, filling in the Result vector. The open angle has been consumed.
2687a9fc44c5SPaul C. Anagnostopoulos // An empty argument list is allowed. Return false if okay, true if an
2688a9fc44c5SPaul C. Anagnostopoulos // error was detected.
2689a9fc44c5SPaul C. Anagnostopoulos //
2690a9fc44c5SPaul C. Anagnostopoulos // TemplateArgList ::= '<' [Value {',' Value}*] '>'
ParseTemplateArgValueList(SmallVectorImpl<Init * > & Result,Record * CurRec,Record * ArgsRec)2691a9fc44c5SPaul C. Anagnostopoulos bool TGParser::ParseTemplateArgValueList(SmallVectorImpl<Init *> &Result,
2692a9fc44c5SPaul C. Anagnostopoulos Record *CurRec, Record *ArgsRec) {
2693a9fc44c5SPaul C. Anagnostopoulos
2694a9fc44c5SPaul C. Anagnostopoulos assert(Result.empty() && "Result vector is not empty");
2695a9fc44c5SPaul C. Anagnostopoulos ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
2696a9fc44c5SPaul C. Anagnostopoulos unsigned ArgIndex = 0;
2697a9fc44c5SPaul C. Anagnostopoulos RecTy *ItemType;
2698a9fc44c5SPaul C. Anagnostopoulos
2699a9fc44c5SPaul C. Anagnostopoulos if (consume(tgtok::greater)) // empty value list
2700a9fc44c5SPaul C. Anagnostopoulos return false;
2701a9fc44c5SPaul C. Anagnostopoulos
2702a9fc44c5SPaul C. Anagnostopoulos while (true) {
2703a9fc44c5SPaul C. Anagnostopoulos if (ArgIndex >= TArgs.size()) {
2704a9fc44c5SPaul C. Anagnostopoulos TokError("Too many template arguments: " + utostr(ArgIndex + 1));
2705a9fc44c5SPaul C. Anagnostopoulos return true;
2706a9fc44c5SPaul C. Anagnostopoulos }
2707a9fc44c5SPaul C. Anagnostopoulos const RecordVal *Arg = ArgsRec->getValue(TArgs[ArgIndex]);
2708a9fc44c5SPaul C. Anagnostopoulos assert(Arg && "Template argument record not found");
2709a9fc44c5SPaul C. Anagnostopoulos
2710a9fc44c5SPaul C. Anagnostopoulos ItemType = Arg->getType();
2711a9fc44c5SPaul C. Anagnostopoulos Init *Value = ParseValue(CurRec, ItemType);
2712a9fc44c5SPaul C. Anagnostopoulos if (!Value)
2713a9fc44c5SPaul C. Anagnostopoulos return true;
2714a9fc44c5SPaul C. Anagnostopoulos Result.push_back(Value);
2715a9fc44c5SPaul C. Anagnostopoulos
2716a9fc44c5SPaul C. Anagnostopoulos if (consume(tgtok::greater)) // end of argument list?
2717a9fc44c5SPaul C. Anagnostopoulos return false;
2718107189a2SAlex Richardson if (!consume(tgtok::comma))
2719107189a2SAlex Richardson return TokError("Expected comma before next argument");
2720a9fc44c5SPaul C. Anagnostopoulos ++ArgIndex;
2721a9fc44c5SPaul C. Anagnostopoulos }
2722a9fc44c5SPaul C. Anagnostopoulos }
2723a9fc44c5SPaul C. Anagnostopoulos
272484c287e3SPeter Collingbourne /// ParseDeclaration - Read a declaration, returning the name of field ID, or an
2725a9fc44c5SPaul C. Anagnostopoulos /// empty string on error. This can happen in a number of different contexts,
2726a9fc44c5SPaul C. Anagnostopoulos /// including within a def or in the template args for a class (in which case
272784c287e3SPeter Collingbourne /// CurRec will be non-null) and within the template args for a multiclass (in
272884c287e3SPeter Collingbourne /// which case CurRec will be null, but CurMultiClass will be set). This can
272984c287e3SPeter Collingbourne /// also happen within a def that is within a multiclass, which will set both
273084c287e3SPeter Collingbourne /// CurRec and CurMultiClass.
273184c287e3SPeter Collingbourne ///
273284c287e3SPeter Collingbourne /// Declaration ::= FIELD? Type ID ('=' Value)?
273384c287e3SPeter Collingbourne ///
ParseDeclaration(Record * CurRec,bool ParsingTemplateArgs)2734db10e691SDavid Greene Init *TGParser::ParseDeclaration(Record *CurRec,
273584c287e3SPeter Collingbourne bool ParsingTemplateArgs) {
273684c287e3SPeter Collingbourne // Read the field prefix if present.
2737e69605bfSFangrui Song bool HasField = consume(tgtok::Field);
273884c287e3SPeter Collingbourne
273984c287e3SPeter Collingbourne RecTy *Type = ParseType();
2740011817a0SCraig Topper if (!Type) return nullptr;
274184c287e3SPeter Collingbourne
274284c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::Id) {
274384c287e3SPeter Collingbourne TokError("Expected identifier in declaration");
2744011817a0SCraig Topper return nullptr;
274584c287e3SPeter Collingbourne }
274684c287e3SPeter Collingbourne
274701d261f1SNicolai Haehnle std::string Str = Lex.getCurStrVal();
274801d261f1SNicolai Haehnle if (Str == "NAME") {
274901d261f1SNicolai Haehnle TokError("'" + Str + "' is a reserved variable name");
275001d261f1SNicolai Haehnle return nullptr;
275101d261f1SNicolai Haehnle }
275201d261f1SNicolai Haehnle
275384c287e3SPeter Collingbourne SMLoc IdLoc = Lex.getLoc();
27542ac3cd20SRiver Riddle Init *DeclName = StringInit::get(Records, Str);
275584c287e3SPeter Collingbourne Lex.Lex();
275684c287e3SPeter Collingbourne
2757a9fc44c5SPaul C. Anagnostopoulos bool BadField;
2758a9fc44c5SPaul C. Anagnostopoulos if (!ParsingTemplateArgs) { // def, possibly in a multiclass
2759a9fc44c5SPaul C. Anagnostopoulos BadField = AddValue(CurRec, IdLoc,
2760a9fc44c5SPaul C. Anagnostopoulos RecordVal(DeclName, IdLoc, Type,
276149d663d5SPaul C. Anagnostopoulos HasField ? RecordVal::FK_NonconcreteOK
2762a9fc44c5SPaul C. Anagnostopoulos : RecordVal::FK_Normal));
2763a9fc44c5SPaul C. Anagnostopoulos
2764a9fc44c5SPaul C. Anagnostopoulos } else if (CurRec) { // class template argument
2765a9fc44c5SPaul C. Anagnostopoulos DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":");
2766a9fc44c5SPaul C. Anagnostopoulos BadField = AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type,
2767a9fc44c5SPaul C. Anagnostopoulos RecordVal::FK_TemplateArg));
2768a9fc44c5SPaul C. Anagnostopoulos
2769a9fc44c5SPaul C. Anagnostopoulos } else { // multiclass template argument
2770a9fc44c5SPaul C. Anagnostopoulos assert(CurMultiClass && "invalid context for template argument");
2771a9fc44c5SPaul C. Anagnostopoulos DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, "::");
2772a9fc44c5SPaul C. Anagnostopoulos BadField = AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type,
2773a9fc44c5SPaul C. Anagnostopoulos RecordVal::FK_TemplateArg));
2774a9fc44c5SPaul C. Anagnostopoulos }
2775a9fc44c5SPaul C. Anagnostopoulos if (BadField)
2776011817a0SCraig Topper return nullptr;
277784c287e3SPeter Collingbourne
2778a9fc44c5SPaul C. Anagnostopoulos // If a value is present, parse it and set new field's value.
2779e69605bfSFangrui Song if (consume(tgtok::equal)) {
278084c287e3SPeter Collingbourne SMLoc ValLoc = Lex.getLoc();
278184c287e3SPeter Collingbourne Init *Val = ParseValue(CurRec, Type);
2782011817a0SCraig Topper if (!Val ||
2783cfd81733SCraig Topper SetValue(CurRec, ValLoc, DeclName, None, Val))
27844cc54cbbSPete Cooper // Return the name, even if an error is thrown. This is so that we can
27854cc54cbbSPete Cooper // continue to make some progress, even without the value having been
27864cc54cbbSPete Cooper // initialized.
27874cc54cbbSPete Cooper return DeclName;
278884c287e3SPeter Collingbourne }
278984c287e3SPeter Collingbourne
279084c287e3SPeter Collingbourne return DeclName;
279184c287e3SPeter Collingbourne }
279284c287e3SPeter Collingbourne
2793fb927af2SDavid Greene /// ParseForeachDeclaration - Read a foreach declaration, returning
2794fb927af2SDavid Greene /// the name of the declared object or a NULL Init on error. Return
2795fb927af2SDavid Greene /// the name of the parsed initializer list through ForeachListName.
2796fb927af2SDavid Greene ///
279736a5c8e5SJakob Stoklund Olesen /// ForeachDeclaration ::= ID '=' '{' RangeList '}'
279836a5c8e5SJakob Stoklund Olesen /// ForeachDeclaration ::= ID '=' RangePiece
27998aa9d583SNicolai Haehnle /// ForeachDeclaration ::= ID '=' Value
2800fb927af2SDavid Greene ///
ParseForeachDeclaration(Init * & ForeachListValue)28017d69e0f3SNicolai Haehnle VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {
2802fb927af2SDavid Greene if (Lex.getCode() != tgtok::Id) {
2803fb927af2SDavid Greene TokError("Expected identifier in foreach declaration");
2804011817a0SCraig Topper return nullptr;
2805fb927af2SDavid Greene }
2806fb927af2SDavid Greene
28072ac3cd20SRiver Riddle Init *DeclName = StringInit::get(Records, Lex.getCurStrVal());
2808fb927af2SDavid Greene Lex.Lex();
2809fb927af2SDavid Greene
2810fb927af2SDavid Greene // If a value is present, parse it.
2811e69605bfSFangrui Song if (!consume(tgtok::equal)) {
2812fb927af2SDavid Greene TokError("Expected '=' in foreach declaration");
2813011817a0SCraig Topper return nullptr;
2814fb927af2SDavid Greene }
2815fb927af2SDavid Greene
2816011817a0SCraig Topper RecTy *IterType = nullptr;
2817c66e7557SMatthias Braun SmallVector<unsigned, 16> Ranges;
2818fb927af2SDavid Greene
281936a5c8e5SJakob Stoklund Olesen switch (Lex.getCode()) {
282036a5c8e5SJakob Stoklund Olesen case tgtok::l_brace: { // '{' RangeList '}'
282136a5c8e5SJakob Stoklund Olesen Lex.Lex(); // eat the '{'
2822c66e7557SMatthias Braun ParseRangeList(Ranges);
2823e69605bfSFangrui Song if (!consume(tgtok::r_brace)) {
282436a5c8e5SJakob Stoklund Olesen TokError("expected '}' at end of bit range list");
2825011817a0SCraig Topper return nullptr;
282636a5c8e5SJakob Stoklund Olesen }
282736a5c8e5SJakob Stoklund Olesen break;
282836a5c8e5SJakob Stoklund Olesen }
28298aa9d583SNicolai Haehnle
28308aa9d583SNicolai Haehnle default: {
28318aa9d583SNicolai Haehnle SMLoc ValueLoc = Lex.getLoc();
28328aa9d583SNicolai Haehnle Init *I = ParseValue(nullptr);
2833b79a25b1SMatt Arsenault if (!I)
28348aa9d583SNicolai Haehnle return nullptr;
2835b79a25b1SMatt Arsenault
2836b79a25b1SMatt Arsenault TypedInit *TI = dyn_cast<TypedInit>(I);
2837b79a25b1SMatt Arsenault if (TI && isa<ListRecTy>(TI->getType())) {
28387d69e0f3SNicolai Haehnle ForeachListValue = I;
28397d69e0f3SNicolai Haehnle IterType = cast<ListRecTy>(TI->getType())->getElementType();
28408aa9d583SNicolai Haehnle break;
28418aa9d583SNicolai Haehnle }
2842b79a25b1SMatt Arsenault
2843b79a25b1SMatt Arsenault if (TI) {
2844b79a25b1SMatt Arsenault if (ParseRangePiece(Ranges, TI))
2845b79a25b1SMatt Arsenault return nullptr;
2846b79a25b1SMatt Arsenault break;
284736a5c8e5SJakob Stoklund Olesen }
284836a5c8e5SJakob Stoklund Olesen
2849407c11b5SPaul C. Anagnostopoulos Error(ValueLoc, "expected a list, got '" + I->getAsString() + "'");
2850b79a25b1SMatt Arsenault if (CurMultiClass) {
2851b79a25b1SMatt Arsenault PrintNote({}, "references to multiclass template arguments cannot be "
2852b79a25b1SMatt Arsenault "resolved at this time");
2853b79a25b1SMatt Arsenault }
2854b79a25b1SMatt Arsenault return nullptr;
2855b79a25b1SMatt Arsenault }
2856b79a25b1SMatt Arsenault }
2857b79a25b1SMatt Arsenault
2858b79a25b1SMatt Arsenault
285936a5c8e5SJakob Stoklund Olesen if (!Ranges.empty()) {
286036a5c8e5SJakob Stoklund Olesen assert(!IterType && "Type already initialized?");
28612ac3cd20SRiver Riddle IterType = IntRecTy::get(Records);
286236a5c8e5SJakob Stoklund Olesen std::vector<Init *> Values;
28638eb764c5SCraig Topper for (unsigned R : Ranges)
28642ac3cd20SRiver Riddle Values.push_back(IntInit::get(Records, R));
286536a5c8e5SJakob Stoklund Olesen ForeachListValue = ListInit::get(Values, IterType);
286636a5c8e5SJakob Stoklund Olesen }
286736a5c8e5SJakob Stoklund Olesen
286836a5c8e5SJakob Stoklund Olesen if (!IterType)
2869011817a0SCraig Topper return nullptr;
287036a5c8e5SJakob Stoklund Olesen
287136a5c8e5SJakob Stoklund Olesen return VarInit::get(DeclName, IterType);
2872fb927af2SDavid Greene }
2873fb927af2SDavid Greene
287484c287e3SPeter Collingbourne /// ParseTemplateArgList - Read a template argument list, which is a non-empty
287584c287e3SPeter Collingbourne /// sequence of template-declarations in <>'s. If CurRec is non-null, these are
28769d609adcSPaul C. Anagnostopoulos /// template args for a class. If null, these are the template args for a
28779d609adcSPaul C. Anagnostopoulos /// multiclass.
287884c287e3SPeter Collingbourne ///
287984c287e3SPeter Collingbourne /// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'
288084c287e3SPeter Collingbourne ///
ParseTemplateArgList(Record * CurRec)288184c287e3SPeter Collingbourne bool TGParser::ParseTemplateArgList(Record *CurRec) {
288284c287e3SPeter Collingbourne assert(Lex.getCode() == tgtok::less && "Not a template arg list!");
288384c287e3SPeter Collingbourne Lex.Lex(); // eat the '<'
288484c287e3SPeter Collingbourne
288584c287e3SPeter Collingbourne Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;
288684c287e3SPeter Collingbourne
288784c287e3SPeter Collingbourne // Read the first declaration.
2888db10e691SDavid Greene Init *TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
2889011817a0SCraig Topper if (!TemplArg)
289084c287e3SPeter Collingbourne return true;
289184c287e3SPeter Collingbourne
289284c287e3SPeter Collingbourne TheRecToAddTo->addTemplateArg(TemplArg);
289384c287e3SPeter Collingbourne
2894e69605bfSFangrui Song while (consume(tgtok::comma)) {
289584c287e3SPeter Collingbourne // Read the following declarations.
2896e7ae0f48SNicolai Haehnle SMLoc Loc = Lex.getLoc();
289784c287e3SPeter Collingbourne TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
2898011817a0SCraig Topper if (!TemplArg)
289984c287e3SPeter Collingbourne return true;
2900e7ae0f48SNicolai Haehnle
2901e7ae0f48SNicolai Haehnle if (TheRecToAddTo->isTemplateArg(TemplArg))
2902e7ae0f48SNicolai Haehnle return Error(Loc, "template argument with the same name has already been "
2903e7ae0f48SNicolai Haehnle "defined");
2904e7ae0f48SNicolai Haehnle
290584c287e3SPeter Collingbourne TheRecToAddTo->addTemplateArg(TemplArg);
290684c287e3SPeter Collingbourne }
290784c287e3SPeter Collingbourne
2908e69605bfSFangrui Song if (!consume(tgtok::greater))
290984c287e3SPeter Collingbourne return TokError("expected '>' at end of template argument list");
291084c287e3SPeter Collingbourne return false;
291184c287e3SPeter Collingbourne }
291284c287e3SPeter Collingbourne
29136e2b6351SPaul C. Anagnostopoulos /// ParseBodyItem - Parse a single item within the body of a def or class.
291484c287e3SPeter Collingbourne ///
291584c287e3SPeter Collingbourne /// BodyItem ::= Declaration ';'
291684c287e3SPeter Collingbourne /// BodyItem ::= LET ID OptionalBitList '=' Value ';'
29173388b0f5SSimon Tatham /// BodyItem ::= Defvar
29186e2b6351SPaul C. Anagnostopoulos /// BodyItem ::= Assert
29199d609adcSPaul C. Anagnostopoulos ///
ParseBodyItem(Record * CurRec)292084c287e3SPeter Collingbourne bool TGParser::ParseBodyItem(Record *CurRec) {
29216e2b6351SPaul C. Anagnostopoulos if (Lex.getCode() == tgtok::Assert)
29226e2b6351SPaul C. Anagnostopoulos return ParseAssert(nullptr, CurRec);
29236e2b6351SPaul C. Anagnostopoulos
29243388b0f5SSimon Tatham if (Lex.getCode() == tgtok::Defvar)
29253388b0f5SSimon Tatham return ParseDefvar();
29263388b0f5SSimon Tatham
292784c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::Let) {
2928011817a0SCraig Topper if (!ParseDeclaration(CurRec, false))
292984c287e3SPeter Collingbourne return true;
293084c287e3SPeter Collingbourne
29318ba36497SFangrui Song if (!consume(tgtok::semi))
293284c287e3SPeter Collingbourne return TokError("expected ';' after declaration");
293384c287e3SPeter Collingbourne return false;
293484c287e3SPeter Collingbourne }
293584c287e3SPeter Collingbourne
293684c287e3SPeter Collingbourne // LET ID OptionalRangeList '=' Value ';'
293784c287e3SPeter Collingbourne if (Lex.Lex() != tgtok::Id)
293884c287e3SPeter Collingbourne return TokError("expected field identifier after let");
293984c287e3SPeter Collingbourne
294084c287e3SPeter Collingbourne SMLoc IdLoc = Lex.getLoc();
29412ac3cd20SRiver Riddle StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());
294284c287e3SPeter Collingbourne Lex.Lex(); // eat the field name.
294384c287e3SPeter Collingbourne
2944c66e7557SMatthias Braun SmallVector<unsigned, 16> BitList;
294584c287e3SPeter Collingbourne if (ParseOptionalBitList(BitList))
294684c287e3SPeter Collingbourne return true;
294784c287e3SPeter Collingbourne std::reverse(BitList.begin(), BitList.end());
294884c287e3SPeter Collingbourne
29498ba36497SFangrui Song if (!consume(tgtok::equal))
295084c287e3SPeter Collingbourne return TokError("expected '=' in let expression");
295184c287e3SPeter Collingbourne
295284c287e3SPeter Collingbourne RecordVal *Field = CurRec->getValue(FieldName);
2953011817a0SCraig Topper if (!Field)
2954215ff84bSMatthias Braun return TokError("Value '" + FieldName->getValue() + "' unknown!");
295584c287e3SPeter Collingbourne
295684c287e3SPeter Collingbourne RecTy *Type = Field->getType();
29575c6b1a6dSSimon Tatham if (!BitList.empty() && isa<BitsRecTy>(Type)) {
29585c6b1a6dSSimon Tatham // When assigning to a subset of a 'bits' object, expect the RHS to have
29595c6b1a6dSSimon Tatham // the type of that subset instead of the type of the whole object.
29602ac3cd20SRiver Riddle Type = BitsRecTy::get(Records, BitList.size());
29615c6b1a6dSSimon Tatham }
296284c287e3SPeter Collingbourne
296384c287e3SPeter Collingbourne Init *Val = ParseValue(CurRec, Type);
2964011817a0SCraig Topper if (!Val) return true;
296584c287e3SPeter Collingbourne
29668ba36497SFangrui Song if (!consume(tgtok::semi))
296784c287e3SPeter Collingbourne return TokError("expected ';' after let expression");
296884c287e3SPeter Collingbourne
296984c287e3SPeter Collingbourne return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
297084c287e3SPeter Collingbourne }
297184c287e3SPeter Collingbourne
297284c287e3SPeter Collingbourne /// ParseBody - Read the body of a class or def. Return true on error, false on
297384c287e3SPeter Collingbourne /// success.
297484c287e3SPeter Collingbourne ///
297584c287e3SPeter Collingbourne /// Body ::= ';'
297684c287e3SPeter Collingbourne /// Body ::= '{' BodyList '}'
297784c287e3SPeter Collingbourne /// BodyList BodyItem*
297884c287e3SPeter Collingbourne ///
ParseBody(Record * CurRec)297984c287e3SPeter Collingbourne bool TGParser::ParseBody(Record *CurRec) {
298084c287e3SPeter Collingbourne // If this is a null definition, just eat the semi and return.
2981e69605bfSFangrui Song if (consume(tgtok::semi))
298284c287e3SPeter Collingbourne return false;
298384c287e3SPeter Collingbourne
2984e69605bfSFangrui Song if (!consume(tgtok::l_brace))
2985a6759477SPaul C. Anagnostopoulos return TokError("Expected '{' to start body or ';' for declaration only");
298684c287e3SPeter Collingbourne
29873388b0f5SSimon Tatham // An object body introduces a new scope for local variables.
29883388b0f5SSimon Tatham TGLocalVarScope *BodyScope = PushLocalScope();
29893388b0f5SSimon Tatham
299084c287e3SPeter Collingbourne while (Lex.getCode() != tgtok::r_brace)
299184c287e3SPeter Collingbourne if (ParseBodyItem(CurRec))
299284c287e3SPeter Collingbourne return true;
299384c287e3SPeter Collingbourne
29943388b0f5SSimon Tatham PopLocalScope(BodyScope);
29953388b0f5SSimon Tatham
299684c287e3SPeter Collingbourne // Eat the '}'.
299784c287e3SPeter Collingbourne Lex.Lex();
2998a6759477SPaul C. Anagnostopoulos
2999a6759477SPaul C. Anagnostopoulos // If we have a semicolon, print a gentle error.
3000a6759477SPaul C. Anagnostopoulos SMLoc SemiLoc = Lex.getLoc();
3001a6759477SPaul C. Anagnostopoulos if (consume(tgtok::semi)) {
3002a6759477SPaul C. Anagnostopoulos PrintError(SemiLoc, "A class or def body should not end with a semicolon");
3003a6759477SPaul C. Anagnostopoulos PrintNote("Semicolon ignored; remove to eliminate this error");
3004a6759477SPaul C. Anagnostopoulos }
3005a6759477SPaul C. Anagnostopoulos
300684c287e3SPeter Collingbourne return false;
300784c287e3SPeter Collingbourne }
300884c287e3SPeter Collingbourne
30095f8f34e4SAdrian Prantl /// Apply the current let bindings to \a CurRec.
3010cb1a75e7SSean Silva /// \returns true on error, false otherwise.
ApplyLetStack(Record * CurRec)3011cb1a75e7SSean Silva bool TGParser::ApplyLetStack(Record *CurRec) {
3012c66e7557SMatthias Braun for (SmallVectorImpl<LetRecord> &LetInfo : LetStack)
30138eb764c5SCraig Topper for (LetRecord &LR : LetInfo)
30148eb764c5SCraig Topper if (SetValue(CurRec, LR.Loc, LR.Name, LR.Bits, LR.Value))
3015cb1a75e7SSean Silva return true;
3016cb1a75e7SSean Silva return false;
3017cb1a75e7SSean Silva }
3018cb1a75e7SSean Silva
3019a5aaec8fSPaul C. Anagnostopoulos /// Apply the current let bindings to the RecordsEntry.
ApplyLetStack(RecordsEntry & Entry)30207d69e0f3SNicolai Haehnle bool TGParser::ApplyLetStack(RecordsEntry &Entry) {
30217d69e0f3SNicolai Haehnle if (Entry.Rec)
30227d69e0f3SNicolai Haehnle return ApplyLetStack(Entry.Rec.get());
30237d69e0f3SNicolai Haehnle
3024a5aaec8fSPaul C. Anagnostopoulos // Let bindings are not applied to assertions.
3025a5aaec8fSPaul C. Anagnostopoulos if (Entry.Assertion)
3026a5aaec8fSPaul C. Anagnostopoulos return false;
3027a5aaec8fSPaul C. Anagnostopoulos
30287d69e0f3SNicolai Haehnle for (auto &E : Entry.Loop->Entries) {
30297d69e0f3SNicolai Haehnle if (ApplyLetStack(E))
30307d69e0f3SNicolai Haehnle return true;
30317d69e0f3SNicolai Haehnle }
30327d69e0f3SNicolai Haehnle
30337d69e0f3SNicolai Haehnle return false;
30347d69e0f3SNicolai Haehnle }
30357d69e0f3SNicolai Haehnle
303684c287e3SPeter Collingbourne /// ParseObjectBody - Parse the body of a def or class. This consists of an
303784c287e3SPeter Collingbourne /// optional ClassList followed by a Body. CurRec is the current def or class
303884c287e3SPeter Collingbourne /// that is being parsed.
303984c287e3SPeter Collingbourne ///
304084c287e3SPeter Collingbourne /// ObjectBody ::= BaseClassList Body
304184c287e3SPeter Collingbourne /// BaseClassList ::= /*empty*/
304284c287e3SPeter Collingbourne /// BaseClassList ::= ':' BaseClassListNE
304384c287e3SPeter Collingbourne /// BaseClassListNE ::= SubClassRef (',' SubClassRef)*
304484c287e3SPeter Collingbourne ///
ParseObjectBody(Record * CurRec)304584c287e3SPeter Collingbourne bool TGParser::ParseObjectBody(Record *CurRec) {
304684c287e3SPeter Collingbourne // If there is a baseclass list, read it.
3047e69605bfSFangrui Song if (consume(tgtok::colon)) {
304884c287e3SPeter Collingbourne
304984c287e3SPeter Collingbourne // Read all of the subclasses.
305084c287e3SPeter Collingbourne SubClassReference SubClass = ParseSubClassReference(CurRec, false);
305133d7b762SEugene Zelenko while (true) {
305284c287e3SPeter Collingbourne // Check for error.
3053011817a0SCraig Topper if (!SubClass.Rec) return true;
305484c287e3SPeter Collingbourne
305584c287e3SPeter Collingbourne // Add it.
305684c287e3SPeter Collingbourne if (AddSubClass(CurRec, SubClass))
305784c287e3SPeter Collingbourne return true;
305884c287e3SPeter Collingbourne
30598ba36497SFangrui Song if (!consume(tgtok::comma))
30608ba36497SFangrui Song break;
306184c287e3SPeter Collingbourne SubClass = ParseSubClassReference(CurRec, false);
306284c287e3SPeter Collingbourne }
306384c287e3SPeter Collingbourne }
306484c287e3SPeter Collingbourne
3065cb1a75e7SSean Silva if (ApplyLetStack(CurRec))
306684c287e3SPeter Collingbourne return true;
306784c287e3SPeter Collingbourne
306884c287e3SPeter Collingbourne return ParseBody(CurRec);
306984c287e3SPeter Collingbourne }
307084c287e3SPeter Collingbourne
3071a5aaec8fSPaul C. Anagnostopoulos /// ParseDef - Parse and return a top level or multiclass record definition.
3072a5aaec8fSPaul C. Anagnostopoulos /// Return false if okay, true if error.
307384c287e3SPeter Collingbourne ///
307484c287e3SPeter Collingbourne /// DefInst ::= DEF ObjectName ObjectBody
307584c287e3SPeter Collingbourne ///
ParseDef(MultiClass * CurMultiClass)307684c287e3SPeter Collingbourne bool TGParser::ParseDef(MultiClass *CurMultiClass) {
307784c287e3SPeter Collingbourne SMLoc DefLoc = Lex.getLoc();
307884c287e3SPeter Collingbourne assert(Lex.getCode() == tgtok::Def && "Unknown tok");
307984c287e3SPeter Collingbourne Lex.Lex(); // Eat the 'def' token.
308084c287e3SPeter Collingbourne
308184c287e3SPeter Collingbourne // Parse ObjectName and make a record for it.
3082420e28c7SNicolai Haehnle std::unique_ptr<Record> CurRec;
3083abdd99b5SJordan Rose Init *Name = ParseObjectName(CurMultiClass);
3084420e28c7SNicolai Haehnle if (!Name)
3085420e28c7SNicolai Haehnle return true;
3086420e28c7SNicolai Haehnle
3087420e28c7SNicolai Haehnle if (isa<UnsetInit>(Name))
30880eaee545SJonas Devlieghere CurRec = std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc, Records,
3089420e28c7SNicolai Haehnle /*Anonymous=*/true);
3090abdd99b5SJordan Rose else
30910eaee545SJonas Devlieghere CurRec = std::make_unique<Record>(Name, DefLoc, Records);
309284c287e3SPeter Collingbourne
3093420e28c7SNicolai Haehnle if (ParseObjectBody(CurRec.get()))
3094a8c1f467SHal Finkel return true;
3095a8c1f467SHal Finkel
30967d69e0f3SNicolai Haehnle return addEntry(std::move(CurRec));
3097fcd6525aSNicolai Haehnle }
3098fcd6525aSNicolai Haehnle
3099fcd6525aSNicolai Haehnle /// ParseDefset - Parse a defset statement.
3100fcd6525aSNicolai Haehnle ///
3101fcd6525aSNicolai Haehnle /// Defset ::= DEFSET Type Id '=' '{' ObjectList '}'
3102fcd6525aSNicolai Haehnle ///
ParseDefset()3103fcd6525aSNicolai Haehnle bool TGParser::ParseDefset() {
3104fcd6525aSNicolai Haehnle assert(Lex.getCode() == tgtok::Defset);
3105fcd6525aSNicolai Haehnle Lex.Lex(); // Eat the 'defset' token
3106fcd6525aSNicolai Haehnle
3107fcd6525aSNicolai Haehnle DefsetRecord Defset;
3108fcd6525aSNicolai Haehnle Defset.Loc = Lex.getLoc();
3109fcd6525aSNicolai Haehnle RecTy *Type = ParseType();
3110fcd6525aSNicolai Haehnle if (!Type)
3111fcd6525aSNicolai Haehnle return true;
3112fcd6525aSNicolai Haehnle if (!isa<ListRecTy>(Type))
3113fcd6525aSNicolai Haehnle return Error(Defset.Loc, "expected list type");
3114fcd6525aSNicolai Haehnle Defset.EltTy = cast<ListRecTy>(Type)->getElementType();
3115fcd6525aSNicolai Haehnle
3116fcd6525aSNicolai Haehnle if (Lex.getCode() != tgtok::Id)
3117fcd6525aSNicolai Haehnle return TokError("expected identifier");
31182ac3cd20SRiver Riddle StringInit *DeclName = StringInit::get(Records, Lex.getCurStrVal());
3119fcd6525aSNicolai Haehnle if (Records.getGlobal(DeclName->getValue()))
3120fcd6525aSNicolai Haehnle return TokError("def or global variable of this name already exists");
3121fcd6525aSNicolai Haehnle
3122fcd6525aSNicolai Haehnle if (Lex.Lex() != tgtok::equal) // Eat the identifier
3123fcd6525aSNicolai Haehnle return TokError("expected '='");
3124fcd6525aSNicolai Haehnle if (Lex.Lex() != tgtok::l_brace) // Eat the '='
3125fcd6525aSNicolai Haehnle return TokError("expected '{'");
3126fcd6525aSNicolai Haehnle SMLoc BraceLoc = Lex.getLoc();
3127fcd6525aSNicolai Haehnle Lex.Lex(); // Eat the '{'
3128fcd6525aSNicolai Haehnle
3129fcd6525aSNicolai Haehnle Defsets.push_back(&Defset);
3130fcd6525aSNicolai Haehnle bool Err = ParseObjectList(nullptr);
3131fcd6525aSNicolai Haehnle Defsets.pop_back();
3132fcd6525aSNicolai Haehnle if (Err)
3133fcd6525aSNicolai Haehnle return true;
3134fcd6525aSNicolai Haehnle
31358ba36497SFangrui Song if (!consume(tgtok::r_brace)) {
3136fcd6525aSNicolai Haehnle TokError("expected '}' at end of defset");
3137fcd6525aSNicolai Haehnle return Error(BraceLoc, "to match this '{'");
3138fcd6525aSNicolai Haehnle }
3139fcd6525aSNicolai Haehnle
3140fcd6525aSNicolai Haehnle Records.addExtraGlobal(DeclName->getValue(),
3141fcd6525aSNicolai Haehnle ListInit::get(Defset.Elements, Defset.EltTy));
3142fcd6525aSNicolai Haehnle return false;
3143fcd6525aSNicolai Haehnle }
3144fcd6525aSNicolai Haehnle
31453388b0f5SSimon Tatham /// ParseDefvar - Parse a defvar statement.
31463388b0f5SSimon Tatham ///
31473388b0f5SSimon Tatham /// Defvar ::= DEFVAR Id '=' Value ';'
31483388b0f5SSimon Tatham ///
ParseDefvar()31493388b0f5SSimon Tatham bool TGParser::ParseDefvar() {
31503388b0f5SSimon Tatham assert(Lex.getCode() == tgtok::Defvar);
31513388b0f5SSimon Tatham Lex.Lex(); // Eat the 'defvar' token
31523388b0f5SSimon Tatham
31533388b0f5SSimon Tatham if (Lex.getCode() != tgtok::Id)
31543388b0f5SSimon Tatham return TokError("expected identifier");
31552ac3cd20SRiver Riddle StringInit *DeclName = StringInit::get(Records, Lex.getCurStrVal());
31563388b0f5SSimon Tatham if (CurLocalScope) {
31573388b0f5SSimon Tatham if (CurLocalScope->varAlreadyDefined(DeclName->getValue()))
31583388b0f5SSimon Tatham return TokError("local variable of this name already exists");
31593388b0f5SSimon Tatham } else {
31603388b0f5SSimon Tatham if (Records.getGlobal(DeclName->getValue()))
31613388b0f5SSimon Tatham return TokError("def or global variable of this name already exists");
31623388b0f5SSimon Tatham }
31633388b0f5SSimon Tatham
31648ba36497SFangrui Song Lex.Lex();
31658ba36497SFangrui Song if (!consume(tgtok::equal))
31663388b0f5SSimon Tatham return TokError("expected '='");
31673388b0f5SSimon Tatham
31683388b0f5SSimon Tatham Init *Value = ParseValue(nullptr);
31693388b0f5SSimon Tatham if (!Value)
31703388b0f5SSimon Tatham return true;
31713388b0f5SSimon Tatham
31728ba36497SFangrui Song if (!consume(tgtok::semi))
31733388b0f5SSimon Tatham return TokError("expected ';'");
31743388b0f5SSimon Tatham
31753388b0f5SSimon Tatham if (CurLocalScope)
31763388b0f5SSimon Tatham CurLocalScope->addVar(DeclName->getValue(), Value);
31773388b0f5SSimon Tatham else
31783388b0f5SSimon Tatham Records.addExtraGlobal(DeclName->getValue(), Value);
31793388b0f5SSimon Tatham
31803388b0f5SSimon Tatham return false;
31813388b0f5SSimon Tatham }
31823388b0f5SSimon Tatham
3183fb927af2SDavid Greene /// ParseForeach - Parse a for statement. Return the record corresponding
3184fb927af2SDavid Greene /// to it. This returns true on error.
3185fb927af2SDavid Greene ///
3186fb927af2SDavid Greene /// Foreach ::= FOREACH Declaration IN '{ ObjectList '}'
3187fb927af2SDavid Greene /// Foreach ::= FOREACH Declaration IN Object
3188fb927af2SDavid Greene ///
ParseForeach(MultiClass * CurMultiClass)3189fb927af2SDavid Greene bool TGParser::ParseForeach(MultiClass *CurMultiClass) {
31907d69e0f3SNicolai Haehnle SMLoc Loc = Lex.getLoc();
3191fb927af2SDavid Greene assert(Lex.getCode() == tgtok::Foreach && "Unknown tok");
3192fb927af2SDavid Greene Lex.Lex(); // Eat the 'for' token.
3193fb927af2SDavid Greene
3194fb927af2SDavid Greene // Make a temporary object to record items associated with the for
3195fb927af2SDavid Greene // loop.
31967d69e0f3SNicolai Haehnle Init *ListValue = nullptr;
31978a120b10SJakob Stoklund Olesen VarInit *IterName = ParseForeachDeclaration(ListValue);
3198011817a0SCraig Topper if (!IterName)
3199fb927af2SDavid Greene return TokError("expected declaration in for");
3200fb927af2SDavid Greene
32018ba36497SFangrui Song if (!consume(tgtok::In))
3202fb927af2SDavid Greene return TokError("Unknown tok");
3203fb927af2SDavid Greene
3204fb927af2SDavid Greene // Create a loop object and remember it.
32050eaee545SJonas Devlieghere Loops.push_back(std::make_unique<ForeachLoop>(Loc, IterName, ListValue));
3206fb927af2SDavid Greene
32073388b0f5SSimon Tatham // A foreach loop introduces a new scope for local variables.
32083388b0f5SSimon Tatham TGLocalVarScope *ForeachScope = PushLocalScope();
32093388b0f5SSimon Tatham
3210fb927af2SDavid Greene if (Lex.getCode() != tgtok::l_brace) {
3211fb927af2SDavid Greene // FOREACH Declaration IN Object
3212fb927af2SDavid Greene if (ParseObject(CurMultiClass))
3213fb927af2SDavid Greene return true;
3214a9642b4eSCraig Topper } else {
3215fb927af2SDavid Greene SMLoc BraceLoc = Lex.getLoc();
3216fb927af2SDavid Greene // Otherwise, this is a group foreach.
3217fb927af2SDavid Greene Lex.Lex(); // eat the '{'.
3218fb927af2SDavid Greene
3219fb927af2SDavid Greene // Parse the object list.
3220fb927af2SDavid Greene if (ParseObjectList(CurMultiClass))
3221fb927af2SDavid Greene return true;
3222fb927af2SDavid Greene
32238ba36497SFangrui Song if (!consume(tgtok::r_brace)) {
3224fb927af2SDavid Greene TokError("expected '}' at end of foreach command");
3225fb927af2SDavid Greene return Error(BraceLoc, "to match this '{'");
3226fb927af2SDavid Greene }
3227fb927af2SDavid Greene }
3228fb927af2SDavid Greene
32293388b0f5SSimon Tatham PopLocalScope(ForeachScope);
32303388b0f5SSimon Tatham
32317d69e0f3SNicolai Haehnle // Resolve the loop or store it for later resolution.
32327d69e0f3SNicolai Haehnle std::unique_ptr<ForeachLoop> Loop = std::move(Loops.back());
3233fb927af2SDavid Greene Loops.pop_back();
3234fb927af2SDavid Greene
32357d69e0f3SNicolai Haehnle return addEntry(std::move(Loop));
323684c287e3SPeter Collingbourne }
323784c287e3SPeter Collingbourne
3238ddbc0b1eSSimon Tatham /// ParseIf - Parse an if statement.
3239ddbc0b1eSSimon Tatham ///
3240ddbc0b1eSSimon Tatham /// If ::= IF Value THEN IfBody
3241ddbc0b1eSSimon Tatham /// If ::= IF Value THEN IfBody ELSE IfBody
3242ddbc0b1eSSimon Tatham ///
ParseIf(MultiClass * CurMultiClass)3243ddbc0b1eSSimon Tatham bool TGParser::ParseIf(MultiClass *CurMultiClass) {
3244ddbc0b1eSSimon Tatham SMLoc Loc = Lex.getLoc();
3245ddbc0b1eSSimon Tatham assert(Lex.getCode() == tgtok::If && "Unknown tok");
3246ddbc0b1eSSimon Tatham Lex.Lex(); // Eat the 'if' token.
3247ddbc0b1eSSimon Tatham
3248ddbc0b1eSSimon Tatham // Make a temporary object to record items associated with the for
3249ddbc0b1eSSimon Tatham // loop.
3250ddbc0b1eSSimon Tatham Init *Condition = ParseValue(nullptr);
3251ddbc0b1eSSimon Tatham if (!Condition)
3252ddbc0b1eSSimon Tatham return true;
3253ddbc0b1eSSimon Tatham
32548ba36497SFangrui Song if (!consume(tgtok::Then))
3255ddbc0b1eSSimon Tatham return TokError("Unknown tok");
3256ddbc0b1eSSimon Tatham
3257ddbc0b1eSSimon Tatham // We have to be able to save if statements to execute later, and they have
3258ddbc0b1eSSimon Tatham // to live on the same stack as foreach loops. The simplest implementation
3259ddbc0b1eSSimon Tatham // technique is to convert each 'then' or 'else' clause *into* a foreach
3260ddbc0b1eSSimon Tatham // loop, over a list of length 0 or 1 depending on the condition, and with no
3261ddbc0b1eSSimon Tatham // iteration variable being assigned.
3262ddbc0b1eSSimon Tatham
32632ac3cd20SRiver Riddle ListInit *EmptyList = ListInit::get({}, BitRecTy::get(Records));
32642aed0813SKazu Hirata ListInit *SingletonList =
32652ac3cd20SRiver Riddle ListInit::get({BitInit::get(Records, true)}, BitRecTy::get(Records));
32662ac3cd20SRiver Riddle RecTy *BitListTy = ListRecTy::get(BitRecTy::get(Records));
3267ddbc0b1eSSimon Tatham
3268ddbc0b1eSSimon Tatham // The foreach containing the then-clause selects SingletonList if
3269ddbc0b1eSSimon Tatham // the condition is true.
3270ddbc0b1eSSimon Tatham Init *ThenClauseList =
3271ddbc0b1eSSimon Tatham TernOpInit::get(TernOpInit::IF, Condition, SingletonList, EmptyList,
3272ddbc0b1eSSimon Tatham BitListTy)
3273ddbc0b1eSSimon Tatham ->Fold(nullptr);
3274ddbc0b1eSSimon Tatham Loops.push_back(std::make_unique<ForeachLoop>(Loc, nullptr, ThenClauseList));
3275ddbc0b1eSSimon Tatham
3276ddbc0b1eSSimon Tatham if (ParseIfBody(CurMultiClass, "then"))
3277ddbc0b1eSSimon Tatham return true;
3278ddbc0b1eSSimon Tatham
3279ddbc0b1eSSimon Tatham std::unique_ptr<ForeachLoop> Loop = std::move(Loops.back());
3280ddbc0b1eSSimon Tatham Loops.pop_back();
3281ddbc0b1eSSimon Tatham
3282ddbc0b1eSSimon Tatham if (addEntry(std::move(Loop)))
3283ddbc0b1eSSimon Tatham return true;
3284ddbc0b1eSSimon Tatham
3285ddbc0b1eSSimon Tatham // Now look for an optional else clause. The if-else syntax has the usual
3286ddbc0b1eSSimon Tatham // dangling-else ambiguity, and by greedily matching an else here if we can,
3287ddbc0b1eSSimon Tatham // we implement the usual resolution of pairing with the innermost unmatched
3288ddbc0b1eSSimon Tatham // if.
3289e69605bfSFangrui Song if (consume(tgtok::ElseKW)) {
3290ddbc0b1eSSimon Tatham // The foreach containing the else-clause uses the same pair of lists as
3291ddbc0b1eSSimon Tatham // above, but this time, selects SingletonList if the condition is *false*.
3292ddbc0b1eSSimon Tatham Init *ElseClauseList =
3293ddbc0b1eSSimon Tatham TernOpInit::get(TernOpInit::IF, Condition, EmptyList, SingletonList,
3294ddbc0b1eSSimon Tatham BitListTy)
3295ddbc0b1eSSimon Tatham ->Fold(nullptr);
3296ddbc0b1eSSimon Tatham Loops.push_back(
3297ddbc0b1eSSimon Tatham std::make_unique<ForeachLoop>(Loc, nullptr, ElseClauseList));
3298ddbc0b1eSSimon Tatham
3299ddbc0b1eSSimon Tatham if (ParseIfBody(CurMultiClass, "else"))
3300ddbc0b1eSSimon Tatham return true;
3301ddbc0b1eSSimon Tatham
3302ddbc0b1eSSimon Tatham Loop = std::move(Loops.back());
3303ddbc0b1eSSimon Tatham Loops.pop_back();
3304ddbc0b1eSSimon Tatham
3305ddbc0b1eSSimon Tatham if (addEntry(std::move(Loop)))
3306ddbc0b1eSSimon Tatham return true;
3307ddbc0b1eSSimon Tatham }
3308ddbc0b1eSSimon Tatham
3309ddbc0b1eSSimon Tatham return false;
3310ddbc0b1eSSimon Tatham }
3311ddbc0b1eSSimon Tatham
3312ddbc0b1eSSimon Tatham /// ParseIfBody - Parse the then-clause or else-clause of an if statement.
3313ddbc0b1eSSimon Tatham ///
3314ddbc0b1eSSimon Tatham /// IfBody ::= Object
3315ddbc0b1eSSimon Tatham /// IfBody ::= '{' ObjectList '}'
3316ddbc0b1eSSimon Tatham ///
ParseIfBody(MultiClass * CurMultiClass,StringRef Kind)3317ddbc0b1eSSimon Tatham bool TGParser::ParseIfBody(MultiClass *CurMultiClass, StringRef Kind) {
3318ddbc0b1eSSimon Tatham TGLocalVarScope *BodyScope = PushLocalScope();
3319ddbc0b1eSSimon Tatham
3320ddbc0b1eSSimon Tatham if (Lex.getCode() != tgtok::l_brace) {
3321ddbc0b1eSSimon Tatham // A single object.
3322ddbc0b1eSSimon Tatham if (ParseObject(CurMultiClass))
3323ddbc0b1eSSimon Tatham return true;
3324ddbc0b1eSSimon Tatham } else {
3325ddbc0b1eSSimon Tatham SMLoc BraceLoc = Lex.getLoc();
3326ddbc0b1eSSimon Tatham // A braced block.
3327ddbc0b1eSSimon Tatham Lex.Lex(); // eat the '{'.
3328ddbc0b1eSSimon Tatham
3329ddbc0b1eSSimon Tatham // Parse the object list.
3330ddbc0b1eSSimon Tatham if (ParseObjectList(CurMultiClass))
3331ddbc0b1eSSimon Tatham return true;
3332ddbc0b1eSSimon Tatham
33338ba36497SFangrui Song if (!consume(tgtok::r_brace)) {
3334ddbc0b1eSSimon Tatham TokError("expected '}' at end of '" + Kind + "' clause");
3335ddbc0b1eSSimon Tatham return Error(BraceLoc, "to match this '{'");
3336ddbc0b1eSSimon Tatham }
3337ddbc0b1eSSimon Tatham }
3338ddbc0b1eSSimon Tatham
3339ddbc0b1eSSimon Tatham PopLocalScope(BodyScope);
3340ddbc0b1eSSimon Tatham return false;
3341ddbc0b1eSSimon Tatham }
3342ddbc0b1eSSimon Tatham
33436e2b6351SPaul C. Anagnostopoulos /// ParseAssert - Parse an assert statement.
33446e2b6351SPaul C. Anagnostopoulos ///
33456e2b6351SPaul C. Anagnostopoulos /// Assert ::= ASSERT condition , message ;
ParseAssert(MultiClass * CurMultiClass,Record * CurRec)33466e2b6351SPaul C. Anagnostopoulos bool TGParser::ParseAssert(MultiClass *CurMultiClass, Record *CurRec) {
33476e2b6351SPaul C. Anagnostopoulos assert(Lex.getCode() == tgtok::Assert && "Unknown tok");
33486e2b6351SPaul C. Anagnostopoulos Lex.Lex(); // Eat the 'assert' token.
33496e2b6351SPaul C. Anagnostopoulos
33506e2b6351SPaul C. Anagnostopoulos SMLoc ConditionLoc = Lex.getLoc();
33516e2b6351SPaul C. Anagnostopoulos Init *Condition = ParseValue(CurRec);
33526e2b6351SPaul C. Anagnostopoulos if (!Condition)
33536e2b6351SPaul C. Anagnostopoulos return true;
33546e2b6351SPaul C. Anagnostopoulos
33556e2b6351SPaul C. Anagnostopoulos if (!consume(tgtok::comma)) {
33566e2b6351SPaul C. Anagnostopoulos TokError("expected ',' in assert statement");
33576e2b6351SPaul C. Anagnostopoulos return true;
33586e2b6351SPaul C. Anagnostopoulos }
33596e2b6351SPaul C. Anagnostopoulos
33606e2b6351SPaul C. Anagnostopoulos Init *Message = ParseValue(CurRec);
33616e2b6351SPaul C. Anagnostopoulos if (!Message)
33626e2b6351SPaul C. Anagnostopoulos return true;
33636e2b6351SPaul C. Anagnostopoulos
33646e2b6351SPaul C. Anagnostopoulos if (!consume(tgtok::semi))
33656e2b6351SPaul C. Anagnostopoulos return TokError("expected ';'");
33666e2b6351SPaul C. Anagnostopoulos
33672d4c4d3cSPaul C. Anagnostopoulos if (CurRec)
33686e2b6351SPaul C. Anagnostopoulos CurRec->addAssertion(ConditionLoc, Condition, Message);
33692d4c4d3cSPaul C. Anagnostopoulos else
33702d4c4d3cSPaul C. Anagnostopoulos addEntry(std::make_unique<Record::AssertionInfo>(ConditionLoc, Condition,
33712d4c4d3cSPaul C. Anagnostopoulos Message));
33726e2b6351SPaul C. Anagnostopoulos return false;
33736e2b6351SPaul C. Anagnostopoulos }
33746e2b6351SPaul C. Anagnostopoulos
337584c287e3SPeter Collingbourne /// ParseClass - Parse a tblgen class definition.
337684c287e3SPeter Collingbourne ///
337784c287e3SPeter Collingbourne /// ClassInst ::= CLASS ID TemplateArgList? ObjectBody
337884c287e3SPeter Collingbourne ///
ParseClass()337984c287e3SPeter Collingbourne bool TGParser::ParseClass() {
338084c287e3SPeter Collingbourne assert(Lex.getCode() == tgtok::Class && "Unexpected token!");
338184c287e3SPeter Collingbourne Lex.Lex();
338284c287e3SPeter Collingbourne
338384c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::Id)
338484c287e3SPeter Collingbourne return TokError("expected class name after 'class' keyword");
338584c287e3SPeter Collingbourne
338684c287e3SPeter Collingbourne Record *CurRec = Records.getClass(Lex.getCurStrVal());
338784c287e3SPeter Collingbourne if (CurRec) {
338884c287e3SPeter Collingbourne // If the body was previously defined, this is an error.
338901d261f1SNicolai Haehnle if (!CurRec->getValues().empty() ||
339084c287e3SPeter Collingbourne !CurRec->getSuperClasses().empty() ||
339184c287e3SPeter Collingbourne !CurRec->getTemplateArgs().empty())
339285c07007SCraig Topper return TokError("Class '" + CurRec->getNameInitAsString() +
339385c07007SCraig Topper "' already defined");
3394*394a388dSRoman Rusyaev
3395*394a388dSRoman Rusyaev CurRec->updateClassLoc(Lex.getLoc());
339684c287e3SPeter Collingbourne } else {
339784c287e3SPeter Collingbourne // If this is the first reference to this class, create and add it.
3398ffbbd53fSHans Wennborg auto NewRec =
33990eaee545SJonas Devlieghere std::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(), Records,
340001d261f1SNicolai Haehnle /*Class=*/true);
3401cdab2326SCraig Topper CurRec = NewRec.get();
3402cdab2326SCraig Topper Records.addClass(std::move(NewRec));
340384c287e3SPeter Collingbourne }
340484c287e3SPeter Collingbourne Lex.Lex(); // eat the name.
340584c287e3SPeter Collingbourne
340684c287e3SPeter Collingbourne // If there are template args, parse them.
340784c287e3SPeter Collingbourne if (Lex.getCode() == tgtok::less)
340884c287e3SPeter Collingbourne if (ParseTemplateArgList(CurRec))
340984c287e3SPeter Collingbourne return true;
341084c287e3SPeter Collingbourne
3411d968b173SCullen Rhodes if (ParseObjectBody(CurRec))
3412d968b173SCullen Rhodes return true;
3413d968b173SCullen Rhodes
3414d968b173SCullen Rhodes if (!NoWarnOnUnusedTemplateArgs)
3415d968b173SCullen Rhodes CurRec->checkUnusedTemplateArgs();
3416d968b173SCullen Rhodes return false;
341784c287e3SPeter Collingbourne }
341884c287e3SPeter Collingbourne
341984c287e3SPeter Collingbourne /// ParseLetList - Parse a non-empty list of assignment expressions into a list
342084c287e3SPeter Collingbourne /// of LetRecords.
342184c287e3SPeter Collingbourne ///
342284c287e3SPeter Collingbourne /// LetList ::= LetItem (',' LetItem)*
342384c287e3SPeter Collingbourne /// LetItem ::= ID OptionalRangeList '=' Value
342484c287e3SPeter Collingbourne ///
ParseLetList(SmallVectorImpl<LetRecord> & Result)3425c66e7557SMatthias Braun void TGParser::ParseLetList(SmallVectorImpl<LetRecord> &Result) {
34268ba36497SFangrui Song do {
342784c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::Id) {
342884c287e3SPeter Collingbourne TokError("expected identifier in let definition");
3429c66e7557SMatthias Braun Result.clear();
3430c66e7557SMatthias Braun return;
343184c287e3SPeter Collingbourne }
3432c66e7557SMatthias Braun
34332ac3cd20SRiver Riddle StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());
343484c287e3SPeter Collingbourne SMLoc NameLoc = Lex.getLoc();
343584c287e3SPeter Collingbourne Lex.Lex(); // Eat the identifier.
343684c287e3SPeter Collingbourne
343784c287e3SPeter Collingbourne // Check for an optional RangeList.
3438c66e7557SMatthias Braun SmallVector<unsigned, 16> Bits;
3439c66e7557SMatthias Braun if (ParseOptionalRangeList(Bits)) {
3440c66e7557SMatthias Braun Result.clear();
3441c66e7557SMatthias Braun return;
3442c66e7557SMatthias Braun }
344384c287e3SPeter Collingbourne std::reverse(Bits.begin(), Bits.end());
344484c287e3SPeter Collingbourne
34458ba36497SFangrui Song if (!consume(tgtok::equal)) {
344684c287e3SPeter Collingbourne TokError("expected '=' in let expression");
3447c66e7557SMatthias Braun Result.clear();
3448c66e7557SMatthias Braun return;
344984c287e3SPeter Collingbourne }
345084c287e3SPeter Collingbourne
3451011817a0SCraig Topper Init *Val = ParseValue(nullptr);
3452c66e7557SMatthias Braun if (!Val) {
3453c66e7557SMatthias Braun Result.clear();
3454c66e7557SMatthias Braun return;
3455c66e7557SMatthias Braun }
345684c287e3SPeter Collingbourne
345784c287e3SPeter Collingbourne // Now that we have everything, add the record.
3458215ff84bSMatthias Braun Result.emplace_back(Name, Bits, Val, NameLoc);
34598ba36497SFangrui Song } while (consume(tgtok::comma));
346084c287e3SPeter Collingbourne }
346184c287e3SPeter Collingbourne
346284c287e3SPeter Collingbourne /// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
346384c287e3SPeter Collingbourne /// different related productions. This works inside multiclasses too.
346484c287e3SPeter Collingbourne ///
346584c287e3SPeter Collingbourne /// Object ::= LET LetList IN '{' ObjectList '}'
346684c287e3SPeter Collingbourne /// Object ::= LET LetList IN Object
346784c287e3SPeter Collingbourne ///
ParseTopLevelLet(MultiClass * CurMultiClass)346884c287e3SPeter Collingbourne bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
346984c287e3SPeter Collingbourne assert(Lex.getCode() == tgtok::Let && "Unexpected token");
347084c287e3SPeter Collingbourne Lex.Lex();
347184c287e3SPeter Collingbourne
347284c287e3SPeter Collingbourne // Add this entry to the let stack.
3473c66e7557SMatthias Braun SmallVector<LetRecord, 8> LetInfo;
3474c66e7557SMatthias Braun ParseLetList(LetInfo);
347584c287e3SPeter Collingbourne if (LetInfo.empty()) return true;
3476e12a6bacSBenjamin Kramer LetStack.push_back(std::move(LetInfo));
347784c287e3SPeter Collingbourne
34788ba36497SFangrui Song if (!consume(tgtok::In))
347984c287e3SPeter Collingbourne return TokError("expected 'in' at end of top-level 'let'");
348084c287e3SPeter Collingbourne
34813388b0f5SSimon Tatham TGLocalVarScope *LetScope = PushLocalScope();
34823388b0f5SSimon Tatham
348384c287e3SPeter Collingbourne // If this is a scalar let, just handle it now
348484c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::l_brace) {
348584c287e3SPeter Collingbourne // LET LetList IN Object
348684c287e3SPeter Collingbourne if (ParseObject(CurMultiClass))
348784c287e3SPeter Collingbourne return true;
348884c287e3SPeter Collingbourne } else { // Object ::= LETCommand '{' ObjectList '}'
348984c287e3SPeter Collingbourne SMLoc BraceLoc = Lex.getLoc();
349084c287e3SPeter Collingbourne // Otherwise, this is a group let.
349184c287e3SPeter Collingbourne Lex.Lex(); // eat the '{'.
349284c287e3SPeter Collingbourne
349384c287e3SPeter Collingbourne // Parse the object list.
349484c287e3SPeter Collingbourne if (ParseObjectList(CurMultiClass))
349584c287e3SPeter Collingbourne return true;
349684c287e3SPeter Collingbourne
34978ba36497SFangrui Song if (!consume(tgtok::r_brace)) {
349884c287e3SPeter Collingbourne TokError("expected '}' at end of top level let command");
349984c287e3SPeter Collingbourne return Error(BraceLoc, "to match this '{'");
350084c287e3SPeter Collingbourne }
350184c287e3SPeter Collingbourne }
350284c287e3SPeter Collingbourne
35033388b0f5SSimon Tatham PopLocalScope(LetScope);
35043388b0f5SSimon Tatham
350584c287e3SPeter Collingbourne // Outside this let scope, this let block is not active.
350684c287e3SPeter Collingbourne LetStack.pop_back();
350784c287e3SPeter Collingbourne return false;
350884c287e3SPeter Collingbourne }
350984c287e3SPeter Collingbourne
351084c287e3SPeter Collingbourne /// ParseMultiClass - Parse a multiclass definition.
351184c287e3SPeter Collingbourne ///
351284c287e3SPeter Collingbourne /// MultiClassInst ::= MULTICLASS ID TemplateArgList?
3513c95fe280SSean Silva /// ':' BaseMultiClassList '{' MultiClassObject+ '}'
35149d609adcSPaul C. Anagnostopoulos /// MultiClassObject ::= Assert
3515c95fe280SSean Silva /// MultiClassObject ::= DefInst
3516c95fe280SSean Silva /// MultiClassObject ::= DefMInst
3517a5aaec8fSPaul C. Anagnostopoulos /// MultiClassObject ::= Defvar
3518a5aaec8fSPaul C. Anagnostopoulos /// MultiClassObject ::= Foreach
3519a5aaec8fSPaul C. Anagnostopoulos /// MultiClassObject ::= If
3520c95fe280SSean Silva /// MultiClassObject ::= LETCommand '{' ObjectList '}'
3521c95fe280SSean Silva /// MultiClassObject ::= LETCommand Object
352284c287e3SPeter Collingbourne ///
ParseMultiClass()352384c287e3SPeter Collingbourne bool TGParser::ParseMultiClass() {
352484c287e3SPeter Collingbourne assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
352584c287e3SPeter Collingbourne Lex.Lex(); // Eat the multiclass token.
352684c287e3SPeter Collingbourne
352784c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::Id)
352884c287e3SPeter Collingbourne return TokError("expected identifier after multiclass for name");
352984c287e3SPeter Collingbourne std::string Name = Lex.getCurStrVal();
353084c287e3SPeter Collingbourne
35317adf2bf7SCraig Topper auto Result =
35327adf2bf7SCraig Topper MultiClasses.insert(std::make_pair(Name,
35330eaee545SJonas Devlieghere std::make_unique<MultiClass>(Name, Lex.getLoc(),Records)));
35347adf2bf7SCraig Topper
35357adf2bf7SCraig Topper if (!Result.second)
353684c287e3SPeter Collingbourne return TokError("multiclass '" + Name + "' already defined");
353784c287e3SPeter Collingbourne
35387adf2bf7SCraig Topper CurMultiClass = Result.first->second.get();
353984c287e3SPeter Collingbourne Lex.Lex(); // Eat the identifier.
354084c287e3SPeter Collingbourne
354184c287e3SPeter Collingbourne // If there are template args, parse them.
354284c287e3SPeter Collingbourne if (Lex.getCode() == tgtok::less)
3543011817a0SCraig Topper if (ParseTemplateArgList(nullptr))
354484c287e3SPeter Collingbourne return true;
354584c287e3SPeter Collingbourne
354684c287e3SPeter Collingbourne bool inherits = false;
354784c287e3SPeter Collingbourne
354884c287e3SPeter Collingbourne // If there are submulticlasses, parse them.
3549e69605bfSFangrui Song if (consume(tgtok::colon)) {
355084c287e3SPeter Collingbourne inherits = true;
355184c287e3SPeter Collingbourne
355284c287e3SPeter Collingbourne // Read all of the submulticlasses.
355384c287e3SPeter Collingbourne SubMultiClassReference SubMultiClass =
355484c287e3SPeter Collingbourne ParseSubMultiClassReference(CurMultiClass);
355533d7b762SEugene Zelenko while (true) {
355684c287e3SPeter Collingbourne // Check for error.
3557011817a0SCraig Topper if (!SubMultiClass.MC) return true;
355884c287e3SPeter Collingbourne
355984c287e3SPeter Collingbourne // Add it.
356084c287e3SPeter Collingbourne if (AddSubMultiClass(CurMultiClass, SubMultiClass))
356184c287e3SPeter Collingbourne return true;
356284c287e3SPeter Collingbourne
3563e69605bfSFangrui Song if (!consume(tgtok::comma))
3564e69605bfSFangrui Song break;
356584c287e3SPeter Collingbourne SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
356684c287e3SPeter Collingbourne }
356784c287e3SPeter Collingbourne }
356884c287e3SPeter Collingbourne
356984c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::l_brace) {
357084c287e3SPeter Collingbourne if (!inherits)
357184c287e3SPeter Collingbourne return TokError("expected '{' in multiclass definition");
3572e69605bfSFangrui Song if (!consume(tgtok::semi))
357384c287e3SPeter Collingbourne return TokError("expected ';' in multiclass definition");
357484c287e3SPeter Collingbourne } else {
357584c287e3SPeter Collingbourne if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
357684c287e3SPeter Collingbourne return TokError("multiclass must contain at least one def");
357784c287e3SPeter Collingbourne
35783388b0f5SSimon Tatham // A multiclass body introduces a new scope for local variables.
35793388b0f5SSimon Tatham TGLocalVarScope *MulticlassScope = PushLocalScope();
35803388b0f5SSimon Tatham
358184c287e3SPeter Collingbourne while (Lex.getCode() != tgtok::r_brace) {
358284c287e3SPeter Collingbourne switch (Lex.getCode()) {
358384c287e3SPeter Collingbourne default:
35846e2b6351SPaul C. Anagnostopoulos return TokError("expected 'assert', 'def', 'defm', 'defvar', "
35856e2b6351SPaul C. Anagnostopoulos "'foreach', 'if', or 'let' in multiclass body");
35866e2b6351SPaul C. Anagnostopoulos
3587a5aaec8fSPaul C. Anagnostopoulos case tgtok::Assert:
358884c287e3SPeter Collingbourne case tgtok::Def:
358984c287e3SPeter Collingbourne case tgtok::Defm:
35903388b0f5SSimon Tatham case tgtok::Defvar:
3591fb927af2SDavid Greene case tgtok::Foreach:
3592ddbc0b1eSSimon Tatham case tgtok::If:
35936e2b6351SPaul C. Anagnostopoulos case tgtok::Let:
359484c287e3SPeter Collingbourne if (ParseObject(CurMultiClass))
359584c287e3SPeter Collingbourne return true;
359684c287e3SPeter Collingbourne break;
359784c287e3SPeter Collingbourne }
359884c287e3SPeter Collingbourne }
359984c287e3SPeter Collingbourne Lex.Lex(); // eat the '}'.
36003388b0f5SSimon Tatham
3601a6759477SPaul C. Anagnostopoulos // If we have a semicolon, print a gentle error.
3602a6759477SPaul C. Anagnostopoulos SMLoc SemiLoc = Lex.getLoc();
3603a6759477SPaul C. Anagnostopoulos if (consume(tgtok::semi)) {
3604a6759477SPaul C. Anagnostopoulos PrintError(SemiLoc, "A multiclass body should not end with a semicolon");
3605a6759477SPaul C. Anagnostopoulos PrintNote("Semicolon ignored; remove to eliminate this error");
3606a6759477SPaul C. Anagnostopoulos }
3607a6759477SPaul C. Anagnostopoulos
36083388b0f5SSimon Tatham PopLocalScope(MulticlassScope);
360984c287e3SPeter Collingbourne }
361084c287e3SPeter Collingbourne
3611d968b173SCullen Rhodes if (!NoWarnOnUnusedTemplateArgs)
3612d968b173SCullen Rhodes CurMultiClass->Rec.checkUnusedTemplateArgs();
3613d968b173SCullen Rhodes
3614011817a0SCraig Topper CurMultiClass = nullptr;
361584c287e3SPeter Collingbourne return false;
361684c287e3SPeter Collingbourne }
361784c287e3SPeter Collingbourne
361884c287e3SPeter Collingbourne /// ParseDefm - Parse the instantiation of a multiclass.
361984c287e3SPeter Collingbourne ///
362084c287e3SPeter Collingbourne /// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
362184c287e3SPeter Collingbourne ///
ParseDefm(MultiClass * CurMultiClass)362284c287e3SPeter Collingbourne bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
362384c287e3SPeter Collingbourne assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
3624420e28c7SNicolai Haehnle Lex.Lex(); // eat the defm
36252affd67bSDavid Greene
3626420e28c7SNicolai Haehnle Init *DefmName = ParseObjectName(CurMultiClass);
3627420e28c7SNicolai Haehnle if (!DefmName)
3628420e28c7SNicolai Haehnle return true;
362901d261f1SNicolai Haehnle if (isa<UnsetInit>(DefmName)) {
3630420e28c7SNicolai Haehnle DefmName = Records.getNewAnonymousName();
363101d261f1SNicolai Haehnle if (CurMultiClass)
363201d261f1SNicolai Haehnle DefmName = BinOpInit::getStrConcat(
363301d261f1SNicolai Haehnle VarInit::get(QualifiedNameOfImplicitName(CurMultiClass),
36342ac3cd20SRiver Riddle StringRecTy::get(Records)),
363501d261f1SNicolai Haehnle DefmName);
363601d261f1SNicolai Haehnle }
363784c287e3SPeter Collingbourne
363884c287e3SPeter Collingbourne if (Lex.getCode() != tgtok::colon)
363984c287e3SPeter Collingbourne return TokError("expected ':' after defm identifier");
364084c287e3SPeter Collingbourne
364184c287e3SPeter Collingbourne // Keep track of the new generated record definitions.
36427d69e0f3SNicolai Haehnle std::vector<RecordsEntry> NewEntries;
364384c287e3SPeter Collingbourne
364484c287e3SPeter Collingbourne // This record also inherits from a regular class (non-multiclass)?
364584c287e3SPeter Collingbourne bool InheritFromClass = false;
364684c287e3SPeter Collingbourne
364784c287e3SPeter Collingbourne // eat the colon.
364884c287e3SPeter Collingbourne Lex.Lex();
364984c287e3SPeter Collingbourne
365084c287e3SPeter Collingbourne SMLoc SubClassLoc = Lex.getLoc();
3651011817a0SCraig Topper SubClassReference Ref = ParseSubClassReference(nullptr, true);
365284c287e3SPeter Collingbourne
365333d7b762SEugene Zelenko while (true) {
3654011817a0SCraig Topper if (!Ref.Rec) return true;
365584c287e3SPeter Collingbourne
3656a9fc44c5SPaul C. Anagnostopoulos // To instantiate a multiclass, we get the multiclass and then loop
3657a9fc44c5SPaul C. Anagnostopoulos // through its template argument names. Substs contains a substitution
3658a9fc44c5SPaul C. Anagnostopoulos // value for each argument, either the value specified or the default.
3659a9fc44c5SPaul C. Anagnostopoulos // Then we can resolve the template arguments.
3660adcd0268SBenjamin Kramer MultiClass *MC = MultiClasses[std::string(Ref.Rec->getName())].get();
36614ca4001dSCraig Topper assert(MC && "Didn't lookup multiclass correctly?");
3662a9fc44c5SPaul C. Anagnostopoulos
3663c66e7557SMatthias Braun ArrayRef<Init *> TemplateVals = Ref.TemplateArgs;
366449d663d5SPaul C. Anagnostopoulos ArrayRef<Init *> TArgs = MC->Rec.getTemplateArgs();
366549d663d5SPaul C. Anagnostopoulos SubstStack Substs;
3666a9fc44c5SPaul C. Anagnostopoulos
3667420e28c7SNicolai Haehnle for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
3668420e28c7SNicolai Haehnle if (i < TemplateVals.size()) {
36697d69e0f3SNicolai Haehnle Substs.emplace_back(TArgs[i], TemplateVals[i]);
3670420e28c7SNicolai Haehnle } else {
3671420e28c7SNicolai Haehnle Init *Default = MC->Rec.getValue(TArgs[i])->getValue();
3672a9fc44c5SPaul C. Anagnostopoulos if (!Default->isComplete())
3673420e28c7SNicolai Haehnle return Error(SubClassLoc,
3674a9fc44c5SPaul C. Anagnostopoulos "value not specified for template argument '" +
3675a9fc44c5SPaul C. Anagnostopoulos TArgs[i]->getAsUnquotedString() + "' (#" +
3676a9fc44c5SPaul C. Anagnostopoulos Twine(i) + ") of multiclass '" +
3677a9fc44c5SPaul C. Anagnostopoulos MC->Rec.getNameInitAsString() + "'");
36787d69e0f3SNicolai Haehnle Substs.emplace_back(TArgs[i], Default);
3679420e28c7SNicolai Haehnle }
368084c287e3SPeter Collingbourne }
368184c287e3SPeter Collingbourne
36827d69e0f3SNicolai Haehnle Substs.emplace_back(QualifiedNameOfImplicitName(MC), DefmName);
368301d261f1SNicolai Haehnle
36845046c5beSJ-Y You if (resolve(MC->Entries, Substs, !CurMultiClass && Loops.empty(),
36855046c5beSJ-Y You &NewEntries, &SubClassLoc))
36867d69e0f3SNicolai Haehnle return true;
3687db445974SDavid Greene
3688e69605bfSFangrui Song if (!consume(tgtok::comma))
3689e69605bfSFangrui Song break;
369084c287e3SPeter Collingbourne
3691998a39aeSCraig Topper if (Lex.getCode() != tgtok::Id)
3692998a39aeSCraig Topper return TokError("expected identifier");
3693998a39aeSCraig Topper
369484c287e3SPeter Collingbourne SubClassLoc = Lex.getLoc();
369584c287e3SPeter Collingbourne
3696a9fc44c5SPaul C. Anagnostopoulos // A defm can inherit from regular classes (non-multiclasses) as
369784c287e3SPeter Collingbourne // long as they come in the end of the inheritance list.
3698011817a0SCraig Topper InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != nullptr);
369984c287e3SPeter Collingbourne
370084c287e3SPeter Collingbourne if (InheritFromClass)
370184c287e3SPeter Collingbourne break;
370284c287e3SPeter Collingbourne
3703011817a0SCraig Topper Ref = ParseSubClassReference(nullptr, true);
370484c287e3SPeter Collingbourne }
370584c287e3SPeter Collingbourne
370684c287e3SPeter Collingbourne if (InheritFromClass) {
370784c287e3SPeter Collingbourne // Process all the classes to inherit as if they were part of a
370884c287e3SPeter Collingbourne // regular 'def' and inherit all record values.
3709011817a0SCraig Topper SubClassReference SubClass = ParseSubClassReference(nullptr, false);
371033d7b762SEugene Zelenko while (true) {
371184c287e3SPeter Collingbourne // Check for error.
3712011817a0SCraig Topper if (!SubClass.Rec) return true;
371384c287e3SPeter Collingbourne
371484c287e3SPeter Collingbourne // Get the expanded definition prototypes and teach them about
371584c287e3SPeter Collingbourne // the record values the current class to inherit has
37167d69e0f3SNicolai Haehnle for (auto &E : NewEntries) {
371784c287e3SPeter Collingbourne // Add it.
37187d69e0f3SNicolai Haehnle if (AddSubClass(E, SubClass))
371984c287e3SPeter Collingbourne return true;
372084c287e3SPeter Collingbourne }
372184c287e3SPeter Collingbourne
3722e69605bfSFangrui Song if (!consume(tgtok::comma))
3723e69605bfSFangrui Song break;
3724011817a0SCraig Topper SubClass = ParseSubClassReference(nullptr, false);
372584c287e3SPeter Collingbourne }
372684c287e3SPeter Collingbourne }
372784c287e3SPeter Collingbourne
37287d69e0f3SNicolai Haehnle for (auto &E : NewEntries) {
37297d69e0f3SNicolai Haehnle if (ApplyLetStack(E))
3730fcd6525aSNicolai Haehnle return true;
3731420e28c7SNicolai Haehnle
37327d69e0f3SNicolai Haehnle addEntry(std::move(E));
37330f529885SNicolai Haehnle }
373484c287e3SPeter Collingbourne
3735e69605bfSFangrui Song if (!consume(tgtok::semi))
373684c287e3SPeter Collingbourne return TokError("expected ';' at end of defm");
373784c287e3SPeter Collingbourne
373884c287e3SPeter Collingbourne return false;
373984c287e3SPeter Collingbourne }
374084c287e3SPeter Collingbourne
374184c287e3SPeter Collingbourne /// ParseObject
374284c287e3SPeter Collingbourne /// Object ::= ClassInst
374384c287e3SPeter Collingbourne /// Object ::= DefInst
374484c287e3SPeter Collingbourne /// Object ::= MultiClassInst
374584c287e3SPeter Collingbourne /// Object ::= DefMInst
374684c287e3SPeter Collingbourne /// Object ::= LETCommand '{' ObjectList '}'
374784c287e3SPeter Collingbourne /// Object ::= LETCommand Object
37483388b0f5SSimon Tatham /// Object ::= Defset
37493388b0f5SSimon Tatham /// Object ::= Defvar
37506e2b6351SPaul C. Anagnostopoulos /// Object ::= Assert
ParseObject(MultiClass * MC)375184c287e3SPeter Collingbourne bool TGParser::ParseObject(MultiClass *MC) {
375284c287e3SPeter Collingbourne switch (Lex.getCode()) {
375384c287e3SPeter Collingbourne default:
37546e2b6351SPaul C. Anagnostopoulos return TokError(
37556e2b6351SPaul C. Anagnostopoulos "Expected assert, class, def, defm, defset, foreach, if, or let");
3756a5aaec8fSPaul C. Anagnostopoulos case tgtok::Assert: return ParseAssert(MC);
375784c287e3SPeter Collingbourne case tgtok::Def: return ParseDef(MC);
37586e2b6351SPaul C. Anagnostopoulos case tgtok::Defm: return ParseDefm(MC);
37596e2b6351SPaul C. Anagnostopoulos case tgtok::Defvar: return ParseDefvar();
3760fb927af2SDavid Greene case tgtok::Foreach: return ParseForeach(MC);
3761ddbc0b1eSSimon Tatham case tgtok::If: return ParseIf(MC);
37626e2b6351SPaul C. Anagnostopoulos case tgtok::Let: return ParseTopLevelLet(MC);
3763fcd6525aSNicolai Haehnle case tgtok::Defset:
3764fcd6525aSNicolai Haehnle if (MC)
3765fcd6525aSNicolai Haehnle return TokError("defset is not allowed inside multiclass");
3766fcd6525aSNicolai Haehnle return ParseDefset();
3767a511dddcSNicolai Haehnle case tgtok::Class:
3768a511dddcSNicolai Haehnle if (MC)
3769a511dddcSNicolai Haehnle return TokError("class is not allowed inside multiclass");
3770a511dddcSNicolai Haehnle if (!Loops.empty())
3771a511dddcSNicolai Haehnle return TokError("class is not allowed inside foreach loop");
3772a511dddcSNicolai Haehnle return ParseClass();
3773a511dddcSNicolai Haehnle case tgtok::MultiClass:
3774a511dddcSNicolai Haehnle if (!Loops.empty())
3775a511dddcSNicolai Haehnle return TokError("multiclass is not allowed inside foreach loop");
3776a511dddcSNicolai Haehnle return ParseMultiClass();
377784c287e3SPeter Collingbourne }
377884c287e3SPeter Collingbourne }
377984c287e3SPeter Collingbourne
378084c287e3SPeter Collingbourne /// ParseObjectList
378184c287e3SPeter Collingbourne /// ObjectList :== Object*
ParseObjectList(MultiClass * MC)378284c287e3SPeter Collingbourne bool TGParser::ParseObjectList(MultiClass *MC) {
378384c287e3SPeter Collingbourne while (isObjectStart(Lex.getCode())) {
378484c287e3SPeter Collingbourne if (ParseObject(MC))
378584c287e3SPeter Collingbourne return true;
378684c287e3SPeter Collingbourne }
378784c287e3SPeter Collingbourne return false;
378884c287e3SPeter Collingbourne }
378984c287e3SPeter Collingbourne
ParseFile()379084c287e3SPeter Collingbourne bool TGParser::ParseFile() {
379184c287e3SPeter Collingbourne Lex.Lex(); // Prime the lexer.
379284c287e3SPeter Collingbourne if (ParseObjectList()) return true;
379384c287e3SPeter Collingbourne
379484c287e3SPeter Collingbourne // If we have unread input at the end of the file, report it.
379584c287e3SPeter Collingbourne if (Lex.getCode() == tgtok::Eof)
379684c287e3SPeter Collingbourne return false;
379784c287e3SPeter Collingbourne
3798a6759477SPaul C. Anagnostopoulos return TokError("Unexpected token at top level");
379984c287e3SPeter Collingbourne }
38007d69e0f3SNicolai Haehnle
3801a9fc44c5SPaul C. Anagnostopoulos // Check the types of the template argument values for a class
3802a9fc44c5SPaul C. Anagnostopoulos // inheritance, multiclass invocation, or anonymous class invocation.
3803a9fc44c5SPaul C. Anagnostopoulos // If necessary, replace an argument with a cast to the required type.
3804a9fc44c5SPaul C. Anagnostopoulos // The argument count has already been checked.
CheckTemplateArgValues(SmallVectorImpl<llvm::Init * > & Values,SMLoc Loc,Record * ArgsRec)3805a9fc44c5SPaul C. Anagnostopoulos bool TGParser::CheckTemplateArgValues(SmallVectorImpl<llvm::Init *> &Values,
3806a9fc44c5SPaul C. Anagnostopoulos SMLoc Loc, Record *ArgsRec) {
3807a9fc44c5SPaul C. Anagnostopoulos
3808a9fc44c5SPaul C. Anagnostopoulos ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
3809a9fc44c5SPaul C. Anagnostopoulos
3810a9fc44c5SPaul C. Anagnostopoulos for (unsigned I = 0, E = Values.size(); I < E; ++I) {
3811a9fc44c5SPaul C. Anagnostopoulos RecordVal *Arg = ArgsRec->getValue(TArgs[I]);
3812a9fc44c5SPaul C. Anagnostopoulos RecTy *ArgType = Arg->getType();
3813a9fc44c5SPaul C. Anagnostopoulos auto *Value = Values[I];
3814a9fc44c5SPaul C. Anagnostopoulos
3815a9fc44c5SPaul C. Anagnostopoulos if (TypedInit *ArgValue = dyn_cast<TypedInit>(Value)) {
3816a9fc44c5SPaul C. Anagnostopoulos auto *CastValue = ArgValue->getCastTo(ArgType);
3817a9fc44c5SPaul C. Anagnostopoulos if (CastValue) {
3818a9fc44c5SPaul C. Anagnostopoulos assert((!isa<TypedInit>(CastValue) ||
3819a9fc44c5SPaul C. Anagnostopoulos cast<TypedInit>(CastValue)->getType()->typeIsA(ArgType)) &&
3820a9fc44c5SPaul C. Anagnostopoulos "result of template arg value cast has wrong type");
3821a9fc44c5SPaul C. Anagnostopoulos Values[I] = CastValue;
3822a9fc44c5SPaul C. Anagnostopoulos } else {
3823a9fc44c5SPaul C. Anagnostopoulos PrintFatalError(Loc,
3824a9fc44c5SPaul C. Anagnostopoulos "Value specified for template argument '" +
3825a9fc44c5SPaul C. Anagnostopoulos Arg->getNameInitAsString() + "' (#" + Twine(I) +
3826a9fc44c5SPaul C. Anagnostopoulos ") is of type " + ArgValue->getType()->getAsString() +
3827a9fc44c5SPaul C. Anagnostopoulos "; expected type " + ArgType->getAsString() + ": " +
3828a9fc44c5SPaul C. Anagnostopoulos ArgValue->getAsString());
3829a9fc44c5SPaul C. Anagnostopoulos }
3830a9fc44c5SPaul C. Anagnostopoulos }
3831a9fc44c5SPaul C. Anagnostopoulos }
3832a9fc44c5SPaul C. Anagnostopoulos
3833a9fc44c5SPaul C. Anagnostopoulos return false;
3834a9fc44c5SPaul C. Anagnostopoulos }
3835a9fc44c5SPaul C. Anagnostopoulos
38367d69e0f3SNicolai Haehnle #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const38377d69e0f3SNicolai Haehnle LLVM_DUMP_METHOD void RecordsEntry::dump() const {
38387d69e0f3SNicolai Haehnle if (Loop)
38397d69e0f3SNicolai Haehnle Loop->dump();
38407d69e0f3SNicolai Haehnle if (Rec)
38417d69e0f3SNicolai Haehnle Rec->dump();
38427d69e0f3SNicolai Haehnle }
38437d69e0f3SNicolai Haehnle
dump() const38447d69e0f3SNicolai Haehnle LLVM_DUMP_METHOD void ForeachLoop::dump() const {
38457d69e0f3SNicolai Haehnle errs() << "foreach " << IterVar->getAsString() << " = "
38467d69e0f3SNicolai Haehnle << ListValue->getAsString() << " in {\n";
38477d69e0f3SNicolai Haehnle
38487d69e0f3SNicolai Haehnle for (const auto &E : Entries)
38497d69e0f3SNicolai Haehnle E.dump();
38507d69e0f3SNicolai Haehnle
38517d69e0f3SNicolai Haehnle errs() << "}\n";
38527d69e0f3SNicolai Haehnle }
38537d69e0f3SNicolai Haehnle
dump() const38547d69e0f3SNicolai Haehnle LLVM_DUMP_METHOD void MultiClass::dump() const {
38557d69e0f3SNicolai Haehnle errs() << "Record:\n";
38567d69e0f3SNicolai Haehnle Rec.dump();
38577d69e0f3SNicolai Haehnle
38587d69e0f3SNicolai Haehnle errs() << "Defs:\n";
38597d69e0f3SNicolai Haehnle for (const auto &E : Entries)
38607d69e0f3SNicolai Haehnle E.dump();
38617d69e0f3SNicolai Haehnle }
38627d69e0f3SNicolai Haehnle #endif
3863