Path: blob/main/contrib/llvm-project/llvm/lib/TableGen/TGParser.cpp
35233 views
//===- TGParser.cpp - Parser for TableGen Files ---------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Implement the Parser for TableGen.9//10//===----------------------------------------------------------------------===//1112#include "TGParser.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/ADT/StringExtras.h"15#include "llvm/ADT/Twine.h"16#include "llvm/Config/llvm-config.h"17#include "llvm/Support/Casting.h"18#include "llvm/Support/Compiler.h"19#include "llvm/Support/ErrorHandling.h"20#include "llvm/Support/raw_ostream.h"21#include <algorithm>22#include <cassert>23#include <cstdint>24#include <limits>2526using namespace llvm;2728//===----------------------------------------------------------------------===//29// Support Code for the Semantic Actions.30//===----------------------------------------------------------------------===//3132namespace llvm {3334struct SubClassReference {35SMRange RefRange;36Record *Rec = nullptr;37SmallVector<ArgumentInit *, 4> TemplateArgs;3839SubClassReference() = default;4041bool isInvalid() const { return Rec == nullptr; }42};4344struct SubMultiClassReference {45SMRange RefRange;46MultiClass *MC = nullptr;47SmallVector<ArgumentInit *, 4> TemplateArgs;4849SubMultiClassReference() = default;5051bool isInvalid() const { return MC == nullptr; }52void dump() const;53};5455#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)56LLVM_DUMP_METHOD void SubMultiClassReference::dump() const {57errs() << "Multiclass:\n";5859MC->dump();6061errs() << "Template args:\n";62for (Init *TA : TemplateArgs)63TA->dump();64}65#endif6667} // end namespace llvm6869static bool checkBitsConcrete(Record &R, const RecordVal &RV) {70BitsInit *BV = cast<BitsInit>(RV.getValue());71for (unsigned i = 0, e = BV->getNumBits(); i != e; ++i) {72Init *Bit = BV->getBit(i);73bool IsReference = false;74if (auto VBI = dyn_cast<VarBitInit>(Bit)) {75if (auto VI = dyn_cast<VarInit>(VBI->getBitVar())) {76if (R.getValue(VI->getName()))77IsReference = true;78}79} else if (isa<VarInit>(Bit)) {80IsReference = true;81}82if (!(IsReference || Bit->isConcrete()))83return false;84}85return true;86}8788static void checkConcrete(Record &R) {89for (const RecordVal &RV : R.getValues()) {90// HACK: Disable this check for variables declared with 'field'. This is91// done merely because existing targets have legitimate cases of92// non-concrete variables in helper defs. Ideally, we'd introduce a93// 'maybe' or 'optional' modifier instead of this.94if (RV.isNonconcreteOK())95continue;9697if (Init *V = RV.getValue()) {98bool Ok = isa<BitsInit>(V) ? checkBitsConcrete(R, RV) : V->isConcrete();99if (!Ok) {100PrintError(R.getLoc(),101Twine("Initializer of '") + RV.getNameInitAsString() +102"' in '" + R.getNameInitAsString() +103"' could not be fully resolved: " +104RV.getValue()->getAsString());105}106}107}108}109110/// Return an Init with a qualifier prefix referring111/// to CurRec's name.112static Init *QualifyName(Record &CurRec, Init *Name) {113RecordKeeper &RK = CurRec.getRecords();114Init *NewName = BinOpInit::getStrConcat(115CurRec.getNameInit(),116StringInit::get(RK, CurRec.isMultiClass() ? "::" : ":"));117NewName = BinOpInit::getStrConcat(NewName, Name);118119if (BinOpInit *BinOp = dyn_cast<BinOpInit>(NewName))120NewName = BinOp->Fold(&CurRec);121return NewName;122}123124static Init *QualifyName(MultiClass *MC, Init *Name) {125return QualifyName(MC->Rec, Name);126}127128/// Return the qualified version of the implicit 'NAME' template argument.129static Init *QualifiedNameOfImplicitName(Record &Rec) {130return QualifyName(Rec, StringInit::get(Rec.getRecords(), "NAME"));131}132133static Init *QualifiedNameOfImplicitName(MultiClass *MC) {134return QualifiedNameOfImplicitName(MC->Rec);135}136137Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass *ParsingMultiClass,138StringInit *Name, SMRange NameLoc,139bool TrackReferenceLocs) const {140// First, we search in local variables.141auto It = Vars.find(Name->getValue());142if (It != Vars.end())143return It->second;144145auto FindValueInArgs = [&](Record *Rec, StringInit *Name) -> Init * {146if (!Rec)147return nullptr;148Init *ArgName = QualifyName(*Rec, Name);149if (Rec->isTemplateArg(ArgName)) {150RecordVal *RV = Rec->getValue(ArgName);151assert(RV && "Template arg doesn't exist??");152RV->setUsed(true);153if (TrackReferenceLocs)154RV->addReferenceLoc(NameLoc);155return VarInit::get(ArgName, RV->getType());156}157return Name->getValue() == "NAME"158? VarInit::get(ArgName, StringRecTy::get(Records))159: nullptr;160};161162// If not found, we try to find the variable in additional variables like163// arguments, loop iterator, etc.164switch (Kind) {165case SK_Local:166break; /* do nothing. */167case SK_Record: {168if (CurRec) {169// The variable is a record field?170if (RecordVal *RV = CurRec->getValue(Name)) {171if (TrackReferenceLocs)172RV->addReferenceLoc(NameLoc);173return VarInit::get(Name, RV->getType());174}175176// The variable is a class template argument?177if (CurRec->isClass())178if (auto *V = FindValueInArgs(CurRec, Name))179return V;180}181break;182}183case SK_ForeachLoop: {184// The variable is a loop iterator?185if (CurLoop->IterVar) {186VarInit *IterVar = dyn_cast<VarInit>(CurLoop->IterVar);187if (IterVar && IterVar->getNameInit() == Name)188return IterVar;189}190break;191}192case SK_MultiClass: {193// The variable is a multiclass template argument?194if (CurMultiClass)195if (auto *V = FindValueInArgs(&CurMultiClass->Rec, Name))196return V;197break;198}199}200201// Then, we try to find the name in parent scope.202if (Parent)203return Parent->getVar(Records, ParsingMultiClass, Name, NameLoc,204TrackReferenceLocs);205206return nullptr;207}208209bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {210if (!CurRec)211CurRec = &CurMultiClass->Rec;212213if (RecordVal *ERV = CurRec->getValue(RV.getNameInit())) {214// The value already exists in the class, treat this as a set.215if (ERV->setValue(RV.getValue()))216return Error(Loc, "New definition of '" + RV.getName() + "' of type '" +217RV.getType()->getAsString() + "' is incompatible with " +218"previous definition of type '" +219ERV->getType()->getAsString() + "'");220} else {221CurRec->addValue(RV);222}223return false;224}225226/// SetValue -227/// Return true on error, false on success.228bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,229ArrayRef<unsigned> BitList, Init *V,230bool AllowSelfAssignment, bool OverrideDefLoc) {231if (!V) return false;232233if (!CurRec) CurRec = &CurMultiClass->Rec;234235RecordVal *RV = CurRec->getValue(ValName);236if (!RV)237return Error(Loc, "Value '" + ValName->getAsUnquotedString() +238"' unknown!");239240// Do not allow assignments like 'X = X'. This will just cause infinite loops241// in the resolution machinery.242if (BitList.empty())243if (VarInit *VI = dyn_cast<VarInit>(V))244if (VI->getNameInit() == ValName && !AllowSelfAssignment)245return Error(Loc, "Recursion / self-assignment forbidden");246247// If we are assigning to a subset of the bits in the value... then we must be248// assigning to a field of BitsRecTy, which must have a BitsInit249// initializer.250//251if (!BitList.empty()) {252BitsInit *CurVal = dyn_cast<BitsInit>(RV->getValue());253if (!CurVal)254return Error(Loc, "Value '" + ValName->getAsUnquotedString() +255"' is not a bits type");256257// Convert the incoming value to a bits type of the appropriate size...258Init *BI = V->getCastTo(BitsRecTy::get(Records, BitList.size()));259if (!BI)260return Error(Loc, "Initializer is not compatible with bit range");261262SmallVector<Init *, 16> NewBits(CurVal->getNumBits());263264// Loop over bits, assigning values as appropriate.265for (unsigned i = 0, e = BitList.size(); i != e; ++i) {266unsigned Bit = BitList[i];267if (NewBits[Bit])268return Error(Loc, "Cannot set bit #" + Twine(Bit) + " of value '" +269ValName->getAsUnquotedString() + "' more than once");270NewBits[Bit] = BI->getBit(i);271}272273for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)274if (!NewBits[i])275NewBits[i] = CurVal->getBit(i);276277V = BitsInit::get(Records, NewBits);278}279280if (OverrideDefLoc ? RV->setValue(V, Loc) : RV->setValue(V)) {281std::string InitType;282if (BitsInit *BI = dyn_cast<BitsInit>(V))283InitType = (Twine("' of type bit initializer with length ") +284Twine(BI->getNumBits())).str();285else if (TypedInit *TI = dyn_cast<TypedInit>(V))286InitType = (Twine("' of type '") + TI->getType()->getAsString()).str();287return Error(Loc, "Field '" + ValName->getAsUnquotedString() +288"' of type '" + RV->getType()->getAsString() +289"' is incompatible with value '" +290V->getAsString() + InitType + "'");291}292return false;293}294295/// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template296/// args as SubClass's template arguments.297bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {298Record *SC = SubClass.Rec;299MapResolver R(CurRec);300301// Loop over all the subclass record's fields. Add regular fields to the new302// record.303for (const RecordVal &Field : SC->getValues())304if (!Field.isTemplateArg())305if (AddValue(CurRec, SubClass.RefRange.Start, Field))306return true;307308if (resolveArgumentsOfClass(R, SC, SubClass.TemplateArgs,309SubClass.RefRange.Start))310return true;311312// Copy the subclass record's assertions to the new record.313CurRec->appendAssertions(SC);314315// Copy the subclass record's dumps to the new record.316CurRec->appendDumps(SC);317318Init *Name;319if (CurRec->isClass())320Name = VarInit::get(QualifiedNameOfImplicitName(*CurRec),321StringRecTy::get(Records));322else323Name = CurRec->getNameInit();324R.set(QualifiedNameOfImplicitName(*SC), Name);325326CurRec->resolveReferences(R);327328// Since everything went well, we can now set the "superclass" list for the329// current record.330ArrayRef<std::pair<Record *, SMRange>> SCs = SC->getSuperClasses();331for (const auto &SCPair : SCs) {332if (CurRec->isSubClassOf(SCPair.first))333return Error(SubClass.RefRange.Start,334"Already subclass of '" + SCPair.first->getName() + "'!\n");335CurRec->addSuperClass(SCPair.first, SCPair.second);336}337338if (CurRec->isSubClassOf(SC))339return Error(SubClass.RefRange.Start,340"Already subclass of '" + SC->getName() + "'!\n");341CurRec->addSuperClass(SC, SubClass.RefRange);342return false;343}344345bool TGParser::AddSubClass(RecordsEntry &Entry, SubClassReference &SubClass) {346if (Entry.Rec)347return AddSubClass(Entry.Rec.get(), SubClass);348349if (Entry.Assertion)350return false;351352for (auto &E : Entry.Loop->Entries) {353if (AddSubClass(E, SubClass))354return true;355}356357return false;358}359360/// AddSubMultiClass - Add SubMultiClass as a subclass to361/// CurMC, resolving its template args as SubMultiClass's362/// template arguments.363bool TGParser::AddSubMultiClass(MultiClass *CurMC,364SubMultiClassReference &SubMultiClass) {365MultiClass *SMC = SubMultiClass.MC;366367SubstStack Substs;368if (resolveArgumentsOfMultiClass(369Substs, SMC, SubMultiClass.TemplateArgs,370VarInit::get(QualifiedNameOfImplicitName(CurMC),371StringRecTy::get(Records)),372SubMultiClass.RefRange.Start))373return true;374375// Add all of the defs in the subclass into the current multiclass.376return resolve(SMC->Entries, Substs, false, &CurMC->Entries);377}378379/// Add a record, foreach loop, or assertion to the current context.380bool TGParser::addEntry(RecordsEntry E) {381assert((!!E.Rec + !!E.Loop + !!E.Assertion + !!E.Dump) == 1 &&382"RecordsEntry has invalid number of items");383384// If we are parsing a loop, add it to the loop's entries.385if (!Loops.empty()) {386Loops.back()->Entries.push_back(std::move(E));387return false;388}389390// If it is a loop, then resolve and perform the loop.391if (E.Loop) {392SubstStack Stack;393return resolve(*E.Loop, Stack, CurMultiClass == nullptr,394CurMultiClass ? &CurMultiClass->Entries : nullptr);395}396397// If we are parsing a multiclass, add it to the multiclass's entries.398if (CurMultiClass) {399CurMultiClass->Entries.push_back(std::move(E));400return false;401}402403// If it is an assertion, then it's a top-level one, so check it.404if (E.Assertion) {405CheckAssert(E.Assertion->Loc, E.Assertion->Condition, E.Assertion->Message);406return false;407}408409if (E.Dump) {410dumpMessage(E.Dump->Loc, E.Dump->Message);411return false;412}413414// It must be a record, so finish it off.415return addDefOne(std::move(E.Rec));416}417418/// Resolve the entries in \p Loop, going over inner loops recursively419/// and making the given subsitutions of (name, value) pairs.420///421/// The resulting records are stored in \p Dest if non-null. Otherwise, they422/// are added to the global record keeper.423bool TGParser::resolve(const ForeachLoop &Loop, SubstStack &Substs,424bool Final, std::vector<RecordsEntry> *Dest,425SMLoc *Loc) {426427MapResolver R;428for (const auto &S : Substs)429R.set(S.first, S.second);430Init *List = Loop.ListValue->resolveReferences(R);431432// For if-then-else blocks, we lower to a foreach loop whose list is a433// ternary selection between lists of different length. Since we don't434// have a means to track variable length record lists, we *must* resolve435// the condition here. We want to defer final resolution of the arms436// until the resulting records are finalized.437// e.g. !if(!exists<SchedWrite>("__does_not_exist__"), [1], [])438if (auto *TI = dyn_cast<TernOpInit>(List);439TI && TI->getOpcode() == TernOpInit::IF && Final) {440Init *OldLHS = TI->getLHS();441R.setFinal(true);442Init *LHS = OldLHS->resolveReferences(R);443if (LHS == OldLHS) {444PrintError(Loop.Loc,445Twine("unable to resolve if condition '") +446LHS->getAsString() + "' at end of containing scope");447return true;448}449Init *MHS = TI->getMHS();450Init *RHS = TI->getRHS();451List = TernOpInit::get(TernOpInit::IF, LHS, MHS, RHS, TI->getType())452->Fold(nullptr);453}454455auto LI = dyn_cast<ListInit>(List);456if (!LI) {457if (!Final) {458Dest->emplace_back(std::make_unique<ForeachLoop>(Loop.Loc, Loop.IterVar,459List));460return resolve(Loop.Entries, Substs, Final, &Dest->back().Loop->Entries,461Loc);462}463464PrintError(Loop.Loc, Twine("attempting to loop over '") +465List->getAsString() + "', expected a list");466return true;467}468469bool Error = false;470for (auto *Elt : *LI) {471if (Loop.IterVar)472Substs.emplace_back(Loop.IterVar->getNameInit(), Elt);473Error = resolve(Loop.Entries, Substs, Final, Dest);474if (Loop.IterVar)475Substs.pop_back();476if (Error)477break;478}479return Error;480}481482/// Resolve the entries in \p Source, going over loops recursively and483/// making the given substitutions of (name, value) pairs.484///485/// The resulting records are stored in \p Dest if non-null. Otherwise, they486/// are added to the global record keeper.487bool TGParser::resolve(const std::vector<RecordsEntry> &Source,488SubstStack &Substs, bool Final,489std::vector<RecordsEntry> *Dest, SMLoc *Loc) {490bool Error = false;491for (auto &E : Source) {492if (E.Loop) {493Error = resolve(*E.Loop, Substs, Final, Dest);494495} else if (E.Assertion) {496MapResolver R;497for (const auto &S : Substs)498R.set(S.first, S.second);499Init *Condition = E.Assertion->Condition->resolveReferences(R);500Init *Message = E.Assertion->Message->resolveReferences(R);501502if (Dest)503Dest->push_back(std::make_unique<Record::AssertionInfo>(504E.Assertion->Loc, Condition, Message));505else506CheckAssert(E.Assertion->Loc, Condition, Message);507508} else if (E.Dump) {509MapResolver R;510for (const auto &S : Substs)511R.set(S.first, S.second);512Init *Message = E.Dump->Message->resolveReferences(R);513514if (Dest)515Dest->push_back(516std::make_unique<Record::DumpInfo>(E.Dump->Loc, Message));517else518dumpMessage(E.Dump->Loc, Message);519520} else {521auto Rec = std::make_unique<Record>(*E.Rec);522if (Loc)523Rec->appendLoc(*Loc);524525MapResolver R(Rec.get());526for (const auto &S : Substs)527R.set(S.first, S.second);528Rec->resolveReferences(R);529530if (Dest)531Dest->push_back(std::move(Rec));532else533Error = addDefOne(std::move(Rec));534}535if (Error)536break;537}538return Error;539}540541/// Resolve the record fully and add it to the record keeper.542bool TGParser::addDefOne(std::unique_ptr<Record> Rec) {543Init *NewName = nullptr;544if (Record *Prev = Records.getDef(Rec->getNameInitAsString())) {545if (!Rec->isAnonymous()) {546PrintError(Rec->getLoc(),547"def already exists: " + Rec->getNameInitAsString());548PrintNote(Prev->getLoc(), "location of previous definition");549return true;550}551NewName = Records.getNewAnonymousName();552}553554Rec->resolveReferences(NewName);555checkConcrete(*Rec);556557if (!isa<StringInit>(Rec->getNameInit())) {558PrintError(Rec->getLoc(), Twine("record name '") +559Rec->getNameInit()->getAsString() +560"' could not be fully resolved");561return true;562}563564// Check the assertions.565Rec->checkRecordAssertions();566567// Run the dumps.568Rec->emitRecordDumps();569570// If ObjectBody has template arguments, it's an error.571assert(Rec->getTemplateArgs().empty() && "How'd this get template args?");572573for (DefsetRecord *Defset : Defsets) {574DefInit *I = Rec->getDefInit();575if (!I->getType()->typeIsA(Defset->EltTy)) {576PrintError(Rec->getLoc(), Twine("adding record of incompatible type '") +577I->getType()->getAsString() +578"' to defset");579PrintNote(Defset->Loc, "location of defset declaration");580return true;581}582Defset->Elements.push_back(I);583}584585Records.addDef(std::move(Rec));586return false;587}588589bool TGParser::resolveArguments(Record *Rec, ArrayRef<ArgumentInit *> ArgValues,590SMLoc Loc, ArgValueHandler ArgValueHandler) {591ArrayRef<Init *> ArgNames = Rec->getTemplateArgs();592assert(ArgValues.size() <= ArgNames.size() &&593"Too many template arguments allowed");594595// Loop over the template arguments and handle the (name, value) pair.596SmallVector<Init *, 2> UnsolvedArgNames(ArgNames);597for (auto *Arg : ArgValues) {598Init *ArgName = nullptr;599Init *ArgValue = Arg->getValue();600if (Arg->isPositional())601ArgName = ArgNames[Arg->getIndex()];602if (Arg->isNamed())603ArgName = Arg->getName();604605// We can only specify the template argument once.606if (!is_contained(UnsolvedArgNames, ArgName))607return Error(Loc, "We can only specify the template argument '" +608ArgName->getAsUnquotedString() + "' once");609610ArgValueHandler(ArgName, ArgValue);611llvm::erase(UnsolvedArgNames, ArgName);612}613614// For unsolved arguments, if there is no default value, complain.615for (auto *UnsolvedArgName : UnsolvedArgNames) {616Init *Default = Rec->getValue(UnsolvedArgName)->getValue();617if (!Default->isComplete()) {618std::string Name = UnsolvedArgName->getAsUnquotedString();619Error(Loc, "value not specified for template argument '" + Name + "'");620PrintNote(Rec->getFieldLoc(Name),621"declared in '" + Rec->getNameInitAsString() + "'");622return true;623}624ArgValueHandler(UnsolvedArgName, Default);625}626627return false;628}629630/// Resolve the arguments of class and set them to MapResolver.631/// Returns true if failed.632bool TGParser::resolveArgumentsOfClass(MapResolver &R, Record *Rec,633ArrayRef<ArgumentInit *> ArgValues,634SMLoc Loc) {635return resolveArguments(Rec, ArgValues, Loc,636[&](Init *Name, Init *Value) { R.set(Name, Value); });637}638639/// Resolve the arguments of multiclass and store them into SubstStack.640/// Returns true if failed.641bool TGParser::resolveArgumentsOfMultiClass(SubstStack &Substs, MultiClass *MC,642ArrayRef<ArgumentInit *> ArgValues,643Init *DefmName, SMLoc Loc) {644// Add an implicit argument NAME.645Substs.emplace_back(QualifiedNameOfImplicitName(MC), DefmName);646return resolveArguments(647&MC->Rec, ArgValues, Loc,648[&](Init *Name, Init *Value) { Substs.emplace_back(Name, Value); });649}650651//===----------------------------------------------------------------------===//652// Parser Code653//===----------------------------------------------------------------------===//654655bool TGParser::consume(tgtok::TokKind K) {656if (Lex.getCode() == K) {657Lex.Lex();658return true;659}660return false;661}662663/// ParseObjectName - If a valid object name is specified, return it. If no664/// name is specified, return the unset initializer. Return nullptr on parse665/// error.666/// ObjectName ::= Value [ '#' Value ]*667/// ObjectName ::= /*empty*/668///669Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) {670switch (Lex.getCode()) {671case tgtok::colon:672case tgtok::semi:673case tgtok::l_brace:674// These are all of the tokens that can begin an object body.675// Some of these can also begin values but we disallow those cases676// because they are unlikely to be useful.677return UnsetInit::get(Records);678default:679break;680}681682Record *CurRec = nullptr;683if (CurMultiClass)684CurRec = &CurMultiClass->Rec;685686Init *Name = ParseValue(CurRec, StringRecTy::get(Records), ParseNameMode);687if (!Name)688return nullptr;689690if (CurMultiClass) {691Init *NameStr = QualifiedNameOfImplicitName(CurMultiClass);692HasReferenceResolver R(NameStr);693Name->resolveReferences(R);694if (!R.found())695Name = BinOpInit::getStrConcat(696VarInit::get(NameStr, StringRecTy::get(Records)), Name);697}698699return Name;700}701702/// ParseClassID - Parse and resolve a reference to a class name. This returns703/// null on error.704///705/// ClassID ::= ID706///707Record *TGParser::ParseClassID() {708if (Lex.getCode() != tgtok::Id) {709TokError("expected name for ClassID");710return nullptr;711}712713Record *Result = Records.getClass(Lex.getCurStrVal());714if (!Result) {715std::string Msg("Couldn't find class '" + Lex.getCurStrVal() + "'");716if (MultiClasses[Lex.getCurStrVal()].get())717TokError(Msg + ". Use 'defm' if you meant to use multiclass '" +718Lex.getCurStrVal() + "'");719else720TokError(Msg);721} else if (TrackReferenceLocs) {722Result->appendReferenceLoc(Lex.getLocRange());723}724725Lex.Lex();726return Result;727}728729/// ParseMultiClassID - Parse and resolve a reference to a multiclass name.730/// This returns null on error.731///732/// MultiClassID ::= ID733///734MultiClass *TGParser::ParseMultiClassID() {735if (Lex.getCode() != tgtok::Id) {736TokError("expected name for MultiClassID");737return nullptr;738}739740MultiClass *Result = MultiClasses[Lex.getCurStrVal()].get();741if (!Result)742TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");743744Lex.Lex();745return Result;746}747748/// ParseSubClassReference - Parse a reference to a subclass or a749/// multiclass. This returns a SubClassRefTy with a null Record* on error.750///751/// SubClassRef ::= ClassID752/// SubClassRef ::= ClassID '<' ArgValueList '>'753///754SubClassReference TGParser::755ParseSubClassReference(Record *CurRec, bool isDefm) {756SubClassReference Result;757Result.RefRange.Start = Lex.getLoc();758759if (isDefm) {760if (MultiClass *MC = ParseMultiClassID())761Result.Rec = &MC->Rec;762} else {763Result.Rec = ParseClassID();764}765if (!Result.Rec) return Result;766767// If there is no template arg list, we're done.768if (!consume(tgtok::less)) {769Result.RefRange.End = Lex.getLoc();770return Result;771}772773if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec)) {774Result.Rec = nullptr; // Error parsing value list.775return Result;776}777778if (CheckTemplateArgValues(Result.TemplateArgs, Result.RefRange.Start,779Result.Rec)) {780Result.Rec = nullptr; // Error checking value list.781return Result;782}783784Result.RefRange.End = Lex.getLoc();785return Result;786}787788/// ParseSubMultiClassReference - Parse a reference to a subclass or to a789/// templated submulticlass. This returns a SubMultiClassRefTy with a null790/// Record* on error.791///792/// SubMultiClassRef ::= MultiClassID793/// SubMultiClassRef ::= MultiClassID '<' ArgValueList '>'794///795SubMultiClassReference TGParser::796ParseSubMultiClassReference(MultiClass *CurMC) {797SubMultiClassReference Result;798Result.RefRange.Start = Lex.getLoc();799800Result.MC = ParseMultiClassID();801if (!Result.MC) return Result;802803// If there is no template arg list, we're done.804if (!consume(tgtok::less)) {805Result.RefRange.End = Lex.getLoc();806return Result;807}808809if (ParseTemplateArgValueList(Result.TemplateArgs, &CurMC->Rec,810&Result.MC->Rec)) {811Result.MC = nullptr; // Error parsing value list.812return Result;813}814815Result.RefRange.End = Lex.getLoc();816817return Result;818}819820/// ParseSliceElement - Parse subscript or range821///822/// SliceElement ::= Value<list<int>>823/// SliceElement ::= Value<int>824/// SliceElement ::= Value<int> '...' Value<int>825/// SliceElement ::= Value<int> '-' Value<int> (deprecated)826/// SliceElement ::= Value<int> INTVAL(Negative; deprecated)827///828/// SliceElement is either IntRecTy, ListRecTy, or nullptr829///830TypedInit *TGParser::ParseSliceElement(Record *CurRec) {831auto LHSLoc = Lex.getLoc();832auto *CurVal = ParseValue(CurRec);833if (!CurVal)834return nullptr;835auto *LHS = cast<TypedInit>(CurVal);836837TypedInit *RHS = nullptr;838switch (Lex.getCode()) {839case tgtok::dotdotdot:840case tgtok::minus: { // Deprecated841Lex.Lex(); // eat842auto RHSLoc = Lex.getLoc();843CurVal = ParseValue(CurRec);844if (!CurVal)845return nullptr;846RHS = cast<TypedInit>(CurVal);847if (!isa<IntRecTy>(RHS->getType())) {848Error(RHSLoc,849"expected int...int, got " + Twine(RHS->getType()->getAsString()));850return nullptr;851}852break;853}854case tgtok::IntVal: { // Deprecated "-num"855auto i = -Lex.getCurIntVal();856if (i < 0) {857TokError("invalid range, cannot be negative");858return nullptr;859}860RHS = IntInit::get(Records, i);861Lex.Lex(); // eat IntVal862break;863}864default: // Single value (IntRecTy or ListRecTy)865return LHS;866}867868assert(RHS);869assert(isa<IntRecTy>(RHS->getType()));870871// Closed-interval range <LHS:IntRecTy>...<RHS:IntRecTy>872if (!isa<IntRecTy>(LHS->getType())) {873Error(LHSLoc,874"expected int...int, got " + Twine(LHS->getType()->getAsString()));875return nullptr;876}877878return cast<TypedInit>(BinOpInit::get(BinOpInit::RANGEC, LHS, RHS,879IntRecTy::get(Records)->getListTy())880->Fold(CurRec));881}882883/// ParseSliceElements - Parse subscripts in square brackets.884///885/// SliceElements ::= ( SliceElement ',' )* SliceElement ','?886///887/// SliceElement is either IntRecTy, ListRecTy, or nullptr888///889/// Returns ListRecTy by defaut.890/// Returns IntRecTy if;891/// - Single=true892/// - SliceElements is Value<int> w/o trailing comma893///894TypedInit *TGParser::ParseSliceElements(Record *CurRec, bool Single) {895TypedInit *CurVal;896SmallVector<Init *, 2> Elems; // int897SmallVector<TypedInit *, 2> Slices; // list<int>898899auto FlushElems = [&] {900if (!Elems.empty()) {901Slices.push_back(ListInit::get(Elems, IntRecTy::get(Records)));902Elems.clear();903}904};905906do {907auto LHSLoc = Lex.getLoc();908CurVal = ParseSliceElement(CurRec);909if (!CurVal)910return nullptr;911auto *CurValTy = CurVal->getType();912913if (auto *ListValTy = dyn_cast<ListRecTy>(CurValTy)) {914if (!isa<IntRecTy>(ListValTy->getElementType())) {915Error(LHSLoc,916"expected list<int>, got " + Twine(ListValTy->getAsString()));917return nullptr;918}919920FlushElems();921Slices.push_back(CurVal);922Single = false;923CurVal = nullptr;924} else if (!isa<IntRecTy>(CurValTy)) {925Error(LHSLoc,926"unhandled type " + Twine(CurValTy->getAsString()) + " in range");927return nullptr;928}929930if (Lex.getCode() != tgtok::comma)931break;932933Lex.Lex(); // eat comma934935// `[i,]` is not LISTELEM but LISTSLICE936Single = false;937if (CurVal)938Elems.push_back(CurVal);939CurVal = nullptr;940} while (Lex.getCode() != tgtok::r_square);941942if (CurVal) {943// LISTELEM944if (Single)945return CurVal;946947Elems.push_back(CurVal);948}949950FlushElems();951952// Concatenate lists in Slices953TypedInit *Result = nullptr;954for (auto *Slice : Slices) {955Result = (Result ? cast<TypedInit>(BinOpInit::getListConcat(Result, Slice))956: Slice);957}958959return Result;960}961962/// ParseRangePiece - Parse a bit/value range.963/// RangePiece ::= INTVAL964/// RangePiece ::= INTVAL '...' INTVAL965/// RangePiece ::= INTVAL '-' INTVAL966/// RangePiece ::= INTVAL INTVAL967// The last two forms are deprecated.968bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges,969TypedInit *FirstItem) {970Init *CurVal = FirstItem;971if (!CurVal)972CurVal = ParseValue(nullptr);973974IntInit *II = dyn_cast_or_null<IntInit>(CurVal);975if (!II)976return TokError("expected integer or bitrange");977978int64_t Start = II->getValue();979int64_t End;980981if (Start < 0)982return TokError("invalid range, cannot be negative");983984switch (Lex.getCode()) {985default:986Ranges.push_back(Start);987return false;988989case tgtok::dotdotdot:990case tgtok::minus: {991Lex.Lex(); // eat992993Init *I_End = ParseValue(nullptr);994IntInit *II_End = dyn_cast_or_null<IntInit>(I_End);995if (!II_End) {996TokError("expected integer value as end of range");997return true;998}9991000End = II_End->getValue();1001break;1002}1003case tgtok::IntVal: {1004End = -Lex.getCurIntVal();1005Lex.Lex();1006break;1007}1008}1009if (End < 0)1010return TokError("invalid range, cannot be negative");10111012// Add to the range.1013if (Start < End)1014for (; Start <= End; ++Start)1015Ranges.push_back(Start);1016else1017for (; Start >= End; --Start)1018Ranges.push_back(Start);1019return false;1020}10211022/// ParseRangeList - Parse a list of scalars and ranges into scalar values.1023///1024/// RangeList ::= RangePiece (',' RangePiece)*1025///1026void TGParser::ParseRangeList(SmallVectorImpl<unsigned> &Result) {1027// Parse the first piece.1028if (ParseRangePiece(Result)) {1029Result.clear();1030return;1031}1032while (consume(tgtok::comma))1033// Parse the next range piece.1034if (ParseRangePiece(Result)) {1035Result.clear();1036return;1037}1038}10391040/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing.1041/// OptionalRangeList ::= '<' RangeList '>'1042/// OptionalRangeList ::= /*empty*/1043bool TGParser::ParseOptionalRangeList(SmallVectorImpl<unsigned> &Ranges) {1044SMLoc StartLoc = Lex.getLoc();1045if (!consume(tgtok::less))1046return false;10471048// Parse the range list.1049ParseRangeList(Ranges);1050if (Ranges.empty()) return true;10511052if (!consume(tgtok::greater)) {1053TokError("expected '>' at end of range list");1054return Error(StartLoc, "to match this '<'");1055}1056return false;1057}10581059/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing.1060/// OptionalBitList ::= '{' RangeList '}'1061/// OptionalBitList ::= /*empty*/1062bool TGParser::ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges) {1063SMLoc StartLoc = Lex.getLoc();1064if (!consume(tgtok::l_brace))1065return false;10661067// Parse the range list.1068ParseRangeList(Ranges);1069if (Ranges.empty()) return true;10701071if (!consume(tgtok::r_brace)) {1072TokError("expected '}' at end of bit list");1073return Error(StartLoc, "to match this '{'");1074}1075return false;1076}10771078/// ParseType - Parse and return a tblgen type. This returns null on error.1079///1080/// Type ::= STRING // string type1081/// Type ::= CODE // code type1082/// Type ::= BIT // bit type1083/// Type ::= BITS '<' INTVAL '>' // bits<x> type1084/// Type ::= INT // int type1085/// Type ::= LIST '<' Type '>' // list<x> type1086/// Type ::= DAG // dag type1087/// Type ::= ClassID // Record Type1088///1089RecTy *TGParser::ParseType() {1090switch (Lex.getCode()) {1091default: TokError("Unknown token when expecting a type"); return nullptr;1092case tgtok::String:1093case tgtok::Code:1094Lex.Lex();1095return StringRecTy::get(Records);1096case tgtok::Bit:1097Lex.Lex();1098return BitRecTy::get(Records);1099case tgtok::Int:1100Lex.Lex();1101return IntRecTy::get(Records);1102case tgtok::Dag:1103Lex.Lex();1104return DagRecTy::get(Records);1105case tgtok::Id: {1106auto I = TypeAliases.find(Lex.getCurStrVal());1107if (I != TypeAliases.end()) {1108Lex.Lex();1109return I->second;1110}1111if (Record *R = ParseClassID())1112return RecordRecTy::get(R);1113TokError("unknown class name");1114return nullptr;1115}1116case tgtok::Bits: {1117if (Lex.Lex() != tgtok::less) { // Eat 'bits'1118TokError("expected '<' after bits type");1119return nullptr;1120}1121if (Lex.Lex() != tgtok::IntVal) { // Eat '<'1122TokError("expected integer in bits<n> type");1123return nullptr;1124}1125uint64_t Val = Lex.getCurIntVal();1126if (Lex.Lex() != tgtok::greater) { // Eat count.1127TokError("expected '>' at end of bits<n> type");1128return nullptr;1129}1130Lex.Lex(); // Eat '>'1131return BitsRecTy::get(Records, Val);1132}1133case tgtok::List: {1134if (Lex.Lex() != tgtok::less) { // Eat 'bits'1135TokError("expected '<' after list type");1136return nullptr;1137}1138Lex.Lex(); // Eat '<'1139RecTy *SubType = ParseType();1140if (!SubType) return nullptr;11411142if (!consume(tgtok::greater)) {1143TokError("expected '>' at end of list<ty> type");1144return nullptr;1145}1146return ListRecTy::get(SubType);1147}1148}1149}11501151/// ParseIDValue1152Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMRange NameLoc,1153IDParseMode Mode) {1154if (Init *I = CurScope->getVar(Records, CurMultiClass, Name, NameLoc,1155TrackReferenceLocs))1156return I;11571158if (Mode == ParseNameMode)1159return Name;11601161if (Init *I = Records.getGlobal(Name->getValue())) {1162// Add a reference to the global if it's a record.1163if (TrackReferenceLocs) {1164if (auto *Def = dyn_cast<DefInit>(I))1165Def->getDef()->appendReferenceLoc(NameLoc);1166}1167return I;1168}11691170// Allow self-references of concrete defs, but delay the lookup so that we1171// get the correct type.1172if (CurRec && !CurRec->isClass() && !CurMultiClass &&1173CurRec->getNameInit() == Name)1174return UnOpInit::get(UnOpInit::CAST, Name, CurRec->getType());11751176Error(NameLoc.Start, "Variable not defined: '" + Name->getValue() + "'");1177return nullptr;1178}11791180/// ParseOperation - Parse an operator. This returns null on error.1181///1182/// Operation ::= XOperator ['<' Type '>'] '(' Args ')'1183///1184Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {1185switch (Lex.getCode()) {1186default:1187TokError("unknown bang operator");1188return nullptr;1189case tgtok::XNOT:1190case tgtok::XToLower:1191case tgtok::XToUpper:1192case tgtok::XLOG2:1193case tgtok::XHead:1194case tgtok::XTail:1195case tgtok::XSize:1196case tgtok::XEmpty:1197case tgtok::XCast:1198case tgtok::XRepr:1199case tgtok::XGetDagOp: { // Value ::= !unop '(' Value ')'1200UnOpInit::UnaryOp Code;1201RecTy *Type = nullptr;12021203switch (Lex.getCode()) {1204default: llvm_unreachable("Unhandled code!");1205case tgtok::XCast:1206Lex.Lex(); // eat the operation1207Code = UnOpInit::CAST;12081209Type = ParseOperatorType();12101211if (!Type) {1212TokError("did not get type for unary operator");1213return nullptr;1214}12151216break;1217case tgtok::XRepr:1218Lex.Lex(); // eat the operation1219Code = UnOpInit::REPR;1220Type = StringRecTy::get(Records);1221break;1222case tgtok::XToLower:1223Lex.Lex(); // eat the operation1224Code = UnOpInit::TOLOWER;1225Type = StringRecTy::get(Records);1226break;1227case tgtok::XToUpper:1228Lex.Lex(); // eat the operation1229Code = UnOpInit::TOUPPER;1230Type = StringRecTy::get(Records);1231break;1232case tgtok::XNOT:1233Lex.Lex(); // eat the operation1234Code = UnOpInit::NOT;1235Type = IntRecTy::get(Records);1236break;1237case tgtok::XLOG2:1238Lex.Lex(); // eat the operation1239Code = UnOpInit::LOG2;1240Type = IntRecTy::get(Records);1241break;1242case tgtok::XHead:1243Lex.Lex(); // eat the operation1244Code = UnOpInit::HEAD;1245break;1246case tgtok::XTail:1247Lex.Lex(); // eat the operation1248Code = UnOpInit::TAIL;1249break;1250case tgtok::XSize:1251Lex.Lex();1252Code = UnOpInit::SIZE;1253Type = IntRecTy::get(Records);1254break;1255case tgtok::XEmpty:1256Lex.Lex(); // eat the operation1257Code = UnOpInit::EMPTY;1258Type = IntRecTy::get(Records);1259break;1260case tgtok::XGetDagOp:1261Lex.Lex(); // eat the operation1262if (Lex.getCode() == tgtok::less) {1263// Parse an optional type suffix, so that you can say1264// !getdagop<BaseClass>(someDag) as a shorthand for1265// !cast<BaseClass>(!getdagop(someDag)).1266Type = ParseOperatorType();12671268if (!Type) {1269TokError("did not get type for unary operator");1270return nullptr;1271}12721273if (!isa<RecordRecTy>(Type)) {1274TokError("type for !getdagop must be a record type");1275// but keep parsing, to consume the operand1276}1277} else {1278Type = RecordRecTy::get(Records, {});1279}1280Code = UnOpInit::GETDAGOP;1281break;1282}1283if (!consume(tgtok::l_paren)) {1284TokError("expected '(' after unary operator");1285return nullptr;1286}12871288Init *LHS = ParseValue(CurRec);1289if (!LHS) return nullptr;12901291if (Code == UnOpInit::EMPTY || Code == UnOpInit::SIZE) {1292ListInit *LHSl = dyn_cast<ListInit>(LHS);1293StringInit *LHSs = dyn_cast<StringInit>(LHS);1294DagInit *LHSd = dyn_cast<DagInit>(LHS);1295TypedInit *LHSt = dyn_cast<TypedInit>(LHS);1296if (!LHSl && !LHSs && !LHSd && !LHSt) {1297TokError("expected string, list, or dag type argument in unary operator");1298return nullptr;1299}1300if (LHSt) {1301ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());1302StringRecTy *SType = dyn_cast<StringRecTy>(LHSt->getType());1303DagRecTy *DType = dyn_cast<DagRecTy>(LHSt->getType());1304if (!LType && !SType && !DType) {1305TokError("expected string, list, or dag type argument in unary operator");1306return nullptr;1307}1308}1309}13101311if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) {1312ListInit *LHSl = dyn_cast<ListInit>(LHS);1313TypedInit *LHSt = dyn_cast<TypedInit>(LHS);1314if (!LHSl && !LHSt) {1315TokError("expected list type argument in unary operator");1316return nullptr;1317}1318if (LHSt) {1319ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());1320if (!LType) {1321TokError("expected list type argument in unary operator");1322return nullptr;1323}1324}13251326if (LHSl && LHSl->empty()) {1327TokError("empty list argument in unary operator");1328return nullptr;1329}1330if (LHSl) {1331Init *Item = LHSl->getElement(0);1332TypedInit *Itemt = dyn_cast<TypedInit>(Item);1333if (!Itemt) {1334TokError("untyped list element in unary operator");1335return nullptr;1336}1337Type = (Code == UnOpInit::HEAD) ? Itemt->getType()1338: ListRecTy::get(Itemt->getType());1339} else {1340assert(LHSt && "expected list type argument in unary operator");1341ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());1342Type = (Code == UnOpInit::HEAD) ? LType->getElementType() : LType;1343}1344}13451346if (!consume(tgtok::r_paren)) {1347TokError("expected ')' in unary operator");1348return nullptr;1349}1350return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec);1351}13521353case tgtok::XIsA: {1354// Value ::= !isa '<' Type '>' '(' Value ')'1355Lex.Lex(); // eat the operation13561357RecTy *Type = ParseOperatorType();1358if (!Type)1359return nullptr;13601361if (!consume(tgtok::l_paren)) {1362TokError("expected '(' after type of !isa");1363return nullptr;1364}13651366Init *LHS = ParseValue(CurRec);1367if (!LHS)1368return nullptr;13691370if (!consume(tgtok::r_paren)) {1371TokError("expected ')' in !isa");1372return nullptr;1373}13741375return (IsAOpInit::get(Type, LHS))->Fold();1376}13771378case tgtok::XExists: {1379// Value ::= !exists '<' Type '>' '(' Value ')'1380Lex.Lex(); // eat the operation13811382RecTy *Type = ParseOperatorType();1383if (!Type)1384return nullptr;13851386if (!consume(tgtok::l_paren)) {1387TokError("expected '(' after type of !exists");1388return nullptr;1389}13901391SMLoc ExprLoc = Lex.getLoc();1392Init *Expr = ParseValue(CurRec);1393if (!Expr)1394return nullptr;13951396TypedInit *ExprType = dyn_cast<TypedInit>(Expr);1397if (!ExprType) {1398Error(ExprLoc, "expected string type argument in !exists operator");1399return nullptr;1400}14011402RecordRecTy *RecType = dyn_cast<RecordRecTy>(ExprType->getType());1403if (RecType) {1404Error(ExprLoc,1405"expected string type argument in !exists operator, please "1406"use !isa instead");1407return nullptr;1408}14091410StringRecTy *SType = dyn_cast<StringRecTy>(ExprType->getType());1411if (!SType) {1412Error(ExprLoc, "expected string type argument in !exists operator");1413return nullptr;1414}14151416if (!consume(tgtok::r_paren)) {1417TokError("expected ')' in !exists");1418return nullptr;1419}14201421return (ExistsOpInit::get(Type, Expr))->Fold(CurRec);1422}14231424case tgtok::XConcat:1425case tgtok::XADD:1426case tgtok::XSUB:1427case tgtok::XMUL:1428case tgtok::XDIV:1429case tgtok::XAND:1430case tgtok::XOR:1431case tgtok::XXOR:1432case tgtok::XSRA:1433case tgtok::XSRL:1434case tgtok::XSHL:1435case tgtok::XEq:1436case tgtok::XNe:1437case tgtok::XLe:1438case tgtok::XLt:1439case tgtok::XGe:1440case tgtok::XGt:1441case tgtok::XListConcat:1442case tgtok::XListSplat:1443case tgtok::XListRemove:1444case tgtok::XStrConcat:1445case tgtok::XInterleave:1446case tgtok::XGetDagArg:1447case tgtok::XGetDagName:1448case tgtok::XSetDagOp: { // Value ::= !binop '(' Value ',' Value ')'1449tgtok::TokKind OpTok = Lex.getCode();1450SMLoc OpLoc = Lex.getLoc();1451Lex.Lex(); // eat the operation14521453BinOpInit::BinaryOp Code;1454switch (OpTok) {1455default: llvm_unreachable("Unhandled code!");1456case tgtok::XConcat: Code = BinOpInit::CONCAT; break;1457case tgtok::XADD: Code = BinOpInit::ADD; break;1458case tgtok::XSUB: Code = BinOpInit::SUB; break;1459case tgtok::XMUL: Code = BinOpInit::MUL; break;1460case tgtok::XDIV: Code = BinOpInit::DIV; break;1461case tgtok::XAND: Code = BinOpInit::AND; break;1462case tgtok::XOR: Code = BinOpInit::OR; break;1463case tgtok::XXOR: Code = BinOpInit::XOR; break;1464case tgtok::XSRA: Code = BinOpInit::SRA; break;1465case tgtok::XSRL: Code = BinOpInit::SRL; break;1466case tgtok::XSHL: Code = BinOpInit::SHL; break;1467case tgtok::XEq: Code = BinOpInit::EQ; break;1468case tgtok::XNe: Code = BinOpInit::NE; break;1469case tgtok::XLe: Code = BinOpInit::LE; break;1470case tgtok::XLt: Code = BinOpInit::LT; break;1471case tgtok::XGe: Code = BinOpInit::GE; break;1472case tgtok::XGt: Code = BinOpInit::GT; break;1473case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break;1474case tgtok::XListSplat: Code = BinOpInit::LISTSPLAT; break;1475case tgtok::XListRemove:1476Code = BinOpInit::LISTREMOVE;1477break;1478case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;1479case tgtok::XInterleave: Code = BinOpInit::INTERLEAVE; break;1480case tgtok::XSetDagOp: Code = BinOpInit::SETDAGOP; break;1481case tgtok::XGetDagArg:1482Code = BinOpInit::GETDAGARG;1483break;1484case tgtok::XGetDagName:1485Code = BinOpInit::GETDAGNAME;1486break;1487}14881489RecTy *Type = nullptr;1490RecTy *ArgType = nullptr;1491switch (OpTok) {1492default:1493llvm_unreachable("Unhandled code!");1494case tgtok::XConcat:1495case tgtok::XSetDagOp:1496Type = DagRecTy::get(Records);1497ArgType = DagRecTy::get(Records);1498break;1499case tgtok::XGetDagArg:1500Type = ParseOperatorType();1501if (!Type) {1502TokError("did not get type for !getdagarg operator");1503return nullptr;1504}1505ArgType = DagRecTy::get(Records);1506break;1507case tgtok::XGetDagName:1508Type = StringRecTy::get(Records);1509ArgType = DagRecTy::get(Records);1510break;1511case tgtok::XAND:1512case tgtok::XOR:1513case tgtok::XXOR:1514case tgtok::XSRA:1515case tgtok::XSRL:1516case tgtok::XSHL:1517case tgtok::XADD:1518case tgtok::XSUB:1519case tgtok::XMUL:1520case tgtok::XDIV:1521Type = IntRecTy::get(Records);1522ArgType = IntRecTy::get(Records);1523break;1524case tgtok::XEq:1525case tgtok::XNe:1526case tgtok::XLe:1527case tgtok::XLt:1528case tgtok::XGe:1529case tgtok::XGt:1530Type = BitRecTy::get(Records);1531// ArgType for the comparison operators is not yet known.1532break;1533case tgtok::XListConcat:1534// We don't know the list type until we parse the first argument.1535ArgType = ItemType;1536break;1537case tgtok::XListSplat:1538// Can't do any typechecking until we parse the first argument.1539break;1540case tgtok::XListRemove:1541// We don't know the list type until we parse the first argument.1542ArgType = ItemType;1543break;1544case tgtok::XStrConcat:1545Type = StringRecTy::get(Records);1546ArgType = StringRecTy::get(Records);1547break;1548case tgtok::XInterleave:1549Type = StringRecTy::get(Records);1550// The first argument type is not yet known.1551}15521553if (Type && ItemType && !Type->typeIsConvertibleTo(ItemType)) {1554Error(OpLoc, Twine("expected value of type '") +1555ItemType->getAsString() + "', got '" +1556Type->getAsString() + "'");1557return nullptr;1558}15591560if (!consume(tgtok::l_paren)) {1561TokError("expected '(' after binary operator");1562return nullptr;1563}15641565SmallVector<Init*, 2> InitList;15661567// Note that this loop consumes an arbitrary number of arguments.1568// The actual count is checked later.1569for (;;) {1570SMLoc InitLoc = Lex.getLoc();1571InitList.push_back(ParseValue(CurRec, ArgType));1572if (!InitList.back()) return nullptr;15731574TypedInit *InitListBack = dyn_cast<TypedInit>(InitList.back());1575if (!InitListBack) {1576Error(OpLoc, Twine("expected value to be a typed value, got '" +1577InitList.back()->getAsString() + "'"));1578return nullptr;1579}1580RecTy *ListType = InitListBack->getType();15811582if (!ArgType) {1583// Argument type must be determined from the argument itself.1584ArgType = ListType;15851586switch (Code) {1587case BinOpInit::LISTCONCAT:1588if (!isa<ListRecTy>(ArgType)) {1589Error(InitLoc, Twine("expected a list, got value of type '") +1590ArgType->getAsString() + "'");1591return nullptr;1592}1593break;1594case BinOpInit::LISTSPLAT:1595if (ItemType && InitList.size() == 1) {1596if (!isa<ListRecTy>(ItemType)) {1597Error(OpLoc,1598Twine("expected output type to be a list, got type '") +1599ItemType->getAsString() + "'");1600return nullptr;1601}1602if (!ArgType->getListTy()->typeIsConvertibleTo(ItemType)) {1603Error(OpLoc, Twine("expected first arg type to be '") +1604ArgType->getAsString() +1605"', got value of type '" +1606cast<ListRecTy>(ItemType)1607->getElementType()1608->getAsString() +1609"'");1610return nullptr;1611}1612}1613if (InitList.size() == 2 && !isa<IntRecTy>(ArgType)) {1614Error(InitLoc, Twine("expected second parameter to be an int, got "1615"value of type '") +1616ArgType->getAsString() + "'");1617return nullptr;1618}1619ArgType = nullptr; // Broken invariant: types not identical.1620break;1621case BinOpInit::LISTREMOVE:1622if (!isa<ListRecTy>(ArgType)) {1623Error(InitLoc, Twine("expected a list, got value of type '") +1624ArgType->getAsString() + "'");1625return nullptr;1626}1627break;1628case BinOpInit::EQ:1629case BinOpInit::NE:1630if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&1631!ArgType->typeIsConvertibleTo(StringRecTy::get(Records)) &&1632!ArgType->typeIsConvertibleTo(RecordRecTy::get(Records, {}))) {1633Error(InitLoc, Twine("expected bit, bits, int, string, or record; "1634"got value of type '") + ArgType->getAsString() +1635"'");1636return nullptr;1637}1638break;1639case BinOpInit::GETDAGARG: // The 2nd argument of !getdagarg could be1640// index or name.1641case BinOpInit::LE:1642case BinOpInit::LT:1643case BinOpInit::GE:1644case BinOpInit::GT:1645if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&1646!ArgType->typeIsConvertibleTo(StringRecTy::get(Records))) {1647Error(InitLoc, Twine("expected bit, bits, int, or string; "1648"got value of type '") + ArgType->getAsString() +1649"'");1650return nullptr;1651}1652break;1653case BinOpInit::INTERLEAVE:1654switch (InitList.size()) {1655case 1: // First argument must be a list of strings or integers.1656if (ArgType != StringRecTy::get(Records)->getListTy() &&1657!ArgType->typeIsConvertibleTo(1658IntRecTy::get(Records)->getListTy())) {1659Error(InitLoc, Twine("expected list of string, int, bits, or bit; "1660"got value of type '") +1661ArgType->getAsString() + "'");1662return nullptr;1663}1664break;1665case 2: // Second argument must be a string.1666if (!isa<StringRecTy>(ArgType)) {1667Error(InitLoc, Twine("expected second argument to be a string, "1668"got value of type '") +1669ArgType->getAsString() + "'");1670return nullptr;1671}1672break;1673default: ;1674}1675ArgType = nullptr; // Broken invariant: types not identical.1676break;1677default: llvm_unreachable("other ops have fixed argument types");1678}16791680} else {1681// Desired argument type is a known and in ArgType.1682RecTy *Resolved = resolveTypes(ArgType, ListType);1683if (!Resolved) {1684Error(InitLoc, Twine("expected value of type '") +1685ArgType->getAsString() + "', got '" +1686ListType->getAsString() + "'");1687return nullptr;1688}1689if (Code != BinOpInit::ADD && Code != BinOpInit::SUB &&1690Code != BinOpInit::AND && Code != BinOpInit::OR &&1691Code != BinOpInit::XOR && Code != BinOpInit::SRA &&1692Code != BinOpInit::SRL && Code != BinOpInit::SHL &&1693Code != BinOpInit::MUL && Code != BinOpInit::DIV)1694ArgType = Resolved;1695}16961697// Deal with BinOps whose arguments have different types, by1698// rewriting ArgType in between them.1699switch (Code) {1700case BinOpInit::SETDAGOP:1701// After parsing the first dag argument, switch to expecting1702// a record, with no restriction on its superclasses.1703ArgType = RecordRecTy::get(Records, {});1704break;1705case BinOpInit::GETDAGARG:1706// After parsing the first dag argument, expect an index integer or a1707// name string.1708ArgType = nullptr;1709break;1710case BinOpInit::GETDAGNAME:1711// After parsing the first dag argument, expect an index integer.1712ArgType = IntRecTy::get(Records);1713break;1714default:1715break;1716}17171718if (!consume(tgtok::comma))1719break;1720}17211722if (!consume(tgtok::r_paren)) {1723TokError("expected ')' in operator");1724return nullptr;1725}17261727// listconcat returns a list with type of the argument.1728if (Code == BinOpInit::LISTCONCAT)1729Type = ArgType;1730// listsplat returns a list of type of the *first* argument.1731if (Code == BinOpInit::LISTSPLAT)1732Type = cast<TypedInit>(InitList.front())->getType()->getListTy();1733// listremove returns a list with type of the argument.1734if (Code == BinOpInit::LISTREMOVE)1735Type = ArgType;17361737// We allow multiple operands to associative operators like !strconcat as1738// shorthand for nesting them.1739if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT ||1740Code == BinOpInit::CONCAT || Code == BinOpInit::ADD ||1741Code == BinOpInit::AND || Code == BinOpInit::OR ||1742Code == BinOpInit::XOR || Code == BinOpInit::MUL) {1743while (InitList.size() > 2) {1744Init *RHS = InitList.pop_back_val();1745RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec);1746InitList.back() = RHS;1747}1748}17491750if (InitList.size() == 2)1751return (BinOpInit::get(Code, InitList[0], InitList[1], Type))1752->Fold(CurRec);17531754Error(OpLoc, "expected two operands to operator");1755return nullptr;1756}17571758case tgtok::XForEach:1759case tgtok::XFilter: {1760return ParseOperationForEachFilter(CurRec, ItemType);1761}17621763case tgtok::XRange: {1764SMLoc OpLoc = Lex.getLoc();1765Lex.Lex(); // eat the operation17661767if (!consume(tgtok::l_paren)) {1768TokError("expected '(' after !range operator");1769return nullptr;1770}17711772SmallVector<Init *, 2> Args;1773bool FirstArgIsList = false;1774for (;;) {1775if (Args.size() >= 3) {1776TokError("expected at most three values of integer");1777return nullptr;1778}17791780SMLoc InitLoc = Lex.getLoc();1781Args.push_back(ParseValue(CurRec));1782if (!Args.back())1783return nullptr;17841785TypedInit *ArgBack = dyn_cast<TypedInit>(Args.back());1786if (!ArgBack) {1787Error(OpLoc, Twine("expected value to be a typed value, got '" +1788Args.back()->getAsString() + "'"));1789return nullptr;1790}17911792RecTy *ArgBackType = ArgBack->getType();1793if (!FirstArgIsList || Args.size() == 1) {1794if (Args.size() == 1 && isa<ListRecTy>(ArgBackType)) {1795FirstArgIsList = true; // Detect error if 2nd arg were present.1796} else if (isa<IntRecTy>(ArgBackType)) {1797// Assume 2nd arg should be IntRecTy1798} else {1799if (Args.size() != 1)1800Error(InitLoc, Twine("expected value of type 'int', got '" +1801ArgBackType->getAsString() + "'"));1802else1803Error(InitLoc, Twine("expected list or int, got value of type '") +1804ArgBackType->getAsString() + "'");1805return nullptr;1806}1807} else {1808// Don't come here unless 1st arg is ListRecTy.1809assert(isa<ListRecTy>(cast<TypedInit>(Args[0])->getType()));1810Error(InitLoc, Twine("expected one list, got extra value of type '") +1811ArgBackType->getAsString() + "'");1812return nullptr;1813}1814if (!consume(tgtok::comma))1815break;1816}18171818if (!consume(tgtok::r_paren)) {1819TokError("expected ')' in operator");1820return nullptr;1821}18221823Init *LHS, *MHS, *RHS;1824auto ArgCount = Args.size();1825assert(ArgCount >= 1);1826auto *Arg0 = cast<TypedInit>(Args[0]);1827auto *Arg0Ty = Arg0->getType();1828if (ArgCount == 1) {1829if (isa<ListRecTy>(Arg0Ty)) {1830// (0, !size(arg), 1)1831LHS = IntInit::get(Records, 0);1832MHS = UnOpInit::get(UnOpInit::SIZE, Arg0, IntRecTy::get(Records))1833->Fold(CurRec);1834RHS = IntInit::get(Records, 1);1835} else {1836assert(isa<IntRecTy>(Arg0Ty));1837// (0, arg, 1)1838LHS = IntInit::get(Records, 0);1839MHS = Arg0;1840RHS = IntInit::get(Records, 1);1841}1842} else {1843assert(isa<IntRecTy>(Arg0Ty));1844auto *Arg1 = cast<TypedInit>(Args[1]);1845assert(isa<IntRecTy>(Arg1->getType()));1846LHS = Arg0;1847MHS = Arg1;1848if (ArgCount == 3) {1849// (start, end, step)1850auto *Arg2 = cast<TypedInit>(Args[2]);1851assert(isa<IntRecTy>(Arg2->getType()));1852RHS = Arg2;1853} else1854// (start, end, 1)1855RHS = IntInit::get(Records, 1);1856}1857return TernOpInit::get(TernOpInit::RANGE, LHS, MHS, RHS,1858IntRecTy::get(Records)->getListTy())1859->Fold(CurRec);1860}18611862case tgtok::XSetDagArg:1863case tgtok::XSetDagName:1864case tgtok::XDag:1865case tgtok::XIf:1866case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'1867TernOpInit::TernaryOp Code;1868RecTy *Type = nullptr;18691870tgtok::TokKind LexCode = Lex.getCode();1871Lex.Lex(); // eat the operation1872switch (LexCode) {1873default: llvm_unreachable("Unhandled code!");1874case tgtok::XDag:1875Code = TernOpInit::DAG;1876Type = DagRecTy::get(Records);1877ItemType = nullptr;1878break;1879case tgtok::XIf:1880Code = TernOpInit::IF;1881break;1882case tgtok::XSubst:1883Code = TernOpInit::SUBST;1884break;1885case tgtok::XSetDagArg:1886Code = TernOpInit::SETDAGARG;1887Type = DagRecTy::get(Records);1888ItemType = nullptr;1889break;1890case tgtok::XSetDagName:1891Code = TernOpInit::SETDAGNAME;1892Type = DagRecTy::get(Records);1893ItemType = nullptr;1894break;1895}1896if (!consume(tgtok::l_paren)) {1897TokError("expected '(' after ternary operator");1898return nullptr;1899}19001901Init *LHS = ParseValue(CurRec);1902if (!LHS) return nullptr;19031904if (!consume(tgtok::comma)) {1905TokError("expected ',' in ternary operator");1906return nullptr;1907}19081909SMLoc MHSLoc = Lex.getLoc();1910Init *MHS = ParseValue(CurRec, ItemType);1911if (!MHS)1912return nullptr;19131914if (!consume(tgtok::comma)) {1915TokError("expected ',' in ternary operator");1916return nullptr;1917}19181919SMLoc RHSLoc = Lex.getLoc();1920Init *RHS = ParseValue(CurRec, ItemType);1921if (!RHS)1922return nullptr;19231924if (!consume(tgtok::r_paren)) {1925TokError("expected ')' in binary operator");1926return nullptr;1927}19281929switch (LexCode) {1930default: llvm_unreachable("Unhandled code!");1931case tgtok::XDag: {1932TypedInit *MHSt = dyn_cast<TypedInit>(MHS);1933if (!MHSt && !isa<UnsetInit>(MHS)) {1934Error(MHSLoc, "could not determine type of the child list in !dag");1935return nullptr;1936}1937if (MHSt && !isa<ListRecTy>(MHSt->getType())) {1938Error(MHSLoc, Twine("expected list of children, got type '") +1939MHSt->getType()->getAsString() + "'");1940return nullptr;1941}19421943TypedInit *RHSt = dyn_cast<TypedInit>(RHS);1944if (!RHSt && !isa<UnsetInit>(RHS)) {1945Error(RHSLoc, "could not determine type of the name list in !dag");1946return nullptr;1947}1948if (RHSt && StringRecTy::get(Records)->getListTy() != RHSt->getType()) {1949Error(RHSLoc, Twine("expected list<string>, got type '") +1950RHSt->getType()->getAsString() + "'");1951return nullptr;1952}19531954if (!MHSt && !RHSt) {1955Error(MHSLoc,1956"cannot have both unset children and unset names in !dag");1957return nullptr;1958}1959break;1960}1961case tgtok::XIf: {1962RecTy *MHSTy = nullptr;1963RecTy *RHSTy = nullptr;19641965if (TypedInit *MHSt = dyn_cast<TypedInit>(MHS))1966MHSTy = MHSt->getType();1967if (BitsInit *MHSbits = dyn_cast<BitsInit>(MHS))1968MHSTy = BitsRecTy::get(Records, MHSbits->getNumBits());1969if (isa<BitInit>(MHS))1970MHSTy = BitRecTy::get(Records);19711972if (TypedInit *RHSt = dyn_cast<TypedInit>(RHS))1973RHSTy = RHSt->getType();1974if (BitsInit *RHSbits = dyn_cast<BitsInit>(RHS))1975RHSTy = BitsRecTy::get(Records, RHSbits->getNumBits());1976if (isa<BitInit>(RHS))1977RHSTy = BitRecTy::get(Records);19781979// For UnsetInit, it's typed from the other hand.1980if (isa<UnsetInit>(MHS))1981MHSTy = RHSTy;1982if (isa<UnsetInit>(RHS))1983RHSTy = MHSTy;19841985if (!MHSTy || !RHSTy) {1986TokError("could not get type for !if");1987return nullptr;1988}19891990Type = resolveTypes(MHSTy, RHSTy);1991if (!Type) {1992TokError(Twine("inconsistent types '") + MHSTy->getAsString() +1993"' and '" + RHSTy->getAsString() + "' for !if");1994return nullptr;1995}1996break;1997}1998case tgtok::XSubst: {1999TypedInit *RHSt = dyn_cast<TypedInit>(RHS);2000if (!RHSt) {2001TokError("could not get type for !subst");2002return nullptr;2003}2004Type = RHSt->getType();2005break;2006}2007case tgtok::XSetDagArg: {2008TypedInit *MHSt = dyn_cast<TypedInit>(MHS);2009if (!MHSt || !isa<IntRecTy, StringRecTy>(MHSt->getType())) {2010Error(MHSLoc, Twine("expected integer index or string name, got ") +2011(MHSt ? ("type '" + MHSt->getType()->getAsString())2012: ("'" + MHS->getAsString())) +2013"'");2014return nullptr;2015}2016break;2017}2018case tgtok::XSetDagName: {2019TypedInit *MHSt = dyn_cast<TypedInit>(MHS);2020if (!MHSt || !isa<IntRecTy, StringRecTy>(MHSt->getType())) {2021Error(MHSLoc, Twine("expected integer index or string name, got ") +2022(MHSt ? ("type '" + MHSt->getType()->getAsString())2023: ("'" + MHS->getAsString())) +2024"'");2025return nullptr;2026}2027TypedInit *RHSt = dyn_cast<TypedInit>(RHS);2028// The name could be a string or unset.2029if (RHSt && !isa<StringRecTy>(RHSt->getType())) {2030Error(RHSLoc, Twine("expected string or unset name, got type '") +2031RHSt->getType()->getAsString() + "'");2032return nullptr;2033}2034break;2035}2036}2037return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);2038}20392040case tgtok::XSubstr:2041return ParseOperationSubstr(CurRec, ItemType);20422043case tgtok::XFind:2044return ParseOperationFind(CurRec, ItemType);20452046case tgtok::XCond:2047return ParseOperationCond(CurRec, ItemType);20482049case tgtok::XFoldl: {2050// Value ::= !foldl '(' Value ',' Value ',' Id ',' Id ',' Expr ')'2051Lex.Lex(); // eat the operation2052if (!consume(tgtok::l_paren)) {2053TokError("expected '(' after !foldl");2054return nullptr;2055}20562057Init *StartUntyped = ParseValue(CurRec);2058if (!StartUntyped)2059return nullptr;20602061TypedInit *Start = dyn_cast<TypedInit>(StartUntyped);2062if (!Start) {2063TokError(Twine("could not get type of !foldl start: '") +2064StartUntyped->getAsString() + "'");2065return nullptr;2066}20672068if (!consume(tgtok::comma)) {2069TokError("expected ',' in !foldl");2070return nullptr;2071}20722073Init *ListUntyped = ParseValue(CurRec);2074if (!ListUntyped)2075return nullptr;20762077TypedInit *List = dyn_cast<TypedInit>(ListUntyped);2078if (!List) {2079TokError(Twine("could not get type of !foldl list: '") +2080ListUntyped->getAsString() + "'");2081return nullptr;2082}20832084ListRecTy *ListType = dyn_cast<ListRecTy>(List->getType());2085if (!ListType) {2086TokError(Twine("!foldl list must be a list, but is of type '") +2087List->getType()->getAsString());2088return nullptr;2089}20902091if (Lex.getCode() != tgtok::comma) {2092TokError("expected ',' in !foldl");2093return nullptr;2094}20952096if (Lex.Lex() != tgtok::Id) { // eat the ','2097TokError("third argument of !foldl must be an identifier");2098return nullptr;2099}21002101Init *A = StringInit::get(Records, Lex.getCurStrVal());2102if (CurRec && CurRec->getValue(A)) {2103TokError((Twine("left !foldl variable '") + A->getAsString() +2104"' already defined")2105.str());2106return nullptr;2107}21082109if (Lex.Lex() != tgtok::comma) { // eat the id2110TokError("expected ',' in !foldl");2111return nullptr;2112}21132114if (Lex.Lex() != tgtok::Id) { // eat the ','2115TokError("fourth argument of !foldl must be an identifier");2116return nullptr;2117}21182119Init *B = StringInit::get(Records, Lex.getCurStrVal());2120if (CurRec && CurRec->getValue(B)) {2121TokError((Twine("right !foldl variable '") + B->getAsString() +2122"' already defined")2123.str());2124return nullptr;2125}21262127if (Lex.Lex() != tgtok::comma) { // eat the id2128TokError("expected ',' in !foldl");2129return nullptr;2130}2131Lex.Lex(); // eat the ','21322133// We need to create a temporary record to provide a scope for the2134// two variables.2135std::unique_ptr<Record> ParseRecTmp;2136Record *ParseRec = CurRec;2137if (!ParseRec) {2138ParseRecTmp = std::make_unique<Record>(".parse", ArrayRef<SMLoc>{}, Records);2139ParseRec = ParseRecTmp.get();2140}21412142TGVarScope *FoldScope = PushScope(ParseRec);2143ParseRec->addValue(RecordVal(A, Start->getType(), RecordVal::FK_Normal));2144ParseRec->addValue(2145RecordVal(B, ListType->getElementType(), RecordVal::FK_Normal));2146Init *ExprUntyped = ParseValue(ParseRec);2147ParseRec->removeValue(A);2148ParseRec->removeValue(B);2149PopScope(FoldScope);2150if (!ExprUntyped)2151return nullptr;21522153TypedInit *Expr = dyn_cast<TypedInit>(ExprUntyped);2154if (!Expr) {2155TokError("could not get type of !foldl expression");2156return nullptr;2157}21582159if (Expr->getType() != Start->getType()) {2160TokError(Twine("!foldl expression must be of same type as start (") +2161Start->getType()->getAsString() + "), but is of type " +2162Expr->getType()->getAsString());2163return nullptr;2164}21652166if (!consume(tgtok::r_paren)) {2167TokError("expected ')' in fold operator");2168return nullptr;2169}21702171return FoldOpInit::get(Start, List, A, B, Expr, Start->getType())2172->Fold(CurRec);2173}2174}2175}21762177/// ParseOperatorType - Parse a type for an operator. This returns2178/// null on error.2179///2180/// OperatorType ::= '<' Type '>'2181///2182RecTy *TGParser::ParseOperatorType() {2183RecTy *Type = nullptr;21842185if (!consume(tgtok::less)) {2186TokError("expected type name for operator");2187return nullptr;2188}21892190if (Lex.getCode() == tgtok::Code)2191TokError("the 'code' type is not allowed in bang operators; use 'string'");21922193Type = ParseType();21942195if (!Type) {2196TokError("expected type name for operator");2197return nullptr;2198}21992200if (!consume(tgtok::greater)) {2201TokError("expected type name for operator");2202return nullptr;2203}22042205return Type;2206}22072208/// Parse the !substr operation. Return null on error.2209///2210/// Substr ::= !substr(string, start-int [, length-int]) => string2211Init *TGParser::ParseOperationSubstr(Record *CurRec, RecTy *ItemType) {2212TernOpInit::TernaryOp Code = TernOpInit::SUBSTR;2213RecTy *Type = StringRecTy::get(Records);22142215Lex.Lex(); // eat the operation22162217if (!consume(tgtok::l_paren)) {2218TokError("expected '(' after !substr operator");2219return nullptr;2220}22212222Init *LHS = ParseValue(CurRec);2223if (!LHS)2224return nullptr;22252226if (!consume(tgtok::comma)) {2227TokError("expected ',' in !substr operator");2228return nullptr;2229}22302231SMLoc MHSLoc = Lex.getLoc();2232Init *MHS = ParseValue(CurRec);2233if (!MHS)2234return nullptr;22352236SMLoc RHSLoc = Lex.getLoc();2237Init *RHS;2238if (consume(tgtok::comma)) {2239RHSLoc = Lex.getLoc();2240RHS = ParseValue(CurRec);2241if (!RHS)2242return nullptr;2243} else {2244RHS = IntInit::get(Records, std::numeric_limits<int64_t>::max());2245}22462247if (!consume(tgtok::r_paren)) {2248TokError("expected ')' in !substr operator");2249return nullptr;2250}22512252if (ItemType && !Type->typeIsConvertibleTo(ItemType)) {2253Error(RHSLoc, Twine("expected value of type '") +2254ItemType->getAsString() + "', got '" +2255Type->getAsString() + "'");2256}22572258TypedInit *LHSt = dyn_cast<TypedInit>(LHS);2259if (!LHSt && !isa<UnsetInit>(LHS)) {2260TokError("could not determine type of the string in !substr");2261return nullptr;2262}2263if (LHSt && !isa<StringRecTy>(LHSt->getType())) {2264TokError(Twine("expected string, got type '") +2265LHSt->getType()->getAsString() + "'");2266return nullptr;2267}22682269TypedInit *MHSt = dyn_cast<TypedInit>(MHS);2270if (!MHSt && !isa<UnsetInit>(MHS)) {2271TokError("could not determine type of the start position in !substr");2272return nullptr;2273}2274if (MHSt && !isa<IntRecTy>(MHSt->getType())) {2275Error(MHSLoc, Twine("expected int, got type '") +2276MHSt->getType()->getAsString() + "'");2277return nullptr;2278}22792280if (RHS) {2281TypedInit *RHSt = dyn_cast<TypedInit>(RHS);2282if (!RHSt && !isa<UnsetInit>(RHS)) {2283TokError("could not determine type of the length in !substr");2284return nullptr;2285}2286if (RHSt && !isa<IntRecTy>(RHSt->getType())) {2287TokError(Twine("expected int, got type '") +2288RHSt->getType()->getAsString() + "'");2289return nullptr;2290}2291}22922293return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);2294}22952296/// Parse the !find operation. Return null on error.2297///2298/// Substr ::= !find(string, string [, start-int]) => int2299Init *TGParser::ParseOperationFind(Record *CurRec, RecTy *ItemType) {2300TernOpInit::TernaryOp Code = TernOpInit::FIND;2301RecTy *Type = IntRecTy::get(Records);23022303Lex.Lex(); // eat the operation23042305if (!consume(tgtok::l_paren)) {2306TokError("expected '(' after !find operator");2307return nullptr;2308}23092310Init *LHS = ParseValue(CurRec);2311if (!LHS)2312return nullptr;23132314if (!consume(tgtok::comma)) {2315TokError("expected ',' in !find operator");2316return nullptr;2317}23182319SMLoc MHSLoc = Lex.getLoc();2320Init *MHS = ParseValue(CurRec);2321if (!MHS)2322return nullptr;23232324SMLoc RHSLoc = Lex.getLoc();2325Init *RHS;2326if (consume(tgtok::comma)) {2327RHSLoc = Lex.getLoc();2328RHS = ParseValue(CurRec);2329if (!RHS)2330return nullptr;2331} else {2332RHS = IntInit::get(Records, 0);2333}23342335if (!consume(tgtok::r_paren)) {2336TokError("expected ')' in !find operator");2337return nullptr;2338}23392340if (ItemType && !Type->typeIsConvertibleTo(ItemType)) {2341Error(RHSLoc, Twine("expected value of type '") +2342ItemType->getAsString() + "', got '" +2343Type->getAsString() + "'");2344}23452346TypedInit *LHSt = dyn_cast<TypedInit>(LHS);2347if (!LHSt && !isa<UnsetInit>(LHS)) {2348TokError("could not determine type of the source string in !find");2349return nullptr;2350}2351if (LHSt && !isa<StringRecTy>(LHSt->getType())) {2352TokError(Twine("expected string, got type '") +2353LHSt->getType()->getAsString() + "'");2354return nullptr;2355}23562357TypedInit *MHSt = dyn_cast<TypedInit>(MHS);2358if (!MHSt && !isa<UnsetInit>(MHS)) {2359TokError("could not determine type of the target string in !find");2360return nullptr;2361}2362if (MHSt && !isa<StringRecTy>(MHSt->getType())) {2363Error(MHSLoc, Twine("expected string, got type '") +2364MHSt->getType()->getAsString() + "'");2365return nullptr;2366}23672368if (RHS) {2369TypedInit *RHSt = dyn_cast<TypedInit>(RHS);2370if (!RHSt && !isa<UnsetInit>(RHS)) {2371TokError("could not determine type of the start position in !find");2372return nullptr;2373}2374if (RHSt && !isa<IntRecTy>(RHSt->getType())) {2375TokError(Twine("expected int, got type '") +2376RHSt->getType()->getAsString() + "'");2377return nullptr;2378}2379}23802381return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);2382}23832384/// Parse the !foreach and !filter operations. Return null on error.2385///2386/// ForEach ::= !foreach(ID, list-or-dag, expr) => list<expr type>2387/// Filter ::= !foreach(ID, list, predicate) ==> list<list type>2388Init *TGParser::ParseOperationForEachFilter(Record *CurRec, RecTy *ItemType) {2389SMLoc OpLoc = Lex.getLoc();2390tgtok::TokKind Operation = Lex.getCode();2391Lex.Lex(); // eat the operation2392if (Lex.getCode() != tgtok::l_paren) {2393TokError("expected '(' after !foreach/!filter");2394return nullptr;2395}23962397if (Lex.Lex() != tgtok::Id) { // eat the '('2398TokError("first argument of !foreach/!filter must be an identifier");2399return nullptr;2400}24012402Init *LHS = StringInit::get(Records, Lex.getCurStrVal());2403Lex.Lex(); // eat the ID.24042405if (CurRec && CurRec->getValue(LHS)) {2406TokError((Twine("iteration variable '") + LHS->getAsString() +2407"' is already defined")2408.str());2409return nullptr;2410}24112412if (!consume(tgtok::comma)) {2413TokError("expected ',' in !foreach/!filter");2414return nullptr;2415}24162417Init *MHS = ParseValue(CurRec);2418if (!MHS)2419return nullptr;24202421if (!consume(tgtok::comma)) {2422TokError("expected ',' in !foreach/!filter");2423return nullptr;2424}24252426TypedInit *MHSt = dyn_cast<TypedInit>(MHS);2427if (!MHSt) {2428TokError("could not get type of !foreach/!filter list or dag");2429return nullptr;2430}24312432RecTy *InEltType = nullptr;2433RecTy *ExprEltType = nullptr;2434bool IsDAG = false;24352436if (ListRecTy *InListTy = dyn_cast<ListRecTy>(MHSt->getType())) {2437InEltType = InListTy->getElementType();2438if (ItemType) {2439if (ListRecTy *OutListTy = dyn_cast<ListRecTy>(ItemType)) {2440ExprEltType = (Operation == tgtok::XForEach)2441? OutListTy->getElementType()2442: IntRecTy::get(Records);2443} else {2444Error(OpLoc,2445"expected value of type '" +2446Twine(ItemType->getAsString()) +2447"', but got list type");2448return nullptr;2449}2450}2451} else if (DagRecTy *InDagTy = dyn_cast<DagRecTy>(MHSt->getType())) {2452if (Operation == tgtok::XFilter) {2453TokError("!filter must have a list argument");2454return nullptr;2455}2456InEltType = InDagTy;2457if (ItemType && !isa<DagRecTy>(ItemType)) {2458Error(OpLoc,2459"expected value of type '" + Twine(ItemType->getAsString()) +2460"', but got dag type");2461return nullptr;2462}2463IsDAG = true;2464} else {2465if (Operation == tgtok::XForEach)2466TokError("!foreach must have a list or dag argument");2467else2468TokError("!filter must have a list argument");2469return nullptr;2470}24712472// We need to create a temporary record to provide a scope for the2473// iteration variable.2474std::unique_ptr<Record> ParseRecTmp;2475Record *ParseRec = CurRec;2476if (!ParseRec) {2477ParseRecTmp =2478std::make_unique<Record>(".parse", ArrayRef<SMLoc>{}, Records);2479ParseRec = ParseRecTmp.get();2480}2481TGVarScope *TempScope = PushScope(ParseRec);2482ParseRec->addValue(RecordVal(LHS, InEltType, RecordVal::FK_Normal));2483Init *RHS = ParseValue(ParseRec, ExprEltType);2484ParseRec->removeValue(LHS);2485PopScope(TempScope);2486if (!RHS)2487return nullptr;24882489if (!consume(tgtok::r_paren)) {2490TokError("expected ')' in !foreach/!filter");2491return nullptr;2492}24932494RecTy *OutType = InEltType;2495if (Operation == tgtok::XForEach && !IsDAG) {2496TypedInit *RHSt = dyn_cast<TypedInit>(RHS);2497if (!RHSt) {2498TokError("could not get type of !foreach result expression");2499return nullptr;2500}2501OutType = RHSt->getType()->getListTy();2502} else if (Operation == tgtok::XFilter) {2503OutType = InEltType->getListTy();2504}25052506return (TernOpInit::get((Operation == tgtok::XForEach) ? TernOpInit::FOREACH2507: TernOpInit::FILTER,2508LHS, MHS, RHS, OutType))2509->Fold(CurRec);2510}25112512Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) {2513Lex.Lex(); // eat the operation 'cond'25142515if (!consume(tgtok::l_paren)) {2516TokError("expected '(' after !cond operator");2517return nullptr;2518}25192520// Parse through '[Case: Val,]+'2521SmallVector<Init *, 4> Case;2522SmallVector<Init *, 4> Val;2523while (true) {2524if (consume(tgtok::r_paren))2525break;25262527Init *V = ParseValue(CurRec);2528if (!V)2529return nullptr;2530Case.push_back(V);25312532if (!consume(tgtok::colon)) {2533TokError("expected ':' following a condition in !cond operator");2534return nullptr;2535}25362537V = ParseValue(CurRec, ItemType);2538if (!V)2539return nullptr;2540Val.push_back(V);25412542if (consume(tgtok::r_paren))2543break;25442545if (!consume(tgtok::comma)) {2546TokError("expected ',' or ')' following a value in !cond operator");2547return nullptr;2548}2549}25502551if (Case.size() < 1) {2552TokError("there should be at least 1 'condition : value' in the !cond operator");2553return nullptr;2554}25552556// resolve type2557RecTy *Type = nullptr;2558for (Init *V : Val) {2559RecTy *VTy = nullptr;2560if (TypedInit *Vt = dyn_cast<TypedInit>(V))2561VTy = Vt->getType();2562if (BitsInit *Vbits = dyn_cast<BitsInit>(V))2563VTy = BitsRecTy::get(Records, Vbits->getNumBits());2564if (isa<BitInit>(V))2565VTy = BitRecTy::get(Records);25662567if (Type == nullptr) {2568if (!isa<UnsetInit>(V))2569Type = VTy;2570} else {2571if (!isa<UnsetInit>(V)) {2572RecTy *RType = resolveTypes(Type, VTy);2573if (!RType) {2574TokError(Twine("inconsistent types '") + Type->getAsString() +2575"' and '" + VTy->getAsString() + "' for !cond");2576return nullptr;2577}2578Type = RType;2579}2580}2581}25822583if (!Type) {2584TokError("could not determine type for !cond from its arguments");2585return nullptr;2586}2587return CondOpInit::get(Case, Val, Type)->Fold(CurRec);2588}25892590/// ParseSimpleValue - Parse a tblgen value. This returns null on error.2591///2592/// SimpleValue ::= IDValue2593/// SimpleValue ::= INTVAL2594/// SimpleValue ::= STRVAL+2595/// SimpleValue ::= CODEFRAGMENT2596/// SimpleValue ::= '?'2597/// SimpleValue ::= '{' ValueList '}'2598/// SimpleValue ::= ID '<' ValueListNE '>'2599/// SimpleValue ::= '[' ValueList ']'2600/// SimpleValue ::= '(' IDValue DagArgList ')'2601/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'2602/// SimpleValue ::= ADDTOK '(' Value ',' Value ')'2603/// SimpleValue ::= DIVTOK '(' Value ',' Value ')'2604/// SimpleValue ::= SUBTOK '(' Value ',' Value ')'2605/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'2606/// SimpleValue ::= SRATOK '(' Value ',' Value ')'2607/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'2608/// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'2609/// SimpleValue ::= LISTSPLATTOK '(' Value ',' Value ')'2610/// SimpleValue ::= LISTREMOVETOK '(' Value ',' Value ')'2611/// SimpleValue ::= RANGE '(' Value ')'2612/// SimpleValue ::= RANGE '(' Value ',' Value ')'2613/// SimpleValue ::= RANGE '(' Value ',' Value ',' Value ')'2614/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'2615/// SimpleValue ::= COND '(' [Value ':' Value,]+ ')'2616///2617Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,2618IDParseMode Mode) {2619Init *R = nullptr;2620tgtok::TokKind Code = Lex.getCode();26212622// Parse bang operators.2623if (tgtok::isBangOperator(Code))2624return ParseOperation(CurRec, ItemType);26252626switch (Code) {2627default: TokError("Unknown or reserved token when parsing a value"); break;26282629case tgtok::TrueVal:2630R = IntInit::get(Records, 1);2631Lex.Lex();2632break;2633case tgtok::FalseVal:2634R = IntInit::get(Records, 0);2635Lex.Lex();2636break;2637case tgtok::IntVal:2638R = IntInit::get(Records, Lex.getCurIntVal());2639Lex.Lex();2640break;2641case tgtok::BinaryIntVal: {2642auto BinaryVal = Lex.getCurBinaryIntVal();2643SmallVector<Init*, 16> Bits(BinaryVal.second);2644for (unsigned i = 0, e = BinaryVal.second; i != e; ++i)2645Bits[i] = BitInit::get(Records, BinaryVal.first & (1LL << i));2646R = BitsInit::get(Records, Bits);2647Lex.Lex();2648break;2649}2650case tgtok::StrVal: {2651std::string Val = Lex.getCurStrVal();2652Lex.Lex();26532654// Handle multiple consecutive concatenated strings.2655while (Lex.getCode() == tgtok::StrVal) {2656Val += Lex.getCurStrVal();2657Lex.Lex();2658}26592660R = StringInit::get(Records, Val);2661break;2662}2663case tgtok::CodeFragment:2664R = StringInit::get(Records, Lex.getCurStrVal(), StringInit::SF_Code);2665Lex.Lex();2666break;2667case tgtok::question:2668R = UnsetInit::get(Records);2669Lex.Lex();2670break;2671case tgtok::Id: {2672SMRange NameLoc = Lex.getLocRange();2673StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());2674tgtok::TokKind Next = Lex.Lex();2675if (Next == tgtok::equal) // Named argument.2676return Name;2677if (Next != tgtok::less) // consume the Id.2678return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue26792680// Value ::= CLASSID '<' ArgValueList '>' (CLASSID has been consumed)2681// This is supposed to synthesize a new anonymous definition, deriving2682// from the class with the template arguments, but no body.2683Record *Class = Records.getClass(Name->getValue());2684if (!Class) {2685Error(NameLoc.Start,2686"Expected a class name, got '" + Name->getValue() + "'");2687return nullptr;2688}26892690SmallVector<ArgumentInit *, 8> Args;2691Lex.Lex(); // consume the <2692if (ParseTemplateArgValueList(Args, CurRec, Class))2693return nullptr; // Error parsing value list.26942695if (CheckTemplateArgValues(Args, NameLoc.Start, Class))2696return nullptr; // Error checking template argument values.26972698if (resolveArguments(Class, Args, NameLoc.Start))2699return nullptr;27002701if (TrackReferenceLocs)2702Class->appendReferenceLoc(NameLoc);2703return VarDefInit::get(Class, Args)->Fold();2704}2705case tgtok::l_brace: { // Value ::= '{' ValueList '}'2706SMLoc BraceLoc = Lex.getLoc();2707Lex.Lex(); // eat the '{'2708SmallVector<Init*, 16> Vals;27092710if (Lex.getCode() != tgtok::r_brace) {2711ParseValueList(Vals, CurRec);2712if (Vals.empty()) return nullptr;2713}2714if (!consume(tgtok::r_brace)) {2715TokError("expected '}' at end of bit list value");2716return nullptr;2717}27182719SmallVector<Init *, 16> NewBits;27202721// As we parse { a, b, ... }, 'a' is the highest bit, but we parse it2722// first. We'll first read everything in to a vector, then we can reverse2723// it to get the bits in the correct order for the BitsInit value.2724for (unsigned i = 0, e = Vals.size(); i != e; ++i) {2725// FIXME: The following two loops would not be duplicated2726// if the API was a little more orthogonal.27272728// bits<n> values are allowed to initialize n bits.2729if (BitsInit *BI = dyn_cast<BitsInit>(Vals[i])) {2730for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)2731NewBits.push_back(BI->getBit((e - i) - 1));2732continue;2733}2734// bits<n> can also come from variable initializers.2735if (VarInit *VI = dyn_cast<VarInit>(Vals[i])) {2736if (BitsRecTy *BitsRec = dyn_cast<BitsRecTy>(VI->getType())) {2737for (unsigned i = 0, e = BitsRec->getNumBits(); i != e; ++i)2738NewBits.push_back(VI->getBit((e - i) - 1));2739continue;2740}2741// Fallthrough to try convert this to a bit.2742}2743// All other values must be convertible to just a single bit.2744Init *Bit = Vals[i]->getCastTo(BitRecTy::get(Records));2745if (!Bit) {2746Error(BraceLoc, "Element #" + Twine(i) + " (" + Vals[i]->getAsString() +2747") is not convertable to a bit");2748return nullptr;2749}2750NewBits.push_back(Bit);2751}2752std::reverse(NewBits.begin(), NewBits.end());2753return BitsInit::get(Records, NewBits);2754}2755case tgtok::l_square: { // Value ::= '[' ValueList ']'2756Lex.Lex(); // eat the '['2757SmallVector<Init*, 16> Vals;27582759RecTy *DeducedEltTy = nullptr;2760ListRecTy *GivenListTy = nullptr;27612762if (ItemType) {2763ListRecTy *ListType = dyn_cast<ListRecTy>(ItemType);2764if (!ListType) {2765TokError(Twine("Encountered a list when expecting a ") +2766ItemType->getAsString());2767return nullptr;2768}2769GivenListTy = ListType;2770}27712772if (Lex.getCode() != tgtok::r_square) {2773ParseValueList(Vals, CurRec,2774GivenListTy ? GivenListTy->getElementType() : nullptr);2775if (Vals.empty()) return nullptr;2776}2777if (!consume(tgtok::r_square)) {2778TokError("expected ']' at end of list value");2779return nullptr;2780}27812782RecTy *GivenEltTy = nullptr;2783if (consume(tgtok::less)) {2784// Optional list element type2785GivenEltTy = ParseType();2786if (!GivenEltTy) {2787// Couldn't parse element type2788return nullptr;2789}27902791if (!consume(tgtok::greater)) {2792TokError("expected '>' at end of list element type");2793return nullptr;2794}2795}27962797// Check elements2798RecTy *EltTy = nullptr;2799for (Init *V : Vals) {2800TypedInit *TArg = dyn_cast<TypedInit>(V);2801if (TArg) {2802if (EltTy) {2803EltTy = resolveTypes(EltTy, TArg->getType());2804if (!EltTy) {2805TokError("Incompatible types in list elements");2806return nullptr;2807}2808} else {2809EltTy = TArg->getType();2810}2811}2812}28132814if (GivenEltTy) {2815if (EltTy) {2816// Verify consistency2817if (!EltTy->typeIsConvertibleTo(GivenEltTy)) {2818TokError("Incompatible types in list elements");2819return nullptr;2820}2821}2822EltTy = GivenEltTy;2823}28242825if (!EltTy) {2826if (!ItemType) {2827TokError("No type for list");2828return nullptr;2829}2830DeducedEltTy = GivenListTy->getElementType();2831} else {2832// Make sure the deduced type is compatible with the given type2833if (GivenListTy) {2834if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) {2835TokError(Twine("Element type mismatch for list: element type '") +2836EltTy->getAsString() + "' not convertible to '" +2837GivenListTy->getElementType()->getAsString());2838return nullptr;2839}2840}2841DeducedEltTy = EltTy;2842}28432844return ListInit::get(Vals, DeducedEltTy);2845}2846case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'2847Lex.Lex(); // eat the '('2848if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast &&2849Lex.getCode() != tgtok::question && Lex.getCode() != tgtok::XGetDagOp) {2850TokError("expected identifier in dag init");2851return nullptr;2852}28532854Init *Operator = ParseValue(CurRec);2855if (!Operator) return nullptr;28562857// If the operator name is present, parse it.2858StringInit *OperatorName = nullptr;2859if (consume(tgtok::colon)) {2860if (Lex.getCode() != tgtok::VarName) { // eat the ':'2861TokError("expected variable name in dag operator");2862return nullptr;2863}2864OperatorName = StringInit::get(Records, Lex.getCurStrVal());2865Lex.Lex(); // eat the VarName.2866}28672868SmallVector<std::pair<llvm::Init*, StringInit*>, 8> DagArgs;2869if (Lex.getCode() != tgtok::r_paren) {2870ParseDagArgList(DagArgs, CurRec);2871if (DagArgs.empty()) return nullptr;2872}28732874if (!consume(tgtok::r_paren)) {2875TokError("expected ')' in dag init");2876return nullptr;2877}28782879return DagInit::get(Operator, OperatorName, DagArgs);2880}2881}28822883return R;2884}28852886/// ParseValue - Parse a TableGen value. This returns null on error.2887///2888/// Value ::= SimpleValue ValueSuffix*2889/// ValueSuffix ::= '{' BitList '}'2890/// ValueSuffix ::= '[' SliceElements ']'2891/// ValueSuffix ::= '.' ID2892///2893Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {2894SMLoc LHSLoc = Lex.getLoc();2895Init *Result = ParseSimpleValue(CurRec, ItemType, Mode);2896if (!Result) return nullptr;28972898// Parse the suffixes now if present.2899while (true) {2900switch (Lex.getCode()) {2901default: return Result;2902case tgtok::l_brace: {2903if (Mode == ParseNameMode)2904// This is the beginning of the object body.2905return Result;29062907SMLoc CurlyLoc = Lex.getLoc();2908Lex.Lex(); // eat the '{'2909SmallVector<unsigned, 16> Ranges;2910ParseRangeList(Ranges);2911if (Ranges.empty()) return nullptr;29122913// Reverse the bitlist.2914std::reverse(Ranges.begin(), Ranges.end());2915Result = Result->convertInitializerBitRange(Ranges);2916if (!Result) {2917Error(CurlyLoc, "Invalid bit range for value");2918return nullptr;2919}29202921// Eat the '}'.2922if (!consume(tgtok::r_brace)) {2923TokError("expected '}' at end of bit range list");2924return nullptr;2925}2926break;2927}2928case tgtok::l_square: {2929auto *LHS = dyn_cast<TypedInit>(Result);2930if (!LHS) {2931Error(LHSLoc, "Invalid value, list expected");2932return nullptr;2933}29342935auto *LHSTy = dyn_cast<ListRecTy>(LHS->getType());2936if (!LHSTy) {2937Error(LHSLoc, "Type '" + Twine(LHS->getType()->getAsString()) +2938"' is invalid, list expected");2939return nullptr;2940}29412942Lex.Lex(); // eat the '['2943TypedInit *RHS = ParseSliceElements(CurRec, /*Single=*/true);2944if (!RHS)2945return nullptr;29462947if (isa<ListRecTy>(RHS->getType())) {2948Result =2949BinOpInit::get(BinOpInit::LISTSLICE, LHS, RHS, LHSTy)->Fold(CurRec);2950} else {2951Result = BinOpInit::get(BinOpInit::LISTELEM, LHS, RHS,2952LHSTy->getElementType())2953->Fold(CurRec);2954}29552956assert(Result);29572958// Eat the ']'.2959if (!consume(tgtok::r_square)) {2960TokError("expected ']' at end of list slice");2961return nullptr;2962}2963break;2964}2965case tgtok::dot: {2966if (Lex.Lex() != tgtok::Id) { // eat the .2967TokError("expected field identifier after '.'");2968return nullptr;2969}2970SMRange FieldNameLoc = Lex.getLocRange();2971StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());2972if (!Result->getFieldType(FieldName)) {2973TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +2974Result->getAsString() + "'");2975return nullptr;2976}29772978// Add a reference to this field if we know the record class.2979if (TrackReferenceLocs) {2980if (auto *DI = dyn_cast<DefInit>(Result)) {2981DI->getDef()->getValue(FieldName)->addReferenceLoc(FieldNameLoc);2982} else if (auto *TI = dyn_cast<TypedInit>(Result)) {2983if (auto *RecTy = dyn_cast<RecordRecTy>(TI->getType())) {2984for (Record *R : RecTy->getClasses())2985if (auto *RV = R->getValue(FieldName))2986RV->addReferenceLoc(FieldNameLoc);2987}2988}2989}29902991Result = FieldInit::get(Result, FieldName)->Fold(CurRec);2992Lex.Lex(); // eat field name2993break;2994}29952996case tgtok::paste:2997SMLoc PasteLoc = Lex.getLoc();2998TypedInit *LHS = dyn_cast<TypedInit>(Result);2999if (!LHS) {3000Error(PasteLoc, "LHS of paste is not typed!");3001return nullptr;3002}30033004// Check if it's a 'listA # listB'3005if (isa<ListRecTy>(LHS->getType())) {3006Lex.Lex(); // Eat the '#'.30073008assert(Mode == ParseValueMode && "encountered paste of lists in name");30093010switch (Lex.getCode()) {3011case tgtok::colon:3012case tgtok::semi:3013case tgtok::l_brace:3014Result = LHS; // trailing paste, ignore.3015break;3016default:3017Init *RHSResult = ParseValue(CurRec, ItemType, ParseValueMode);3018if (!RHSResult)3019return nullptr;3020Result = BinOpInit::getListConcat(LHS, RHSResult);3021break;3022}3023break;3024}30253026// Create a !strconcat() operation, first casting each operand to3027// a string if necessary.3028if (LHS->getType() != StringRecTy::get(Records)) {3029auto CastLHS = dyn_cast<TypedInit>(3030UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get(Records))3031->Fold(CurRec));3032if (!CastLHS) {3033Error(PasteLoc,3034Twine("can't cast '") + LHS->getAsString() + "' to string");3035return nullptr;3036}3037LHS = CastLHS;3038}30393040TypedInit *RHS = nullptr;30413042Lex.Lex(); // Eat the '#'.3043switch (Lex.getCode()) {3044case tgtok::colon:3045case tgtok::semi:3046case tgtok::l_brace:3047// These are all of the tokens that can begin an object body.3048// Some of these can also begin values but we disallow those cases3049// because they are unlikely to be useful.30503051// Trailing paste, concat with an empty string.3052RHS = StringInit::get(Records, "");3053break;30543055default:3056Init *RHSResult = ParseValue(CurRec, nullptr, ParseNameMode);3057if (!RHSResult)3058return nullptr;3059RHS = dyn_cast<TypedInit>(RHSResult);3060if (!RHS) {3061Error(PasteLoc, "RHS of paste is not typed!");3062return nullptr;3063}30643065if (RHS->getType() != StringRecTy::get(Records)) {3066auto CastRHS = dyn_cast<TypedInit>(3067UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get(Records))3068->Fold(CurRec));3069if (!CastRHS) {3070Error(PasteLoc,3071Twine("can't cast '") + RHS->getAsString() + "' to string");3072return nullptr;3073}3074RHS = CastRHS;3075}30763077break;3078}30793080Result = BinOpInit::getStrConcat(LHS, RHS);3081break;3082}3083}3084}30853086/// ParseDagArgList - Parse the argument list for a dag literal expression.3087///3088/// DagArg ::= Value (':' VARNAME)?3089/// DagArg ::= VARNAME3090/// DagArgList ::= DagArg3091/// DagArgList ::= DagArgList ',' DagArg3092void TGParser::ParseDagArgList(3093SmallVectorImpl<std::pair<llvm::Init*, StringInit*>> &Result,3094Record *CurRec) {30953096while (true) {3097// DagArg ::= VARNAME3098if (Lex.getCode() == tgtok::VarName) {3099// A missing value is treated like '?'.3100StringInit *VarName = StringInit::get(Records, Lex.getCurStrVal());3101Result.emplace_back(UnsetInit::get(Records), VarName);3102Lex.Lex();3103} else {3104// DagArg ::= Value (':' VARNAME)?3105Init *Val = ParseValue(CurRec);3106if (!Val) {3107Result.clear();3108return;3109}31103111// If the variable name is present, add it.3112StringInit *VarName = nullptr;3113if (Lex.getCode() == tgtok::colon) {3114if (Lex.Lex() != tgtok::VarName) { // eat the ':'3115TokError("expected variable name in dag literal");3116Result.clear();3117return;3118}3119VarName = StringInit::get(Records, Lex.getCurStrVal());3120Lex.Lex(); // eat the VarName.3121}31223123Result.push_back(std::make_pair(Val, VarName));3124}3125if (!consume(tgtok::comma))3126break;3127}3128}31293130/// ParseValueList - Parse a comma separated list of values, returning them3131/// in a vector. Note that this always expects to be able to parse at least one3132/// value. It returns an empty list if this is not possible.3133///3134/// ValueList ::= Value (',' Value)3135///3136void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec,3137RecTy *ItemType) {31383139Result.push_back(ParseValue(CurRec, ItemType));3140if (!Result.back()) {3141Result.clear();3142return;3143}31443145while (consume(tgtok::comma)) {3146// ignore trailing comma for lists3147if (Lex.getCode() == tgtok::r_square)3148return;3149Result.push_back(ParseValue(CurRec, ItemType));3150if (!Result.back()) {3151Result.clear();3152return;3153}3154}3155}31563157// ParseTemplateArgValueList - Parse a template argument list with the syntax3158// shown, filling in the Result vector. The open angle has been consumed.3159// An empty argument list is allowed. Return false if okay, true if an3160// error was detected.3161//3162// ArgValueList ::= '<' PostionalArgValueList [','] NamedArgValueList '>'3163// PostionalArgValueList ::= [Value {',' Value}*]3164// NamedArgValueList ::= [NameValue '=' Value {',' NameValue '=' Value}*]3165bool TGParser::ParseTemplateArgValueList(3166SmallVectorImpl<ArgumentInit *> &Result, Record *CurRec, Record *ArgsRec) {3167assert(Result.empty() && "Result vector is not empty");3168ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();31693170if (consume(tgtok::greater)) // empty value list3171return false;31723173bool HasNamedArg = false;3174unsigned ArgIndex = 0;3175while (true) {3176if (ArgIndex >= TArgs.size()) {3177TokError("Too many template arguments: " + utostr(ArgIndex + 1));3178return true;3179}31803181SMLoc ValueLoc = Lex.getLoc();3182// If we are parsing named argument, we don't need to know the argument name3183// and argument type will be resolved after we know the name.3184Init *Value = ParseValue(3185CurRec,3186HasNamedArg ? nullptr : ArgsRec->getValue(TArgs[ArgIndex])->getType());3187if (!Value)3188return true;31893190// If we meet '=', then we are parsing named arguments.3191if (Lex.getCode() == tgtok::equal) {3192if (!isa<StringInit>(Value))3193return Error(ValueLoc,3194"The name of named argument should be a valid identifier");31953196auto *Name = cast<StringInit>(Value);3197Init *QualifiedName = QualifyName(*ArgsRec, Name);3198auto *NamedArg = ArgsRec->getValue(QualifiedName);3199if (!NamedArg)3200return Error(ValueLoc,3201"Argument " + Name->getAsString() + " doesn't exist");32023203Lex.Lex(); // eat the '='.3204ValueLoc = Lex.getLoc();3205Value = ParseValue(CurRec, NamedArg->getType());3206// Named value can't be uninitialized.3207if (isa<UnsetInit>(Value))3208return Error(ValueLoc,3209"The value of named argument should be initialized, "3210"but we got '" +3211Value->getAsString() + "'");32123213Result.push_back(ArgumentInit::get(Value, QualifiedName));3214HasNamedArg = true;3215} else {3216// Positional arguments should be put before named arguments.3217if (HasNamedArg)3218return Error(ValueLoc,3219"Positional argument should be put before named argument");32203221Result.push_back(ArgumentInit::get(Value, ArgIndex));3222}32233224if (consume(tgtok::greater)) // end of argument list?3225return false;3226if (!consume(tgtok::comma))3227return TokError("Expected comma before next argument");3228++ArgIndex;3229}3230}32313232/// ParseDeclaration - Read a declaration, returning the name of field ID, or an3233/// empty string on error. This can happen in a number of different contexts,3234/// including within a def or in the template args for a class (in which case3235/// CurRec will be non-null) and within the template args for a multiclass (in3236/// which case CurRec will be null, but CurMultiClass will be set). This can3237/// also happen within a def that is within a multiclass, which will set both3238/// CurRec and CurMultiClass.3239///3240/// Declaration ::= FIELD? Type ID ('=' Value)?3241///3242Init *TGParser::ParseDeclaration(Record *CurRec,3243bool ParsingTemplateArgs) {3244// Read the field prefix if present.3245bool HasField = consume(tgtok::Field);32463247RecTy *Type = ParseType();3248if (!Type) return nullptr;32493250if (Lex.getCode() != tgtok::Id) {3251TokError("Expected identifier in declaration");3252return nullptr;3253}32543255std::string Str = Lex.getCurStrVal();3256if (Str == "NAME") {3257TokError("'" + Str + "' is a reserved variable name");3258return nullptr;3259}32603261if (!ParsingTemplateArgs && CurScope->varAlreadyDefined(Str)) {3262TokError("local variable of this name already exists");3263return nullptr;3264}32653266SMLoc IdLoc = Lex.getLoc();3267Init *DeclName = StringInit::get(Records, Str);3268Lex.Lex();32693270bool BadField;3271if (!ParsingTemplateArgs) { // def, possibly in a multiclass3272BadField = AddValue(CurRec, IdLoc,3273RecordVal(DeclName, IdLoc, Type,3274HasField ? RecordVal::FK_NonconcreteOK3275: RecordVal::FK_Normal));3276} else if (CurRec) { // class template argument3277DeclName = QualifyName(*CurRec, DeclName);3278BadField =3279AddValue(CurRec, IdLoc,3280RecordVal(DeclName, IdLoc, Type, RecordVal::FK_TemplateArg));3281} else { // multiclass template argument3282assert(CurMultiClass && "invalid context for template argument");3283DeclName = QualifyName(CurMultiClass, DeclName);3284BadField =3285AddValue(CurRec, IdLoc,3286RecordVal(DeclName, IdLoc, Type, RecordVal::FK_TemplateArg));3287}3288if (BadField)3289return nullptr;32903291// If a value is present, parse it and set new field's value.3292if (consume(tgtok::equal)) {3293SMLoc ValLoc = Lex.getLoc();3294Init *Val = ParseValue(CurRec, Type);3295if (!Val ||3296SetValue(CurRec, ValLoc, DeclName, std::nullopt, Val,3297/*AllowSelfAssignment=*/false, /*OverrideDefLoc=*/false)) {3298// Return the name, even if an error is thrown. This is so that we can3299// continue to make some progress, even without the value having been3300// initialized.3301return DeclName;3302}3303}33043305return DeclName;3306}33073308/// ParseForeachDeclaration - Read a foreach declaration, returning3309/// the name of the declared object or a NULL Init on error. Return3310/// the name of the parsed initializer list through ForeachListName.3311///3312/// ForeachDeclaration ::= ID '=' '{' RangeList '}'3313/// ForeachDeclaration ::= ID '=' RangePiece3314/// ForeachDeclaration ::= ID '=' Value3315///3316VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {3317if (Lex.getCode() != tgtok::Id) {3318TokError("Expected identifier in foreach declaration");3319return nullptr;3320}33213322Init *DeclName = StringInit::get(Records, Lex.getCurStrVal());3323Lex.Lex();33243325// If a value is present, parse it.3326if (!consume(tgtok::equal)) {3327TokError("Expected '=' in foreach declaration");3328return nullptr;3329}33303331RecTy *IterType = nullptr;3332SmallVector<unsigned, 16> Ranges;33333334switch (Lex.getCode()) {3335case tgtok::l_brace: { // '{' RangeList '}'3336Lex.Lex(); // eat the '{'3337ParseRangeList(Ranges);3338if (!consume(tgtok::r_brace)) {3339TokError("expected '}' at end of bit range list");3340return nullptr;3341}3342break;3343}33443345default: {3346SMLoc ValueLoc = Lex.getLoc();3347Init *I = ParseValue(nullptr);3348if (!I)3349return nullptr;33503351TypedInit *TI = dyn_cast<TypedInit>(I);3352if (TI && isa<ListRecTy>(TI->getType())) {3353ForeachListValue = I;3354IterType = cast<ListRecTy>(TI->getType())->getElementType();3355break;3356}33573358if (TI) {3359if (ParseRangePiece(Ranges, TI))3360return nullptr;3361break;3362}33633364Error(ValueLoc, "expected a list, got '" + I->getAsString() + "'");3365if (CurMultiClass) {3366PrintNote({}, "references to multiclass template arguments cannot be "3367"resolved at this time");3368}3369return nullptr;3370}3371}337233733374if (!Ranges.empty()) {3375assert(!IterType && "Type already initialized?");3376IterType = IntRecTy::get(Records);3377std::vector<Init *> Values;3378for (unsigned R : Ranges)3379Values.push_back(IntInit::get(Records, R));3380ForeachListValue = ListInit::get(Values, IterType);3381}33823383if (!IterType)3384return nullptr;33853386return VarInit::get(DeclName, IterType);3387}33883389/// ParseTemplateArgList - Read a template argument list, which is a non-empty3390/// sequence of template-declarations in <>'s. If CurRec is non-null, these are3391/// template args for a class. If null, these are the template args for a3392/// multiclass.3393///3394/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'3395///3396bool TGParser::ParseTemplateArgList(Record *CurRec) {3397assert(Lex.getCode() == tgtok::less && "Not a template arg list!");3398Lex.Lex(); // eat the '<'33993400Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;34013402// Read the first declaration.3403Init *TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);3404if (!TemplArg)3405return true;34063407TheRecToAddTo->addTemplateArg(TemplArg);34083409while (consume(tgtok::comma)) {3410// Read the following declarations.3411SMLoc Loc = Lex.getLoc();3412TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);3413if (!TemplArg)3414return true;34153416if (TheRecToAddTo->isTemplateArg(TemplArg))3417return Error(Loc, "template argument with the same name has already been "3418"defined");34193420TheRecToAddTo->addTemplateArg(TemplArg);3421}34223423if (!consume(tgtok::greater))3424return TokError("expected '>' at end of template argument list");3425return false;3426}34273428/// ParseBodyItem - Parse a single item within the body of a def or class.3429///3430/// BodyItem ::= Declaration ';'3431/// BodyItem ::= LET ID OptionalBitList '=' Value ';'3432/// BodyItem ::= Defvar3433/// BodyItem ::= Dump3434/// BodyItem ::= Assert3435///3436bool TGParser::ParseBodyItem(Record *CurRec) {3437if (Lex.getCode() == tgtok::Assert)3438return ParseAssert(nullptr, CurRec);34393440if (Lex.getCode() == tgtok::Defvar)3441return ParseDefvar(CurRec);34423443if (Lex.getCode() == tgtok::Dump)3444return ParseDump(nullptr, CurRec);34453446if (Lex.getCode() != tgtok::Let) {3447if (!ParseDeclaration(CurRec, false))3448return true;34493450if (!consume(tgtok::semi))3451return TokError("expected ';' after declaration");3452return false;3453}34543455// LET ID OptionalRangeList '=' Value ';'3456if (Lex.Lex() != tgtok::Id)3457return TokError("expected field identifier after let");34583459SMLoc IdLoc = Lex.getLoc();3460StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());3461Lex.Lex(); // eat the field name.34623463SmallVector<unsigned, 16> BitList;3464if (ParseOptionalBitList(BitList))3465return true;3466std::reverse(BitList.begin(), BitList.end());34673468if (!consume(tgtok::equal))3469return TokError("expected '=' in let expression");34703471RecordVal *Field = CurRec->getValue(FieldName);3472if (!Field)3473return TokError("Value '" + FieldName->getValue() + "' unknown!");34743475RecTy *Type = Field->getType();3476if (!BitList.empty() && isa<BitsRecTy>(Type)) {3477// When assigning to a subset of a 'bits' object, expect the RHS to have3478// the type of that subset instead of the type of the whole object.3479Type = BitsRecTy::get(Records, BitList.size());3480}34813482Init *Val = ParseValue(CurRec, Type);3483if (!Val) return true;34843485if (!consume(tgtok::semi))3486return TokError("expected ';' after let expression");34873488return SetValue(CurRec, IdLoc, FieldName, BitList, Val);3489}34903491/// ParseBody - Read the body of a class or def. Return true on error, false on3492/// success.3493///3494/// Body ::= ';'3495/// Body ::= '{' BodyList '}'3496/// BodyList BodyItem*3497///3498bool TGParser::ParseBody(Record *CurRec) {3499// If this is a null definition, just eat the semi and return.3500if (consume(tgtok::semi))3501return false;35023503if (!consume(tgtok::l_brace))3504return TokError("Expected '{' to start body or ';' for declaration only");35053506while (Lex.getCode() != tgtok::r_brace)3507if (ParseBodyItem(CurRec))3508return true;35093510// Eat the '}'.3511Lex.Lex();35123513// If we have a semicolon, print a gentle error.3514SMLoc SemiLoc = Lex.getLoc();3515if (consume(tgtok::semi)) {3516PrintError(SemiLoc, "A class or def body should not end with a semicolon");3517PrintNote("Semicolon ignored; remove to eliminate this error");3518}35193520return false;3521}35223523/// Apply the current let bindings to \a CurRec.3524/// \returns true on error, false otherwise.3525bool TGParser::ApplyLetStack(Record *CurRec) {3526for (SmallVectorImpl<LetRecord> &LetInfo : LetStack)3527for (LetRecord &LR : LetInfo)3528if (SetValue(CurRec, LR.Loc, LR.Name, LR.Bits, LR.Value))3529return true;3530return false;3531}35323533/// Apply the current let bindings to the RecordsEntry.3534bool TGParser::ApplyLetStack(RecordsEntry &Entry) {3535if (Entry.Rec)3536return ApplyLetStack(Entry.Rec.get());35373538// Let bindings are not applied to assertions.3539if (Entry.Assertion)3540return false;35413542// Let bindings are not applied to dumps.3543if (Entry.Dump)3544return false;35453546for (auto &E : Entry.Loop->Entries) {3547if (ApplyLetStack(E))3548return true;3549}35503551return false;3552}35533554/// ParseObjectBody - Parse the body of a def or class. This consists of an3555/// optional ClassList followed by a Body. CurRec is the current def or class3556/// that is being parsed.3557///3558/// ObjectBody ::= BaseClassList Body3559/// BaseClassList ::= /*empty*/3560/// BaseClassList ::= ':' BaseClassListNE3561/// BaseClassListNE ::= SubClassRef (',' SubClassRef)*3562///3563bool TGParser::ParseObjectBody(Record *CurRec) {3564// An object body introduces a new scope for local variables.3565TGVarScope *ObjectScope = PushScope(CurRec);3566// If there is a baseclass list, read it.3567if (consume(tgtok::colon)) {35683569// Read all of the subclasses.3570SubClassReference SubClass = ParseSubClassReference(CurRec, false);3571while (true) {3572// Check for error.3573if (!SubClass.Rec) return true;35743575// Add it.3576if (AddSubClass(CurRec, SubClass))3577return true;35783579if (!consume(tgtok::comma))3580break;3581SubClass = ParseSubClassReference(CurRec, false);3582}3583}35843585if (ApplyLetStack(CurRec))3586return true;35873588bool Result = ParseBody(CurRec);3589PopScope(ObjectScope);3590return Result;3591}35923593/// ParseDef - Parse and return a top level or multiclass record definition.3594/// Return false if okay, true if error.3595///3596/// DefInst ::= DEF ObjectName ObjectBody3597///3598bool TGParser::ParseDef(MultiClass *CurMultiClass) {3599SMLoc DefLoc = Lex.getLoc();3600assert(Lex.getCode() == tgtok::Def && "Unknown tok");3601Lex.Lex(); // Eat the 'def' token.36023603// If the name of the def is an Id token, use that for the location.3604// Otherwise, the name is more complex and we use the location of the 'def'3605// token.3606SMLoc NameLoc = Lex.getCode() == tgtok::Id ? Lex.getLoc() : DefLoc;36073608// Parse ObjectName and make a record for it.3609std::unique_ptr<Record> CurRec;3610Init *Name = ParseObjectName(CurMultiClass);3611if (!Name)3612return true;36133614if (isa<UnsetInit>(Name)) {3615CurRec = std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc,3616Records, Record::RK_AnonymousDef);3617} else {3618CurRec = std::make_unique<Record>(Name, NameLoc, Records);3619}36203621if (ParseObjectBody(CurRec.get()))3622return true;36233624return addEntry(std::move(CurRec));3625}36263627/// ParseDefset - Parse a defset statement.3628///3629/// Defset ::= DEFSET Type Id '=' '{' ObjectList '}'3630///3631bool TGParser::ParseDefset() {3632assert(Lex.getCode() == tgtok::Defset);3633Lex.Lex(); // Eat the 'defset' token36343635DefsetRecord Defset;3636Defset.Loc = Lex.getLoc();3637RecTy *Type = ParseType();3638if (!Type)3639return true;3640if (!isa<ListRecTy>(Type))3641return Error(Defset.Loc, "expected list type");3642Defset.EltTy = cast<ListRecTy>(Type)->getElementType();36433644if (Lex.getCode() != tgtok::Id)3645return TokError("expected identifier");3646StringInit *DeclName = StringInit::get(Records, Lex.getCurStrVal());3647if (Records.getGlobal(DeclName->getValue()))3648return TokError("def or global variable of this name already exists");36493650if (Lex.Lex() != tgtok::equal) // Eat the identifier3651return TokError("expected '='");3652if (Lex.Lex() != tgtok::l_brace) // Eat the '='3653return TokError("expected '{'");3654SMLoc BraceLoc = Lex.getLoc();3655Lex.Lex(); // Eat the '{'36563657Defsets.push_back(&Defset);3658bool Err = ParseObjectList(nullptr);3659Defsets.pop_back();3660if (Err)3661return true;36623663if (!consume(tgtok::r_brace)) {3664TokError("expected '}' at end of defset");3665return Error(BraceLoc, "to match this '{'");3666}36673668Records.addExtraGlobal(DeclName->getValue(),3669ListInit::get(Defset.Elements, Defset.EltTy));3670return false;3671}36723673/// ParseDeftype - Parse a defvar statement.3674///3675/// Deftype ::= DEFTYPE Id '=' Type ';'3676///3677bool TGParser::ParseDeftype() {3678assert(Lex.getCode() == tgtok::Deftype);3679Lex.Lex(); // Eat the 'deftype' token36803681if (Lex.getCode() != tgtok::Id)3682return TokError("expected identifier");36833684const std::string TypeName = Lex.getCurStrVal();3685if (TypeAliases.count(TypeName) || Records.getClass(TypeName))3686return TokError("type of this name '" + TypeName + "' already exists");36873688Lex.Lex();3689if (!consume(tgtok::equal))3690return TokError("expected '='");36913692SMLoc Loc = Lex.getLoc();3693RecTy *Type = ParseType();3694if (!Type)3695return true;36963697if (Type->getRecTyKind() == RecTy::RecordRecTyKind)3698return Error(Loc, "cannot define type alias for class type '" +3699Type->getAsString() + "'");37003701TypeAliases[TypeName] = Type;37023703if (!consume(tgtok::semi))3704return TokError("expected ';'");37053706return false;3707}37083709/// ParseDefvar - Parse a defvar statement.3710///3711/// Defvar ::= DEFVAR Id '=' Value ';'3712///3713bool TGParser::ParseDefvar(Record *CurRec) {3714assert(Lex.getCode() == tgtok::Defvar);3715Lex.Lex(); // Eat the 'defvar' token37163717if (Lex.getCode() != tgtok::Id)3718return TokError("expected identifier");3719StringInit *DeclName = StringInit::get(Records, Lex.getCurStrVal());3720if (CurScope->varAlreadyDefined(DeclName->getValue()))3721return TokError("local variable of this name already exists");37223723// The name should not be conflicted with existed field names.3724if (CurRec) {3725auto *V = CurRec->getValue(DeclName->getValue());3726if (V && !V->isTemplateArg())3727return TokError("field of this name already exists");3728}37293730// If this defvar is in the top level, the name should not be conflicted3731// with existed global names.3732if (CurScope->isOutermost() && Records.getGlobal(DeclName->getValue()))3733return TokError("def or global variable of this name already exists");37343735Lex.Lex();3736if (!consume(tgtok::equal))3737return TokError("expected '='");37383739Init *Value = ParseValue(CurRec);3740if (!Value)3741return true;37423743if (!consume(tgtok::semi))3744return TokError("expected ';'");37453746if (!CurScope->isOutermost())3747CurScope->addVar(DeclName->getValue(), Value);3748else3749Records.addExtraGlobal(DeclName->getValue(), Value);37503751return false;3752}37533754/// ParseForeach - Parse a for statement. Return the record corresponding3755/// to it. This returns true on error.3756///3757/// Foreach ::= FOREACH Declaration IN '{ ObjectList '}'3758/// Foreach ::= FOREACH Declaration IN Object3759///3760bool TGParser::ParseForeach(MultiClass *CurMultiClass) {3761SMLoc Loc = Lex.getLoc();3762assert(Lex.getCode() == tgtok::Foreach && "Unknown tok");3763Lex.Lex(); // Eat the 'for' token.37643765// Make a temporary object to record items associated with the for3766// loop.3767Init *ListValue = nullptr;3768VarInit *IterName = ParseForeachDeclaration(ListValue);3769if (!IterName)3770return TokError("expected declaration in for");37713772if (!consume(tgtok::In))3773return TokError("Unknown tok");37743775// Create a loop object and remember it.3776auto TheLoop = std::make_unique<ForeachLoop>(Loc, IterName, ListValue);3777// A foreach loop introduces a new scope for local variables.3778TGVarScope *ForeachScope = PushScope(TheLoop.get());3779Loops.push_back(std::move(TheLoop));37803781if (Lex.getCode() != tgtok::l_brace) {3782// FOREACH Declaration IN Object3783if (ParseObject(CurMultiClass))3784return true;3785} else {3786SMLoc BraceLoc = Lex.getLoc();3787// Otherwise, this is a group foreach.3788Lex.Lex(); // eat the '{'.37893790// Parse the object list.3791if (ParseObjectList(CurMultiClass))3792return true;37933794if (!consume(tgtok::r_brace)) {3795TokError("expected '}' at end of foreach command");3796return Error(BraceLoc, "to match this '{'");3797}3798}37993800PopScope(ForeachScope);38013802// Resolve the loop or store it for later resolution.3803std::unique_ptr<ForeachLoop> Loop = std::move(Loops.back());3804Loops.pop_back();38053806return addEntry(std::move(Loop));3807}38083809/// ParseIf - Parse an if statement.3810///3811/// If ::= IF Value THEN IfBody3812/// If ::= IF Value THEN IfBody ELSE IfBody3813///3814bool TGParser::ParseIf(MultiClass *CurMultiClass) {3815SMLoc Loc = Lex.getLoc();3816assert(Lex.getCode() == tgtok::If && "Unknown tok");3817Lex.Lex(); // Eat the 'if' token.38183819// Make a temporary object to record items associated with the for3820// loop.3821Init *Condition = ParseValue(nullptr);3822if (!Condition)3823return true;38243825if (!consume(tgtok::Then))3826return TokError("Unknown tok");38273828// We have to be able to save if statements to execute later, and they have3829// to live on the same stack as foreach loops. The simplest implementation3830// technique is to convert each 'then' or 'else' clause *into* a foreach3831// loop, over a list of length 0 or 1 depending on the condition, and with no3832// iteration variable being assigned.38333834ListInit *EmptyList = ListInit::get({}, BitRecTy::get(Records));3835ListInit *SingletonList =3836ListInit::get({BitInit::get(Records, true)}, BitRecTy::get(Records));3837RecTy *BitListTy = ListRecTy::get(BitRecTy::get(Records));38383839// The foreach containing the then-clause selects SingletonList if3840// the condition is true.3841Init *ThenClauseList =3842TernOpInit::get(TernOpInit::IF, Condition, SingletonList, EmptyList,3843BitListTy)3844->Fold(nullptr);3845Loops.push_back(std::make_unique<ForeachLoop>(Loc, nullptr, ThenClauseList));38463847if (ParseIfBody(CurMultiClass, "then"))3848return true;38493850std::unique_ptr<ForeachLoop> Loop = std::move(Loops.back());3851Loops.pop_back();38523853if (addEntry(std::move(Loop)))3854return true;38553856// Now look for an optional else clause. The if-else syntax has the usual3857// dangling-else ambiguity, and by greedily matching an else here if we can,3858// we implement the usual resolution of pairing with the innermost unmatched3859// if.3860if (consume(tgtok::ElseKW)) {3861// The foreach containing the else-clause uses the same pair of lists as3862// above, but this time, selects SingletonList if the condition is *false*.3863Init *ElseClauseList =3864TernOpInit::get(TernOpInit::IF, Condition, EmptyList, SingletonList,3865BitListTy)3866->Fold(nullptr);3867Loops.push_back(3868std::make_unique<ForeachLoop>(Loc, nullptr, ElseClauseList));38693870if (ParseIfBody(CurMultiClass, "else"))3871return true;38723873Loop = std::move(Loops.back());3874Loops.pop_back();38753876if (addEntry(std::move(Loop)))3877return true;3878}38793880return false;3881}38823883/// ParseIfBody - Parse the then-clause or else-clause of an if statement.3884///3885/// IfBody ::= Object3886/// IfBody ::= '{' ObjectList '}'3887///3888bool TGParser::ParseIfBody(MultiClass *CurMultiClass, StringRef Kind) {3889// An if-statement introduces a new scope for local variables.3890TGVarScope *BodyScope = PushScope();38913892if (Lex.getCode() != tgtok::l_brace) {3893// A single object.3894if (ParseObject(CurMultiClass))3895return true;3896} else {3897SMLoc BraceLoc = Lex.getLoc();3898// A braced block.3899Lex.Lex(); // eat the '{'.39003901// Parse the object list.3902if (ParseObjectList(CurMultiClass))3903return true;39043905if (!consume(tgtok::r_brace)) {3906TokError("expected '}' at end of '" + Kind + "' clause");3907return Error(BraceLoc, "to match this '{'");3908}3909}39103911PopScope(BodyScope);3912return false;3913}39143915/// ParseAssert - Parse an assert statement.3916///3917/// Assert ::= ASSERT condition , message ;3918bool TGParser::ParseAssert(MultiClass *CurMultiClass, Record *CurRec) {3919assert(Lex.getCode() == tgtok::Assert && "Unknown tok");3920Lex.Lex(); // Eat the 'assert' token.39213922SMLoc ConditionLoc = Lex.getLoc();3923Init *Condition = ParseValue(CurRec);3924if (!Condition)3925return true;39263927if (!consume(tgtok::comma)) {3928TokError("expected ',' in assert statement");3929return true;3930}39313932Init *Message = ParseValue(CurRec);3933if (!Message)3934return true;39353936if (!consume(tgtok::semi))3937return TokError("expected ';'");39383939if (CurRec)3940CurRec->addAssertion(ConditionLoc, Condition, Message);3941else3942addEntry(std::make_unique<Record::AssertionInfo>(ConditionLoc, Condition,3943Message));3944return false;3945}39463947/// ParseClass - Parse a tblgen class definition.3948///3949/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody3950///3951bool TGParser::ParseClass() {3952assert(Lex.getCode() == tgtok::Class && "Unexpected token!");3953Lex.Lex();39543955if (Lex.getCode() != tgtok::Id)3956return TokError("expected class name after 'class' keyword");39573958const std::string &Name = Lex.getCurStrVal();3959Record *CurRec = Records.getClass(Name);3960if (CurRec) {3961// If the body was previously defined, this is an error.3962if (!CurRec->getValues().empty() ||3963!CurRec->getSuperClasses().empty() ||3964!CurRec->getTemplateArgs().empty())3965return TokError("Class '" + CurRec->getNameInitAsString() +3966"' already defined");39673968CurRec->updateClassLoc(Lex.getLoc());3969} else {3970// If this is the first reference to this class, create and add it.3971auto NewRec = std::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(),3972Records, Record::RK_Class);3973CurRec = NewRec.get();3974Records.addClass(std::move(NewRec));3975}39763977if (TypeAliases.count(Name))3978return TokError("there is already a defined type alias '" + Name + "'");39793980Lex.Lex(); // eat the name.39813982// A class definition introduces a new scope.3983TGVarScope *ClassScope = PushScope(CurRec);3984// If there are template args, parse them.3985if (Lex.getCode() == tgtok::less)3986if (ParseTemplateArgList(CurRec))3987return true;39883989if (ParseObjectBody(CurRec))3990return true;39913992if (!NoWarnOnUnusedTemplateArgs)3993CurRec->checkUnusedTemplateArgs();39943995PopScope(ClassScope);3996return false;3997}39983999/// ParseLetList - Parse a non-empty list of assignment expressions into a list4000/// of LetRecords.4001///4002/// LetList ::= LetItem (',' LetItem)*4003/// LetItem ::= ID OptionalRangeList '=' Value4004///4005void TGParser::ParseLetList(SmallVectorImpl<LetRecord> &Result) {4006do {4007if (Lex.getCode() != tgtok::Id) {4008TokError("expected identifier in let definition");4009Result.clear();4010return;4011}40124013StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());4014SMLoc NameLoc = Lex.getLoc();4015Lex.Lex(); // Eat the identifier.40164017// Check for an optional RangeList.4018SmallVector<unsigned, 16> Bits;4019if (ParseOptionalRangeList(Bits)) {4020Result.clear();4021return;4022}4023std::reverse(Bits.begin(), Bits.end());40244025if (!consume(tgtok::equal)) {4026TokError("expected '=' in let expression");4027Result.clear();4028return;4029}40304031Init *Val = ParseValue(nullptr);4032if (!Val) {4033Result.clear();4034return;4035}40364037// Now that we have everything, add the record.4038Result.emplace_back(Name, Bits, Val, NameLoc);4039} while (consume(tgtok::comma));4040}40414042/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of4043/// different related productions. This works inside multiclasses too.4044///4045/// Object ::= LET LetList IN '{' ObjectList '}'4046/// Object ::= LET LetList IN Object4047///4048bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {4049assert(Lex.getCode() == tgtok::Let && "Unexpected token");4050Lex.Lex();40514052// Add this entry to the let stack.4053SmallVector<LetRecord, 8> LetInfo;4054ParseLetList(LetInfo);4055if (LetInfo.empty()) return true;4056LetStack.push_back(std::move(LetInfo));40574058if (!consume(tgtok::In))4059return TokError("expected 'in' at end of top-level 'let'");40604061// If this is a scalar let, just handle it now4062if (Lex.getCode() != tgtok::l_brace) {4063// LET LetList IN Object4064if (ParseObject(CurMultiClass))4065return true;4066} else { // Object ::= LETCommand '{' ObjectList '}'4067SMLoc BraceLoc = Lex.getLoc();4068// Otherwise, this is a group let.4069Lex.Lex(); // eat the '{'.40704071// A group let introduces a new scope for local variables.4072TGVarScope *LetScope = PushScope();40734074// Parse the object list.4075if (ParseObjectList(CurMultiClass))4076return true;40774078if (!consume(tgtok::r_brace)) {4079TokError("expected '}' at end of top level let command");4080return Error(BraceLoc, "to match this '{'");4081}40824083PopScope(LetScope);4084}40854086// Outside this let scope, this let block is not active.4087LetStack.pop_back();4088return false;4089}40904091/// ParseMultiClass - Parse a multiclass definition.4092///4093/// MultiClassInst ::= MULTICLASS ID TemplateArgList?4094/// ':' BaseMultiClassList '{' MultiClassObject+ '}'4095/// MultiClassObject ::= Assert4096/// MultiClassObject ::= DefInst4097/// MultiClassObject ::= DefMInst4098/// MultiClassObject ::= Defvar4099/// MultiClassObject ::= Foreach4100/// MultiClassObject ::= If4101/// MultiClassObject ::= LETCommand '{' ObjectList '}'4102/// MultiClassObject ::= LETCommand Object4103///4104bool TGParser::ParseMultiClass() {4105assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");4106Lex.Lex(); // Eat the multiclass token.41074108if (Lex.getCode() != tgtok::Id)4109return TokError("expected identifier after multiclass for name");4110std::string Name = Lex.getCurStrVal();41114112auto Result =4113MultiClasses.insert(std::make_pair(Name,4114std::make_unique<MultiClass>(Name, Lex.getLoc(),Records)));41154116if (!Result.second)4117return TokError("multiclass '" + Name + "' already defined");41184119CurMultiClass = Result.first->second.get();4120Lex.Lex(); // Eat the identifier.41214122// A multiclass body introduces a new scope for local variables.4123TGVarScope *MulticlassScope = PushScope(CurMultiClass);41244125// If there are template args, parse them.4126if (Lex.getCode() == tgtok::less)4127if (ParseTemplateArgList(nullptr))4128return true;41294130bool inherits = false;41314132// If there are submulticlasses, parse them.4133if (consume(tgtok::colon)) {4134inherits = true;41354136// Read all of the submulticlasses.4137SubMultiClassReference SubMultiClass =4138ParseSubMultiClassReference(CurMultiClass);4139while (true) {4140// Check for error.4141if (!SubMultiClass.MC) return true;41424143// Add it.4144if (AddSubMultiClass(CurMultiClass, SubMultiClass))4145return true;41464147if (!consume(tgtok::comma))4148break;4149SubMultiClass = ParseSubMultiClassReference(CurMultiClass);4150}4151}41524153if (Lex.getCode() != tgtok::l_brace) {4154if (!inherits)4155return TokError("expected '{' in multiclass definition");4156if (!consume(tgtok::semi))4157return TokError("expected ';' in multiclass definition");4158} else {4159if (Lex.Lex() == tgtok::r_brace) // eat the '{'.4160return TokError("multiclass must contain at least one def");41614162while (Lex.getCode() != tgtok::r_brace) {4163switch (Lex.getCode()) {4164default:4165return TokError("expected 'assert', 'def', 'defm', 'defvar', 'dump', "4166"'foreach', 'if', or 'let' in multiclass body");41674168case tgtok::Assert:4169case tgtok::Def:4170case tgtok::Defm:4171case tgtok::Defvar:4172case tgtok::Dump:4173case tgtok::Foreach:4174case tgtok::If:4175case tgtok::Let:4176if (ParseObject(CurMultiClass))4177return true;4178break;4179}4180}4181Lex.Lex(); // eat the '}'.41824183// If we have a semicolon, print a gentle error.4184SMLoc SemiLoc = Lex.getLoc();4185if (consume(tgtok::semi)) {4186PrintError(SemiLoc, "A multiclass body should not end with a semicolon");4187PrintNote("Semicolon ignored; remove to eliminate this error");4188}4189}41904191if (!NoWarnOnUnusedTemplateArgs)4192CurMultiClass->Rec.checkUnusedTemplateArgs();41934194PopScope(MulticlassScope);4195CurMultiClass = nullptr;4196return false;4197}41984199/// ParseDefm - Parse the instantiation of a multiclass.4200///4201/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'4202///4203bool TGParser::ParseDefm(MultiClass *CurMultiClass) {4204assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");4205Lex.Lex(); // eat the defm42064207Init *DefmName = ParseObjectName(CurMultiClass);4208if (!DefmName)4209return true;4210if (isa<UnsetInit>(DefmName)) {4211DefmName = Records.getNewAnonymousName();4212if (CurMultiClass)4213DefmName = BinOpInit::getStrConcat(4214VarInit::get(QualifiedNameOfImplicitName(CurMultiClass),4215StringRecTy::get(Records)),4216DefmName);4217}42184219if (Lex.getCode() != tgtok::colon)4220return TokError("expected ':' after defm identifier");42214222// Keep track of the new generated record definitions.4223std::vector<RecordsEntry> NewEntries;42244225// This record also inherits from a regular class (non-multiclass)?4226bool InheritFromClass = false;42274228// eat the colon.4229Lex.Lex();42304231SMLoc SubClassLoc = Lex.getLoc();4232SubClassReference Ref = ParseSubClassReference(nullptr, true);42334234while (true) {4235if (!Ref.Rec) return true;42364237// To instantiate a multiclass, we get the multiclass and then loop4238// through its template argument names. Substs contains a substitution4239// value for each argument, either the value specified or the default.4240// Then we can resolve the template arguments.4241MultiClass *MC = MultiClasses[std::string(Ref.Rec->getName())].get();4242assert(MC && "Didn't lookup multiclass correctly?");42434244SubstStack Substs;4245if (resolveArgumentsOfMultiClass(Substs, MC, Ref.TemplateArgs, DefmName,4246SubClassLoc))4247return true;42484249if (resolve(MC->Entries, Substs, !CurMultiClass && Loops.empty(),4250&NewEntries, &SubClassLoc))4251return true;42524253if (!consume(tgtok::comma))4254break;42554256if (Lex.getCode() != tgtok::Id)4257return TokError("expected identifier");42584259SubClassLoc = Lex.getLoc();42604261// A defm can inherit from regular classes (non-multiclasses) as4262// long as they come in the end of the inheritance list.4263InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != nullptr);42644265if (InheritFromClass)4266break;42674268Ref = ParseSubClassReference(nullptr, true);4269}42704271if (InheritFromClass) {4272// Process all the classes to inherit as if they were part of a4273// regular 'def' and inherit all record values.4274SubClassReference SubClass = ParseSubClassReference(nullptr, false);4275while (true) {4276// Check for error.4277if (!SubClass.Rec) return true;42784279// Get the expanded definition prototypes and teach them about4280// the record values the current class to inherit has4281for (auto &E : NewEntries) {4282// Add it.4283if (AddSubClass(E, SubClass))4284return true;4285}42864287if (!consume(tgtok::comma))4288break;4289SubClass = ParseSubClassReference(nullptr, false);4290}4291}42924293for (auto &E : NewEntries) {4294if (ApplyLetStack(E))4295return true;42964297addEntry(std::move(E));4298}42994300if (!consume(tgtok::semi))4301return TokError("expected ';' at end of defm");43024303return false;4304}43054306/// ParseObject4307/// Object ::= ClassInst4308/// Object ::= DefInst4309/// Object ::= MultiClassInst4310/// Object ::= DefMInst4311/// Object ::= LETCommand '{' ObjectList '}'4312/// Object ::= LETCommand Object4313/// Object ::= Defset4314/// Object ::= Deftype4315/// Object ::= Defvar4316/// Object ::= Assert4317/// Object ::= Dump4318bool TGParser::ParseObject(MultiClass *MC) {4319switch (Lex.getCode()) {4320default:4321return TokError(4322"Expected assert, class, def, defm, defset, dump, foreach, if, or let");4323case tgtok::Assert: return ParseAssert(MC);4324case tgtok::Def: return ParseDef(MC);4325case tgtok::Defm: return ParseDefm(MC);4326case tgtok::Deftype:4327return ParseDeftype();4328case tgtok::Defvar: return ParseDefvar();4329case tgtok::Dump:4330return ParseDump(MC);4331case tgtok::Foreach: return ParseForeach(MC);4332case tgtok::If: return ParseIf(MC);4333case tgtok::Let: return ParseTopLevelLet(MC);4334case tgtok::Defset:4335if (MC)4336return TokError("defset is not allowed inside multiclass");4337return ParseDefset();4338case tgtok::Class:4339if (MC)4340return TokError("class is not allowed inside multiclass");4341if (!Loops.empty())4342return TokError("class is not allowed inside foreach loop");4343return ParseClass();4344case tgtok::MultiClass:4345if (!Loops.empty())4346return TokError("multiclass is not allowed inside foreach loop");4347return ParseMultiClass();4348}4349}43504351/// ParseObjectList4352/// ObjectList :== Object*4353bool TGParser::ParseObjectList(MultiClass *MC) {4354while (tgtok::isObjectStart(Lex.getCode())) {4355if (ParseObject(MC))4356return true;4357}4358return false;4359}43604361bool TGParser::ParseFile() {4362Lex.Lex(); // Prime the lexer.4363TGVarScope *GlobalScope = PushScope();4364if (ParseObjectList())4365return true;4366PopScope(GlobalScope);43674368// If we have unread input at the end of the file, report it.4369if (Lex.getCode() == tgtok::Eof)4370return false;43714372return TokError("Unexpected token at top level");4373}43744375// Check the types of the template argument values for a class4376// inheritance, multiclass invocation, or anonymous class invocation.4377// If necessary, replace an argument with a cast to the required type.4378// The argument count has already been checked.4379bool TGParser::CheckTemplateArgValues(4380SmallVectorImpl<llvm::ArgumentInit *> &Values, SMLoc Loc, Record *ArgsRec) {4381ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();43824383for (llvm::ArgumentInit *&Value : Values) {4384Init *ArgName = nullptr;4385if (Value->isPositional())4386ArgName = TArgs[Value->getIndex()];4387if (Value->isNamed())4388ArgName = Value->getName();43894390RecordVal *Arg = ArgsRec->getValue(ArgName);4391RecTy *ArgType = Arg->getType();43924393if (TypedInit *ArgValue = dyn_cast<TypedInit>(Value->getValue())) {4394auto *CastValue = ArgValue->getCastTo(ArgType);4395if (CastValue) {4396assert((!isa<TypedInit>(CastValue) ||4397cast<TypedInit>(CastValue)->getType()->typeIsA(ArgType)) &&4398"result of template arg value cast has wrong type");4399Value = Value->cloneWithValue(CastValue);4400} else {4401PrintFatalError(Loc, "Value specified for template argument '" +4402Arg->getNameInitAsString() + "' is of type " +4403ArgValue->getType()->getAsString() +4404"; expected type " + ArgType->getAsString() +4405": " + ArgValue->getAsString());4406}4407}4408}44094410return false;4411}44124413#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)4414LLVM_DUMP_METHOD void RecordsEntry::dump() const {4415if (Loop)4416Loop->dump();4417if (Rec)4418Rec->dump();4419}44204421LLVM_DUMP_METHOD void ForeachLoop::dump() const {4422errs() << "foreach " << IterVar->getAsString() << " = "4423<< ListValue->getAsString() << " in {\n";44244425for (const auto &E : Entries)4426E.dump();44274428errs() << "}\n";4429}44304431LLVM_DUMP_METHOD void MultiClass::dump() const {4432errs() << "Record:\n";4433Rec.dump();44344435errs() << "Defs:\n";4436for (const auto &E : Entries)4437E.dump();4438}4439#endif44404441bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) {4442// Location of the `dump` statement.4443SMLoc Loc = Lex.getLoc();4444assert(Lex.getCode() == tgtok::Dump && "Unknown tok");4445Lex.Lex(); // eat the operation44464447Init *Message = ParseValue(CurRec);4448if (!Message)4449return true;44504451// Allow to use dump directly on `defvar` and `def`, by wrapping4452// them with a `!repl`.4453if (isa<DefInit>(Message))4454Message = UnOpInit::get(UnOpInit::REPR, Message, StringRecTy::get(Records))4455->Fold(CurRec);44564457if (!consume(tgtok::semi))4458return TokError("expected ';'");44594460if (CurRec)4461CurRec->addDump(Loc, Message);4462else4463addEntry(std::make_unique<Record::DumpInfo>(Loc, Message));44644465return false;4466}446744684469