10b57cec5SDimitry Andric //===- TGParser.cpp - Parser for TableGen Files ---------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Implement the Parser for TableGen.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "TGParser.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
150b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
165ffd83dbSDimitry Andric #include "llvm/ADT/Twine.h"
170b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
180b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
190b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
220b57cec5SDimitry Andric #include <algorithm>
230b57cec5SDimitry Andric #include <cassert>
240b57cec5SDimitry Andric #include <cstdint>
25e8d8bef9SDimitry Andric #include <limits>
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric using namespace llvm;
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
300b57cec5SDimitry Andric // Support Code for the Semantic Actions.
310b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric namespace llvm {
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric struct SubClassReference {
360b57cec5SDimitry Andric SMRange RefRange;
375f757f3fSDimitry Andric Record *Rec = nullptr;
3806c3fb27SDimitry Andric SmallVector<ArgumentInit *, 4> TemplateArgs;
390b57cec5SDimitry Andric
405f757f3fSDimitry Andric SubClassReference() = default;
410b57cec5SDimitry Andric
isInvalidllvm::SubClassReference420b57cec5SDimitry Andric bool isInvalid() const { return Rec == nullptr; }
430b57cec5SDimitry Andric };
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric struct SubMultiClassReference {
460b57cec5SDimitry Andric SMRange RefRange;
475f757f3fSDimitry Andric MultiClass *MC = nullptr;
4806c3fb27SDimitry Andric SmallVector<ArgumentInit *, 4> TemplateArgs;
490b57cec5SDimitry Andric
505f757f3fSDimitry Andric SubMultiClassReference() = default;
510b57cec5SDimitry Andric
isInvalidllvm::SubMultiClassReference520b57cec5SDimitry Andric bool isInvalid() const { return MC == nullptr; }
530b57cec5SDimitry Andric void dump() const;
540b57cec5SDimitry Andric };
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const570b57cec5SDimitry Andric LLVM_DUMP_METHOD void SubMultiClassReference::dump() const {
580b57cec5SDimitry Andric errs() << "Multiclass:\n";
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric MC->dump();
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric errs() << "Template args:\n";
630b57cec5SDimitry Andric for (Init *TA : TemplateArgs)
640b57cec5SDimitry Andric TA->dump();
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric #endif
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric } // end namespace llvm
690b57cec5SDimitry Andric
checkBitsConcrete(Record & R,const RecordVal & RV)700b57cec5SDimitry Andric static bool checkBitsConcrete(Record &R, const RecordVal &RV) {
710b57cec5SDimitry Andric BitsInit *BV = cast<BitsInit>(RV.getValue());
720b57cec5SDimitry Andric for (unsigned i = 0, e = BV->getNumBits(); i != e; ++i) {
730b57cec5SDimitry Andric Init *Bit = BV->getBit(i);
740b57cec5SDimitry Andric bool IsReference = false;
750b57cec5SDimitry Andric if (auto VBI = dyn_cast<VarBitInit>(Bit)) {
760b57cec5SDimitry Andric if (auto VI = dyn_cast<VarInit>(VBI->getBitVar())) {
770b57cec5SDimitry Andric if (R.getValue(VI->getName()))
780b57cec5SDimitry Andric IsReference = true;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric } else if (isa<VarInit>(Bit)) {
810b57cec5SDimitry Andric IsReference = true;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric if (!(IsReference || Bit->isConcrete()))
840b57cec5SDimitry Andric return false;
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric return true;
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric
checkConcrete(Record & R)890b57cec5SDimitry Andric static void checkConcrete(Record &R) {
900b57cec5SDimitry Andric for (const RecordVal &RV : R.getValues()) {
910b57cec5SDimitry Andric // HACK: Disable this check for variables declared with 'field'. This is
920b57cec5SDimitry Andric // done merely because existing targets have legitimate cases of
930b57cec5SDimitry Andric // non-concrete variables in helper defs. Ideally, we'd introduce a
940b57cec5SDimitry Andric // 'maybe' or 'optional' modifier instead of this.
95e8d8bef9SDimitry Andric if (RV.isNonconcreteOK())
960b57cec5SDimitry Andric continue;
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric if (Init *V = RV.getValue()) {
990b57cec5SDimitry Andric bool Ok = isa<BitsInit>(V) ? checkBitsConcrete(R, RV) : V->isConcrete();
1000b57cec5SDimitry Andric if (!Ok) {
1010b57cec5SDimitry Andric PrintError(R.getLoc(),
1020b57cec5SDimitry Andric Twine("Initializer of '") + RV.getNameInitAsString() +
1030b57cec5SDimitry Andric "' in '" + R.getNameInitAsString() +
1040b57cec5SDimitry Andric "' could not be fully resolved: " +
1050b57cec5SDimitry Andric RV.getValue()->getAsString());
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric
1110b57cec5SDimitry Andric /// Return an Init with a qualifier prefix referring
1120b57cec5SDimitry Andric /// to CurRec's name.
QualifyName(Record & CurRec,Init * Name)1135f757f3fSDimitry Andric static Init *QualifyName(Record &CurRec, Init *Name) {
11481ad6265SDimitry Andric RecordKeeper &RK = CurRec.getRecords();
1155f757f3fSDimitry Andric Init *NewName = BinOpInit::getStrConcat(
1165f757f3fSDimitry Andric CurRec.getNameInit(),
1175f757f3fSDimitry Andric StringInit::get(RK, CurRec.isMultiClass() ? "::" : ":"));
1180b57cec5SDimitry Andric NewName = BinOpInit::getStrConcat(NewName, Name);
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric if (BinOpInit *BinOp = dyn_cast<BinOpInit>(NewName))
1210b57cec5SDimitry Andric NewName = BinOp->Fold(&CurRec);
1220b57cec5SDimitry Andric return NewName;
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
QualifyName(MultiClass * MC,Init * Name)1255f757f3fSDimitry Andric static Init *QualifyName(MultiClass *MC, Init *Name) {
1265f757f3fSDimitry Andric return QualifyName(MC->Rec, Name);
1275f757f3fSDimitry Andric }
1285f757f3fSDimitry Andric
1290b57cec5SDimitry Andric /// Return the qualified version of the implicit 'NAME' template argument.
QualifiedNameOfImplicitName(Record & Rec)1305f757f3fSDimitry Andric static Init *QualifiedNameOfImplicitName(Record &Rec) {
1315f757f3fSDimitry Andric return QualifyName(Rec, StringInit::get(Rec.getRecords(), "NAME"));
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
QualifiedNameOfImplicitName(MultiClass * MC)1340b57cec5SDimitry Andric static Init *QualifiedNameOfImplicitName(MultiClass *MC) {
1355f757f3fSDimitry Andric return QualifiedNameOfImplicitName(MC->Rec);
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric
getVar(RecordKeeper & Records,MultiClass * ParsingMultiClass,StringInit * Name,SMRange NameLoc,bool TrackReferenceLocs) const13806c3fb27SDimitry Andric Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass *ParsingMultiClass,
13906c3fb27SDimitry Andric StringInit *Name, SMRange NameLoc,
14006c3fb27SDimitry Andric bool TrackReferenceLocs) const {
14106c3fb27SDimitry Andric // First, we search in local variables.
14206c3fb27SDimitry Andric auto It = Vars.find(Name->getValue());
14306c3fb27SDimitry Andric if (It != Vars.end())
14406c3fb27SDimitry Andric return It->second;
14506c3fb27SDimitry Andric
1465f757f3fSDimitry Andric auto FindValueInArgs = [&](Record *Rec, StringInit *Name) -> Init * {
14706c3fb27SDimitry Andric if (!Rec)
14806c3fb27SDimitry Andric return nullptr;
1495f757f3fSDimitry Andric Init *ArgName = QualifyName(*Rec, Name);
15006c3fb27SDimitry Andric if (Rec->isTemplateArg(ArgName)) {
15106c3fb27SDimitry Andric RecordVal *RV = Rec->getValue(ArgName);
15206c3fb27SDimitry Andric assert(RV && "Template arg doesn't exist??");
15306c3fb27SDimitry Andric RV->setUsed(true);
15406c3fb27SDimitry Andric if (TrackReferenceLocs)
15506c3fb27SDimitry Andric RV->addReferenceLoc(NameLoc);
15606c3fb27SDimitry Andric return VarInit::get(ArgName, RV->getType());
15706c3fb27SDimitry Andric }
15806c3fb27SDimitry Andric return Name->getValue() == "NAME"
15906c3fb27SDimitry Andric ? VarInit::get(ArgName, StringRecTy::get(Records))
16006c3fb27SDimitry Andric : nullptr;
16106c3fb27SDimitry Andric };
16206c3fb27SDimitry Andric
16306c3fb27SDimitry Andric // If not found, we try to find the variable in additional variables like
16406c3fb27SDimitry Andric // arguments, loop iterator, etc.
16506c3fb27SDimitry Andric switch (Kind) {
16606c3fb27SDimitry Andric case SK_Local:
16706c3fb27SDimitry Andric break; /* do nothing. */
16806c3fb27SDimitry Andric case SK_Record: {
16906c3fb27SDimitry Andric if (CurRec) {
17006c3fb27SDimitry Andric // The variable is a record field?
17106c3fb27SDimitry Andric if (RecordVal *RV = CurRec->getValue(Name)) {
17206c3fb27SDimitry Andric if (TrackReferenceLocs)
17306c3fb27SDimitry Andric RV->addReferenceLoc(NameLoc);
17406c3fb27SDimitry Andric return VarInit::get(Name, RV->getType());
17506c3fb27SDimitry Andric }
17606c3fb27SDimitry Andric
17706c3fb27SDimitry Andric // The variable is a class template argument?
17806c3fb27SDimitry Andric if (CurRec->isClass())
1795f757f3fSDimitry Andric if (auto *V = FindValueInArgs(CurRec, Name))
18006c3fb27SDimitry Andric return V;
18106c3fb27SDimitry Andric }
18206c3fb27SDimitry Andric break;
18306c3fb27SDimitry Andric }
18406c3fb27SDimitry Andric case SK_ForeachLoop: {
18506c3fb27SDimitry Andric // The variable is a loop iterator?
18606c3fb27SDimitry Andric if (CurLoop->IterVar) {
18706c3fb27SDimitry Andric VarInit *IterVar = dyn_cast<VarInit>(CurLoop->IterVar);
18806c3fb27SDimitry Andric if (IterVar && IterVar->getNameInit() == Name)
18906c3fb27SDimitry Andric return IterVar;
19006c3fb27SDimitry Andric }
19106c3fb27SDimitry Andric break;
19206c3fb27SDimitry Andric }
19306c3fb27SDimitry Andric case SK_MultiClass: {
19406c3fb27SDimitry Andric // The variable is a multiclass template argument?
19506c3fb27SDimitry Andric if (CurMultiClass)
1965f757f3fSDimitry Andric if (auto *V = FindValueInArgs(&CurMultiClass->Rec, Name))
19706c3fb27SDimitry Andric return V;
19806c3fb27SDimitry Andric break;
19906c3fb27SDimitry Andric }
20006c3fb27SDimitry Andric }
20106c3fb27SDimitry Andric
20206c3fb27SDimitry Andric // Then, we try to find the name in parent scope.
20306c3fb27SDimitry Andric if (Parent)
20406c3fb27SDimitry Andric return Parent->getVar(Records, ParsingMultiClass, Name, NameLoc,
20506c3fb27SDimitry Andric TrackReferenceLocs);
20606c3fb27SDimitry Andric
20706c3fb27SDimitry Andric return nullptr;
20806c3fb27SDimitry Andric }
20906c3fb27SDimitry Andric
AddValue(Record * CurRec,SMLoc Loc,const RecordVal & RV)2100b57cec5SDimitry Andric bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
2110b57cec5SDimitry Andric if (!CurRec)
2120b57cec5SDimitry Andric CurRec = &CurMultiClass->Rec;
2130b57cec5SDimitry Andric
2140b57cec5SDimitry Andric if (RecordVal *ERV = CurRec->getValue(RV.getNameInit())) {
2150b57cec5SDimitry Andric // The value already exists in the class, treat this as a set.
2160b57cec5SDimitry Andric if (ERV->setValue(RV.getValue()))
2170b57cec5SDimitry Andric return Error(Loc, "New definition of '" + RV.getName() + "' of type '" +
2180b57cec5SDimitry Andric RV.getType()->getAsString() + "' is incompatible with " +
2190b57cec5SDimitry Andric "previous definition of type '" +
2200b57cec5SDimitry Andric ERV->getType()->getAsString() + "'");
2210b57cec5SDimitry Andric } else {
2220b57cec5SDimitry Andric CurRec->addValue(RV);
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric return false;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andric /// SetValue -
2280b57cec5SDimitry Andric /// Return true on error, false on success.
SetValue(Record * CurRec,SMLoc Loc,Init * ValName,ArrayRef<unsigned> BitList,Init * V,bool AllowSelfAssignment,bool OverrideDefLoc)2290b57cec5SDimitry Andric bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName,
2300b57cec5SDimitry Andric ArrayRef<unsigned> BitList, Init *V,
231bdd1243dSDimitry Andric bool AllowSelfAssignment, bool OverrideDefLoc) {
2320b57cec5SDimitry Andric if (!V) return false;
2330b57cec5SDimitry Andric
2340b57cec5SDimitry Andric if (!CurRec) CurRec = &CurMultiClass->Rec;
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric RecordVal *RV = CurRec->getValue(ValName);
2370b57cec5SDimitry Andric if (!RV)
2380b57cec5SDimitry Andric return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
2390b57cec5SDimitry Andric "' unknown!");
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andric // Do not allow assignments like 'X = X'. This will just cause infinite loops
2420b57cec5SDimitry Andric // in the resolution machinery.
2430b57cec5SDimitry Andric if (BitList.empty())
2440b57cec5SDimitry Andric if (VarInit *VI = dyn_cast<VarInit>(V))
2450b57cec5SDimitry Andric if (VI->getNameInit() == ValName && !AllowSelfAssignment)
2460b57cec5SDimitry Andric return Error(Loc, "Recursion / self-assignment forbidden");
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric // If we are assigning to a subset of the bits in the value... then we must be
2490b57cec5SDimitry Andric // assigning to a field of BitsRecTy, which must have a BitsInit
2500b57cec5SDimitry Andric // initializer.
2510b57cec5SDimitry Andric //
2520b57cec5SDimitry Andric if (!BitList.empty()) {
2530b57cec5SDimitry Andric BitsInit *CurVal = dyn_cast<BitsInit>(RV->getValue());
2540b57cec5SDimitry Andric if (!CurVal)
2550b57cec5SDimitry Andric return Error(Loc, "Value '" + ValName->getAsUnquotedString() +
2560b57cec5SDimitry Andric "' is not a bits type");
2570b57cec5SDimitry Andric
2580b57cec5SDimitry Andric // Convert the incoming value to a bits type of the appropriate size...
25981ad6265SDimitry Andric Init *BI = V->getCastTo(BitsRecTy::get(Records, BitList.size()));
2600b57cec5SDimitry Andric if (!BI)
2610b57cec5SDimitry Andric return Error(Loc, "Initializer is not compatible with bit range");
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric SmallVector<Init *, 16> NewBits(CurVal->getNumBits());
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric // Loop over bits, assigning values as appropriate.
2660b57cec5SDimitry Andric for (unsigned i = 0, e = BitList.size(); i != e; ++i) {
2670b57cec5SDimitry Andric unsigned Bit = BitList[i];
2680b57cec5SDimitry Andric if (NewBits[Bit])
2690b57cec5SDimitry Andric return Error(Loc, "Cannot set bit #" + Twine(Bit) + " of value '" +
2700b57cec5SDimitry Andric ValName->getAsUnquotedString() + "' more than once");
2710b57cec5SDimitry Andric NewBits[Bit] = BI->getBit(i);
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric
2740b57cec5SDimitry Andric for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
2750b57cec5SDimitry Andric if (!NewBits[i])
2760b57cec5SDimitry Andric NewBits[i] = CurVal->getBit(i);
2770b57cec5SDimitry Andric
27881ad6265SDimitry Andric V = BitsInit::get(Records, NewBits);
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric
281bdd1243dSDimitry Andric if (OverrideDefLoc ? RV->setValue(V, Loc) : RV->setValue(V)) {
2820b57cec5SDimitry Andric std::string InitType;
2830b57cec5SDimitry Andric if (BitsInit *BI = dyn_cast<BitsInit>(V))
2840b57cec5SDimitry Andric InitType = (Twine("' of type bit initializer with length ") +
2850b57cec5SDimitry Andric Twine(BI->getNumBits())).str();
2860b57cec5SDimitry Andric else if (TypedInit *TI = dyn_cast<TypedInit>(V))
2870b57cec5SDimitry Andric InitType = (Twine("' of type '") + TI->getType()->getAsString()).str();
288e8d8bef9SDimitry Andric return Error(Loc, "Field '" + ValName->getAsUnquotedString() +
2890b57cec5SDimitry Andric "' of type '" + RV->getType()->getAsString() +
290e8d8bef9SDimitry Andric "' is incompatible with value '" +
2910b57cec5SDimitry Andric V->getAsString() + InitType + "'");
2920b57cec5SDimitry Andric }
2930b57cec5SDimitry Andric return false;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric /// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template
2970b57cec5SDimitry Andric /// args as SubClass's template arguments.
AddSubClass(Record * CurRec,SubClassReference & SubClass)2980b57cec5SDimitry Andric bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
2990b57cec5SDimitry Andric Record *SC = SubClass.Rec;
3000b57cec5SDimitry Andric MapResolver R(CurRec);
3010b57cec5SDimitry Andric
30206c3fb27SDimitry Andric // Loop over all the subclass record's fields. Add regular fields to the new
30306c3fb27SDimitry Andric // record.
30406c3fb27SDimitry Andric for (const RecordVal &Field : SC->getValues())
30506c3fb27SDimitry Andric if (!Field.isTemplateArg())
306fe6060f1SDimitry Andric if (AddValue(CurRec, SubClass.RefRange.Start, Field))
3070b57cec5SDimitry Andric return true;
308fe6060f1SDimitry Andric
30906c3fb27SDimitry Andric if (resolveArgumentsOfClass(R, SC, SubClass.TemplateArgs,
31006c3fb27SDimitry Andric SubClass.RefRange.Start))
31106c3fb27SDimitry Andric return true;
3120b57cec5SDimitry Andric
313fe6060f1SDimitry Andric // Copy the subclass record's assertions to the new record.
314fe6060f1SDimitry Andric CurRec->appendAssertions(SC);
3150b57cec5SDimitry Andric
3165f757f3fSDimitry Andric // Copy the subclass record's dumps to the new record.
3175f757f3fSDimitry Andric CurRec->appendDumps(SC);
3185f757f3fSDimitry Andric
3190b57cec5SDimitry Andric Init *Name;
3200b57cec5SDimitry Andric if (CurRec->isClass())
32181ad6265SDimitry Andric Name = VarInit::get(QualifiedNameOfImplicitName(*CurRec),
32281ad6265SDimitry Andric StringRecTy::get(Records));
3230b57cec5SDimitry Andric else
3240b57cec5SDimitry Andric Name = CurRec->getNameInit();
3250b57cec5SDimitry Andric R.set(QualifiedNameOfImplicitName(*SC), Name);
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andric CurRec->resolveReferences(R);
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andric // Since everything went well, we can now set the "superclass" list for the
3300b57cec5SDimitry Andric // current record.
3310b57cec5SDimitry Andric ArrayRef<std::pair<Record *, SMRange>> SCs = SC->getSuperClasses();
3320b57cec5SDimitry Andric for (const auto &SCPair : SCs) {
3330b57cec5SDimitry Andric if (CurRec->isSubClassOf(SCPair.first))
3340b57cec5SDimitry Andric return Error(SubClass.RefRange.Start,
3350b57cec5SDimitry Andric "Already subclass of '" + SCPair.first->getName() + "'!\n");
3360b57cec5SDimitry Andric CurRec->addSuperClass(SCPair.first, SCPair.second);
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andric if (CurRec->isSubClassOf(SC))
3400b57cec5SDimitry Andric return Error(SubClass.RefRange.Start,
3410b57cec5SDimitry Andric "Already subclass of '" + SC->getName() + "'!\n");
3420b57cec5SDimitry Andric CurRec->addSuperClass(SC, SubClass.RefRange);
3430b57cec5SDimitry Andric return false;
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric
AddSubClass(RecordsEntry & Entry,SubClassReference & SubClass)3460b57cec5SDimitry Andric bool TGParser::AddSubClass(RecordsEntry &Entry, SubClassReference &SubClass) {
3470b57cec5SDimitry Andric if (Entry.Rec)
3480b57cec5SDimitry Andric return AddSubClass(Entry.Rec.get(), SubClass);
3490b57cec5SDimitry Andric
350fe6060f1SDimitry Andric if (Entry.Assertion)
351fe6060f1SDimitry Andric return false;
352fe6060f1SDimitry Andric
3530b57cec5SDimitry Andric for (auto &E : Entry.Loop->Entries) {
3540b57cec5SDimitry Andric if (AddSubClass(E, SubClass))
3550b57cec5SDimitry Andric return true;
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric return false;
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric
3610b57cec5SDimitry Andric /// AddSubMultiClass - Add SubMultiClass as a subclass to
3620b57cec5SDimitry Andric /// CurMC, resolving its template args as SubMultiClass's
3630b57cec5SDimitry Andric /// template arguments.
AddSubMultiClass(MultiClass * CurMC,SubMultiClassReference & SubMultiClass)3640b57cec5SDimitry Andric bool TGParser::AddSubMultiClass(MultiClass *CurMC,
3650b57cec5SDimitry Andric SubMultiClassReference &SubMultiClass) {
3660b57cec5SDimitry Andric MultiClass *SMC = SubMultiClass.MC;
3670b57cec5SDimitry Andric
36806c3fb27SDimitry Andric SubstStack Substs;
36906c3fb27SDimitry Andric if (resolveArgumentsOfMultiClass(
37006c3fb27SDimitry Andric Substs, SMC, SubMultiClass.TemplateArgs,
37181ad6265SDimitry Andric VarInit::get(QualifiedNameOfImplicitName(CurMC),
37206c3fb27SDimitry Andric StringRecTy::get(Records)),
37306c3fb27SDimitry Andric SubMultiClass.RefRange.Start))
37406c3fb27SDimitry Andric return true;
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric // Add all of the defs in the subclass into the current multiclass.
37706c3fb27SDimitry Andric return resolve(SMC->Entries, Substs, false, &CurMC->Entries);
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric
380fe6060f1SDimitry Andric /// Add a record, foreach loop, or assertion to the current context.
addEntry(RecordsEntry E)3810b57cec5SDimitry Andric bool TGParser::addEntry(RecordsEntry E) {
3825f757f3fSDimitry Andric assert((!!E.Rec + !!E.Loop + !!E.Assertion + !!E.Dump) == 1 &&
383fe6060f1SDimitry Andric "RecordsEntry has invalid number of items");
3840b57cec5SDimitry Andric
385fe6060f1SDimitry Andric // If we are parsing a loop, add it to the loop's entries.
3860b57cec5SDimitry Andric if (!Loops.empty()) {
3870b57cec5SDimitry Andric Loops.back()->Entries.push_back(std::move(E));
3880b57cec5SDimitry Andric return false;
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric
391fe6060f1SDimitry Andric // If it is a loop, then resolve and perform the loop.
3920b57cec5SDimitry Andric if (E.Loop) {
3930b57cec5SDimitry Andric SubstStack Stack;
3940b57cec5SDimitry Andric return resolve(*E.Loop, Stack, CurMultiClass == nullptr,
3950b57cec5SDimitry Andric CurMultiClass ? &CurMultiClass->Entries : nullptr);
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric
398fe6060f1SDimitry Andric // If we are parsing a multiclass, add it to the multiclass's entries.
3990b57cec5SDimitry Andric if (CurMultiClass) {
4000b57cec5SDimitry Andric CurMultiClass->Entries.push_back(std::move(E));
4010b57cec5SDimitry Andric return false;
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric
404fe6060f1SDimitry Andric // If it is an assertion, then it's a top-level one, so check it.
405fe6060f1SDimitry Andric if (E.Assertion) {
406fe6060f1SDimitry Andric CheckAssert(E.Assertion->Loc, E.Assertion->Condition, E.Assertion->Message);
407fe6060f1SDimitry Andric return false;
408fe6060f1SDimitry Andric }
409fe6060f1SDimitry Andric
4105f757f3fSDimitry Andric if (E.Dump) {
4115f757f3fSDimitry Andric dumpMessage(E.Dump->Loc, E.Dump->Message);
4125f757f3fSDimitry Andric return false;
4135f757f3fSDimitry Andric }
4145f757f3fSDimitry Andric
415fe6060f1SDimitry Andric // It must be a record, so finish it off.
4160b57cec5SDimitry Andric return addDefOne(std::move(E.Rec));
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric
4190b57cec5SDimitry Andric /// Resolve the entries in \p Loop, going over inner loops recursively
4200b57cec5SDimitry Andric /// and making the given subsitutions of (name, value) pairs.
4210b57cec5SDimitry Andric ///
4220b57cec5SDimitry Andric /// The resulting records are stored in \p Dest if non-null. Otherwise, they
4230b57cec5SDimitry Andric /// are added to the global record keeper.
resolve(const ForeachLoop & Loop,SubstStack & Substs,bool Final,std::vector<RecordsEntry> * Dest,SMLoc * Loc)4240b57cec5SDimitry Andric bool TGParser::resolve(const ForeachLoop &Loop, SubstStack &Substs,
4250b57cec5SDimitry Andric bool Final, std::vector<RecordsEntry> *Dest,
4260b57cec5SDimitry Andric SMLoc *Loc) {
42706c3fb27SDimitry Andric
4280b57cec5SDimitry Andric MapResolver R;
4290b57cec5SDimitry Andric for (const auto &S : Substs)
4300b57cec5SDimitry Andric R.set(S.first, S.second);
4310b57cec5SDimitry Andric Init *List = Loop.ListValue->resolveReferences(R);
43206c3fb27SDimitry Andric
43306c3fb27SDimitry Andric // For if-then-else blocks, we lower to a foreach loop whose list is a
43406c3fb27SDimitry Andric // ternary selection between lists of different length. Since we don't
43506c3fb27SDimitry Andric // have a means to track variable length record lists, we *must* resolve
43606c3fb27SDimitry Andric // the condition here. We want to defer final resolution of the arms
43706c3fb27SDimitry Andric // until the resulting records are finalized.
43806c3fb27SDimitry Andric // e.g. !if(!exists<SchedWrite>("__does_not_exist__"), [1], [])
43906c3fb27SDimitry Andric if (auto *TI = dyn_cast<TernOpInit>(List);
44006c3fb27SDimitry Andric TI && TI->getOpcode() == TernOpInit::IF && Final) {
44106c3fb27SDimitry Andric Init *OldLHS = TI->getLHS();
44206c3fb27SDimitry Andric R.setFinal(true);
44306c3fb27SDimitry Andric Init *LHS = OldLHS->resolveReferences(R);
44406c3fb27SDimitry Andric if (LHS == OldLHS) {
44506c3fb27SDimitry Andric PrintError(Loop.Loc,
44606c3fb27SDimitry Andric Twine("unable to resolve if condition '") +
44706c3fb27SDimitry Andric LHS->getAsString() + "' at end of containing scope");
44806c3fb27SDimitry Andric return true;
44906c3fb27SDimitry Andric }
45006c3fb27SDimitry Andric Init *MHS = TI->getMHS();
45106c3fb27SDimitry Andric Init *RHS = TI->getRHS();
45206c3fb27SDimitry Andric List = TernOpInit::get(TernOpInit::IF, LHS, MHS, RHS, TI->getType())
45306c3fb27SDimitry Andric ->Fold(nullptr);
45406c3fb27SDimitry Andric }
45506c3fb27SDimitry Andric
4560b57cec5SDimitry Andric auto LI = dyn_cast<ListInit>(List);
4570b57cec5SDimitry Andric if (!LI) {
4580b57cec5SDimitry Andric if (!Final) {
4598bcb0991SDimitry Andric Dest->emplace_back(std::make_unique<ForeachLoop>(Loop.Loc, Loop.IterVar,
4600b57cec5SDimitry Andric List));
4610b57cec5SDimitry Andric return resolve(Loop.Entries, Substs, Final, &Dest->back().Loop->Entries,
4620b57cec5SDimitry Andric Loc);
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric
4650b57cec5SDimitry Andric PrintError(Loop.Loc, Twine("attempting to loop over '") +
4660b57cec5SDimitry Andric List->getAsString() + "', expected a list");
4670b57cec5SDimitry Andric return true;
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric
4700b57cec5SDimitry Andric bool Error = false;
471bdd1243dSDimitry Andric for (auto *Elt : *LI) {
472480093f4SDimitry Andric if (Loop.IterVar)
4730b57cec5SDimitry Andric Substs.emplace_back(Loop.IterVar->getNameInit(), Elt);
4740b57cec5SDimitry Andric Error = resolve(Loop.Entries, Substs, Final, Dest);
475480093f4SDimitry Andric if (Loop.IterVar)
4760b57cec5SDimitry Andric Substs.pop_back();
4770b57cec5SDimitry Andric if (Error)
4780b57cec5SDimitry Andric break;
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric return Error;
4810b57cec5SDimitry Andric }
4820b57cec5SDimitry Andric
4830b57cec5SDimitry Andric /// Resolve the entries in \p Source, going over loops recursively and
4840b57cec5SDimitry Andric /// making the given substitutions of (name, value) pairs.
4850b57cec5SDimitry Andric ///
4860b57cec5SDimitry Andric /// The resulting records are stored in \p Dest if non-null. Otherwise, they
4870b57cec5SDimitry Andric /// are added to the global record keeper.
resolve(const std::vector<RecordsEntry> & Source,SubstStack & Substs,bool Final,std::vector<RecordsEntry> * Dest,SMLoc * Loc)4880b57cec5SDimitry Andric bool TGParser::resolve(const std::vector<RecordsEntry> &Source,
4890b57cec5SDimitry Andric SubstStack &Substs, bool Final,
4900b57cec5SDimitry Andric std::vector<RecordsEntry> *Dest, SMLoc *Loc) {
4910b57cec5SDimitry Andric bool Error = false;
4920b57cec5SDimitry Andric for (auto &E : Source) {
4930b57cec5SDimitry Andric if (E.Loop) {
4940b57cec5SDimitry Andric Error = resolve(*E.Loop, Substs, Final, Dest);
495fe6060f1SDimitry Andric
496fe6060f1SDimitry Andric } else if (E.Assertion) {
497fe6060f1SDimitry Andric MapResolver R;
498fe6060f1SDimitry Andric for (const auto &S : Substs)
499fe6060f1SDimitry Andric R.set(S.first, S.second);
500fe6060f1SDimitry Andric Init *Condition = E.Assertion->Condition->resolveReferences(R);
501fe6060f1SDimitry Andric Init *Message = E.Assertion->Message->resolveReferences(R);
502fe6060f1SDimitry Andric
503fe6060f1SDimitry Andric if (Dest)
504fe6060f1SDimitry Andric Dest->push_back(std::make_unique<Record::AssertionInfo>(
505fe6060f1SDimitry Andric E.Assertion->Loc, Condition, Message));
506fe6060f1SDimitry Andric else
507fe6060f1SDimitry Andric CheckAssert(E.Assertion->Loc, Condition, Message);
508fe6060f1SDimitry Andric
5095f757f3fSDimitry Andric } else if (E.Dump) {
5105f757f3fSDimitry Andric MapResolver R;
5115f757f3fSDimitry Andric for (const auto &S : Substs)
5125f757f3fSDimitry Andric R.set(S.first, S.second);
5135f757f3fSDimitry Andric Init *Message = E.Dump->Message->resolveReferences(R);
5145f757f3fSDimitry Andric
5155f757f3fSDimitry Andric if (Dest)
5165f757f3fSDimitry Andric Dest->push_back(
5175f757f3fSDimitry Andric std::make_unique<Record::DumpInfo>(E.Dump->Loc, Message));
5185f757f3fSDimitry Andric else
5195f757f3fSDimitry Andric dumpMessage(E.Dump->Loc, Message);
5205f757f3fSDimitry Andric
5210b57cec5SDimitry Andric } else {
5228bcb0991SDimitry Andric auto Rec = std::make_unique<Record>(*E.Rec);
5230b57cec5SDimitry Andric if (Loc)
5240b57cec5SDimitry Andric Rec->appendLoc(*Loc);
5250b57cec5SDimitry Andric
5260b57cec5SDimitry Andric MapResolver R(Rec.get());
5270b57cec5SDimitry Andric for (const auto &S : Substs)
5280b57cec5SDimitry Andric R.set(S.first, S.second);
5290b57cec5SDimitry Andric Rec->resolveReferences(R);
5300b57cec5SDimitry Andric
5310b57cec5SDimitry Andric if (Dest)
5320b57cec5SDimitry Andric Dest->push_back(std::move(Rec));
5330b57cec5SDimitry Andric else
5340b57cec5SDimitry Andric Error = addDefOne(std::move(Rec));
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric if (Error)
5370b57cec5SDimitry Andric break;
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric return Error;
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andric /// Resolve the record fully and add it to the record keeper.
addDefOne(std::unique_ptr<Record> Rec)5430b57cec5SDimitry Andric bool TGParser::addDefOne(std::unique_ptr<Record> Rec) {
544fe6060f1SDimitry Andric Init *NewName = nullptr;
5450b57cec5SDimitry Andric if (Record *Prev = Records.getDef(Rec->getNameInitAsString())) {
5460b57cec5SDimitry Andric if (!Rec->isAnonymous()) {
5470b57cec5SDimitry Andric PrintError(Rec->getLoc(),
5480b57cec5SDimitry Andric "def already exists: " + Rec->getNameInitAsString());
5490b57cec5SDimitry Andric PrintNote(Prev->getLoc(), "location of previous definition");
5500b57cec5SDimitry Andric return true;
5510b57cec5SDimitry Andric }
552fe6060f1SDimitry Andric NewName = Records.getNewAnonymousName();
5530b57cec5SDimitry Andric }
5540b57cec5SDimitry Andric
555fe6060f1SDimitry Andric Rec->resolveReferences(NewName);
5560b57cec5SDimitry Andric checkConcrete(*Rec);
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric if (!isa<StringInit>(Rec->getNameInit())) {
5590b57cec5SDimitry Andric PrintError(Rec->getLoc(), Twine("record name '") +
5600b57cec5SDimitry Andric Rec->getNameInit()->getAsString() +
5610b57cec5SDimitry Andric "' could not be fully resolved");
5620b57cec5SDimitry Andric return true;
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric
565fe6060f1SDimitry Andric // Check the assertions.
566fe6060f1SDimitry Andric Rec->checkRecordAssertions();
567fe6060f1SDimitry Andric
5685f757f3fSDimitry Andric // Run the dumps.
5695f757f3fSDimitry Andric Rec->emitRecordDumps();
5705f757f3fSDimitry Andric
5710b57cec5SDimitry Andric // If ObjectBody has template arguments, it's an error.
5720b57cec5SDimitry Andric assert(Rec->getTemplateArgs().empty() && "How'd this get template args?");
5730b57cec5SDimitry Andric
5740b57cec5SDimitry Andric for (DefsetRecord *Defset : Defsets) {
5750b57cec5SDimitry Andric DefInit *I = Rec->getDefInit();
5760b57cec5SDimitry Andric if (!I->getType()->typeIsA(Defset->EltTy)) {
5770b57cec5SDimitry Andric PrintError(Rec->getLoc(), Twine("adding record of incompatible type '") +
5780b57cec5SDimitry Andric I->getType()->getAsString() +
5790b57cec5SDimitry Andric "' to defset");
5800b57cec5SDimitry Andric PrintNote(Defset->Loc, "location of defset declaration");
5810b57cec5SDimitry Andric return true;
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric Defset->Elements.push_back(I);
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric
5860b57cec5SDimitry Andric Records.addDef(std::move(Rec));
5870b57cec5SDimitry Andric return false;
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric
resolveArguments(Record * Rec,ArrayRef<ArgumentInit * > ArgValues,SMLoc Loc,ArgValueHandler ArgValueHandler)59006c3fb27SDimitry Andric bool TGParser::resolveArguments(Record *Rec, ArrayRef<ArgumentInit *> ArgValues,
59106c3fb27SDimitry Andric SMLoc Loc, ArgValueHandler ArgValueHandler) {
59206c3fb27SDimitry Andric ArrayRef<Init *> ArgNames = Rec->getTemplateArgs();
59306c3fb27SDimitry Andric assert(ArgValues.size() <= ArgNames.size() &&
59406c3fb27SDimitry Andric "Too many template arguments allowed");
59506c3fb27SDimitry Andric
59606c3fb27SDimitry Andric // Loop over the template arguments and handle the (name, value) pair.
59706c3fb27SDimitry Andric SmallVector<Init *, 2> UnsolvedArgNames(ArgNames);
59806c3fb27SDimitry Andric for (auto *Arg : ArgValues) {
59906c3fb27SDimitry Andric Init *ArgName = nullptr;
60006c3fb27SDimitry Andric Init *ArgValue = Arg->getValue();
60106c3fb27SDimitry Andric if (Arg->isPositional())
60206c3fb27SDimitry Andric ArgName = ArgNames[Arg->getIndex()];
60306c3fb27SDimitry Andric if (Arg->isNamed())
60406c3fb27SDimitry Andric ArgName = Arg->getName();
60506c3fb27SDimitry Andric
60606c3fb27SDimitry Andric // We can only specify the template argument once.
60706c3fb27SDimitry Andric if (!is_contained(UnsolvedArgNames, ArgName))
60806c3fb27SDimitry Andric return Error(Loc, "We can only specify the template argument '" +
60906c3fb27SDimitry Andric ArgName->getAsUnquotedString() + "' once");
61006c3fb27SDimitry Andric
61106c3fb27SDimitry Andric ArgValueHandler(ArgName, ArgValue);
6125f757f3fSDimitry Andric llvm::erase(UnsolvedArgNames, ArgName);
61306c3fb27SDimitry Andric }
61406c3fb27SDimitry Andric
61506c3fb27SDimitry Andric // For unsolved arguments, if there is no default value, complain.
61606c3fb27SDimitry Andric for (auto *UnsolvedArgName : UnsolvedArgNames) {
61706c3fb27SDimitry Andric Init *Default = Rec->getValue(UnsolvedArgName)->getValue();
61806c3fb27SDimitry Andric if (!Default->isComplete()) {
6198a4dda33SDimitry Andric std::string Name = UnsolvedArgName->getAsUnquotedString();
6208a4dda33SDimitry Andric Error(Loc, "value not specified for template argument '" + Name + "'");
6218a4dda33SDimitry Andric PrintNote(Rec->getFieldLoc(Name),
6228a4dda33SDimitry Andric "declared in '" + Rec->getNameInitAsString() + "'");
6238a4dda33SDimitry Andric return true;
62406c3fb27SDimitry Andric }
62506c3fb27SDimitry Andric ArgValueHandler(UnsolvedArgName, Default);
62606c3fb27SDimitry Andric }
62706c3fb27SDimitry Andric
62806c3fb27SDimitry Andric return false;
62906c3fb27SDimitry Andric }
63006c3fb27SDimitry Andric
63106c3fb27SDimitry Andric /// Resolve the arguments of class and set them to MapResolver.
63206c3fb27SDimitry Andric /// Returns true if failed.
resolveArgumentsOfClass(MapResolver & R,Record * Rec,ArrayRef<ArgumentInit * > ArgValues,SMLoc Loc)63306c3fb27SDimitry Andric bool TGParser::resolveArgumentsOfClass(MapResolver &R, Record *Rec,
63406c3fb27SDimitry Andric ArrayRef<ArgumentInit *> ArgValues,
63506c3fb27SDimitry Andric SMLoc Loc) {
63606c3fb27SDimitry Andric return resolveArguments(Rec, ArgValues, Loc,
63706c3fb27SDimitry Andric [&](Init *Name, Init *Value) { R.set(Name, Value); });
63806c3fb27SDimitry Andric }
63906c3fb27SDimitry Andric
64006c3fb27SDimitry Andric /// Resolve the arguments of multiclass and store them into SubstStack.
64106c3fb27SDimitry Andric /// Returns true if failed.
resolveArgumentsOfMultiClass(SubstStack & Substs,MultiClass * MC,ArrayRef<ArgumentInit * > ArgValues,Init * DefmName,SMLoc Loc)64206c3fb27SDimitry Andric bool TGParser::resolveArgumentsOfMultiClass(SubstStack &Substs, MultiClass *MC,
64306c3fb27SDimitry Andric ArrayRef<ArgumentInit *> ArgValues,
64406c3fb27SDimitry Andric Init *DefmName, SMLoc Loc) {
64506c3fb27SDimitry Andric // Add an implicit argument NAME.
64606c3fb27SDimitry Andric Substs.emplace_back(QualifiedNameOfImplicitName(MC), DefmName);
64706c3fb27SDimitry Andric return resolveArguments(
64806c3fb27SDimitry Andric &MC->Rec, ArgValues, Loc,
64906c3fb27SDimitry Andric [&](Init *Name, Init *Value) { Substs.emplace_back(Name, Value); });
65006c3fb27SDimitry Andric }
65106c3fb27SDimitry Andric
6520b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6530b57cec5SDimitry Andric // Parser Code
6540b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6550b57cec5SDimitry Andric
consume(tgtok::TokKind K)6565ffd83dbSDimitry Andric bool TGParser::consume(tgtok::TokKind K) {
6575ffd83dbSDimitry Andric if (Lex.getCode() == K) {
6585ffd83dbSDimitry Andric Lex.Lex();
6595ffd83dbSDimitry Andric return true;
6605ffd83dbSDimitry Andric }
6615ffd83dbSDimitry Andric return false;
6625ffd83dbSDimitry Andric }
6635ffd83dbSDimitry Andric
6640b57cec5SDimitry Andric /// ParseObjectName - If a valid object name is specified, return it. If no
6650b57cec5SDimitry Andric /// name is specified, return the unset initializer. Return nullptr on parse
6660b57cec5SDimitry Andric /// error.
6670b57cec5SDimitry Andric /// ObjectName ::= Value [ '#' Value ]*
6680b57cec5SDimitry Andric /// ObjectName ::= /*empty*/
6690b57cec5SDimitry Andric ///
ParseObjectName(MultiClass * CurMultiClass)6700b57cec5SDimitry Andric Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) {
6710b57cec5SDimitry Andric switch (Lex.getCode()) {
6720b57cec5SDimitry Andric case tgtok::colon:
6730b57cec5SDimitry Andric case tgtok::semi:
6740b57cec5SDimitry Andric case tgtok::l_brace:
6750b57cec5SDimitry Andric // These are all of the tokens that can begin an object body.
6760b57cec5SDimitry Andric // Some of these can also begin values but we disallow those cases
6770b57cec5SDimitry Andric // because they are unlikely to be useful.
67881ad6265SDimitry Andric return UnsetInit::get(Records);
6790b57cec5SDimitry Andric default:
6800b57cec5SDimitry Andric break;
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric
6830b57cec5SDimitry Andric Record *CurRec = nullptr;
6840b57cec5SDimitry Andric if (CurMultiClass)
6850b57cec5SDimitry Andric CurRec = &CurMultiClass->Rec;
6860b57cec5SDimitry Andric
68781ad6265SDimitry Andric Init *Name = ParseValue(CurRec, StringRecTy::get(Records), ParseNameMode);
6880b57cec5SDimitry Andric if (!Name)
6890b57cec5SDimitry Andric return nullptr;
6900b57cec5SDimitry Andric
6910b57cec5SDimitry Andric if (CurMultiClass) {
6920b57cec5SDimitry Andric Init *NameStr = QualifiedNameOfImplicitName(CurMultiClass);
6930b57cec5SDimitry Andric HasReferenceResolver R(NameStr);
6940b57cec5SDimitry Andric Name->resolveReferences(R);
6950b57cec5SDimitry Andric if (!R.found())
69681ad6265SDimitry Andric Name = BinOpInit::getStrConcat(
69781ad6265SDimitry Andric VarInit::get(NameStr, StringRecTy::get(Records)), Name);
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric
7000b57cec5SDimitry Andric return Name;
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric
7030b57cec5SDimitry Andric /// ParseClassID - Parse and resolve a reference to a class name. This returns
7040b57cec5SDimitry Andric /// null on error.
7050b57cec5SDimitry Andric ///
7060b57cec5SDimitry Andric /// ClassID ::= ID
7070b57cec5SDimitry Andric ///
ParseClassID()7080b57cec5SDimitry Andric Record *TGParser::ParseClassID() {
7090b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id) {
7100b57cec5SDimitry Andric TokError("expected name for ClassID");
7110b57cec5SDimitry Andric return nullptr;
7120b57cec5SDimitry Andric }
7130b57cec5SDimitry Andric
7140b57cec5SDimitry Andric Record *Result = Records.getClass(Lex.getCurStrVal());
7150b57cec5SDimitry Andric if (!Result) {
7160b57cec5SDimitry Andric std::string Msg("Couldn't find class '" + Lex.getCurStrVal() + "'");
7170b57cec5SDimitry Andric if (MultiClasses[Lex.getCurStrVal()].get())
7180b57cec5SDimitry Andric TokError(Msg + ". Use 'defm' if you meant to use multiclass '" +
7190b57cec5SDimitry Andric Lex.getCurStrVal() + "'");
7200b57cec5SDimitry Andric else
7210b57cec5SDimitry Andric TokError(Msg);
722bdd1243dSDimitry Andric } else if (TrackReferenceLocs) {
723bdd1243dSDimitry Andric Result->appendReferenceLoc(Lex.getLocRange());
7240b57cec5SDimitry Andric }
7250b57cec5SDimitry Andric
7260b57cec5SDimitry Andric Lex.Lex();
7270b57cec5SDimitry Andric return Result;
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric
7300b57cec5SDimitry Andric /// ParseMultiClassID - Parse and resolve a reference to a multiclass name.
7310b57cec5SDimitry Andric /// This returns null on error.
7320b57cec5SDimitry Andric ///
7330b57cec5SDimitry Andric /// MultiClassID ::= ID
7340b57cec5SDimitry Andric ///
ParseMultiClassID()7350b57cec5SDimitry Andric MultiClass *TGParser::ParseMultiClassID() {
7360b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id) {
7370b57cec5SDimitry Andric TokError("expected name for MultiClassID");
7380b57cec5SDimitry Andric return nullptr;
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric MultiClass *Result = MultiClasses[Lex.getCurStrVal()].get();
7420b57cec5SDimitry Andric if (!Result)
7430b57cec5SDimitry Andric TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
7440b57cec5SDimitry Andric
7450b57cec5SDimitry Andric Lex.Lex();
7460b57cec5SDimitry Andric return Result;
7470b57cec5SDimitry Andric }
7480b57cec5SDimitry Andric
749fe6060f1SDimitry Andric /// ParseSubClassReference - Parse a reference to a subclass or a
750fe6060f1SDimitry Andric /// multiclass. This returns a SubClassRefTy with a null Record* on error.
7510b57cec5SDimitry Andric ///
7520b57cec5SDimitry Andric /// SubClassRef ::= ClassID
75306c3fb27SDimitry Andric /// SubClassRef ::= ClassID '<' ArgValueList '>'
7540b57cec5SDimitry Andric ///
7550b57cec5SDimitry Andric SubClassReference TGParser::
ParseSubClassReference(Record * CurRec,bool isDefm)7560b57cec5SDimitry Andric ParseSubClassReference(Record *CurRec, bool isDefm) {
7570b57cec5SDimitry Andric SubClassReference Result;
7580b57cec5SDimitry Andric Result.RefRange.Start = Lex.getLoc();
7590b57cec5SDimitry Andric
7600b57cec5SDimitry Andric if (isDefm) {
7610b57cec5SDimitry Andric if (MultiClass *MC = ParseMultiClassID())
7620b57cec5SDimitry Andric Result.Rec = &MC->Rec;
7630b57cec5SDimitry Andric } else {
7640b57cec5SDimitry Andric Result.Rec = ParseClassID();
7650b57cec5SDimitry Andric }
7660b57cec5SDimitry Andric if (!Result.Rec) return Result;
7670b57cec5SDimitry Andric
7680b57cec5SDimitry Andric // If there is no template arg list, we're done.
7695ffd83dbSDimitry Andric if (!consume(tgtok::less)) {
7700b57cec5SDimitry Andric Result.RefRange.End = Lex.getLoc();
7710b57cec5SDimitry Andric return Result;
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric
7745f757f3fSDimitry Andric if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec)) {
7750b57cec5SDimitry Andric Result.Rec = nullptr; // Error parsing value list.
7760b57cec5SDimitry Andric return Result;
7770b57cec5SDimitry Andric }
7780b57cec5SDimitry Andric
779fe6060f1SDimitry Andric if (CheckTemplateArgValues(Result.TemplateArgs, Result.RefRange.Start,
780fe6060f1SDimitry Andric Result.Rec)) {
781fe6060f1SDimitry Andric Result.Rec = nullptr; // Error checking value list.
7820b57cec5SDimitry Andric return Result;
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric
785fe6060f1SDimitry Andric Result.RefRange.End = Lex.getLoc();
7860b57cec5SDimitry Andric return Result;
7870b57cec5SDimitry Andric }
7880b57cec5SDimitry Andric
7890b57cec5SDimitry Andric /// ParseSubMultiClassReference - Parse a reference to a subclass or to a
7900b57cec5SDimitry Andric /// templated submulticlass. This returns a SubMultiClassRefTy with a null
7910b57cec5SDimitry Andric /// Record* on error.
7920b57cec5SDimitry Andric ///
7930b57cec5SDimitry Andric /// SubMultiClassRef ::= MultiClassID
79406c3fb27SDimitry Andric /// SubMultiClassRef ::= MultiClassID '<' ArgValueList '>'
7950b57cec5SDimitry Andric ///
7960b57cec5SDimitry Andric SubMultiClassReference TGParser::
ParseSubMultiClassReference(MultiClass * CurMC)7970b57cec5SDimitry Andric ParseSubMultiClassReference(MultiClass *CurMC) {
7980b57cec5SDimitry Andric SubMultiClassReference Result;
7990b57cec5SDimitry Andric Result.RefRange.Start = Lex.getLoc();
8000b57cec5SDimitry Andric
8010b57cec5SDimitry Andric Result.MC = ParseMultiClassID();
8020b57cec5SDimitry Andric if (!Result.MC) return Result;
8030b57cec5SDimitry Andric
8040b57cec5SDimitry Andric // If there is no template arg list, we're done.
8055ffd83dbSDimitry Andric if (!consume(tgtok::less)) {
8060b57cec5SDimitry Andric Result.RefRange.End = Lex.getLoc();
8070b57cec5SDimitry Andric return Result;
8080b57cec5SDimitry Andric }
8090b57cec5SDimitry Andric
810fe6060f1SDimitry Andric if (ParseTemplateArgValueList(Result.TemplateArgs, &CurMC->Rec,
8115f757f3fSDimitry Andric &Result.MC->Rec)) {
8120b57cec5SDimitry Andric Result.MC = nullptr; // Error parsing value list.
8130b57cec5SDimitry Andric return Result;
8140b57cec5SDimitry Andric }
8150b57cec5SDimitry Andric
8160b57cec5SDimitry Andric Result.RefRange.End = Lex.getLoc();
8170b57cec5SDimitry Andric
8180b57cec5SDimitry Andric return Result;
8190b57cec5SDimitry Andric }
8200b57cec5SDimitry Andric
82106c3fb27SDimitry Andric /// ParseSliceElement - Parse subscript or range
82206c3fb27SDimitry Andric ///
82306c3fb27SDimitry Andric /// SliceElement ::= Value<list<int>>
82406c3fb27SDimitry Andric /// SliceElement ::= Value<int>
82506c3fb27SDimitry Andric /// SliceElement ::= Value<int> '...' Value<int>
82606c3fb27SDimitry Andric /// SliceElement ::= Value<int> '-' Value<int> (deprecated)
82706c3fb27SDimitry Andric /// SliceElement ::= Value<int> INTVAL(Negative; deprecated)
82806c3fb27SDimitry Andric ///
82906c3fb27SDimitry Andric /// SliceElement is either IntRecTy, ListRecTy, or nullptr
83006c3fb27SDimitry Andric ///
ParseSliceElement(Record * CurRec)83106c3fb27SDimitry Andric TypedInit *TGParser::ParseSliceElement(Record *CurRec) {
83206c3fb27SDimitry Andric auto LHSLoc = Lex.getLoc();
83306c3fb27SDimitry Andric auto *CurVal = ParseValue(CurRec);
83406c3fb27SDimitry Andric if (!CurVal)
83506c3fb27SDimitry Andric return nullptr;
83606c3fb27SDimitry Andric auto *LHS = cast<TypedInit>(CurVal);
83706c3fb27SDimitry Andric
83806c3fb27SDimitry Andric TypedInit *RHS = nullptr;
83906c3fb27SDimitry Andric switch (Lex.getCode()) {
84006c3fb27SDimitry Andric case tgtok::dotdotdot:
84106c3fb27SDimitry Andric case tgtok::minus: { // Deprecated
84206c3fb27SDimitry Andric Lex.Lex(); // eat
84306c3fb27SDimitry Andric auto RHSLoc = Lex.getLoc();
84406c3fb27SDimitry Andric CurVal = ParseValue(CurRec);
84506c3fb27SDimitry Andric if (!CurVal)
84606c3fb27SDimitry Andric return nullptr;
84706c3fb27SDimitry Andric RHS = cast<TypedInit>(CurVal);
84806c3fb27SDimitry Andric if (!isa<IntRecTy>(RHS->getType())) {
84906c3fb27SDimitry Andric Error(RHSLoc,
85006c3fb27SDimitry Andric "expected int...int, got " + Twine(RHS->getType()->getAsString()));
85106c3fb27SDimitry Andric return nullptr;
85206c3fb27SDimitry Andric }
85306c3fb27SDimitry Andric break;
85406c3fb27SDimitry Andric }
85506c3fb27SDimitry Andric case tgtok::IntVal: { // Deprecated "-num"
85606c3fb27SDimitry Andric auto i = -Lex.getCurIntVal();
85706c3fb27SDimitry Andric if (i < 0) {
85806c3fb27SDimitry Andric TokError("invalid range, cannot be negative");
85906c3fb27SDimitry Andric return nullptr;
86006c3fb27SDimitry Andric }
86106c3fb27SDimitry Andric RHS = IntInit::get(Records, i);
86206c3fb27SDimitry Andric Lex.Lex(); // eat IntVal
86306c3fb27SDimitry Andric break;
86406c3fb27SDimitry Andric }
86506c3fb27SDimitry Andric default: // Single value (IntRecTy or ListRecTy)
86606c3fb27SDimitry Andric return LHS;
86706c3fb27SDimitry Andric }
86806c3fb27SDimitry Andric
86906c3fb27SDimitry Andric assert(RHS);
87006c3fb27SDimitry Andric assert(isa<IntRecTy>(RHS->getType()));
87106c3fb27SDimitry Andric
87206c3fb27SDimitry Andric // Closed-interval range <LHS:IntRecTy>...<RHS:IntRecTy>
87306c3fb27SDimitry Andric if (!isa<IntRecTy>(LHS->getType())) {
87406c3fb27SDimitry Andric Error(LHSLoc,
87506c3fb27SDimitry Andric "expected int...int, got " + Twine(LHS->getType()->getAsString()));
87606c3fb27SDimitry Andric return nullptr;
87706c3fb27SDimitry Andric }
87806c3fb27SDimitry Andric
87906c3fb27SDimitry Andric return cast<TypedInit>(BinOpInit::get(BinOpInit::RANGEC, LHS, RHS,
88006c3fb27SDimitry Andric IntRecTy::get(Records)->getListTy())
88106c3fb27SDimitry Andric ->Fold(CurRec));
88206c3fb27SDimitry Andric }
88306c3fb27SDimitry Andric
88406c3fb27SDimitry Andric /// ParseSliceElements - Parse subscripts in square brackets.
88506c3fb27SDimitry Andric ///
88606c3fb27SDimitry Andric /// SliceElements ::= ( SliceElement ',' )* SliceElement ','?
88706c3fb27SDimitry Andric ///
88806c3fb27SDimitry Andric /// SliceElement is either IntRecTy, ListRecTy, or nullptr
88906c3fb27SDimitry Andric ///
89006c3fb27SDimitry Andric /// Returns ListRecTy by defaut.
89106c3fb27SDimitry Andric /// Returns IntRecTy if;
89206c3fb27SDimitry Andric /// - Single=true
89306c3fb27SDimitry Andric /// - SliceElements is Value<int> w/o trailing comma
89406c3fb27SDimitry Andric ///
ParseSliceElements(Record * CurRec,bool Single)89506c3fb27SDimitry Andric TypedInit *TGParser::ParseSliceElements(Record *CurRec, bool Single) {
89606c3fb27SDimitry Andric TypedInit *CurVal;
89706c3fb27SDimitry Andric SmallVector<Init *, 2> Elems; // int
89806c3fb27SDimitry Andric SmallVector<TypedInit *, 2> Slices; // list<int>
89906c3fb27SDimitry Andric
90006c3fb27SDimitry Andric auto FlushElems = [&] {
90106c3fb27SDimitry Andric if (!Elems.empty()) {
90206c3fb27SDimitry Andric Slices.push_back(ListInit::get(Elems, IntRecTy::get(Records)));
90306c3fb27SDimitry Andric Elems.clear();
90406c3fb27SDimitry Andric }
90506c3fb27SDimitry Andric };
90606c3fb27SDimitry Andric
90706c3fb27SDimitry Andric do {
90806c3fb27SDimitry Andric auto LHSLoc = Lex.getLoc();
90906c3fb27SDimitry Andric CurVal = ParseSliceElement(CurRec);
91006c3fb27SDimitry Andric if (!CurVal)
91106c3fb27SDimitry Andric return nullptr;
91206c3fb27SDimitry Andric auto *CurValTy = CurVal->getType();
91306c3fb27SDimitry Andric
91406c3fb27SDimitry Andric if (auto *ListValTy = dyn_cast<ListRecTy>(CurValTy)) {
91506c3fb27SDimitry Andric if (!isa<IntRecTy>(ListValTy->getElementType())) {
91606c3fb27SDimitry Andric Error(LHSLoc,
91706c3fb27SDimitry Andric "expected list<int>, got " + Twine(ListValTy->getAsString()));
91806c3fb27SDimitry Andric return nullptr;
91906c3fb27SDimitry Andric }
92006c3fb27SDimitry Andric
92106c3fb27SDimitry Andric FlushElems();
92206c3fb27SDimitry Andric Slices.push_back(CurVal);
92306c3fb27SDimitry Andric Single = false;
92406c3fb27SDimitry Andric CurVal = nullptr;
92506c3fb27SDimitry Andric } else if (!isa<IntRecTy>(CurValTy)) {
92606c3fb27SDimitry Andric Error(LHSLoc,
92706c3fb27SDimitry Andric "unhandled type " + Twine(CurValTy->getAsString()) + " in range");
92806c3fb27SDimitry Andric return nullptr;
92906c3fb27SDimitry Andric }
93006c3fb27SDimitry Andric
93106c3fb27SDimitry Andric if (Lex.getCode() != tgtok::comma)
93206c3fb27SDimitry Andric break;
93306c3fb27SDimitry Andric
93406c3fb27SDimitry Andric Lex.Lex(); // eat comma
93506c3fb27SDimitry Andric
93606c3fb27SDimitry Andric // `[i,]` is not LISTELEM but LISTSLICE
93706c3fb27SDimitry Andric Single = false;
93806c3fb27SDimitry Andric if (CurVal)
93906c3fb27SDimitry Andric Elems.push_back(CurVal);
94006c3fb27SDimitry Andric CurVal = nullptr;
94106c3fb27SDimitry Andric } while (Lex.getCode() != tgtok::r_square);
94206c3fb27SDimitry Andric
94306c3fb27SDimitry Andric if (CurVal) {
94406c3fb27SDimitry Andric // LISTELEM
94506c3fb27SDimitry Andric if (Single)
94606c3fb27SDimitry Andric return CurVal;
94706c3fb27SDimitry Andric
94806c3fb27SDimitry Andric Elems.push_back(CurVal);
94906c3fb27SDimitry Andric }
95006c3fb27SDimitry Andric
95106c3fb27SDimitry Andric FlushElems();
95206c3fb27SDimitry Andric
95306c3fb27SDimitry Andric // Concatenate lists in Slices
95406c3fb27SDimitry Andric TypedInit *Result = nullptr;
95506c3fb27SDimitry Andric for (auto *Slice : Slices) {
95606c3fb27SDimitry Andric Result = (Result ? cast<TypedInit>(BinOpInit::getListConcat(Result, Slice))
95706c3fb27SDimitry Andric : Slice);
95806c3fb27SDimitry Andric }
95906c3fb27SDimitry Andric
96006c3fb27SDimitry Andric return Result;
96106c3fb27SDimitry Andric }
96206c3fb27SDimitry Andric
9630b57cec5SDimitry Andric /// ParseRangePiece - Parse a bit/value range.
9640b57cec5SDimitry Andric /// RangePiece ::= INTVAL
965e8d8bef9SDimitry Andric /// RangePiece ::= INTVAL '...' INTVAL
9660b57cec5SDimitry Andric /// RangePiece ::= INTVAL '-' INTVAL
9670b57cec5SDimitry Andric /// RangePiece ::= INTVAL INTVAL
968e8d8bef9SDimitry Andric // The last two forms are deprecated.
ParseRangePiece(SmallVectorImpl<unsigned> & Ranges,TypedInit * FirstItem)9690b57cec5SDimitry Andric bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges,
9700b57cec5SDimitry Andric TypedInit *FirstItem) {
9710b57cec5SDimitry Andric Init *CurVal = FirstItem;
9720b57cec5SDimitry Andric if (!CurVal)
9730b57cec5SDimitry Andric CurVal = ParseValue(nullptr);
9740b57cec5SDimitry Andric
9750b57cec5SDimitry Andric IntInit *II = dyn_cast_or_null<IntInit>(CurVal);
9760b57cec5SDimitry Andric if (!II)
9770b57cec5SDimitry Andric return TokError("expected integer or bitrange");
9780b57cec5SDimitry Andric
9790b57cec5SDimitry Andric int64_t Start = II->getValue();
9800b57cec5SDimitry Andric int64_t End;
9810b57cec5SDimitry Andric
9820b57cec5SDimitry Andric if (Start < 0)
9830b57cec5SDimitry Andric return TokError("invalid range, cannot be negative");
9840b57cec5SDimitry Andric
9850b57cec5SDimitry Andric switch (Lex.getCode()) {
9860b57cec5SDimitry Andric default:
9870b57cec5SDimitry Andric Ranges.push_back(Start);
9880b57cec5SDimitry Andric return false;
989e8d8bef9SDimitry Andric
990e8d8bef9SDimitry Andric case tgtok::dotdotdot:
9910b57cec5SDimitry Andric case tgtok::minus: {
9920b57cec5SDimitry Andric Lex.Lex(); // eat
9930b57cec5SDimitry Andric
9940b57cec5SDimitry Andric Init *I_End = ParseValue(nullptr);
9950b57cec5SDimitry Andric IntInit *II_End = dyn_cast_or_null<IntInit>(I_End);
9960b57cec5SDimitry Andric if (!II_End) {
9970b57cec5SDimitry Andric TokError("expected integer value as end of range");
9980b57cec5SDimitry Andric return true;
9990b57cec5SDimitry Andric }
10000b57cec5SDimitry Andric
10010b57cec5SDimitry Andric End = II_End->getValue();
10020b57cec5SDimitry Andric break;
10030b57cec5SDimitry Andric }
10040b57cec5SDimitry Andric case tgtok::IntVal: {
10050b57cec5SDimitry Andric End = -Lex.getCurIntVal();
10060b57cec5SDimitry Andric Lex.Lex();
10070b57cec5SDimitry Andric break;
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric if (End < 0)
10110b57cec5SDimitry Andric return TokError("invalid range, cannot be negative");
10120b57cec5SDimitry Andric
10130b57cec5SDimitry Andric // Add to the range.
10140b57cec5SDimitry Andric if (Start < End)
10150b57cec5SDimitry Andric for (; Start <= End; ++Start)
10160b57cec5SDimitry Andric Ranges.push_back(Start);
10170b57cec5SDimitry Andric else
10180b57cec5SDimitry Andric for (; Start >= End; --Start)
10190b57cec5SDimitry Andric Ranges.push_back(Start);
10200b57cec5SDimitry Andric return false;
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric
10230b57cec5SDimitry Andric /// ParseRangeList - Parse a list of scalars and ranges into scalar values.
10240b57cec5SDimitry Andric ///
10250b57cec5SDimitry Andric /// RangeList ::= RangePiece (',' RangePiece)*
10260b57cec5SDimitry Andric ///
ParseRangeList(SmallVectorImpl<unsigned> & Result)10270b57cec5SDimitry Andric void TGParser::ParseRangeList(SmallVectorImpl<unsigned> &Result) {
10280b57cec5SDimitry Andric // Parse the first piece.
10290b57cec5SDimitry Andric if (ParseRangePiece(Result)) {
10300b57cec5SDimitry Andric Result.clear();
10310b57cec5SDimitry Andric return;
10320b57cec5SDimitry Andric }
10335ffd83dbSDimitry Andric while (consume(tgtok::comma))
10340b57cec5SDimitry Andric // Parse the next range piece.
10350b57cec5SDimitry Andric if (ParseRangePiece(Result)) {
10360b57cec5SDimitry Andric Result.clear();
10370b57cec5SDimitry Andric return;
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric }
10400b57cec5SDimitry Andric
10410b57cec5SDimitry Andric /// ParseOptionalRangeList - Parse either a range list in <>'s or nothing.
10420b57cec5SDimitry Andric /// OptionalRangeList ::= '<' RangeList '>'
10430b57cec5SDimitry Andric /// OptionalRangeList ::= /*empty*/
ParseOptionalRangeList(SmallVectorImpl<unsigned> & Ranges)10440b57cec5SDimitry Andric bool TGParser::ParseOptionalRangeList(SmallVectorImpl<unsigned> &Ranges) {
10450b57cec5SDimitry Andric SMLoc StartLoc = Lex.getLoc();
10465ffd83dbSDimitry Andric if (!consume(tgtok::less))
10475ffd83dbSDimitry Andric return false;
10480b57cec5SDimitry Andric
10490b57cec5SDimitry Andric // Parse the range list.
10500b57cec5SDimitry Andric ParseRangeList(Ranges);
10510b57cec5SDimitry Andric if (Ranges.empty()) return true;
10520b57cec5SDimitry Andric
10535ffd83dbSDimitry Andric if (!consume(tgtok::greater)) {
10540b57cec5SDimitry Andric TokError("expected '>' at end of range list");
10550b57cec5SDimitry Andric return Error(StartLoc, "to match this '<'");
10560b57cec5SDimitry Andric }
10570b57cec5SDimitry Andric return false;
10580b57cec5SDimitry Andric }
10590b57cec5SDimitry Andric
10600b57cec5SDimitry Andric /// ParseOptionalBitList - Parse either a bit list in {}'s or nothing.
10610b57cec5SDimitry Andric /// OptionalBitList ::= '{' RangeList '}'
10620b57cec5SDimitry Andric /// OptionalBitList ::= /*empty*/
ParseOptionalBitList(SmallVectorImpl<unsigned> & Ranges)10630b57cec5SDimitry Andric bool TGParser::ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges) {
10640b57cec5SDimitry Andric SMLoc StartLoc = Lex.getLoc();
10655ffd83dbSDimitry Andric if (!consume(tgtok::l_brace))
10665ffd83dbSDimitry Andric return false;
10670b57cec5SDimitry Andric
10680b57cec5SDimitry Andric // Parse the range list.
10690b57cec5SDimitry Andric ParseRangeList(Ranges);
10700b57cec5SDimitry Andric if (Ranges.empty()) return true;
10710b57cec5SDimitry Andric
10725ffd83dbSDimitry Andric if (!consume(tgtok::r_brace)) {
10730b57cec5SDimitry Andric TokError("expected '}' at end of bit list");
10740b57cec5SDimitry Andric return Error(StartLoc, "to match this '{'");
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric return false;
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric
10790b57cec5SDimitry Andric /// ParseType - Parse and return a tblgen type. This returns null on error.
10800b57cec5SDimitry Andric ///
10810b57cec5SDimitry Andric /// Type ::= STRING // string type
10820b57cec5SDimitry Andric /// Type ::= CODE // code type
10830b57cec5SDimitry Andric /// Type ::= BIT // bit type
10840b57cec5SDimitry Andric /// Type ::= BITS '<' INTVAL '>' // bits<x> type
10850b57cec5SDimitry Andric /// Type ::= INT // int type
10860b57cec5SDimitry Andric /// Type ::= LIST '<' Type '>' // list<x> type
10870b57cec5SDimitry Andric /// Type ::= DAG // dag type
10880b57cec5SDimitry Andric /// Type ::= ClassID // Record Type
10890b57cec5SDimitry Andric ///
ParseType()10900b57cec5SDimitry Andric RecTy *TGParser::ParseType() {
10910b57cec5SDimitry Andric switch (Lex.getCode()) {
10920b57cec5SDimitry Andric default: TokError("Unknown token when expecting a type"); return nullptr;
1093e8d8bef9SDimitry Andric case tgtok::String:
109481ad6265SDimitry Andric case tgtok::Code:
109581ad6265SDimitry Andric Lex.Lex();
109681ad6265SDimitry Andric return StringRecTy::get(Records);
109781ad6265SDimitry Andric case tgtok::Bit:
109881ad6265SDimitry Andric Lex.Lex();
109981ad6265SDimitry Andric return BitRecTy::get(Records);
110081ad6265SDimitry Andric case tgtok::Int:
110181ad6265SDimitry Andric Lex.Lex();
110281ad6265SDimitry Andric return IntRecTy::get(Records);
110381ad6265SDimitry Andric case tgtok::Dag:
110481ad6265SDimitry Andric Lex.Lex();
110581ad6265SDimitry Andric return DagRecTy::get(Records);
1106*0fca6ea1SDimitry Andric case tgtok::Id: {
1107*0fca6ea1SDimitry Andric auto I = TypeAliases.find(Lex.getCurStrVal());
1108*0fca6ea1SDimitry Andric if (I != TypeAliases.end()) {
1109*0fca6ea1SDimitry Andric Lex.Lex();
1110*0fca6ea1SDimitry Andric return I->second;
1111*0fca6ea1SDimitry Andric }
111281ad6265SDimitry Andric if (Record *R = ParseClassID())
111381ad6265SDimitry Andric return RecordRecTy::get(R);
11140b57cec5SDimitry Andric TokError("unknown class name");
11150b57cec5SDimitry Andric return nullptr;
1116*0fca6ea1SDimitry Andric }
11170b57cec5SDimitry Andric case tgtok::Bits: {
11180b57cec5SDimitry Andric if (Lex.Lex() != tgtok::less) { // Eat 'bits'
11190b57cec5SDimitry Andric TokError("expected '<' after bits type");
11200b57cec5SDimitry Andric return nullptr;
11210b57cec5SDimitry Andric }
11220b57cec5SDimitry Andric if (Lex.Lex() != tgtok::IntVal) { // Eat '<'
11230b57cec5SDimitry Andric TokError("expected integer in bits<n> type");
11240b57cec5SDimitry Andric return nullptr;
11250b57cec5SDimitry Andric }
11260b57cec5SDimitry Andric uint64_t Val = Lex.getCurIntVal();
11270b57cec5SDimitry Andric if (Lex.Lex() != tgtok::greater) { // Eat count.
11280b57cec5SDimitry Andric TokError("expected '>' at end of bits<n> type");
11290b57cec5SDimitry Andric return nullptr;
11300b57cec5SDimitry Andric }
11310b57cec5SDimitry Andric Lex.Lex(); // Eat '>'
113281ad6265SDimitry Andric return BitsRecTy::get(Records, Val);
11330b57cec5SDimitry Andric }
11340b57cec5SDimitry Andric case tgtok::List: {
11350b57cec5SDimitry Andric if (Lex.Lex() != tgtok::less) { // Eat 'bits'
11360b57cec5SDimitry Andric TokError("expected '<' after list type");
11370b57cec5SDimitry Andric return nullptr;
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric Lex.Lex(); // Eat '<'
11400b57cec5SDimitry Andric RecTy *SubType = ParseType();
11410b57cec5SDimitry Andric if (!SubType) return nullptr;
11420b57cec5SDimitry Andric
11435ffd83dbSDimitry Andric if (!consume(tgtok::greater)) {
11440b57cec5SDimitry Andric TokError("expected '>' at end of list<ty> type");
11450b57cec5SDimitry Andric return nullptr;
11460b57cec5SDimitry Andric }
11470b57cec5SDimitry Andric return ListRecTy::get(SubType);
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric }
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric
1152e8d8bef9SDimitry Andric /// ParseIDValue
ParseIDValue(Record * CurRec,StringInit * Name,SMRange NameLoc,IDParseMode Mode)1153bdd1243dSDimitry Andric Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMRange NameLoc,
11540b57cec5SDimitry Andric IDParseMode Mode) {
115506c3fb27SDimitry Andric if (Init *I = CurScope->getVar(Records, CurMultiClass, Name, NameLoc,
115606c3fb27SDimitry Andric TrackReferenceLocs))
1157480093f4SDimitry Andric return I;
1158480093f4SDimitry Andric
11590b57cec5SDimitry Andric if (Mode == ParseNameMode)
11600b57cec5SDimitry Andric return Name;
11610b57cec5SDimitry Andric
1162bdd1243dSDimitry Andric if (Init *I = Records.getGlobal(Name->getValue())) {
1163bdd1243dSDimitry Andric // Add a reference to the global if it's a record.
1164bdd1243dSDimitry Andric if (TrackReferenceLocs) {
1165bdd1243dSDimitry Andric if (auto *Def = dyn_cast<DefInit>(I))
1166bdd1243dSDimitry Andric Def->getDef()->appendReferenceLoc(NameLoc);
1167bdd1243dSDimitry Andric }
11680b57cec5SDimitry Andric return I;
1169bdd1243dSDimitry Andric }
11700b57cec5SDimitry Andric
11710b57cec5SDimitry Andric // Allow self-references of concrete defs, but delay the lookup so that we
11720b57cec5SDimitry Andric // get the correct type.
11730b57cec5SDimitry Andric if (CurRec && !CurRec->isClass() && !CurMultiClass &&
11740b57cec5SDimitry Andric CurRec->getNameInit() == Name)
11750b57cec5SDimitry Andric return UnOpInit::get(UnOpInit::CAST, Name, CurRec->getType());
11760b57cec5SDimitry Andric
1177bdd1243dSDimitry Andric Error(NameLoc.Start, "Variable not defined: '" + Name->getValue() + "'");
11780b57cec5SDimitry Andric return nullptr;
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric
11810b57cec5SDimitry Andric /// ParseOperation - Parse an operator. This returns null on error.
11820b57cec5SDimitry Andric ///
11830b57cec5SDimitry Andric /// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
11840b57cec5SDimitry Andric ///
ParseOperation(Record * CurRec,RecTy * ItemType)11850b57cec5SDimitry Andric Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
11860b57cec5SDimitry Andric switch (Lex.getCode()) {
11870b57cec5SDimitry Andric default:
1188e8d8bef9SDimitry Andric TokError("unknown bang operator");
11890b57cec5SDimitry Andric return nullptr;
1190e8d8bef9SDimitry Andric case tgtok::XNOT:
119106c3fb27SDimitry Andric case tgtok::XToLower:
119206c3fb27SDimitry Andric case tgtok::XToUpper:
1193bdd1243dSDimitry Andric case tgtok::XLOG2:
11940b57cec5SDimitry Andric case tgtok::XHead:
11950b57cec5SDimitry Andric case tgtok::XTail:
11960b57cec5SDimitry Andric case tgtok::XSize:
11970b57cec5SDimitry Andric case tgtok::XEmpty:
1198480093f4SDimitry Andric case tgtok::XCast:
11995f757f3fSDimitry Andric case tgtok::XRepr:
1200e8d8bef9SDimitry Andric case tgtok::XGetDagOp: { // Value ::= !unop '(' Value ')'
12010b57cec5SDimitry Andric UnOpInit::UnaryOp Code;
12020b57cec5SDimitry Andric RecTy *Type = nullptr;
12030b57cec5SDimitry Andric
12040b57cec5SDimitry Andric switch (Lex.getCode()) {
12050b57cec5SDimitry Andric default: llvm_unreachable("Unhandled code!");
12060b57cec5SDimitry Andric case tgtok::XCast:
12070b57cec5SDimitry Andric Lex.Lex(); // eat the operation
12080b57cec5SDimitry Andric Code = UnOpInit::CAST;
12090b57cec5SDimitry Andric
12100b57cec5SDimitry Andric Type = ParseOperatorType();
12110b57cec5SDimitry Andric
12120b57cec5SDimitry Andric if (!Type) {
12130b57cec5SDimitry Andric TokError("did not get type for unary operator");
12140b57cec5SDimitry Andric return nullptr;
12150b57cec5SDimitry Andric }
12160b57cec5SDimitry Andric
12170b57cec5SDimitry Andric break;
12185f757f3fSDimitry Andric case tgtok::XRepr:
12195f757f3fSDimitry Andric Lex.Lex(); // eat the operation
12205f757f3fSDimitry Andric Code = UnOpInit::REPR;
12215f757f3fSDimitry Andric Type = StringRecTy::get(Records);
12225f757f3fSDimitry Andric break;
122306c3fb27SDimitry Andric case tgtok::XToLower:
122406c3fb27SDimitry Andric Lex.Lex(); // eat the operation
122506c3fb27SDimitry Andric Code = UnOpInit::TOLOWER;
122606c3fb27SDimitry Andric Type = StringRecTy::get(Records);
122706c3fb27SDimitry Andric break;
122806c3fb27SDimitry Andric case tgtok::XToUpper:
122906c3fb27SDimitry Andric Lex.Lex(); // eat the operation
123006c3fb27SDimitry Andric Code = UnOpInit::TOUPPER;
123106c3fb27SDimitry Andric Type = StringRecTy::get(Records);
123206c3fb27SDimitry Andric break;
1233e8d8bef9SDimitry Andric case tgtok::XNOT:
1234e8d8bef9SDimitry Andric Lex.Lex(); // eat the operation
1235e8d8bef9SDimitry Andric Code = UnOpInit::NOT;
123681ad6265SDimitry Andric Type = IntRecTy::get(Records);
1237e8d8bef9SDimitry Andric break;
1238bdd1243dSDimitry Andric case tgtok::XLOG2:
1239bdd1243dSDimitry Andric Lex.Lex(); // eat the operation
1240bdd1243dSDimitry Andric Code = UnOpInit::LOG2;
1241bdd1243dSDimitry Andric Type = IntRecTy::get(Records);
1242bdd1243dSDimitry Andric break;
12430b57cec5SDimitry Andric case tgtok::XHead:
12440b57cec5SDimitry Andric Lex.Lex(); // eat the operation
12450b57cec5SDimitry Andric Code = UnOpInit::HEAD;
12460b57cec5SDimitry Andric break;
12470b57cec5SDimitry Andric case tgtok::XTail:
12480b57cec5SDimitry Andric Lex.Lex(); // eat the operation
12490b57cec5SDimitry Andric Code = UnOpInit::TAIL;
12500b57cec5SDimitry Andric break;
12510b57cec5SDimitry Andric case tgtok::XSize:
12520b57cec5SDimitry Andric Lex.Lex();
12530b57cec5SDimitry Andric Code = UnOpInit::SIZE;
125481ad6265SDimitry Andric Type = IntRecTy::get(Records);
12550b57cec5SDimitry Andric break;
12560b57cec5SDimitry Andric case tgtok::XEmpty:
12570b57cec5SDimitry Andric Lex.Lex(); // eat the operation
12580b57cec5SDimitry Andric Code = UnOpInit::EMPTY;
125981ad6265SDimitry Andric Type = IntRecTy::get(Records);
12600b57cec5SDimitry Andric break;
1261e8d8bef9SDimitry Andric case tgtok::XGetDagOp:
1262480093f4SDimitry Andric Lex.Lex(); // eat the operation
1263480093f4SDimitry Andric if (Lex.getCode() == tgtok::less) {
1264480093f4SDimitry Andric // Parse an optional type suffix, so that you can say
1265e8d8bef9SDimitry Andric // !getdagop<BaseClass>(someDag) as a shorthand for
1266e8d8bef9SDimitry Andric // !cast<BaseClass>(!getdagop(someDag)).
1267480093f4SDimitry Andric Type = ParseOperatorType();
1268480093f4SDimitry Andric
1269480093f4SDimitry Andric if (!Type) {
1270480093f4SDimitry Andric TokError("did not get type for unary operator");
1271480093f4SDimitry Andric return nullptr;
1272480093f4SDimitry Andric }
1273480093f4SDimitry Andric
1274480093f4SDimitry Andric if (!isa<RecordRecTy>(Type)) {
1275e8d8bef9SDimitry Andric TokError("type for !getdagop must be a record type");
1276480093f4SDimitry Andric // but keep parsing, to consume the operand
1277480093f4SDimitry Andric }
1278480093f4SDimitry Andric } else {
127981ad6265SDimitry Andric Type = RecordRecTy::get(Records, {});
1280480093f4SDimitry Andric }
1281e8d8bef9SDimitry Andric Code = UnOpInit::GETDAGOP;
1282480093f4SDimitry Andric break;
12830b57cec5SDimitry Andric }
12845ffd83dbSDimitry Andric if (!consume(tgtok::l_paren)) {
12850b57cec5SDimitry Andric TokError("expected '(' after unary operator");
12860b57cec5SDimitry Andric return nullptr;
12870b57cec5SDimitry Andric }
12880b57cec5SDimitry Andric
12890b57cec5SDimitry Andric Init *LHS = ParseValue(CurRec);
12900b57cec5SDimitry Andric if (!LHS) return nullptr;
12910b57cec5SDimitry Andric
1292e8d8bef9SDimitry Andric if (Code == UnOpInit::EMPTY || Code == UnOpInit::SIZE) {
12930b57cec5SDimitry Andric ListInit *LHSl = dyn_cast<ListInit>(LHS);
12940b57cec5SDimitry Andric StringInit *LHSs = dyn_cast<StringInit>(LHS);
1295e8d8bef9SDimitry Andric DagInit *LHSd = dyn_cast<DagInit>(LHS);
12960b57cec5SDimitry Andric TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
1297e8d8bef9SDimitry Andric if (!LHSl && !LHSs && !LHSd && !LHSt) {
1298e8d8bef9SDimitry Andric TokError("expected string, list, or dag type argument in unary operator");
12990b57cec5SDimitry Andric return nullptr;
13000b57cec5SDimitry Andric }
13010b57cec5SDimitry Andric if (LHSt) {
13020b57cec5SDimitry Andric ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
13030b57cec5SDimitry Andric StringRecTy *SType = dyn_cast<StringRecTy>(LHSt->getType());
1304e8d8bef9SDimitry Andric DagRecTy *DType = dyn_cast<DagRecTy>(LHSt->getType());
1305e8d8bef9SDimitry Andric if (!LType && !SType && !DType) {
1306e8d8bef9SDimitry Andric TokError("expected string, list, or dag type argument in unary operator");
13070b57cec5SDimitry Andric return nullptr;
13080b57cec5SDimitry Andric }
13090b57cec5SDimitry Andric }
1310e8d8bef9SDimitry Andric }
13110b57cec5SDimitry Andric
1312e8d8bef9SDimitry Andric if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) {
1313e8d8bef9SDimitry Andric ListInit *LHSl = dyn_cast<ListInit>(LHS);
1314e8d8bef9SDimitry Andric TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
13150b57cec5SDimitry Andric if (!LHSl && !LHSt) {
13160b57cec5SDimitry Andric TokError("expected list type argument in unary operator");
13170b57cec5SDimitry Andric return nullptr;
13180b57cec5SDimitry Andric }
1319e8d8bef9SDimitry Andric if (LHSt) {
1320e8d8bef9SDimitry Andric ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
1321e8d8bef9SDimitry Andric if (!LType) {
1322e8d8bef9SDimitry Andric TokError("expected list type argument in unary operator");
1323e8d8bef9SDimitry Andric return nullptr;
1324e8d8bef9SDimitry Andric }
13250b57cec5SDimitry Andric }
13260b57cec5SDimitry Andric
13270b57cec5SDimitry Andric if (LHSl && LHSl->empty()) {
13280b57cec5SDimitry Andric TokError("empty list argument in unary operator");
13290b57cec5SDimitry Andric return nullptr;
13300b57cec5SDimitry Andric }
13310b57cec5SDimitry Andric if (LHSl) {
13320b57cec5SDimitry Andric Init *Item = LHSl->getElement(0);
13330b57cec5SDimitry Andric TypedInit *Itemt = dyn_cast<TypedInit>(Item);
13340b57cec5SDimitry Andric if (!Itemt) {
13350b57cec5SDimitry Andric TokError("untyped list element in unary operator");
13360b57cec5SDimitry Andric return nullptr;
13370b57cec5SDimitry Andric }
13380b57cec5SDimitry Andric Type = (Code == UnOpInit::HEAD) ? Itemt->getType()
13390b57cec5SDimitry Andric : ListRecTy::get(Itemt->getType());
13400b57cec5SDimitry Andric } else {
13410b57cec5SDimitry Andric assert(LHSt && "expected list type argument in unary operator");
13420b57cec5SDimitry Andric ListRecTy *LType = dyn_cast<ListRecTy>(LHSt->getType());
13430b57cec5SDimitry Andric Type = (Code == UnOpInit::HEAD) ? LType->getElementType() : LType;
13440b57cec5SDimitry Andric }
13450b57cec5SDimitry Andric }
13460b57cec5SDimitry Andric
13475ffd83dbSDimitry Andric if (!consume(tgtok::r_paren)) {
13480b57cec5SDimitry Andric TokError("expected ')' in unary operator");
13490b57cec5SDimitry Andric return nullptr;
13500b57cec5SDimitry Andric }
13510b57cec5SDimitry Andric return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec);
13520b57cec5SDimitry Andric }
13530b57cec5SDimitry Andric
13540b57cec5SDimitry Andric case tgtok::XIsA: {
13550b57cec5SDimitry Andric // Value ::= !isa '<' Type '>' '(' Value ')'
13560b57cec5SDimitry Andric Lex.Lex(); // eat the operation
13570b57cec5SDimitry Andric
13580b57cec5SDimitry Andric RecTy *Type = ParseOperatorType();
13590b57cec5SDimitry Andric if (!Type)
13600b57cec5SDimitry Andric return nullptr;
13610b57cec5SDimitry Andric
13625ffd83dbSDimitry Andric if (!consume(tgtok::l_paren)) {
13630b57cec5SDimitry Andric TokError("expected '(' after type of !isa");
13640b57cec5SDimitry Andric return nullptr;
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric
13670b57cec5SDimitry Andric Init *LHS = ParseValue(CurRec);
13680b57cec5SDimitry Andric if (!LHS)
13690b57cec5SDimitry Andric return nullptr;
13700b57cec5SDimitry Andric
13715ffd83dbSDimitry Andric if (!consume(tgtok::r_paren)) {
13720b57cec5SDimitry Andric TokError("expected ')' in !isa");
13730b57cec5SDimitry Andric return nullptr;
13740b57cec5SDimitry Andric }
13750b57cec5SDimitry Andric
13760b57cec5SDimitry Andric return (IsAOpInit::get(Type, LHS))->Fold();
13770b57cec5SDimitry Andric }
13780b57cec5SDimitry Andric
137981ad6265SDimitry Andric case tgtok::XExists: {
138081ad6265SDimitry Andric // Value ::= !exists '<' Type '>' '(' Value ')'
138181ad6265SDimitry Andric Lex.Lex(); // eat the operation
138281ad6265SDimitry Andric
138381ad6265SDimitry Andric RecTy *Type = ParseOperatorType();
138481ad6265SDimitry Andric if (!Type)
138581ad6265SDimitry Andric return nullptr;
138681ad6265SDimitry Andric
138781ad6265SDimitry Andric if (!consume(tgtok::l_paren)) {
138881ad6265SDimitry Andric TokError("expected '(' after type of !exists");
138981ad6265SDimitry Andric return nullptr;
139081ad6265SDimitry Andric }
139181ad6265SDimitry Andric
139281ad6265SDimitry Andric SMLoc ExprLoc = Lex.getLoc();
139381ad6265SDimitry Andric Init *Expr = ParseValue(CurRec);
139481ad6265SDimitry Andric if (!Expr)
139581ad6265SDimitry Andric return nullptr;
139681ad6265SDimitry Andric
139781ad6265SDimitry Andric TypedInit *ExprType = dyn_cast<TypedInit>(Expr);
139881ad6265SDimitry Andric if (!ExprType) {
139981ad6265SDimitry Andric Error(ExprLoc, "expected string type argument in !exists operator");
140081ad6265SDimitry Andric return nullptr;
140181ad6265SDimitry Andric }
140281ad6265SDimitry Andric
140381ad6265SDimitry Andric RecordRecTy *RecType = dyn_cast<RecordRecTy>(ExprType->getType());
140481ad6265SDimitry Andric if (RecType) {
140581ad6265SDimitry Andric Error(ExprLoc,
140681ad6265SDimitry Andric "expected string type argument in !exists operator, please "
140781ad6265SDimitry Andric "use !isa instead");
140881ad6265SDimitry Andric return nullptr;
140981ad6265SDimitry Andric }
141081ad6265SDimitry Andric
141181ad6265SDimitry Andric StringRecTy *SType = dyn_cast<StringRecTy>(ExprType->getType());
141281ad6265SDimitry Andric if (!SType) {
141381ad6265SDimitry Andric Error(ExprLoc, "expected string type argument in !exists operator");
141481ad6265SDimitry Andric return nullptr;
141581ad6265SDimitry Andric }
141681ad6265SDimitry Andric
141781ad6265SDimitry Andric if (!consume(tgtok::r_paren)) {
141881ad6265SDimitry Andric TokError("expected ')' in !exists");
141981ad6265SDimitry Andric return nullptr;
142081ad6265SDimitry Andric }
142181ad6265SDimitry Andric
142281ad6265SDimitry Andric return (ExistsOpInit::get(Type, Expr))->Fold(CurRec);
142381ad6265SDimitry Andric }
142481ad6265SDimitry Andric
14250b57cec5SDimitry Andric case tgtok::XConcat:
14260b57cec5SDimitry Andric case tgtok::XADD:
1427e8d8bef9SDimitry Andric case tgtok::XSUB:
14280b57cec5SDimitry Andric case tgtok::XMUL:
1429bdd1243dSDimitry Andric case tgtok::XDIV:
14300b57cec5SDimitry Andric case tgtok::XAND:
14310b57cec5SDimitry Andric case tgtok::XOR:
1432e8d8bef9SDimitry Andric case tgtok::XXOR:
14330b57cec5SDimitry Andric case tgtok::XSRA:
14340b57cec5SDimitry Andric case tgtok::XSRL:
14350b57cec5SDimitry Andric case tgtok::XSHL:
14360b57cec5SDimitry Andric case tgtok::XEq:
14370b57cec5SDimitry Andric case tgtok::XNe:
14380b57cec5SDimitry Andric case tgtok::XLe:
14390b57cec5SDimitry Andric case tgtok::XLt:
14400b57cec5SDimitry Andric case tgtok::XGe:
14410b57cec5SDimitry Andric case tgtok::XGt:
14420b57cec5SDimitry Andric case tgtok::XListConcat:
14430b57cec5SDimitry Andric case tgtok::XListSplat:
1444bdd1243dSDimitry Andric case tgtok::XListRemove:
1445480093f4SDimitry Andric case tgtok::XStrConcat:
1446e8d8bef9SDimitry Andric case tgtok::XInterleave:
144706c3fb27SDimitry Andric case tgtok::XGetDagArg:
144806c3fb27SDimitry Andric case tgtok::XGetDagName:
1449e8d8bef9SDimitry Andric case tgtok::XSetDagOp: { // Value ::= !binop '(' Value ',' Value ')'
14500b57cec5SDimitry Andric tgtok::TokKind OpTok = Lex.getCode();
14510b57cec5SDimitry Andric SMLoc OpLoc = Lex.getLoc();
14520b57cec5SDimitry Andric Lex.Lex(); // eat the operation
14530b57cec5SDimitry Andric
14540b57cec5SDimitry Andric BinOpInit::BinaryOp Code;
14550b57cec5SDimitry Andric switch (OpTok) {
14560b57cec5SDimitry Andric default: llvm_unreachable("Unhandled code!");
14570b57cec5SDimitry Andric case tgtok::XConcat: Code = BinOpInit::CONCAT; break;
14580b57cec5SDimitry Andric case tgtok::XADD: Code = BinOpInit::ADD; break;
1459e8d8bef9SDimitry Andric case tgtok::XSUB: Code = BinOpInit::SUB; break;
14600b57cec5SDimitry Andric case tgtok::XMUL: Code = BinOpInit::MUL; break;
1461bdd1243dSDimitry Andric case tgtok::XDIV: Code = BinOpInit::DIV; break;
14620b57cec5SDimitry Andric case tgtok::XAND: Code = BinOpInit::AND; break;
14630b57cec5SDimitry Andric case tgtok::XOR: Code = BinOpInit::OR; break;
1464e8d8bef9SDimitry Andric case tgtok::XXOR: Code = BinOpInit::XOR; break;
14650b57cec5SDimitry Andric case tgtok::XSRA: Code = BinOpInit::SRA; break;
14660b57cec5SDimitry Andric case tgtok::XSRL: Code = BinOpInit::SRL; break;
14670b57cec5SDimitry Andric case tgtok::XSHL: Code = BinOpInit::SHL; break;
14680b57cec5SDimitry Andric case tgtok::XEq: Code = BinOpInit::EQ; break;
14690b57cec5SDimitry Andric case tgtok::XNe: Code = BinOpInit::NE; break;
14700b57cec5SDimitry Andric case tgtok::XLe: Code = BinOpInit::LE; break;
14710b57cec5SDimitry Andric case tgtok::XLt: Code = BinOpInit::LT; break;
14720b57cec5SDimitry Andric case tgtok::XGe: Code = BinOpInit::GE; break;
14730b57cec5SDimitry Andric case tgtok::XGt: Code = BinOpInit::GT; break;
14740b57cec5SDimitry Andric case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break;
14750b57cec5SDimitry Andric case tgtok::XListSplat: Code = BinOpInit::LISTSPLAT; break;
14765f757f3fSDimitry Andric case tgtok::XListRemove:
14775f757f3fSDimitry Andric Code = BinOpInit::LISTREMOVE;
14785f757f3fSDimitry Andric break;
14790b57cec5SDimitry Andric case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;
1480e8d8bef9SDimitry Andric case tgtok::XInterleave: Code = BinOpInit::INTERLEAVE; break;
1481e8d8bef9SDimitry Andric case tgtok::XSetDagOp: Code = BinOpInit::SETDAGOP; break;
148206c3fb27SDimitry Andric case tgtok::XGetDagArg:
148306c3fb27SDimitry Andric Code = BinOpInit::GETDAGARG;
148406c3fb27SDimitry Andric break;
148506c3fb27SDimitry Andric case tgtok::XGetDagName:
148606c3fb27SDimitry Andric Code = BinOpInit::GETDAGNAME;
148706c3fb27SDimitry Andric break;
14880b57cec5SDimitry Andric }
14890b57cec5SDimitry Andric
14900b57cec5SDimitry Andric RecTy *Type = nullptr;
14910b57cec5SDimitry Andric RecTy *ArgType = nullptr;
14920b57cec5SDimitry Andric switch (OpTok) {
14930b57cec5SDimitry Andric default:
14940b57cec5SDimitry Andric llvm_unreachable("Unhandled code!");
14950b57cec5SDimitry Andric case tgtok::XConcat:
1496e8d8bef9SDimitry Andric case tgtok::XSetDagOp:
149781ad6265SDimitry Andric Type = DagRecTy::get(Records);
149881ad6265SDimitry Andric ArgType = DagRecTy::get(Records);
14990b57cec5SDimitry Andric break;
150006c3fb27SDimitry Andric case tgtok::XGetDagArg:
150106c3fb27SDimitry Andric Type = ParseOperatorType();
150206c3fb27SDimitry Andric if (!Type) {
150306c3fb27SDimitry Andric TokError("did not get type for !getdagarg operator");
150406c3fb27SDimitry Andric return nullptr;
150506c3fb27SDimitry Andric }
150606c3fb27SDimitry Andric ArgType = DagRecTy::get(Records);
150706c3fb27SDimitry Andric break;
150806c3fb27SDimitry Andric case tgtok::XGetDagName:
150906c3fb27SDimitry Andric Type = StringRecTy::get(Records);
151006c3fb27SDimitry Andric ArgType = DagRecTy::get(Records);
151106c3fb27SDimitry Andric break;
15120b57cec5SDimitry Andric case tgtok::XAND:
15130b57cec5SDimitry Andric case tgtok::XOR:
1514e8d8bef9SDimitry Andric case tgtok::XXOR:
15150b57cec5SDimitry Andric case tgtok::XSRA:
15160b57cec5SDimitry Andric case tgtok::XSRL:
15170b57cec5SDimitry Andric case tgtok::XSHL:
15180b57cec5SDimitry Andric case tgtok::XADD:
1519e8d8bef9SDimitry Andric case tgtok::XSUB:
15200b57cec5SDimitry Andric case tgtok::XMUL:
1521bdd1243dSDimitry Andric case tgtok::XDIV:
152281ad6265SDimitry Andric Type = IntRecTy::get(Records);
152381ad6265SDimitry Andric ArgType = IntRecTy::get(Records);
15240b57cec5SDimitry Andric break;
15250b57cec5SDimitry Andric case tgtok::XEq:
15260b57cec5SDimitry Andric case tgtok::XNe:
15270b57cec5SDimitry Andric case tgtok::XLe:
15280b57cec5SDimitry Andric case tgtok::XLt:
15290b57cec5SDimitry Andric case tgtok::XGe:
15300b57cec5SDimitry Andric case tgtok::XGt:
153181ad6265SDimitry Andric Type = BitRecTy::get(Records);
1532e8d8bef9SDimitry Andric // ArgType for the comparison operators is not yet known.
15330b57cec5SDimitry Andric break;
15340b57cec5SDimitry Andric case tgtok::XListConcat:
1535bdd1243dSDimitry Andric // We don't know the list type until we parse the first argument.
15360b57cec5SDimitry Andric ArgType = ItemType;
15370b57cec5SDimitry Andric break;
15380b57cec5SDimitry Andric case tgtok::XListSplat:
15390b57cec5SDimitry Andric // Can't do any typechecking until we parse the first argument.
15400b57cec5SDimitry Andric break;
1541bdd1243dSDimitry Andric case tgtok::XListRemove:
1542bdd1243dSDimitry Andric // We don't know the list type until we parse the first argument.
1543bdd1243dSDimitry Andric ArgType = ItemType;
1544bdd1243dSDimitry Andric break;
15450b57cec5SDimitry Andric case tgtok::XStrConcat:
154681ad6265SDimitry Andric Type = StringRecTy::get(Records);
154781ad6265SDimitry Andric ArgType = StringRecTy::get(Records);
15480b57cec5SDimitry Andric break;
1549e8d8bef9SDimitry Andric case tgtok::XInterleave:
155081ad6265SDimitry Andric Type = StringRecTy::get(Records);
1551e8d8bef9SDimitry Andric // The first argument type is not yet known.
15520b57cec5SDimitry Andric }
15530b57cec5SDimitry Andric
15540b57cec5SDimitry Andric if (Type && ItemType && !Type->typeIsConvertibleTo(ItemType)) {
15550b57cec5SDimitry Andric Error(OpLoc, Twine("expected value of type '") +
15560b57cec5SDimitry Andric ItemType->getAsString() + "', got '" +
15570b57cec5SDimitry Andric Type->getAsString() + "'");
15580b57cec5SDimitry Andric return nullptr;
15590b57cec5SDimitry Andric }
15600b57cec5SDimitry Andric
15615ffd83dbSDimitry Andric if (!consume(tgtok::l_paren)) {
15620b57cec5SDimitry Andric TokError("expected '(' after binary operator");
15630b57cec5SDimitry Andric return nullptr;
15640b57cec5SDimitry Andric }
15650b57cec5SDimitry Andric
15660b57cec5SDimitry Andric SmallVector<Init*, 2> InitList;
15670b57cec5SDimitry Andric
1568e8d8bef9SDimitry Andric // Note that this loop consumes an arbitrary number of arguments.
1569e8d8bef9SDimitry Andric // The actual count is checked later.
15700b57cec5SDimitry Andric for (;;) {
15710b57cec5SDimitry Andric SMLoc InitLoc = Lex.getLoc();
15720b57cec5SDimitry Andric InitList.push_back(ParseValue(CurRec, ArgType));
15730b57cec5SDimitry Andric if (!InitList.back()) return nullptr;
15740b57cec5SDimitry Andric
15755ffd83dbSDimitry Andric TypedInit *InitListBack = dyn_cast<TypedInit>(InitList.back());
15765ffd83dbSDimitry Andric if (!InitListBack) {
15775ffd83dbSDimitry Andric Error(OpLoc, Twine("expected value to be a typed value, got '" +
15785ffd83dbSDimitry Andric InitList.back()->getAsString() + "'"));
15795ffd83dbSDimitry Andric return nullptr;
15805ffd83dbSDimitry Andric }
15815ffd83dbSDimitry Andric RecTy *ListType = InitListBack->getType();
1582e8d8bef9SDimitry Andric
15830b57cec5SDimitry Andric if (!ArgType) {
1584e8d8bef9SDimitry Andric // Argument type must be determined from the argument itself.
15858bcb0991SDimitry Andric ArgType = ListType;
15860b57cec5SDimitry Andric
15870b57cec5SDimitry Andric switch (Code) {
15880b57cec5SDimitry Andric case BinOpInit::LISTCONCAT:
15890b57cec5SDimitry Andric if (!isa<ListRecTy>(ArgType)) {
15900b57cec5SDimitry Andric Error(InitLoc, Twine("expected a list, got value of type '") +
15910b57cec5SDimitry Andric ArgType->getAsString() + "'");
15920b57cec5SDimitry Andric return nullptr;
15930b57cec5SDimitry Andric }
15940b57cec5SDimitry Andric break;
15950b57cec5SDimitry Andric case BinOpInit::LISTSPLAT:
15960b57cec5SDimitry Andric if (ItemType && InitList.size() == 1) {
15970b57cec5SDimitry Andric if (!isa<ListRecTy>(ItemType)) {
15980b57cec5SDimitry Andric Error(OpLoc,
15990b57cec5SDimitry Andric Twine("expected output type to be a list, got type '") +
16000b57cec5SDimitry Andric ItemType->getAsString() + "'");
16010b57cec5SDimitry Andric return nullptr;
16020b57cec5SDimitry Andric }
16030b57cec5SDimitry Andric if (!ArgType->getListTy()->typeIsConvertibleTo(ItemType)) {
16040b57cec5SDimitry Andric Error(OpLoc, Twine("expected first arg type to be '") +
16050b57cec5SDimitry Andric ArgType->getAsString() +
16060b57cec5SDimitry Andric "', got value of type '" +
16070b57cec5SDimitry Andric cast<ListRecTy>(ItemType)
16080b57cec5SDimitry Andric ->getElementType()
16090b57cec5SDimitry Andric ->getAsString() +
16100b57cec5SDimitry Andric "'");
16110b57cec5SDimitry Andric return nullptr;
16120b57cec5SDimitry Andric }
16130b57cec5SDimitry Andric }
16140b57cec5SDimitry Andric if (InitList.size() == 2 && !isa<IntRecTy>(ArgType)) {
16150b57cec5SDimitry Andric Error(InitLoc, Twine("expected second parameter to be an int, got "
16160b57cec5SDimitry Andric "value of type '") +
16170b57cec5SDimitry Andric ArgType->getAsString() + "'");
16180b57cec5SDimitry Andric return nullptr;
16190b57cec5SDimitry Andric }
16200b57cec5SDimitry Andric ArgType = nullptr; // Broken invariant: types not identical.
16210b57cec5SDimitry Andric break;
1622bdd1243dSDimitry Andric case BinOpInit::LISTREMOVE:
1623bdd1243dSDimitry Andric if (!isa<ListRecTy>(ArgType)) {
1624bdd1243dSDimitry Andric Error(InitLoc, Twine("expected a list, got value of type '") +
1625bdd1243dSDimitry Andric ArgType->getAsString() + "'");
1626bdd1243dSDimitry Andric return nullptr;
1627bdd1243dSDimitry Andric }
1628bdd1243dSDimitry Andric break;
16290b57cec5SDimitry Andric case BinOpInit::EQ:
16300b57cec5SDimitry Andric case BinOpInit::NE:
163181ad6265SDimitry Andric if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&
163281ad6265SDimitry Andric !ArgType->typeIsConvertibleTo(StringRecTy::get(Records)) &&
163381ad6265SDimitry Andric !ArgType->typeIsConvertibleTo(RecordRecTy::get(Records, {}))) {
1634e8d8bef9SDimitry Andric Error(InitLoc, Twine("expected bit, bits, int, string, or record; "
1635e8d8bef9SDimitry Andric "got value of type '") + ArgType->getAsString() +
1636e8d8bef9SDimitry Andric "'");
16370b57cec5SDimitry Andric return nullptr;
16380b57cec5SDimitry Andric }
16390b57cec5SDimitry Andric break;
164006c3fb27SDimitry Andric case BinOpInit::GETDAGARG: // The 2nd argument of !getdagarg could be
164106c3fb27SDimitry Andric // index or name.
1642e8d8bef9SDimitry Andric case BinOpInit::LE:
1643e8d8bef9SDimitry Andric case BinOpInit::LT:
1644e8d8bef9SDimitry Andric case BinOpInit::GE:
1645e8d8bef9SDimitry Andric case BinOpInit::GT:
164681ad6265SDimitry Andric if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) &&
164781ad6265SDimitry Andric !ArgType->typeIsConvertibleTo(StringRecTy::get(Records))) {
1648e8d8bef9SDimitry Andric Error(InitLoc, Twine("expected bit, bits, int, or string; "
1649e8d8bef9SDimitry Andric "got value of type '") + ArgType->getAsString() +
1650e8d8bef9SDimitry Andric "'");
1651e8d8bef9SDimitry Andric return nullptr;
1652e8d8bef9SDimitry Andric }
1653e8d8bef9SDimitry Andric break;
1654e8d8bef9SDimitry Andric case BinOpInit::INTERLEAVE:
1655e8d8bef9SDimitry Andric switch (InitList.size()) {
1656e8d8bef9SDimitry Andric case 1: // First argument must be a list of strings or integers.
165781ad6265SDimitry Andric if (ArgType != StringRecTy::get(Records)->getListTy() &&
165881ad6265SDimitry Andric !ArgType->typeIsConvertibleTo(
165981ad6265SDimitry Andric IntRecTy::get(Records)->getListTy())) {
1660e8d8bef9SDimitry Andric Error(InitLoc, Twine("expected list of string, int, bits, or bit; "
1661e8d8bef9SDimitry Andric "got value of type '") +
1662e8d8bef9SDimitry Andric ArgType->getAsString() + "'");
1663e8d8bef9SDimitry Andric return nullptr;
1664e8d8bef9SDimitry Andric }
1665e8d8bef9SDimitry Andric break;
1666e8d8bef9SDimitry Andric case 2: // Second argument must be a string.
1667e8d8bef9SDimitry Andric if (!isa<StringRecTy>(ArgType)) {
1668e8d8bef9SDimitry Andric Error(InitLoc, Twine("expected second argument to be a string, "
1669e8d8bef9SDimitry Andric "got value of type '") +
1670e8d8bef9SDimitry Andric ArgType->getAsString() + "'");
1671e8d8bef9SDimitry Andric return nullptr;
1672e8d8bef9SDimitry Andric }
1673e8d8bef9SDimitry Andric break;
1674e8d8bef9SDimitry Andric default: ;
1675e8d8bef9SDimitry Andric }
1676e8d8bef9SDimitry Andric ArgType = nullptr; // Broken invariant: types not identical.
1677e8d8bef9SDimitry Andric break;
16780b57cec5SDimitry Andric default: llvm_unreachable("other ops have fixed argument types");
16790b57cec5SDimitry Andric }
1680e8d8bef9SDimitry Andric
16810b57cec5SDimitry Andric } else {
1682e8d8bef9SDimitry Andric // Desired argument type is a known and in ArgType.
16838bcb0991SDimitry Andric RecTy *Resolved = resolveTypes(ArgType, ListType);
16840b57cec5SDimitry Andric if (!Resolved) {
16850b57cec5SDimitry Andric Error(InitLoc, Twine("expected value of type '") +
16860b57cec5SDimitry Andric ArgType->getAsString() + "', got '" +
16878bcb0991SDimitry Andric ListType->getAsString() + "'");
16880b57cec5SDimitry Andric return nullptr;
16890b57cec5SDimitry Andric }
1690e8d8bef9SDimitry Andric if (Code != BinOpInit::ADD && Code != BinOpInit::SUB &&
1691e8d8bef9SDimitry Andric Code != BinOpInit::AND && Code != BinOpInit::OR &&
1692e8d8bef9SDimitry Andric Code != BinOpInit::XOR && Code != BinOpInit::SRA &&
16930b57cec5SDimitry Andric Code != BinOpInit::SRL && Code != BinOpInit::SHL &&
1694bdd1243dSDimitry Andric Code != BinOpInit::MUL && Code != BinOpInit::DIV)
16950b57cec5SDimitry Andric ArgType = Resolved;
16960b57cec5SDimitry Andric }
16970b57cec5SDimitry Andric
1698480093f4SDimitry Andric // Deal with BinOps whose arguments have different types, by
1699480093f4SDimitry Andric // rewriting ArgType in between them.
1700480093f4SDimitry Andric switch (Code) {
1701e8d8bef9SDimitry Andric case BinOpInit::SETDAGOP:
1702480093f4SDimitry Andric // After parsing the first dag argument, switch to expecting
1703480093f4SDimitry Andric // a record, with no restriction on its superclasses.
170481ad6265SDimitry Andric ArgType = RecordRecTy::get(Records, {});
1705480093f4SDimitry Andric break;
170606c3fb27SDimitry Andric case BinOpInit::GETDAGARG:
170706c3fb27SDimitry Andric // After parsing the first dag argument, expect an index integer or a
170806c3fb27SDimitry Andric // name string.
170906c3fb27SDimitry Andric ArgType = nullptr;
171006c3fb27SDimitry Andric break;
171106c3fb27SDimitry Andric case BinOpInit::GETDAGNAME:
171206c3fb27SDimitry Andric // After parsing the first dag argument, expect an index integer.
171306c3fb27SDimitry Andric ArgType = IntRecTy::get(Records);
171406c3fb27SDimitry Andric break;
1715480093f4SDimitry Andric default:
1716480093f4SDimitry Andric break;
1717480093f4SDimitry Andric }
1718480093f4SDimitry Andric
17195ffd83dbSDimitry Andric if (!consume(tgtok::comma))
17200b57cec5SDimitry Andric break;
17210b57cec5SDimitry Andric }
17220b57cec5SDimitry Andric
17235ffd83dbSDimitry Andric if (!consume(tgtok::r_paren)) {
17240b57cec5SDimitry Andric TokError("expected ')' in operator");
17250b57cec5SDimitry Andric return nullptr;
17260b57cec5SDimitry Andric }
17270b57cec5SDimitry Andric
17280b57cec5SDimitry Andric // listconcat returns a list with type of the argument.
17290b57cec5SDimitry Andric if (Code == BinOpInit::LISTCONCAT)
17300b57cec5SDimitry Andric Type = ArgType;
17310b57cec5SDimitry Andric // listsplat returns a list of type of the *first* argument.
17320b57cec5SDimitry Andric if (Code == BinOpInit::LISTSPLAT)
17330b57cec5SDimitry Andric Type = cast<TypedInit>(InitList.front())->getType()->getListTy();
1734bdd1243dSDimitry Andric // listremove returns a list with type of the argument.
1735bdd1243dSDimitry Andric if (Code == BinOpInit::LISTREMOVE)
1736bdd1243dSDimitry Andric Type = ArgType;
17370b57cec5SDimitry Andric
17380b57cec5SDimitry Andric // We allow multiple operands to associative operators like !strconcat as
17390b57cec5SDimitry Andric // shorthand for nesting them.
17400b57cec5SDimitry Andric if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT ||
17410b57cec5SDimitry Andric Code == BinOpInit::CONCAT || Code == BinOpInit::ADD ||
17420b57cec5SDimitry Andric Code == BinOpInit::AND || Code == BinOpInit::OR ||
1743e8d8bef9SDimitry Andric Code == BinOpInit::XOR || Code == BinOpInit::MUL) {
17440b57cec5SDimitry Andric while (InitList.size() > 2) {
17450b57cec5SDimitry Andric Init *RHS = InitList.pop_back_val();
17460b57cec5SDimitry Andric RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec);
17470b57cec5SDimitry Andric InitList.back() = RHS;
17480b57cec5SDimitry Andric }
17490b57cec5SDimitry Andric }
17500b57cec5SDimitry Andric
17510b57cec5SDimitry Andric if (InitList.size() == 2)
17520b57cec5SDimitry Andric return (BinOpInit::get(Code, InitList[0], InitList[1], Type))
17530b57cec5SDimitry Andric ->Fold(CurRec);
17540b57cec5SDimitry Andric
17550b57cec5SDimitry Andric Error(OpLoc, "expected two operands to operator");
17560b57cec5SDimitry Andric return nullptr;
17570b57cec5SDimitry Andric }
17580b57cec5SDimitry Andric
1759e8d8bef9SDimitry Andric case tgtok::XForEach:
1760e8d8bef9SDimitry Andric case tgtok::XFilter: {
1761e8d8bef9SDimitry Andric return ParseOperationForEachFilter(CurRec, ItemType);
17620b57cec5SDimitry Andric }
17630b57cec5SDimitry Andric
17645f757f3fSDimitry Andric case tgtok::XRange: {
17655f757f3fSDimitry Andric SMLoc OpLoc = Lex.getLoc();
17665f757f3fSDimitry Andric Lex.Lex(); // eat the operation
17675f757f3fSDimitry Andric
17685f757f3fSDimitry Andric if (!consume(tgtok::l_paren)) {
17695f757f3fSDimitry Andric TokError("expected '(' after !range operator");
17705f757f3fSDimitry Andric return nullptr;
17715f757f3fSDimitry Andric }
17725f757f3fSDimitry Andric
17735f757f3fSDimitry Andric SmallVector<Init *, 2> Args;
17745f757f3fSDimitry Andric bool FirstArgIsList = false;
17755f757f3fSDimitry Andric for (;;) {
17765f757f3fSDimitry Andric if (Args.size() >= 3) {
17775f757f3fSDimitry Andric TokError("expected at most three values of integer");
17785f757f3fSDimitry Andric return nullptr;
17795f757f3fSDimitry Andric }
17805f757f3fSDimitry Andric
17815f757f3fSDimitry Andric SMLoc InitLoc = Lex.getLoc();
17825f757f3fSDimitry Andric Args.push_back(ParseValue(CurRec));
17835f757f3fSDimitry Andric if (!Args.back())
17845f757f3fSDimitry Andric return nullptr;
17855f757f3fSDimitry Andric
17865f757f3fSDimitry Andric TypedInit *ArgBack = dyn_cast<TypedInit>(Args.back());
17875f757f3fSDimitry Andric if (!ArgBack) {
17885f757f3fSDimitry Andric Error(OpLoc, Twine("expected value to be a typed value, got '" +
17895f757f3fSDimitry Andric Args.back()->getAsString() + "'"));
17905f757f3fSDimitry Andric return nullptr;
17915f757f3fSDimitry Andric }
17925f757f3fSDimitry Andric
17935f757f3fSDimitry Andric RecTy *ArgBackType = ArgBack->getType();
17945f757f3fSDimitry Andric if (!FirstArgIsList || Args.size() == 1) {
17955f757f3fSDimitry Andric if (Args.size() == 1 && isa<ListRecTy>(ArgBackType)) {
17965f757f3fSDimitry Andric FirstArgIsList = true; // Detect error if 2nd arg were present.
17975f757f3fSDimitry Andric } else if (isa<IntRecTy>(ArgBackType)) {
17985f757f3fSDimitry Andric // Assume 2nd arg should be IntRecTy
17995f757f3fSDimitry Andric } else {
18005f757f3fSDimitry Andric if (Args.size() != 1)
18015f757f3fSDimitry Andric Error(InitLoc, Twine("expected value of type 'int', got '" +
18025f757f3fSDimitry Andric ArgBackType->getAsString() + "'"));
18035f757f3fSDimitry Andric else
18045f757f3fSDimitry Andric Error(InitLoc, Twine("expected list or int, got value of type '") +
18055f757f3fSDimitry Andric ArgBackType->getAsString() + "'");
18065f757f3fSDimitry Andric return nullptr;
18075f757f3fSDimitry Andric }
18085f757f3fSDimitry Andric } else {
18095f757f3fSDimitry Andric // Don't come here unless 1st arg is ListRecTy.
18105f757f3fSDimitry Andric assert(isa<ListRecTy>(cast<TypedInit>(Args[0])->getType()));
18115f757f3fSDimitry Andric Error(InitLoc, Twine("expected one list, got extra value of type '") +
18125f757f3fSDimitry Andric ArgBackType->getAsString() + "'");
18135f757f3fSDimitry Andric return nullptr;
18145f757f3fSDimitry Andric }
18155f757f3fSDimitry Andric if (!consume(tgtok::comma))
18165f757f3fSDimitry Andric break;
18175f757f3fSDimitry Andric }
18185f757f3fSDimitry Andric
18195f757f3fSDimitry Andric if (!consume(tgtok::r_paren)) {
18205f757f3fSDimitry Andric TokError("expected ')' in operator");
18215f757f3fSDimitry Andric return nullptr;
18225f757f3fSDimitry Andric }
18235f757f3fSDimitry Andric
18245f757f3fSDimitry Andric Init *LHS, *MHS, *RHS;
18255f757f3fSDimitry Andric auto ArgCount = Args.size();
18265f757f3fSDimitry Andric assert(ArgCount >= 1);
18275f757f3fSDimitry Andric auto *Arg0 = cast<TypedInit>(Args[0]);
18285f757f3fSDimitry Andric auto *Arg0Ty = Arg0->getType();
18295f757f3fSDimitry Andric if (ArgCount == 1) {
18305f757f3fSDimitry Andric if (isa<ListRecTy>(Arg0Ty)) {
18315f757f3fSDimitry Andric // (0, !size(arg), 1)
18325f757f3fSDimitry Andric LHS = IntInit::get(Records, 0);
18335f757f3fSDimitry Andric MHS = UnOpInit::get(UnOpInit::SIZE, Arg0, IntRecTy::get(Records))
18345f757f3fSDimitry Andric ->Fold(CurRec);
18355f757f3fSDimitry Andric RHS = IntInit::get(Records, 1);
18365f757f3fSDimitry Andric } else {
18375f757f3fSDimitry Andric assert(isa<IntRecTy>(Arg0Ty));
18385f757f3fSDimitry Andric // (0, arg, 1)
18395f757f3fSDimitry Andric LHS = IntInit::get(Records, 0);
18405f757f3fSDimitry Andric MHS = Arg0;
18415f757f3fSDimitry Andric RHS = IntInit::get(Records, 1);
18425f757f3fSDimitry Andric }
18435f757f3fSDimitry Andric } else {
18445f757f3fSDimitry Andric assert(isa<IntRecTy>(Arg0Ty));
18455f757f3fSDimitry Andric auto *Arg1 = cast<TypedInit>(Args[1]);
18465f757f3fSDimitry Andric assert(isa<IntRecTy>(Arg1->getType()));
18475f757f3fSDimitry Andric LHS = Arg0;
18485f757f3fSDimitry Andric MHS = Arg1;
18495f757f3fSDimitry Andric if (ArgCount == 3) {
18505f757f3fSDimitry Andric // (start, end, step)
18515f757f3fSDimitry Andric auto *Arg2 = cast<TypedInit>(Args[2]);
18525f757f3fSDimitry Andric assert(isa<IntRecTy>(Arg2->getType()));
18535f757f3fSDimitry Andric RHS = Arg2;
18545f757f3fSDimitry Andric } else
18555f757f3fSDimitry Andric // (start, end, 1)
18565f757f3fSDimitry Andric RHS = IntInit::get(Records, 1);
18575f757f3fSDimitry Andric }
18585f757f3fSDimitry Andric return TernOpInit::get(TernOpInit::RANGE, LHS, MHS, RHS,
18595f757f3fSDimitry Andric IntRecTy::get(Records)->getListTy())
18605f757f3fSDimitry Andric ->Fold(CurRec);
18615f757f3fSDimitry Andric }
18625f757f3fSDimitry Andric
186306c3fb27SDimitry Andric case tgtok::XSetDagArg:
186406c3fb27SDimitry Andric case tgtok::XSetDagName:
18650b57cec5SDimitry Andric case tgtok::XDag:
18660b57cec5SDimitry Andric case tgtok::XIf:
18670b57cec5SDimitry Andric case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
18680b57cec5SDimitry Andric TernOpInit::TernaryOp Code;
18690b57cec5SDimitry Andric RecTy *Type = nullptr;
18700b57cec5SDimitry Andric
18710b57cec5SDimitry Andric tgtok::TokKind LexCode = Lex.getCode();
18720b57cec5SDimitry Andric Lex.Lex(); // eat the operation
18730b57cec5SDimitry Andric switch (LexCode) {
18740b57cec5SDimitry Andric default: llvm_unreachable("Unhandled code!");
18750b57cec5SDimitry Andric case tgtok::XDag:
18760b57cec5SDimitry Andric Code = TernOpInit::DAG;
187781ad6265SDimitry Andric Type = DagRecTy::get(Records);
18780b57cec5SDimitry Andric ItemType = nullptr;
18790b57cec5SDimitry Andric break;
18800b57cec5SDimitry Andric case tgtok::XIf:
18810b57cec5SDimitry Andric Code = TernOpInit::IF;
18820b57cec5SDimitry Andric break;
18830b57cec5SDimitry Andric case tgtok::XSubst:
18840b57cec5SDimitry Andric Code = TernOpInit::SUBST;
18850b57cec5SDimitry Andric break;
188606c3fb27SDimitry Andric case tgtok::XSetDagArg:
188706c3fb27SDimitry Andric Code = TernOpInit::SETDAGARG;
188806c3fb27SDimitry Andric Type = DagRecTy::get(Records);
188906c3fb27SDimitry Andric ItemType = nullptr;
189006c3fb27SDimitry Andric break;
189106c3fb27SDimitry Andric case tgtok::XSetDagName:
189206c3fb27SDimitry Andric Code = TernOpInit::SETDAGNAME;
189306c3fb27SDimitry Andric Type = DagRecTy::get(Records);
189406c3fb27SDimitry Andric ItemType = nullptr;
189506c3fb27SDimitry Andric break;
18960b57cec5SDimitry Andric }
18975ffd83dbSDimitry Andric if (!consume(tgtok::l_paren)) {
18980b57cec5SDimitry Andric TokError("expected '(' after ternary operator");
18990b57cec5SDimitry Andric return nullptr;
19000b57cec5SDimitry Andric }
19010b57cec5SDimitry Andric
19020b57cec5SDimitry Andric Init *LHS = ParseValue(CurRec);
19030b57cec5SDimitry Andric if (!LHS) return nullptr;
19040b57cec5SDimitry Andric
19055ffd83dbSDimitry Andric if (!consume(tgtok::comma)) {
19060b57cec5SDimitry Andric TokError("expected ',' in ternary operator");
19070b57cec5SDimitry Andric return nullptr;
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric
19100b57cec5SDimitry Andric SMLoc MHSLoc = Lex.getLoc();
19110b57cec5SDimitry Andric Init *MHS = ParseValue(CurRec, ItemType);
19120b57cec5SDimitry Andric if (!MHS)
19130b57cec5SDimitry Andric return nullptr;
19140b57cec5SDimitry Andric
19155ffd83dbSDimitry Andric if (!consume(tgtok::comma)) {
19160b57cec5SDimitry Andric TokError("expected ',' in ternary operator");
19170b57cec5SDimitry Andric return nullptr;
19180b57cec5SDimitry Andric }
19190b57cec5SDimitry Andric
19200b57cec5SDimitry Andric SMLoc RHSLoc = Lex.getLoc();
19210b57cec5SDimitry Andric Init *RHS = ParseValue(CurRec, ItemType);
19220b57cec5SDimitry Andric if (!RHS)
19230b57cec5SDimitry Andric return nullptr;
19240b57cec5SDimitry Andric
19255ffd83dbSDimitry Andric if (!consume(tgtok::r_paren)) {
19260b57cec5SDimitry Andric TokError("expected ')' in binary operator");
19270b57cec5SDimitry Andric return nullptr;
19280b57cec5SDimitry Andric }
19290b57cec5SDimitry Andric
19300b57cec5SDimitry Andric switch (LexCode) {
19310b57cec5SDimitry Andric default: llvm_unreachable("Unhandled code!");
19320b57cec5SDimitry Andric case tgtok::XDag: {
19330b57cec5SDimitry Andric TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
19340b57cec5SDimitry Andric if (!MHSt && !isa<UnsetInit>(MHS)) {
19350b57cec5SDimitry Andric Error(MHSLoc, "could not determine type of the child list in !dag");
19360b57cec5SDimitry Andric return nullptr;
19370b57cec5SDimitry Andric }
19380b57cec5SDimitry Andric if (MHSt && !isa<ListRecTy>(MHSt->getType())) {
19390b57cec5SDimitry Andric Error(MHSLoc, Twine("expected list of children, got type '") +
19400b57cec5SDimitry Andric MHSt->getType()->getAsString() + "'");
19410b57cec5SDimitry Andric return nullptr;
19420b57cec5SDimitry Andric }
19430b57cec5SDimitry Andric
19440b57cec5SDimitry Andric TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
19450b57cec5SDimitry Andric if (!RHSt && !isa<UnsetInit>(RHS)) {
19460b57cec5SDimitry Andric Error(RHSLoc, "could not determine type of the name list in !dag");
19470b57cec5SDimitry Andric return nullptr;
19480b57cec5SDimitry Andric }
194981ad6265SDimitry Andric if (RHSt && StringRecTy::get(Records)->getListTy() != RHSt->getType()) {
19500b57cec5SDimitry Andric Error(RHSLoc, Twine("expected list<string>, got type '") +
19510b57cec5SDimitry Andric RHSt->getType()->getAsString() + "'");
19520b57cec5SDimitry Andric return nullptr;
19530b57cec5SDimitry Andric }
19540b57cec5SDimitry Andric
19550b57cec5SDimitry Andric if (!MHSt && !RHSt) {
19560b57cec5SDimitry Andric Error(MHSLoc,
19570b57cec5SDimitry Andric "cannot have both unset children and unset names in !dag");
19580b57cec5SDimitry Andric return nullptr;
19590b57cec5SDimitry Andric }
19600b57cec5SDimitry Andric break;
19610b57cec5SDimitry Andric }
19620b57cec5SDimitry Andric case tgtok::XIf: {
19630b57cec5SDimitry Andric RecTy *MHSTy = nullptr;
19640b57cec5SDimitry Andric RecTy *RHSTy = nullptr;
19650b57cec5SDimitry Andric
19660b57cec5SDimitry Andric if (TypedInit *MHSt = dyn_cast<TypedInit>(MHS))
19670b57cec5SDimitry Andric MHSTy = MHSt->getType();
19680b57cec5SDimitry Andric if (BitsInit *MHSbits = dyn_cast<BitsInit>(MHS))
196981ad6265SDimitry Andric MHSTy = BitsRecTy::get(Records, MHSbits->getNumBits());
19700b57cec5SDimitry Andric if (isa<BitInit>(MHS))
197181ad6265SDimitry Andric MHSTy = BitRecTy::get(Records);
19720b57cec5SDimitry Andric
19730b57cec5SDimitry Andric if (TypedInit *RHSt = dyn_cast<TypedInit>(RHS))
19740b57cec5SDimitry Andric RHSTy = RHSt->getType();
19750b57cec5SDimitry Andric if (BitsInit *RHSbits = dyn_cast<BitsInit>(RHS))
197681ad6265SDimitry Andric RHSTy = BitsRecTy::get(Records, RHSbits->getNumBits());
19770b57cec5SDimitry Andric if (isa<BitInit>(RHS))
197881ad6265SDimitry Andric RHSTy = BitRecTy::get(Records);
19790b57cec5SDimitry Andric
19800b57cec5SDimitry Andric // For UnsetInit, it's typed from the other hand.
19810b57cec5SDimitry Andric if (isa<UnsetInit>(MHS))
19820b57cec5SDimitry Andric MHSTy = RHSTy;
19830b57cec5SDimitry Andric if (isa<UnsetInit>(RHS))
19840b57cec5SDimitry Andric RHSTy = MHSTy;
19850b57cec5SDimitry Andric
19860b57cec5SDimitry Andric if (!MHSTy || !RHSTy) {
19870b57cec5SDimitry Andric TokError("could not get type for !if");
19880b57cec5SDimitry Andric return nullptr;
19890b57cec5SDimitry Andric }
19900b57cec5SDimitry Andric
19910b57cec5SDimitry Andric Type = resolveTypes(MHSTy, RHSTy);
19920b57cec5SDimitry Andric if (!Type) {
19930b57cec5SDimitry Andric TokError(Twine("inconsistent types '") + MHSTy->getAsString() +
19940b57cec5SDimitry Andric "' and '" + RHSTy->getAsString() + "' for !if");
19950b57cec5SDimitry Andric return nullptr;
19960b57cec5SDimitry Andric }
19970b57cec5SDimitry Andric break;
19980b57cec5SDimitry Andric }
19990b57cec5SDimitry Andric case tgtok::XSubst: {
20000b57cec5SDimitry Andric TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
20010b57cec5SDimitry Andric if (!RHSt) {
20020b57cec5SDimitry Andric TokError("could not get type for !subst");
20030b57cec5SDimitry Andric return nullptr;
20040b57cec5SDimitry Andric }
20050b57cec5SDimitry Andric Type = RHSt->getType();
20060b57cec5SDimitry Andric break;
20070b57cec5SDimitry Andric }
200806c3fb27SDimitry Andric case tgtok::XSetDagArg: {
200906c3fb27SDimitry Andric TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
201006c3fb27SDimitry Andric if (!MHSt || !isa<IntRecTy, StringRecTy>(MHSt->getType())) {
201106c3fb27SDimitry Andric Error(MHSLoc, Twine("expected integer index or string name, got ") +
201206c3fb27SDimitry Andric (MHSt ? ("type '" + MHSt->getType()->getAsString())
201306c3fb27SDimitry Andric : ("'" + MHS->getAsString())) +
201406c3fb27SDimitry Andric "'");
201506c3fb27SDimitry Andric return nullptr;
201606c3fb27SDimitry Andric }
201706c3fb27SDimitry Andric break;
201806c3fb27SDimitry Andric }
201906c3fb27SDimitry Andric case tgtok::XSetDagName: {
202006c3fb27SDimitry Andric TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
202106c3fb27SDimitry Andric if (!MHSt || !isa<IntRecTy, StringRecTy>(MHSt->getType())) {
202206c3fb27SDimitry Andric Error(MHSLoc, Twine("expected integer index or string name, got ") +
202306c3fb27SDimitry Andric (MHSt ? ("type '" + MHSt->getType()->getAsString())
202406c3fb27SDimitry Andric : ("'" + MHS->getAsString())) +
202506c3fb27SDimitry Andric "'");
202606c3fb27SDimitry Andric return nullptr;
202706c3fb27SDimitry Andric }
202806c3fb27SDimitry Andric TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
202906c3fb27SDimitry Andric // The name could be a string or unset.
203006c3fb27SDimitry Andric if (RHSt && !isa<StringRecTy>(RHSt->getType())) {
203106c3fb27SDimitry Andric Error(RHSLoc, Twine("expected string or unset name, got type '") +
203206c3fb27SDimitry Andric RHSt->getType()->getAsString() + "'");
203306c3fb27SDimitry Andric return nullptr;
203406c3fb27SDimitry Andric }
203506c3fb27SDimitry Andric break;
203606c3fb27SDimitry Andric }
20370b57cec5SDimitry Andric }
20380b57cec5SDimitry Andric return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);
20390b57cec5SDimitry Andric }
20400b57cec5SDimitry Andric
2041e8d8bef9SDimitry Andric case tgtok::XSubstr:
2042e8d8bef9SDimitry Andric return ParseOperationSubstr(CurRec, ItemType);
2043e8d8bef9SDimitry Andric
2044fe6060f1SDimitry Andric case tgtok::XFind:
2045fe6060f1SDimitry Andric return ParseOperationFind(CurRec, ItemType);
2046fe6060f1SDimitry Andric
20470b57cec5SDimitry Andric case tgtok::XCond:
20480b57cec5SDimitry Andric return ParseOperationCond(CurRec, ItemType);
20490b57cec5SDimitry Andric
20500b57cec5SDimitry Andric case tgtok::XFoldl: {
2051e8d8bef9SDimitry Andric // Value ::= !foldl '(' Value ',' Value ',' Id ',' Id ',' Expr ')'
20520b57cec5SDimitry Andric Lex.Lex(); // eat the operation
20535ffd83dbSDimitry Andric if (!consume(tgtok::l_paren)) {
20540b57cec5SDimitry Andric TokError("expected '(' after !foldl");
20550b57cec5SDimitry Andric return nullptr;
20560b57cec5SDimitry Andric }
20570b57cec5SDimitry Andric
20580b57cec5SDimitry Andric Init *StartUntyped = ParseValue(CurRec);
20590b57cec5SDimitry Andric if (!StartUntyped)
20600b57cec5SDimitry Andric return nullptr;
20610b57cec5SDimitry Andric
20620b57cec5SDimitry Andric TypedInit *Start = dyn_cast<TypedInit>(StartUntyped);
20630b57cec5SDimitry Andric if (!Start) {
20640b57cec5SDimitry Andric TokError(Twine("could not get type of !foldl start: '") +
20650b57cec5SDimitry Andric StartUntyped->getAsString() + "'");
20660b57cec5SDimitry Andric return nullptr;
20670b57cec5SDimitry Andric }
20680b57cec5SDimitry Andric
20695ffd83dbSDimitry Andric if (!consume(tgtok::comma)) {
20700b57cec5SDimitry Andric TokError("expected ',' in !foldl");
20710b57cec5SDimitry Andric return nullptr;
20720b57cec5SDimitry Andric }
20730b57cec5SDimitry Andric
20740b57cec5SDimitry Andric Init *ListUntyped = ParseValue(CurRec);
20750b57cec5SDimitry Andric if (!ListUntyped)
20760b57cec5SDimitry Andric return nullptr;
20770b57cec5SDimitry Andric
20780b57cec5SDimitry Andric TypedInit *List = dyn_cast<TypedInit>(ListUntyped);
20790b57cec5SDimitry Andric if (!List) {
20800b57cec5SDimitry Andric TokError(Twine("could not get type of !foldl list: '") +
20810b57cec5SDimitry Andric ListUntyped->getAsString() + "'");
20820b57cec5SDimitry Andric return nullptr;
20830b57cec5SDimitry Andric }
20840b57cec5SDimitry Andric
20850b57cec5SDimitry Andric ListRecTy *ListType = dyn_cast<ListRecTy>(List->getType());
20860b57cec5SDimitry Andric if (!ListType) {
20870b57cec5SDimitry Andric TokError(Twine("!foldl list must be a list, but is of type '") +
20880b57cec5SDimitry Andric List->getType()->getAsString());
20890b57cec5SDimitry Andric return nullptr;
20900b57cec5SDimitry Andric }
20910b57cec5SDimitry Andric
20920b57cec5SDimitry Andric if (Lex.getCode() != tgtok::comma) {
20930b57cec5SDimitry Andric TokError("expected ',' in !foldl");
20940b57cec5SDimitry Andric return nullptr;
20950b57cec5SDimitry Andric }
20960b57cec5SDimitry Andric
20970b57cec5SDimitry Andric if (Lex.Lex() != tgtok::Id) { // eat the ','
20980b57cec5SDimitry Andric TokError("third argument of !foldl must be an identifier");
20990b57cec5SDimitry Andric return nullptr;
21000b57cec5SDimitry Andric }
21010b57cec5SDimitry Andric
210281ad6265SDimitry Andric Init *A = StringInit::get(Records, Lex.getCurStrVal());
21030b57cec5SDimitry Andric if (CurRec && CurRec->getValue(A)) {
21040b57cec5SDimitry Andric TokError((Twine("left !foldl variable '") + A->getAsString() +
21050b57cec5SDimitry Andric "' already defined")
21060b57cec5SDimitry Andric .str());
21070b57cec5SDimitry Andric return nullptr;
21080b57cec5SDimitry Andric }
21090b57cec5SDimitry Andric
21100b57cec5SDimitry Andric if (Lex.Lex() != tgtok::comma) { // eat the id
21110b57cec5SDimitry Andric TokError("expected ',' in !foldl");
21120b57cec5SDimitry Andric return nullptr;
21130b57cec5SDimitry Andric }
21140b57cec5SDimitry Andric
21150b57cec5SDimitry Andric if (Lex.Lex() != tgtok::Id) { // eat the ','
21160b57cec5SDimitry Andric TokError("fourth argument of !foldl must be an identifier");
21170b57cec5SDimitry Andric return nullptr;
21180b57cec5SDimitry Andric }
21190b57cec5SDimitry Andric
212081ad6265SDimitry Andric Init *B = StringInit::get(Records, Lex.getCurStrVal());
21210b57cec5SDimitry Andric if (CurRec && CurRec->getValue(B)) {
21220b57cec5SDimitry Andric TokError((Twine("right !foldl variable '") + B->getAsString() +
21230b57cec5SDimitry Andric "' already defined")
21240b57cec5SDimitry Andric .str());
21250b57cec5SDimitry Andric return nullptr;
21260b57cec5SDimitry Andric }
21270b57cec5SDimitry Andric
21280b57cec5SDimitry Andric if (Lex.Lex() != tgtok::comma) { // eat the id
21290b57cec5SDimitry Andric TokError("expected ',' in !foldl");
21300b57cec5SDimitry Andric return nullptr;
21310b57cec5SDimitry Andric }
21320b57cec5SDimitry Andric Lex.Lex(); // eat the ','
21330b57cec5SDimitry Andric
2134e8d8bef9SDimitry Andric // We need to create a temporary record to provide a scope for the
2135e8d8bef9SDimitry Andric // two variables.
21360b57cec5SDimitry Andric std::unique_ptr<Record> ParseRecTmp;
21370b57cec5SDimitry Andric Record *ParseRec = CurRec;
21380b57cec5SDimitry Andric if (!ParseRec) {
21398bcb0991SDimitry Andric ParseRecTmp = std::make_unique<Record>(".parse", ArrayRef<SMLoc>{}, Records);
21400b57cec5SDimitry Andric ParseRec = ParseRecTmp.get();
21410b57cec5SDimitry Andric }
21420b57cec5SDimitry Andric
214306c3fb27SDimitry Andric TGVarScope *FoldScope = PushScope(ParseRec);
2144e8d8bef9SDimitry Andric ParseRec->addValue(RecordVal(A, Start->getType(), RecordVal::FK_Normal));
214506c3fb27SDimitry Andric ParseRec->addValue(
214606c3fb27SDimitry Andric RecordVal(B, ListType->getElementType(), RecordVal::FK_Normal));
21470b57cec5SDimitry Andric Init *ExprUntyped = ParseValue(ParseRec);
21480b57cec5SDimitry Andric ParseRec->removeValue(A);
21490b57cec5SDimitry Andric ParseRec->removeValue(B);
215006c3fb27SDimitry Andric PopScope(FoldScope);
21510b57cec5SDimitry Andric if (!ExprUntyped)
21520b57cec5SDimitry Andric return nullptr;
21530b57cec5SDimitry Andric
21540b57cec5SDimitry Andric TypedInit *Expr = dyn_cast<TypedInit>(ExprUntyped);
21550b57cec5SDimitry Andric if (!Expr) {
21560b57cec5SDimitry Andric TokError("could not get type of !foldl expression");
21570b57cec5SDimitry Andric return nullptr;
21580b57cec5SDimitry Andric }
21590b57cec5SDimitry Andric
21600b57cec5SDimitry Andric if (Expr->getType() != Start->getType()) {
21610b57cec5SDimitry Andric TokError(Twine("!foldl expression must be of same type as start (") +
21620b57cec5SDimitry Andric Start->getType()->getAsString() + "), but is of type " +
21630b57cec5SDimitry Andric Expr->getType()->getAsString());
21640b57cec5SDimitry Andric return nullptr;
21650b57cec5SDimitry Andric }
21660b57cec5SDimitry Andric
21675ffd83dbSDimitry Andric if (!consume(tgtok::r_paren)) {
21680b57cec5SDimitry Andric TokError("expected ')' in fold operator");
21690b57cec5SDimitry Andric return nullptr;
21700b57cec5SDimitry Andric }
21710b57cec5SDimitry Andric
21720b57cec5SDimitry Andric return FoldOpInit::get(Start, List, A, B, Expr, Start->getType())
21730b57cec5SDimitry Andric ->Fold(CurRec);
21740b57cec5SDimitry Andric }
21750b57cec5SDimitry Andric }
21760b57cec5SDimitry Andric }
21770b57cec5SDimitry Andric
21780b57cec5SDimitry Andric /// ParseOperatorType - Parse a type for an operator. This returns
21790b57cec5SDimitry Andric /// null on error.
21800b57cec5SDimitry Andric ///
21810b57cec5SDimitry Andric /// OperatorType ::= '<' Type '>'
21820b57cec5SDimitry Andric ///
ParseOperatorType()21830b57cec5SDimitry Andric RecTy *TGParser::ParseOperatorType() {
21840b57cec5SDimitry Andric RecTy *Type = nullptr;
21850b57cec5SDimitry Andric
21865ffd83dbSDimitry Andric if (!consume(tgtok::less)) {
21870b57cec5SDimitry Andric TokError("expected type name for operator");
21880b57cec5SDimitry Andric return nullptr;
21890b57cec5SDimitry Andric }
21900b57cec5SDimitry Andric
2191e8d8bef9SDimitry Andric if (Lex.getCode() == tgtok::Code)
2192e8d8bef9SDimitry Andric TokError("the 'code' type is not allowed in bang operators; use 'string'");
2193e8d8bef9SDimitry Andric
21940b57cec5SDimitry Andric Type = ParseType();
21950b57cec5SDimitry Andric
21960b57cec5SDimitry Andric if (!Type) {
21970b57cec5SDimitry Andric TokError("expected type name for operator");
21980b57cec5SDimitry Andric return nullptr;
21990b57cec5SDimitry Andric }
22000b57cec5SDimitry Andric
22015ffd83dbSDimitry Andric if (!consume(tgtok::greater)) {
22020b57cec5SDimitry Andric TokError("expected type name for operator");
22030b57cec5SDimitry Andric return nullptr;
22040b57cec5SDimitry Andric }
22050b57cec5SDimitry Andric
22060b57cec5SDimitry Andric return Type;
22070b57cec5SDimitry Andric }
22080b57cec5SDimitry Andric
2209e8d8bef9SDimitry Andric /// Parse the !substr operation. Return null on error.
2210e8d8bef9SDimitry Andric ///
2211e8d8bef9SDimitry Andric /// Substr ::= !substr(string, start-int [, length-int]) => string
ParseOperationSubstr(Record * CurRec,RecTy * ItemType)2212e8d8bef9SDimitry Andric Init *TGParser::ParseOperationSubstr(Record *CurRec, RecTy *ItemType) {
2213e8d8bef9SDimitry Andric TernOpInit::TernaryOp Code = TernOpInit::SUBSTR;
221481ad6265SDimitry Andric RecTy *Type = StringRecTy::get(Records);
2215e8d8bef9SDimitry Andric
2216e8d8bef9SDimitry Andric Lex.Lex(); // eat the operation
2217e8d8bef9SDimitry Andric
2218e8d8bef9SDimitry Andric if (!consume(tgtok::l_paren)) {
2219e8d8bef9SDimitry Andric TokError("expected '(' after !substr operator");
2220e8d8bef9SDimitry Andric return nullptr;
2221e8d8bef9SDimitry Andric }
2222e8d8bef9SDimitry Andric
2223e8d8bef9SDimitry Andric Init *LHS = ParseValue(CurRec);
2224e8d8bef9SDimitry Andric if (!LHS)
2225e8d8bef9SDimitry Andric return nullptr;
2226e8d8bef9SDimitry Andric
2227e8d8bef9SDimitry Andric if (!consume(tgtok::comma)) {
2228e8d8bef9SDimitry Andric TokError("expected ',' in !substr operator");
2229e8d8bef9SDimitry Andric return nullptr;
2230e8d8bef9SDimitry Andric }
2231e8d8bef9SDimitry Andric
2232e8d8bef9SDimitry Andric SMLoc MHSLoc = Lex.getLoc();
2233e8d8bef9SDimitry Andric Init *MHS = ParseValue(CurRec);
2234e8d8bef9SDimitry Andric if (!MHS)
2235e8d8bef9SDimitry Andric return nullptr;
2236e8d8bef9SDimitry Andric
2237e8d8bef9SDimitry Andric SMLoc RHSLoc = Lex.getLoc();
2238e8d8bef9SDimitry Andric Init *RHS;
2239e8d8bef9SDimitry Andric if (consume(tgtok::comma)) {
2240e8d8bef9SDimitry Andric RHSLoc = Lex.getLoc();
2241e8d8bef9SDimitry Andric RHS = ParseValue(CurRec);
2242e8d8bef9SDimitry Andric if (!RHS)
2243e8d8bef9SDimitry Andric return nullptr;
2244e8d8bef9SDimitry Andric } else {
224581ad6265SDimitry Andric RHS = IntInit::get(Records, std::numeric_limits<int64_t>::max());
2246e8d8bef9SDimitry Andric }
2247e8d8bef9SDimitry Andric
2248e8d8bef9SDimitry Andric if (!consume(tgtok::r_paren)) {
2249e8d8bef9SDimitry Andric TokError("expected ')' in !substr operator");
2250e8d8bef9SDimitry Andric return nullptr;
2251e8d8bef9SDimitry Andric }
2252e8d8bef9SDimitry Andric
2253e8d8bef9SDimitry Andric if (ItemType && !Type->typeIsConvertibleTo(ItemType)) {
2254e8d8bef9SDimitry Andric Error(RHSLoc, Twine("expected value of type '") +
2255e8d8bef9SDimitry Andric ItemType->getAsString() + "', got '" +
2256e8d8bef9SDimitry Andric Type->getAsString() + "'");
2257e8d8bef9SDimitry Andric }
2258e8d8bef9SDimitry Andric
2259e8d8bef9SDimitry Andric TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
2260e8d8bef9SDimitry Andric if (!LHSt && !isa<UnsetInit>(LHS)) {
2261e8d8bef9SDimitry Andric TokError("could not determine type of the string in !substr");
2262e8d8bef9SDimitry Andric return nullptr;
2263e8d8bef9SDimitry Andric }
2264e8d8bef9SDimitry Andric if (LHSt && !isa<StringRecTy>(LHSt->getType())) {
2265e8d8bef9SDimitry Andric TokError(Twine("expected string, got type '") +
2266e8d8bef9SDimitry Andric LHSt->getType()->getAsString() + "'");
2267e8d8bef9SDimitry Andric return nullptr;
2268e8d8bef9SDimitry Andric }
2269e8d8bef9SDimitry Andric
2270e8d8bef9SDimitry Andric TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
2271e8d8bef9SDimitry Andric if (!MHSt && !isa<UnsetInit>(MHS)) {
2272e8d8bef9SDimitry Andric TokError("could not determine type of the start position in !substr");
2273e8d8bef9SDimitry Andric return nullptr;
2274e8d8bef9SDimitry Andric }
2275e8d8bef9SDimitry Andric if (MHSt && !isa<IntRecTy>(MHSt->getType())) {
2276e8d8bef9SDimitry Andric Error(MHSLoc, Twine("expected int, got type '") +
2277e8d8bef9SDimitry Andric MHSt->getType()->getAsString() + "'");
2278e8d8bef9SDimitry Andric return nullptr;
2279e8d8bef9SDimitry Andric }
2280e8d8bef9SDimitry Andric
2281e8d8bef9SDimitry Andric if (RHS) {
2282e8d8bef9SDimitry Andric TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
2283e8d8bef9SDimitry Andric if (!RHSt && !isa<UnsetInit>(RHS)) {
2284e8d8bef9SDimitry Andric TokError("could not determine type of the length in !substr");
2285e8d8bef9SDimitry Andric return nullptr;
2286e8d8bef9SDimitry Andric }
2287e8d8bef9SDimitry Andric if (RHSt && !isa<IntRecTy>(RHSt->getType())) {
2288e8d8bef9SDimitry Andric TokError(Twine("expected int, got type '") +
2289e8d8bef9SDimitry Andric RHSt->getType()->getAsString() + "'");
2290e8d8bef9SDimitry Andric return nullptr;
2291e8d8bef9SDimitry Andric }
2292e8d8bef9SDimitry Andric }
2293e8d8bef9SDimitry Andric
2294e8d8bef9SDimitry Andric return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);
2295e8d8bef9SDimitry Andric }
2296e8d8bef9SDimitry Andric
2297fe6060f1SDimitry Andric /// Parse the !find operation. Return null on error.
2298fe6060f1SDimitry Andric ///
2299fe6060f1SDimitry Andric /// Substr ::= !find(string, string [, start-int]) => int
ParseOperationFind(Record * CurRec,RecTy * ItemType)2300fe6060f1SDimitry Andric Init *TGParser::ParseOperationFind(Record *CurRec, RecTy *ItemType) {
2301fe6060f1SDimitry Andric TernOpInit::TernaryOp Code = TernOpInit::FIND;
230281ad6265SDimitry Andric RecTy *Type = IntRecTy::get(Records);
2303fe6060f1SDimitry Andric
2304fe6060f1SDimitry Andric Lex.Lex(); // eat the operation
2305fe6060f1SDimitry Andric
2306fe6060f1SDimitry Andric if (!consume(tgtok::l_paren)) {
2307fe6060f1SDimitry Andric TokError("expected '(' after !find operator");
2308fe6060f1SDimitry Andric return nullptr;
2309fe6060f1SDimitry Andric }
2310fe6060f1SDimitry Andric
2311fe6060f1SDimitry Andric Init *LHS = ParseValue(CurRec);
2312fe6060f1SDimitry Andric if (!LHS)
2313fe6060f1SDimitry Andric return nullptr;
2314fe6060f1SDimitry Andric
2315fe6060f1SDimitry Andric if (!consume(tgtok::comma)) {
2316fe6060f1SDimitry Andric TokError("expected ',' in !find operator");
2317fe6060f1SDimitry Andric return nullptr;
2318fe6060f1SDimitry Andric }
2319fe6060f1SDimitry Andric
2320fe6060f1SDimitry Andric SMLoc MHSLoc = Lex.getLoc();
2321fe6060f1SDimitry Andric Init *MHS = ParseValue(CurRec);
2322fe6060f1SDimitry Andric if (!MHS)
2323fe6060f1SDimitry Andric return nullptr;
2324fe6060f1SDimitry Andric
2325fe6060f1SDimitry Andric SMLoc RHSLoc = Lex.getLoc();
2326fe6060f1SDimitry Andric Init *RHS;
2327fe6060f1SDimitry Andric if (consume(tgtok::comma)) {
2328fe6060f1SDimitry Andric RHSLoc = Lex.getLoc();
2329fe6060f1SDimitry Andric RHS = ParseValue(CurRec);
2330fe6060f1SDimitry Andric if (!RHS)
2331fe6060f1SDimitry Andric return nullptr;
2332fe6060f1SDimitry Andric } else {
233381ad6265SDimitry Andric RHS = IntInit::get(Records, 0);
2334fe6060f1SDimitry Andric }
2335fe6060f1SDimitry Andric
2336fe6060f1SDimitry Andric if (!consume(tgtok::r_paren)) {
2337fe6060f1SDimitry Andric TokError("expected ')' in !find operator");
2338fe6060f1SDimitry Andric return nullptr;
2339fe6060f1SDimitry Andric }
2340fe6060f1SDimitry Andric
2341fe6060f1SDimitry Andric if (ItemType && !Type->typeIsConvertibleTo(ItemType)) {
2342fe6060f1SDimitry Andric Error(RHSLoc, Twine("expected value of type '") +
2343fe6060f1SDimitry Andric ItemType->getAsString() + "', got '" +
2344fe6060f1SDimitry Andric Type->getAsString() + "'");
2345fe6060f1SDimitry Andric }
2346fe6060f1SDimitry Andric
2347fe6060f1SDimitry Andric TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
2348fe6060f1SDimitry Andric if (!LHSt && !isa<UnsetInit>(LHS)) {
2349fe6060f1SDimitry Andric TokError("could not determine type of the source string in !find");
2350fe6060f1SDimitry Andric return nullptr;
2351fe6060f1SDimitry Andric }
2352fe6060f1SDimitry Andric if (LHSt && !isa<StringRecTy>(LHSt->getType())) {
2353fe6060f1SDimitry Andric TokError(Twine("expected string, got type '") +
2354fe6060f1SDimitry Andric LHSt->getType()->getAsString() + "'");
2355fe6060f1SDimitry Andric return nullptr;
2356fe6060f1SDimitry Andric }
2357fe6060f1SDimitry Andric
2358fe6060f1SDimitry Andric TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
2359fe6060f1SDimitry Andric if (!MHSt && !isa<UnsetInit>(MHS)) {
2360fe6060f1SDimitry Andric TokError("could not determine type of the target string in !find");
2361fe6060f1SDimitry Andric return nullptr;
2362fe6060f1SDimitry Andric }
2363fe6060f1SDimitry Andric if (MHSt && !isa<StringRecTy>(MHSt->getType())) {
2364fe6060f1SDimitry Andric Error(MHSLoc, Twine("expected string, got type '") +
2365fe6060f1SDimitry Andric MHSt->getType()->getAsString() + "'");
2366fe6060f1SDimitry Andric return nullptr;
2367fe6060f1SDimitry Andric }
2368fe6060f1SDimitry Andric
2369fe6060f1SDimitry Andric if (RHS) {
2370fe6060f1SDimitry Andric TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
2371fe6060f1SDimitry Andric if (!RHSt && !isa<UnsetInit>(RHS)) {
2372fe6060f1SDimitry Andric TokError("could not determine type of the start position in !find");
2373fe6060f1SDimitry Andric return nullptr;
2374fe6060f1SDimitry Andric }
2375fe6060f1SDimitry Andric if (RHSt && !isa<IntRecTy>(RHSt->getType())) {
2376fe6060f1SDimitry Andric TokError(Twine("expected int, got type '") +
2377fe6060f1SDimitry Andric RHSt->getType()->getAsString() + "'");
2378fe6060f1SDimitry Andric return nullptr;
2379fe6060f1SDimitry Andric }
2380fe6060f1SDimitry Andric }
2381fe6060f1SDimitry Andric
2382fe6060f1SDimitry Andric return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);
2383fe6060f1SDimitry Andric }
2384fe6060f1SDimitry Andric
2385e8d8bef9SDimitry Andric /// Parse the !foreach and !filter operations. Return null on error.
2386e8d8bef9SDimitry Andric ///
2387e8d8bef9SDimitry Andric /// ForEach ::= !foreach(ID, list-or-dag, expr) => list<expr type>
2388e8d8bef9SDimitry Andric /// Filter ::= !foreach(ID, list, predicate) ==> list<list type>
ParseOperationForEachFilter(Record * CurRec,RecTy * ItemType)2389e8d8bef9SDimitry Andric Init *TGParser::ParseOperationForEachFilter(Record *CurRec, RecTy *ItemType) {
2390e8d8bef9SDimitry Andric SMLoc OpLoc = Lex.getLoc();
2391e8d8bef9SDimitry Andric tgtok::TokKind Operation = Lex.getCode();
2392e8d8bef9SDimitry Andric Lex.Lex(); // eat the operation
2393e8d8bef9SDimitry Andric if (Lex.getCode() != tgtok::l_paren) {
2394e8d8bef9SDimitry Andric TokError("expected '(' after !foreach/!filter");
2395e8d8bef9SDimitry Andric return nullptr;
2396e8d8bef9SDimitry Andric }
2397e8d8bef9SDimitry Andric
2398e8d8bef9SDimitry Andric if (Lex.Lex() != tgtok::Id) { // eat the '('
2399e8d8bef9SDimitry Andric TokError("first argument of !foreach/!filter must be an identifier");
2400e8d8bef9SDimitry Andric return nullptr;
2401e8d8bef9SDimitry Andric }
2402e8d8bef9SDimitry Andric
240381ad6265SDimitry Andric Init *LHS = StringInit::get(Records, Lex.getCurStrVal());
2404e8d8bef9SDimitry Andric Lex.Lex(); // eat the ID.
2405e8d8bef9SDimitry Andric
2406e8d8bef9SDimitry Andric if (CurRec && CurRec->getValue(LHS)) {
2407e8d8bef9SDimitry Andric TokError((Twine("iteration variable '") + LHS->getAsString() +
2408e8d8bef9SDimitry Andric "' is already defined")
2409e8d8bef9SDimitry Andric .str());
2410e8d8bef9SDimitry Andric return nullptr;
2411e8d8bef9SDimitry Andric }
2412e8d8bef9SDimitry Andric
2413e8d8bef9SDimitry Andric if (!consume(tgtok::comma)) {
2414e8d8bef9SDimitry Andric TokError("expected ',' in !foreach/!filter");
2415e8d8bef9SDimitry Andric return nullptr;
2416e8d8bef9SDimitry Andric }
2417e8d8bef9SDimitry Andric
2418e8d8bef9SDimitry Andric Init *MHS = ParseValue(CurRec);
2419e8d8bef9SDimitry Andric if (!MHS)
2420e8d8bef9SDimitry Andric return nullptr;
2421e8d8bef9SDimitry Andric
2422e8d8bef9SDimitry Andric if (!consume(tgtok::comma)) {
2423e8d8bef9SDimitry Andric TokError("expected ',' in !foreach/!filter");
2424e8d8bef9SDimitry Andric return nullptr;
2425e8d8bef9SDimitry Andric }
2426e8d8bef9SDimitry Andric
2427e8d8bef9SDimitry Andric TypedInit *MHSt = dyn_cast<TypedInit>(MHS);
2428e8d8bef9SDimitry Andric if (!MHSt) {
2429e8d8bef9SDimitry Andric TokError("could not get type of !foreach/!filter list or dag");
2430e8d8bef9SDimitry Andric return nullptr;
2431e8d8bef9SDimitry Andric }
2432e8d8bef9SDimitry Andric
2433e8d8bef9SDimitry Andric RecTy *InEltType = nullptr;
2434e8d8bef9SDimitry Andric RecTy *ExprEltType = nullptr;
2435e8d8bef9SDimitry Andric bool IsDAG = false;
2436e8d8bef9SDimitry Andric
2437e8d8bef9SDimitry Andric if (ListRecTy *InListTy = dyn_cast<ListRecTy>(MHSt->getType())) {
2438e8d8bef9SDimitry Andric InEltType = InListTy->getElementType();
2439e8d8bef9SDimitry Andric if (ItemType) {
2440e8d8bef9SDimitry Andric if (ListRecTy *OutListTy = dyn_cast<ListRecTy>(ItemType)) {
2441e8d8bef9SDimitry Andric ExprEltType = (Operation == tgtok::XForEach)
2442e8d8bef9SDimitry Andric ? OutListTy->getElementType()
244381ad6265SDimitry Andric : IntRecTy::get(Records);
2444e8d8bef9SDimitry Andric } else {
2445e8d8bef9SDimitry Andric Error(OpLoc,
2446e8d8bef9SDimitry Andric "expected value of type '" +
2447e8d8bef9SDimitry Andric Twine(ItemType->getAsString()) +
2448e8d8bef9SDimitry Andric "', but got list type");
2449e8d8bef9SDimitry Andric return nullptr;
2450e8d8bef9SDimitry Andric }
2451e8d8bef9SDimitry Andric }
2452e8d8bef9SDimitry Andric } else if (DagRecTy *InDagTy = dyn_cast<DagRecTy>(MHSt->getType())) {
2453e8d8bef9SDimitry Andric if (Operation == tgtok::XFilter) {
2454e8d8bef9SDimitry Andric TokError("!filter must have a list argument");
2455e8d8bef9SDimitry Andric return nullptr;
2456e8d8bef9SDimitry Andric }
2457e8d8bef9SDimitry Andric InEltType = InDagTy;
2458e8d8bef9SDimitry Andric if (ItemType && !isa<DagRecTy>(ItemType)) {
2459e8d8bef9SDimitry Andric Error(OpLoc,
2460e8d8bef9SDimitry Andric "expected value of type '" + Twine(ItemType->getAsString()) +
2461e8d8bef9SDimitry Andric "', but got dag type");
2462e8d8bef9SDimitry Andric return nullptr;
2463e8d8bef9SDimitry Andric }
2464e8d8bef9SDimitry Andric IsDAG = true;
2465e8d8bef9SDimitry Andric } else {
2466e8d8bef9SDimitry Andric if (Operation == tgtok::XForEach)
2467e8d8bef9SDimitry Andric TokError("!foreach must have a list or dag argument");
2468e8d8bef9SDimitry Andric else
2469e8d8bef9SDimitry Andric TokError("!filter must have a list argument");
2470e8d8bef9SDimitry Andric return nullptr;
2471e8d8bef9SDimitry Andric }
2472e8d8bef9SDimitry Andric
2473e8d8bef9SDimitry Andric // We need to create a temporary record to provide a scope for the
2474e8d8bef9SDimitry Andric // iteration variable.
2475e8d8bef9SDimitry Andric std::unique_ptr<Record> ParseRecTmp;
2476e8d8bef9SDimitry Andric Record *ParseRec = CurRec;
2477e8d8bef9SDimitry Andric if (!ParseRec) {
2478e8d8bef9SDimitry Andric ParseRecTmp =
2479e8d8bef9SDimitry Andric std::make_unique<Record>(".parse", ArrayRef<SMLoc>{}, Records);
2480e8d8bef9SDimitry Andric ParseRec = ParseRecTmp.get();
2481e8d8bef9SDimitry Andric }
248206c3fb27SDimitry Andric TGVarScope *TempScope = PushScope(ParseRec);
2483e8d8bef9SDimitry Andric ParseRec->addValue(RecordVal(LHS, InEltType, RecordVal::FK_Normal));
2484e8d8bef9SDimitry Andric Init *RHS = ParseValue(ParseRec, ExprEltType);
2485e8d8bef9SDimitry Andric ParseRec->removeValue(LHS);
248606c3fb27SDimitry Andric PopScope(TempScope);
2487e8d8bef9SDimitry Andric if (!RHS)
2488e8d8bef9SDimitry Andric return nullptr;
2489e8d8bef9SDimitry Andric
2490e8d8bef9SDimitry Andric if (!consume(tgtok::r_paren)) {
2491e8d8bef9SDimitry Andric TokError("expected ')' in !foreach/!filter");
2492e8d8bef9SDimitry Andric return nullptr;
2493e8d8bef9SDimitry Andric }
2494e8d8bef9SDimitry Andric
2495e8d8bef9SDimitry Andric RecTy *OutType = InEltType;
2496e8d8bef9SDimitry Andric if (Operation == tgtok::XForEach && !IsDAG) {
2497e8d8bef9SDimitry Andric TypedInit *RHSt = dyn_cast<TypedInit>(RHS);
2498e8d8bef9SDimitry Andric if (!RHSt) {
2499e8d8bef9SDimitry Andric TokError("could not get type of !foreach result expression");
2500e8d8bef9SDimitry Andric return nullptr;
2501e8d8bef9SDimitry Andric }
2502e8d8bef9SDimitry Andric OutType = RHSt->getType()->getListTy();
2503e8d8bef9SDimitry Andric } else if (Operation == tgtok::XFilter) {
2504e8d8bef9SDimitry Andric OutType = InEltType->getListTy();
2505e8d8bef9SDimitry Andric }
2506e8d8bef9SDimitry Andric
2507e8d8bef9SDimitry Andric return (TernOpInit::get((Operation == tgtok::XForEach) ? TernOpInit::FOREACH
2508e8d8bef9SDimitry Andric : TernOpInit::FILTER,
2509e8d8bef9SDimitry Andric LHS, MHS, RHS, OutType))
2510e8d8bef9SDimitry Andric ->Fold(CurRec);
2511e8d8bef9SDimitry Andric }
2512e8d8bef9SDimitry Andric
ParseOperationCond(Record * CurRec,RecTy * ItemType)25130b57cec5SDimitry Andric Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) {
25140b57cec5SDimitry Andric Lex.Lex(); // eat the operation 'cond'
25150b57cec5SDimitry Andric
25165ffd83dbSDimitry Andric if (!consume(tgtok::l_paren)) {
25170b57cec5SDimitry Andric TokError("expected '(' after !cond operator");
25180b57cec5SDimitry Andric return nullptr;
25190b57cec5SDimitry Andric }
25200b57cec5SDimitry Andric
25210b57cec5SDimitry Andric // Parse through '[Case: Val,]+'
25220b57cec5SDimitry Andric SmallVector<Init *, 4> Case;
25230b57cec5SDimitry Andric SmallVector<Init *, 4> Val;
25240b57cec5SDimitry Andric while (true) {
25255ffd83dbSDimitry Andric if (consume(tgtok::r_paren))
25260b57cec5SDimitry Andric break;
25270b57cec5SDimitry Andric
25280b57cec5SDimitry Andric Init *V = ParseValue(CurRec);
25290b57cec5SDimitry Andric if (!V)
25300b57cec5SDimitry Andric return nullptr;
25310b57cec5SDimitry Andric Case.push_back(V);
25320b57cec5SDimitry Andric
25335ffd83dbSDimitry Andric if (!consume(tgtok::colon)) {
25340b57cec5SDimitry Andric TokError("expected ':' following a condition in !cond operator");
25350b57cec5SDimitry Andric return nullptr;
25360b57cec5SDimitry Andric }
25370b57cec5SDimitry Andric
25380b57cec5SDimitry Andric V = ParseValue(CurRec, ItemType);
25390b57cec5SDimitry Andric if (!V)
25400b57cec5SDimitry Andric return nullptr;
25410b57cec5SDimitry Andric Val.push_back(V);
25420b57cec5SDimitry Andric
25435ffd83dbSDimitry Andric if (consume(tgtok::r_paren))
25440b57cec5SDimitry Andric break;
25450b57cec5SDimitry Andric
25465ffd83dbSDimitry Andric if (!consume(tgtok::comma)) {
25470b57cec5SDimitry Andric TokError("expected ',' or ')' following a value in !cond operator");
25480b57cec5SDimitry Andric return nullptr;
25490b57cec5SDimitry Andric }
25500b57cec5SDimitry Andric }
25510b57cec5SDimitry Andric
25520b57cec5SDimitry Andric if (Case.size() < 1) {
25530b57cec5SDimitry Andric TokError("there should be at least 1 'condition : value' in the !cond operator");
25540b57cec5SDimitry Andric return nullptr;
25550b57cec5SDimitry Andric }
25560b57cec5SDimitry Andric
25570b57cec5SDimitry Andric // resolve type
25580b57cec5SDimitry Andric RecTy *Type = nullptr;
25590b57cec5SDimitry Andric for (Init *V : Val) {
25600b57cec5SDimitry Andric RecTy *VTy = nullptr;
25610b57cec5SDimitry Andric if (TypedInit *Vt = dyn_cast<TypedInit>(V))
25620b57cec5SDimitry Andric VTy = Vt->getType();
25630b57cec5SDimitry Andric if (BitsInit *Vbits = dyn_cast<BitsInit>(V))
256481ad6265SDimitry Andric VTy = BitsRecTy::get(Records, Vbits->getNumBits());
25650b57cec5SDimitry Andric if (isa<BitInit>(V))
256681ad6265SDimitry Andric VTy = BitRecTy::get(Records);
25670b57cec5SDimitry Andric
25680b57cec5SDimitry Andric if (Type == nullptr) {
25690b57cec5SDimitry Andric if (!isa<UnsetInit>(V))
25700b57cec5SDimitry Andric Type = VTy;
25710b57cec5SDimitry Andric } else {
25720b57cec5SDimitry Andric if (!isa<UnsetInit>(V)) {
25730b57cec5SDimitry Andric RecTy *RType = resolveTypes(Type, VTy);
25740b57cec5SDimitry Andric if (!RType) {
25750b57cec5SDimitry Andric TokError(Twine("inconsistent types '") + Type->getAsString() +
25760b57cec5SDimitry Andric "' and '" + VTy->getAsString() + "' for !cond");
25770b57cec5SDimitry Andric return nullptr;
25780b57cec5SDimitry Andric }
25790b57cec5SDimitry Andric Type = RType;
25800b57cec5SDimitry Andric }
25810b57cec5SDimitry Andric }
25820b57cec5SDimitry Andric }
25830b57cec5SDimitry Andric
25840b57cec5SDimitry Andric if (!Type) {
25850b57cec5SDimitry Andric TokError("could not determine type for !cond from its arguments");
25860b57cec5SDimitry Andric return nullptr;
25870b57cec5SDimitry Andric }
25880b57cec5SDimitry Andric return CondOpInit::get(Case, Val, Type)->Fold(CurRec);
25890b57cec5SDimitry Andric }
25900b57cec5SDimitry Andric
25910b57cec5SDimitry Andric /// ParseSimpleValue - Parse a tblgen value. This returns null on error.
25920b57cec5SDimitry Andric ///
25930b57cec5SDimitry Andric /// SimpleValue ::= IDValue
25940b57cec5SDimitry Andric /// SimpleValue ::= INTVAL
25950b57cec5SDimitry Andric /// SimpleValue ::= STRVAL+
25960b57cec5SDimitry Andric /// SimpleValue ::= CODEFRAGMENT
25970b57cec5SDimitry Andric /// SimpleValue ::= '?'
25980b57cec5SDimitry Andric /// SimpleValue ::= '{' ValueList '}'
25990b57cec5SDimitry Andric /// SimpleValue ::= ID '<' ValueListNE '>'
26000b57cec5SDimitry Andric /// SimpleValue ::= '[' ValueList ']'
26010b57cec5SDimitry Andric /// SimpleValue ::= '(' IDValue DagArgList ')'
26020b57cec5SDimitry Andric /// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'
26030b57cec5SDimitry Andric /// SimpleValue ::= ADDTOK '(' Value ',' Value ')'
2604bdd1243dSDimitry Andric /// SimpleValue ::= DIVTOK '(' Value ',' Value ')'
2605e8d8bef9SDimitry Andric /// SimpleValue ::= SUBTOK '(' Value ',' Value ')'
26060b57cec5SDimitry Andric /// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
26070b57cec5SDimitry Andric /// SimpleValue ::= SRATOK '(' Value ',' Value ')'
26080b57cec5SDimitry Andric /// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
26090b57cec5SDimitry Andric /// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'
26100b57cec5SDimitry Andric /// SimpleValue ::= LISTSPLATTOK '(' Value ',' Value ')'
2611bdd1243dSDimitry Andric /// SimpleValue ::= LISTREMOVETOK '(' Value ',' Value ')'
261206c3fb27SDimitry Andric /// SimpleValue ::= RANGE '(' Value ')'
261306c3fb27SDimitry Andric /// SimpleValue ::= RANGE '(' Value ',' Value ')'
26145f757f3fSDimitry Andric /// SimpleValue ::= RANGE '(' Value ',' Value ',' Value ')'
26150b57cec5SDimitry Andric /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
26160b57cec5SDimitry Andric /// SimpleValue ::= COND '(' [Value ':' Value,]+ ')'
26170b57cec5SDimitry Andric ///
ParseSimpleValue(Record * CurRec,RecTy * ItemType,IDParseMode Mode)26180b57cec5SDimitry Andric Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
26190b57cec5SDimitry Andric IDParseMode Mode) {
26200b57cec5SDimitry Andric Init *R = nullptr;
26215f757f3fSDimitry Andric tgtok::TokKind Code = Lex.getCode();
26225f757f3fSDimitry Andric
26235f757f3fSDimitry Andric // Parse bang operators.
26245f757f3fSDimitry Andric if (tgtok::isBangOperator(Code))
26255f757f3fSDimitry Andric return ParseOperation(CurRec, ItemType);
26265f757f3fSDimitry Andric
26275f757f3fSDimitry Andric switch (Code) {
2628e8d8bef9SDimitry Andric default: TokError("Unknown or reserved token when parsing a value"); break;
2629e8d8bef9SDimitry Andric
2630e8d8bef9SDimitry Andric case tgtok::TrueVal:
263181ad6265SDimitry Andric R = IntInit::get(Records, 1);
2632e8d8bef9SDimitry Andric Lex.Lex();
2633e8d8bef9SDimitry Andric break;
2634e8d8bef9SDimitry Andric case tgtok::FalseVal:
263581ad6265SDimitry Andric R = IntInit::get(Records, 0);
2636e8d8bef9SDimitry Andric Lex.Lex();
2637e8d8bef9SDimitry Andric break;
2638e8d8bef9SDimitry Andric case tgtok::IntVal:
263981ad6265SDimitry Andric R = IntInit::get(Records, Lex.getCurIntVal());
2640e8d8bef9SDimitry Andric Lex.Lex();
2641e8d8bef9SDimitry Andric break;
26420b57cec5SDimitry Andric case tgtok::BinaryIntVal: {
26430b57cec5SDimitry Andric auto BinaryVal = Lex.getCurBinaryIntVal();
26440b57cec5SDimitry Andric SmallVector<Init*, 16> Bits(BinaryVal.second);
26450b57cec5SDimitry Andric for (unsigned i = 0, e = BinaryVal.second; i != e; ++i)
264681ad6265SDimitry Andric Bits[i] = BitInit::get(Records, BinaryVal.first & (1LL << i));
264781ad6265SDimitry Andric R = BitsInit::get(Records, Bits);
26480b57cec5SDimitry Andric Lex.Lex();
26490b57cec5SDimitry Andric break;
26500b57cec5SDimitry Andric }
26510b57cec5SDimitry Andric case tgtok::StrVal: {
26520b57cec5SDimitry Andric std::string Val = Lex.getCurStrVal();
26530b57cec5SDimitry Andric Lex.Lex();
26540b57cec5SDimitry Andric
26550b57cec5SDimitry Andric // Handle multiple consecutive concatenated strings.
26560b57cec5SDimitry Andric while (Lex.getCode() == tgtok::StrVal) {
26570b57cec5SDimitry Andric Val += Lex.getCurStrVal();
26580b57cec5SDimitry Andric Lex.Lex();
26590b57cec5SDimitry Andric }
26600b57cec5SDimitry Andric
266181ad6265SDimitry Andric R = StringInit::get(Records, Val);
26620b57cec5SDimitry Andric break;
26630b57cec5SDimitry Andric }
26640b57cec5SDimitry Andric case tgtok::CodeFragment:
266581ad6265SDimitry Andric R = StringInit::get(Records, Lex.getCurStrVal(), StringInit::SF_Code);
26660b57cec5SDimitry Andric Lex.Lex();
26670b57cec5SDimitry Andric break;
26680b57cec5SDimitry Andric case tgtok::question:
266981ad6265SDimitry Andric R = UnsetInit::get(Records);
26700b57cec5SDimitry Andric Lex.Lex();
26710b57cec5SDimitry Andric break;
26720b57cec5SDimitry Andric case tgtok::Id: {
2673bdd1243dSDimitry Andric SMRange NameLoc = Lex.getLocRange();
267481ad6265SDimitry Andric StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());
267506c3fb27SDimitry Andric tgtok::TokKind Next = Lex.Lex();
267606c3fb27SDimitry Andric if (Next == tgtok::equal) // Named argument.
267706c3fb27SDimitry Andric return Name;
267806c3fb27SDimitry Andric if (Next != tgtok::less) // consume the Id.
26790b57cec5SDimitry Andric return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue
26800b57cec5SDimitry Andric
268106c3fb27SDimitry Andric // Value ::= CLASSID '<' ArgValueList '>' (CLASSID has been consumed)
2682fe6060f1SDimitry Andric // This is supposed to synthesize a new anonymous definition, deriving
2683fe6060f1SDimitry Andric // from the class with the template arguments, but no body.
26840b57cec5SDimitry Andric Record *Class = Records.getClass(Name->getValue());
26850b57cec5SDimitry Andric if (!Class) {
2686bdd1243dSDimitry Andric Error(NameLoc.Start,
2687bdd1243dSDimitry Andric "Expected a class name, got '" + Name->getValue() + "'");
26880b57cec5SDimitry Andric return nullptr;
26890b57cec5SDimitry Andric }
26900b57cec5SDimitry Andric
269106c3fb27SDimitry Andric SmallVector<ArgumentInit *, 8> Args;
2692fe6060f1SDimitry Andric Lex.Lex(); // consume the <
2693fe6060f1SDimitry Andric if (ParseTemplateArgValueList(Args, CurRec, Class))
2694fe6060f1SDimitry Andric return nullptr; // Error parsing value list.
26950b57cec5SDimitry Andric
2696bdd1243dSDimitry Andric if (CheckTemplateArgValues(Args, NameLoc.Start, Class))
2697fe6060f1SDimitry Andric return nullptr; // Error checking template argument values.
26980b57cec5SDimitry Andric
269906c3fb27SDimitry Andric if (resolveArguments(Class, Args, NameLoc.Start))
270006c3fb27SDimitry Andric return nullptr;
27010b57cec5SDimitry Andric
2702bdd1243dSDimitry Andric if (TrackReferenceLocs)
2703bdd1243dSDimitry Andric Class->appendReferenceLoc(NameLoc);
27040b57cec5SDimitry Andric return VarDefInit::get(Class, Args)->Fold();
27050b57cec5SDimitry Andric }
27060b57cec5SDimitry Andric case tgtok::l_brace: { // Value ::= '{' ValueList '}'
27070b57cec5SDimitry Andric SMLoc BraceLoc = Lex.getLoc();
27080b57cec5SDimitry Andric Lex.Lex(); // eat the '{'
27090b57cec5SDimitry Andric SmallVector<Init*, 16> Vals;
27100b57cec5SDimitry Andric
27110b57cec5SDimitry Andric if (Lex.getCode() != tgtok::r_brace) {
27120b57cec5SDimitry Andric ParseValueList(Vals, CurRec);
27130b57cec5SDimitry Andric if (Vals.empty()) return nullptr;
27140b57cec5SDimitry Andric }
27155ffd83dbSDimitry Andric if (!consume(tgtok::r_brace)) {
27160b57cec5SDimitry Andric TokError("expected '}' at end of bit list value");
27170b57cec5SDimitry Andric return nullptr;
27180b57cec5SDimitry Andric }
27190b57cec5SDimitry Andric
27200b57cec5SDimitry Andric SmallVector<Init *, 16> NewBits;
27210b57cec5SDimitry Andric
27220b57cec5SDimitry Andric // As we parse { a, b, ... }, 'a' is the highest bit, but we parse it
27230b57cec5SDimitry Andric // first. We'll first read everything in to a vector, then we can reverse
27240b57cec5SDimitry Andric // it to get the bits in the correct order for the BitsInit value.
27250b57cec5SDimitry Andric for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
27260b57cec5SDimitry Andric // FIXME: The following two loops would not be duplicated
27270b57cec5SDimitry Andric // if the API was a little more orthogonal.
27280b57cec5SDimitry Andric
27290b57cec5SDimitry Andric // bits<n> values are allowed to initialize n bits.
27300b57cec5SDimitry Andric if (BitsInit *BI = dyn_cast<BitsInit>(Vals[i])) {
27310b57cec5SDimitry Andric for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
27320b57cec5SDimitry Andric NewBits.push_back(BI->getBit((e - i) - 1));
27330b57cec5SDimitry Andric continue;
27340b57cec5SDimitry Andric }
27350b57cec5SDimitry Andric // bits<n> can also come from variable initializers.
27360b57cec5SDimitry Andric if (VarInit *VI = dyn_cast<VarInit>(Vals[i])) {
27370b57cec5SDimitry Andric if (BitsRecTy *BitsRec = dyn_cast<BitsRecTy>(VI->getType())) {
27380b57cec5SDimitry Andric for (unsigned i = 0, e = BitsRec->getNumBits(); i != e; ++i)
27390b57cec5SDimitry Andric NewBits.push_back(VI->getBit((e - i) - 1));
27400b57cec5SDimitry Andric continue;
27410b57cec5SDimitry Andric }
27420b57cec5SDimitry Andric // Fallthrough to try convert this to a bit.
27430b57cec5SDimitry Andric }
27440b57cec5SDimitry Andric // All other values must be convertible to just a single bit.
274581ad6265SDimitry Andric Init *Bit = Vals[i]->getCastTo(BitRecTy::get(Records));
27460b57cec5SDimitry Andric if (!Bit) {
27470b57cec5SDimitry Andric Error(BraceLoc, "Element #" + Twine(i) + " (" + Vals[i]->getAsString() +
27480b57cec5SDimitry Andric ") is not convertable to a bit");
27490b57cec5SDimitry Andric return nullptr;
27500b57cec5SDimitry Andric }
27510b57cec5SDimitry Andric NewBits.push_back(Bit);
27520b57cec5SDimitry Andric }
27530b57cec5SDimitry Andric std::reverse(NewBits.begin(), NewBits.end());
275481ad6265SDimitry Andric return BitsInit::get(Records, NewBits);
27550b57cec5SDimitry Andric }
27560b57cec5SDimitry Andric case tgtok::l_square: { // Value ::= '[' ValueList ']'
27570b57cec5SDimitry Andric Lex.Lex(); // eat the '['
27580b57cec5SDimitry Andric SmallVector<Init*, 16> Vals;
27590b57cec5SDimitry Andric
27600b57cec5SDimitry Andric RecTy *DeducedEltTy = nullptr;
27610b57cec5SDimitry Andric ListRecTy *GivenListTy = nullptr;
27620b57cec5SDimitry Andric
27630b57cec5SDimitry Andric if (ItemType) {
27640b57cec5SDimitry Andric ListRecTy *ListType = dyn_cast<ListRecTy>(ItemType);
27650b57cec5SDimitry Andric if (!ListType) {
2766e8d8bef9SDimitry Andric TokError(Twine("Encountered a list when expecting a ") +
27670b57cec5SDimitry Andric ItemType->getAsString());
27680b57cec5SDimitry Andric return nullptr;
27690b57cec5SDimitry Andric }
27700b57cec5SDimitry Andric GivenListTy = ListType;
27710b57cec5SDimitry Andric }
27720b57cec5SDimitry Andric
27730b57cec5SDimitry Andric if (Lex.getCode() != tgtok::r_square) {
2774fe6060f1SDimitry Andric ParseValueList(Vals, CurRec,
27750b57cec5SDimitry Andric GivenListTy ? GivenListTy->getElementType() : nullptr);
27760b57cec5SDimitry Andric if (Vals.empty()) return nullptr;
27770b57cec5SDimitry Andric }
27785ffd83dbSDimitry Andric if (!consume(tgtok::r_square)) {
27790b57cec5SDimitry Andric TokError("expected ']' at end of list value");
27800b57cec5SDimitry Andric return nullptr;
27810b57cec5SDimitry Andric }
27820b57cec5SDimitry Andric
27830b57cec5SDimitry Andric RecTy *GivenEltTy = nullptr;
27845ffd83dbSDimitry Andric if (consume(tgtok::less)) {
27850b57cec5SDimitry Andric // Optional list element type
27860b57cec5SDimitry Andric GivenEltTy = ParseType();
27870b57cec5SDimitry Andric if (!GivenEltTy) {
27880b57cec5SDimitry Andric // Couldn't parse element type
27890b57cec5SDimitry Andric return nullptr;
27900b57cec5SDimitry Andric }
27910b57cec5SDimitry Andric
27925ffd83dbSDimitry Andric if (!consume(tgtok::greater)) {
27930b57cec5SDimitry Andric TokError("expected '>' at end of list element type");
27940b57cec5SDimitry Andric return nullptr;
27950b57cec5SDimitry Andric }
27960b57cec5SDimitry Andric }
27970b57cec5SDimitry Andric
27980b57cec5SDimitry Andric // Check elements
27990b57cec5SDimitry Andric RecTy *EltTy = nullptr;
28000b57cec5SDimitry Andric for (Init *V : Vals) {
28010b57cec5SDimitry Andric TypedInit *TArg = dyn_cast<TypedInit>(V);
28020b57cec5SDimitry Andric if (TArg) {
28030b57cec5SDimitry Andric if (EltTy) {
28040b57cec5SDimitry Andric EltTy = resolveTypes(EltTy, TArg->getType());
28050b57cec5SDimitry Andric if (!EltTy) {
28060b57cec5SDimitry Andric TokError("Incompatible types in list elements");
28070b57cec5SDimitry Andric return nullptr;
28080b57cec5SDimitry Andric }
28090b57cec5SDimitry Andric } else {
28100b57cec5SDimitry Andric EltTy = TArg->getType();
28110b57cec5SDimitry Andric }
28120b57cec5SDimitry Andric }
28130b57cec5SDimitry Andric }
28140b57cec5SDimitry Andric
28150b57cec5SDimitry Andric if (GivenEltTy) {
28160b57cec5SDimitry Andric if (EltTy) {
28170b57cec5SDimitry Andric // Verify consistency
28180b57cec5SDimitry Andric if (!EltTy->typeIsConvertibleTo(GivenEltTy)) {
28190b57cec5SDimitry Andric TokError("Incompatible types in list elements");
28200b57cec5SDimitry Andric return nullptr;
28210b57cec5SDimitry Andric }
28220b57cec5SDimitry Andric }
28230b57cec5SDimitry Andric EltTy = GivenEltTy;
28240b57cec5SDimitry Andric }
28250b57cec5SDimitry Andric
28260b57cec5SDimitry Andric if (!EltTy) {
28270b57cec5SDimitry Andric if (!ItemType) {
28280b57cec5SDimitry Andric TokError("No type for list");
28290b57cec5SDimitry Andric return nullptr;
28300b57cec5SDimitry Andric }
28310b57cec5SDimitry Andric DeducedEltTy = GivenListTy->getElementType();
28320b57cec5SDimitry Andric } else {
28330b57cec5SDimitry Andric // Make sure the deduced type is compatible with the given type
28340b57cec5SDimitry Andric if (GivenListTy) {
28350b57cec5SDimitry Andric if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) {
28360b57cec5SDimitry Andric TokError(Twine("Element type mismatch for list: element type '") +
28370b57cec5SDimitry Andric EltTy->getAsString() + "' not convertible to '" +
28380b57cec5SDimitry Andric GivenListTy->getElementType()->getAsString());
28390b57cec5SDimitry Andric return nullptr;
28400b57cec5SDimitry Andric }
28410b57cec5SDimitry Andric }
28420b57cec5SDimitry Andric DeducedEltTy = EltTy;
28430b57cec5SDimitry Andric }
28440b57cec5SDimitry Andric
28450b57cec5SDimitry Andric return ListInit::get(Vals, DeducedEltTy);
28460b57cec5SDimitry Andric }
28470b57cec5SDimitry Andric case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
28480b57cec5SDimitry Andric Lex.Lex(); // eat the '('
2849480093f4SDimitry Andric if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast &&
2850e8d8bef9SDimitry Andric Lex.getCode() != tgtok::question && Lex.getCode() != tgtok::XGetDagOp) {
28510b57cec5SDimitry Andric TokError("expected identifier in dag init");
28520b57cec5SDimitry Andric return nullptr;
28530b57cec5SDimitry Andric }
28540b57cec5SDimitry Andric
28550b57cec5SDimitry Andric Init *Operator = ParseValue(CurRec);
28560b57cec5SDimitry Andric if (!Operator) return nullptr;
28570b57cec5SDimitry Andric
28580b57cec5SDimitry Andric // If the operator name is present, parse it.
28590b57cec5SDimitry Andric StringInit *OperatorName = nullptr;
28605ffd83dbSDimitry Andric if (consume(tgtok::colon)) {
28615ffd83dbSDimitry Andric if (Lex.getCode() != tgtok::VarName) { // eat the ':'
28620b57cec5SDimitry Andric TokError("expected variable name in dag operator");
28630b57cec5SDimitry Andric return nullptr;
28640b57cec5SDimitry Andric }
286581ad6265SDimitry Andric OperatorName = StringInit::get(Records, Lex.getCurStrVal());
28660b57cec5SDimitry Andric Lex.Lex(); // eat the VarName.
28670b57cec5SDimitry Andric }
28680b57cec5SDimitry Andric
28690b57cec5SDimitry Andric SmallVector<std::pair<llvm::Init*, StringInit*>, 8> DagArgs;
28700b57cec5SDimitry Andric if (Lex.getCode() != tgtok::r_paren) {
28710b57cec5SDimitry Andric ParseDagArgList(DagArgs, CurRec);
28720b57cec5SDimitry Andric if (DagArgs.empty()) return nullptr;
28730b57cec5SDimitry Andric }
28740b57cec5SDimitry Andric
28755ffd83dbSDimitry Andric if (!consume(tgtok::r_paren)) {
28760b57cec5SDimitry Andric TokError("expected ')' in dag init");
28770b57cec5SDimitry Andric return nullptr;
28780b57cec5SDimitry Andric }
28790b57cec5SDimitry Andric
28800b57cec5SDimitry Andric return DagInit::get(Operator, OperatorName, DagArgs);
28810b57cec5SDimitry Andric }
28820b57cec5SDimitry Andric }
28830b57cec5SDimitry Andric
28840b57cec5SDimitry Andric return R;
28850b57cec5SDimitry Andric }
28860b57cec5SDimitry Andric
2887e8d8bef9SDimitry Andric /// ParseValue - Parse a TableGen value. This returns null on error.
28880b57cec5SDimitry Andric ///
28890b57cec5SDimitry Andric /// Value ::= SimpleValue ValueSuffix*
28900b57cec5SDimitry Andric /// ValueSuffix ::= '{' BitList '}'
289106c3fb27SDimitry Andric /// ValueSuffix ::= '[' SliceElements ']'
28920b57cec5SDimitry Andric /// ValueSuffix ::= '.' ID
28930b57cec5SDimitry Andric ///
ParseValue(Record * CurRec,RecTy * ItemType,IDParseMode Mode)28940b57cec5SDimitry Andric Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
289506c3fb27SDimitry Andric SMLoc LHSLoc = Lex.getLoc();
28960b57cec5SDimitry Andric Init *Result = ParseSimpleValue(CurRec, ItemType, Mode);
28970b57cec5SDimitry Andric if (!Result) return nullptr;
28980b57cec5SDimitry Andric
28990b57cec5SDimitry Andric // Parse the suffixes now if present.
29000b57cec5SDimitry Andric while (true) {
29010b57cec5SDimitry Andric switch (Lex.getCode()) {
29020b57cec5SDimitry Andric default: return Result;
29030b57cec5SDimitry Andric case tgtok::l_brace: {
29040b57cec5SDimitry Andric if (Mode == ParseNameMode)
29050b57cec5SDimitry Andric // This is the beginning of the object body.
29060b57cec5SDimitry Andric return Result;
29070b57cec5SDimitry Andric
29080b57cec5SDimitry Andric SMLoc CurlyLoc = Lex.getLoc();
29090b57cec5SDimitry Andric Lex.Lex(); // eat the '{'
29100b57cec5SDimitry Andric SmallVector<unsigned, 16> Ranges;
29110b57cec5SDimitry Andric ParseRangeList(Ranges);
29120b57cec5SDimitry Andric if (Ranges.empty()) return nullptr;
29130b57cec5SDimitry Andric
29140b57cec5SDimitry Andric // Reverse the bitlist.
29150b57cec5SDimitry Andric std::reverse(Ranges.begin(), Ranges.end());
29160b57cec5SDimitry Andric Result = Result->convertInitializerBitRange(Ranges);
29170b57cec5SDimitry Andric if (!Result) {
29180b57cec5SDimitry Andric Error(CurlyLoc, "Invalid bit range for value");
29190b57cec5SDimitry Andric return nullptr;
29200b57cec5SDimitry Andric }
29210b57cec5SDimitry Andric
29220b57cec5SDimitry Andric // Eat the '}'.
29235ffd83dbSDimitry Andric if (!consume(tgtok::r_brace)) {
29240b57cec5SDimitry Andric TokError("expected '}' at end of bit range list");
29250b57cec5SDimitry Andric return nullptr;
29260b57cec5SDimitry Andric }
29270b57cec5SDimitry Andric break;
29280b57cec5SDimitry Andric }
29290b57cec5SDimitry Andric case tgtok::l_square: {
293006c3fb27SDimitry Andric auto *LHS = dyn_cast<TypedInit>(Result);
293106c3fb27SDimitry Andric if (!LHS) {
293206c3fb27SDimitry Andric Error(LHSLoc, "Invalid value, list expected");
29330b57cec5SDimitry Andric return nullptr;
29340b57cec5SDimitry Andric }
29350b57cec5SDimitry Andric
293606c3fb27SDimitry Andric auto *LHSTy = dyn_cast<ListRecTy>(LHS->getType());
293706c3fb27SDimitry Andric if (!LHSTy) {
293806c3fb27SDimitry Andric Error(LHSLoc, "Type '" + Twine(LHS->getType()->getAsString()) +
293906c3fb27SDimitry Andric "' is invalid, list expected");
294006c3fb27SDimitry Andric return nullptr;
294106c3fb27SDimitry Andric }
294206c3fb27SDimitry Andric
294306c3fb27SDimitry Andric Lex.Lex(); // eat the '['
294406c3fb27SDimitry Andric TypedInit *RHS = ParseSliceElements(CurRec, /*Single=*/true);
294506c3fb27SDimitry Andric if (!RHS)
294606c3fb27SDimitry Andric return nullptr;
294706c3fb27SDimitry Andric
294806c3fb27SDimitry Andric if (isa<ListRecTy>(RHS->getType())) {
294906c3fb27SDimitry Andric Result =
295006c3fb27SDimitry Andric BinOpInit::get(BinOpInit::LISTSLICE, LHS, RHS, LHSTy)->Fold(CurRec);
295106c3fb27SDimitry Andric } else {
295206c3fb27SDimitry Andric Result = BinOpInit::get(BinOpInit::LISTELEM, LHS, RHS,
295306c3fb27SDimitry Andric LHSTy->getElementType())
295406c3fb27SDimitry Andric ->Fold(CurRec);
295506c3fb27SDimitry Andric }
295606c3fb27SDimitry Andric
295706c3fb27SDimitry Andric assert(Result);
295806c3fb27SDimitry Andric
29590b57cec5SDimitry Andric // Eat the ']'.
29605ffd83dbSDimitry Andric if (!consume(tgtok::r_square)) {
29610b57cec5SDimitry Andric TokError("expected ']' at end of list slice");
29620b57cec5SDimitry Andric return nullptr;
29630b57cec5SDimitry Andric }
29640b57cec5SDimitry Andric break;
29650b57cec5SDimitry Andric }
2966e8d8bef9SDimitry Andric case tgtok::dot: {
29670b57cec5SDimitry Andric if (Lex.Lex() != tgtok::Id) { // eat the .
29680b57cec5SDimitry Andric TokError("expected field identifier after '.'");
29690b57cec5SDimitry Andric return nullptr;
29700b57cec5SDimitry Andric }
2971bdd1243dSDimitry Andric SMRange FieldNameLoc = Lex.getLocRange();
297281ad6265SDimitry Andric StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());
29730b57cec5SDimitry Andric if (!Result->getFieldType(FieldName)) {
29740b57cec5SDimitry Andric TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
29750b57cec5SDimitry Andric Result->getAsString() + "'");
29760b57cec5SDimitry Andric return nullptr;
29770b57cec5SDimitry Andric }
2978bdd1243dSDimitry Andric
2979bdd1243dSDimitry Andric // Add a reference to this field if we know the record class.
2980bdd1243dSDimitry Andric if (TrackReferenceLocs) {
2981bdd1243dSDimitry Andric if (auto *DI = dyn_cast<DefInit>(Result)) {
2982bdd1243dSDimitry Andric DI->getDef()->getValue(FieldName)->addReferenceLoc(FieldNameLoc);
2983bdd1243dSDimitry Andric } else if (auto *TI = dyn_cast<TypedInit>(Result)) {
2984bdd1243dSDimitry Andric if (auto *RecTy = dyn_cast<RecordRecTy>(TI->getType())) {
2985bdd1243dSDimitry Andric for (Record *R : RecTy->getClasses())
2986bdd1243dSDimitry Andric if (auto *RV = R->getValue(FieldName))
2987bdd1243dSDimitry Andric RV->addReferenceLoc(FieldNameLoc);
2988bdd1243dSDimitry Andric }
2989bdd1243dSDimitry Andric }
2990bdd1243dSDimitry Andric }
2991bdd1243dSDimitry Andric
29920b57cec5SDimitry Andric Result = FieldInit::get(Result, FieldName)->Fold(CurRec);
29930b57cec5SDimitry Andric Lex.Lex(); // eat field name
29940b57cec5SDimitry Andric break;
29950b57cec5SDimitry Andric }
29960b57cec5SDimitry Andric
29970b57cec5SDimitry Andric case tgtok::paste:
29980b57cec5SDimitry Andric SMLoc PasteLoc = Lex.getLoc();
29990b57cec5SDimitry Andric TypedInit *LHS = dyn_cast<TypedInit>(Result);
30000b57cec5SDimitry Andric if (!LHS) {
30010b57cec5SDimitry Andric Error(PasteLoc, "LHS of paste is not typed!");
30020b57cec5SDimitry Andric return nullptr;
30030b57cec5SDimitry Andric }
30040b57cec5SDimitry Andric
30050b57cec5SDimitry Andric // Check if it's a 'listA # listB'
30060b57cec5SDimitry Andric if (isa<ListRecTy>(LHS->getType())) {
30070b57cec5SDimitry Andric Lex.Lex(); // Eat the '#'.
30080b57cec5SDimitry Andric
3009e8d8bef9SDimitry Andric assert(Mode == ParseValueMode && "encountered paste of lists in name");
3010e8d8bef9SDimitry Andric
30110b57cec5SDimitry Andric switch (Lex.getCode()) {
30120b57cec5SDimitry Andric case tgtok::colon:
30130b57cec5SDimitry Andric case tgtok::semi:
30140b57cec5SDimitry Andric case tgtok::l_brace:
30150b57cec5SDimitry Andric Result = LHS; // trailing paste, ignore.
30160b57cec5SDimitry Andric break;
30170b57cec5SDimitry Andric default:
3018e8d8bef9SDimitry Andric Init *RHSResult = ParseValue(CurRec, ItemType, ParseValueMode);
3019e8d8bef9SDimitry Andric if (!RHSResult)
3020e8d8bef9SDimitry Andric return nullptr;
30210b57cec5SDimitry Andric Result = BinOpInit::getListConcat(LHS, RHSResult);
3022e8d8bef9SDimitry Andric break;
30230b57cec5SDimitry Andric }
30240b57cec5SDimitry Andric break;
30250b57cec5SDimitry Andric }
30260b57cec5SDimitry Andric
30270b57cec5SDimitry Andric // Create a !strconcat() operation, first casting each operand to
30280b57cec5SDimitry Andric // a string if necessary.
302981ad6265SDimitry Andric if (LHS->getType() != StringRecTy::get(Records)) {
30300b57cec5SDimitry Andric auto CastLHS = dyn_cast<TypedInit>(
303181ad6265SDimitry Andric UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get(Records))
30320b57cec5SDimitry Andric ->Fold(CurRec));
30330b57cec5SDimitry Andric if (!CastLHS) {
30340b57cec5SDimitry Andric Error(PasteLoc,
30350b57cec5SDimitry Andric Twine("can't cast '") + LHS->getAsString() + "' to string");
30360b57cec5SDimitry Andric return nullptr;
30370b57cec5SDimitry Andric }
30380b57cec5SDimitry Andric LHS = CastLHS;
30390b57cec5SDimitry Andric }
30400b57cec5SDimitry Andric
30410b57cec5SDimitry Andric TypedInit *RHS = nullptr;
30420b57cec5SDimitry Andric
30430b57cec5SDimitry Andric Lex.Lex(); // Eat the '#'.
30440b57cec5SDimitry Andric switch (Lex.getCode()) {
30450b57cec5SDimitry Andric case tgtok::colon:
30460b57cec5SDimitry Andric case tgtok::semi:
30470b57cec5SDimitry Andric case tgtok::l_brace:
30480b57cec5SDimitry Andric // These are all of the tokens that can begin an object body.
30490b57cec5SDimitry Andric // Some of these can also begin values but we disallow those cases
30500b57cec5SDimitry Andric // because they are unlikely to be useful.
30510b57cec5SDimitry Andric
30520b57cec5SDimitry Andric // Trailing paste, concat with an empty string.
305381ad6265SDimitry Andric RHS = StringInit::get(Records, "");
30540b57cec5SDimitry Andric break;
30550b57cec5SDimitry Andric
30560b57cec5SDimitry Andric default:
30570b57cec5SDimitry Andric Init *RHSResult = ParseValue(CurRec, nullptr, ParseNameMode);
3058e8d8bef9SDimitry Andric if (!RHSResult)
3059e8d8bef9SDimitry Andric return nullptr;
30600b57cec5SDimitry Andric RHS = dyn_cast<TypedInit>(RHSResult);
30610b57cec5SDimitry Andric if (!RHS) {
30620b57cec5SDimitry Andric Error(PasteLoc, "RHS of paste is not typed!");
30630b57cec5SDimitry Andric return nullptr;
30640b57cec5SDimitry Andric }
30650b57cec5SDimitry Andric
306681ad6265SDimitry Andric if (RHS->getType() != StringRecTy::get(Records)) {
30670b57cec5SDimitry Andric auto CastRHS = dyn_cast<TypedInit>(
306881ad6265SDimitry Andric UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get(Records))
30690b57cec5SDimitry Andric ->Fold(CurRec));
30700b57cec5SDimitry Andric if (!CastRHS) {
30710b57cec5SDimitry Andric Error(PasteLoc,
30720b57cec5SDimitry Andric Twine("can't cast '") + RHS->getAsString() + "' to string");
30730b57cec5SDimitry Andric return nullptr;
30740b57cec5SDimitry Andric }
30750b57cec5SDimitry Andric RHS = CastRHS;
30760b57cec5SDimitry Andric }
30770b57cec5SDimitry Andric
30780b57cec5SDimitry Andric break;
30790b57cec5SDimitry Andric }
30800b57cec5SDimitry Andric
30810b57cec5SDimitry Andric Result = BinOpInit::getStrConcat(LHS, RHS);
30820b57cec5SDimitry Andric break;
30830b57cec5SDimitry Andric }
30840b57cec5SDimitry Andric }
30850b57cec5SDimitry Andric }
30860b57cec5SDimitry Andric
30870b57cec5SDimitry Andric /// ParseDagArgList - Parse the argument list for a dag literal expression.
30880b57cec5SDimitry Andric ///
30890b57cec5SDimitry Andric /// DagArg ::= Value (':' VARNAME)?
30900b57cec5SDimitry Andric /// DagArg ::= VARNAME
30910b57cec5SDimitry Andric /// DagArgList ::= DagArg
30920b57cec5SDimitry Andric /// DagArgList ::= DagArgList ',' DagArg
ParseDagArgList(SmallVectorImpl<std::pair<llvm::Init *,StringInit * >> & Result,Record * CurRec)30930b57cec5SDimitry Andric void TGParser::ParseDagArgList(
30940b57cec5SDimitry Andric SmallVectorImpl<std::pair<llvm::Init*, StringInit*>> &Result,
30950b57cec5SDimitry Andric Record *CurRec) {
30960b57cec5SDimitry Andric
30970b57cec5SDimitry Andric while (true) {
30980b57cec5SDimitry Andric // DagArg ::= VARNAME
30990b57cec5SDimitry Andric if (Lex.getCode() == tgtok::VarName) {
31000b57cec5SDimitry Andric // A missing value is treated like '?'.
310181ad6265SDimitry Andric StringInit *VarName = StringInit::get(Records, Lex.getCurStrVal());
310281ad6265SDimitry Andric Result.emplace_back(UnsetInit::get(Records), VarName);
31030b57cec5SDimitry Andric Lex.Lex();
31040b57cec5SDimitry Andric } else {
31050b57cec5SDimitry Andric // DagArg ::= Value (':' VARNAME)?
31060b57cec5SDimitry Andric Init *Val = ParseValue(CurRec);
31070b57cec5SDimitry Andric if (!Val) {
31080b57cec5SDimitry Andric Result.clear();
31090b57cec5SDimitry Andric return;
31100b57cec5SDimitry Andric }
31110b57cec5SDimitry Andric
31120b57cec5SDimitry Andric // If the variable name is present, add it.
31130b57cec5SDimitry Andric StringInit *VarName = nullptr;
31140b57cec5SDimitry Andric if (Lex.getCode() == tgtok::colon) {
31150b57cec5SDimitry Andric if (Lex.Lex() != tgtok::VarName) { // eat the ':'
31160b57cec5SDimitry Andric TokError("expected variable name in dag literal");
31170b57cec5SDimitry Andric Result.clear();
31180b57cec5SDimitry Andric return;
31190b57cec5SDimitry Andric }
312081ad6265SDimitry Andric VarName = StringInit::get(Records, Lex.getCurStrVal());
31210b57cec5SDimitry Andric Lex.Lex(); // eat the VarName.
31220b57cec5SDimitry Andric }
31230b57cec5SDimitry Andric
31240b57cec5SDimitry Andric Result.push_back(std::make_pair(Val, VarName));
31250b57cec5SDimitry Andric }
31265ffd83dbSDimitry Andric if (!consume(tgtok::comma))
31275ffd83dbSDimitry Andric break;
31280b57cec5SDimitry Andric }
31290b57cec5SDimitry Andric }
31300b57cec5SDimitry Andric
3131fe6060f1SDimitry Andric /// ParseValueList - Parse a comma separated list of values, returning them
3132fe6060f1SDimitry Andric /// in a vector. Note that this always expects to be able to parse at least one
31330b57cec5SDimitry Andric /// value. It returns an empty list if this is not possible.
31340b57cec5SDimitry Andric ///
31350b57cec5SDimitry Andric /// ValueList ::= Value (',' Value)
31360b57cec5SDimitry Andric ///
ParseValueList(SmallVectorImpl<Init * > & Result,Record * CurRec,RecTy * ItemType)31370b57cec5SDimitry Andric void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec,
3138fe6060f1SDimitry Andric RecTy *ItemType) {
3139fe6060f1SDimitry Andric
31400b57cec5SDimitry Andric Result.push_back(ParseValue(CurRec, ItemType));
31410b57cec5SDimitry Andric if (!Result.back()) {
31420b57cec5SDimitry Andric Result.clear();
31430b57cec5SDimitry Andric return;
31440b57cec5SDimitry Andric }
31450b57cec5SDimitry Andric
31465ffd83dbSDimitry Andric while (consume(tgtok::comma)) {
31470b57cec5SDimitry Andric // ignore trailing comma for lists
31480b57cec5SDimitry Andric if (Lex.getCode() == tgtok::r_square)
31490b57cec5SDimitry Andric return;
31500b57cec5SDimitry Andric Result.push_back(ParseValue(CurRec, ItemType));
31510b57cec5SDimitry Andric if (!Result.back()) {
31520b57cec5SDimitry Andric Result.clear();
31530b57cec5SDimitry Andric return;
31540b57cec5SDimitry Andric }
31550b57cec5SDimitry Andric }
31560b57cec5SDimitry Andric }
31570b57cec5SDimitry Andric
3158fe6060f1SDimitry Andric // ParseTemplateArgValueList - Parse a template argument list with the syntax
3159fe6060f1SDimitry Andric // shown, filling in the Result vector. The open angle has been consumed.
3160fe6060f1SDimitry Andric // An empty argument list is allowed. Return false if okay, true if an
3161fe6060f1SDimitry Andric // error was detected.
3162fe6060f1SDimitry Andric //
316306c3fb27SDimitry Andric // ArgValueList ::= '<' PostionalArgValueList [','] NamedArgValueList '>'
316406c3fb27SDimitry Andric // PostionalArgValueList ::= [Value {',' Value}*]
316506c3fb27SDimitry Andric // NamedArgValueList ::= [NameValue '=' Value {',' NameValue '=' Value}*]
ParseTemplateArgValueList(SmallVectorImpl<ArgumentInit * > & Result,Record * CurRec,Record * ArgsRec)316606c3fb27SDimitry Andric bool TGParser::ParseTemplateArgValueList(
31675f757f3fSDimitry Andric SmallVectorImpl<ArgumentInit *> &Result, Record *CurRec, Record *ArgsRec) {
3168fe6060f1SDimitry Andric assert(Result.empty() && "Result vector is not empty");
3169fe6060f1SDimitry Andric ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
3170fe6060f1SDimitry Andric
3171fe6060f1SDimitry Andric if (consume(tgtok::greater)) // empty value list
3172fe6060f1SDimitry Andric return false;
3173fe6060f1SDimitry Andric
317406c3fb27SDimitry Andric bool HasNamedArg = false;
317506c3fb27SDimitry Andric unsigned ArgIndex = 0;
3176fe6060f1SDimitry Andric while (true) {
3177fe6060f1SDimitry Andric if (ArgIndex >= TArgs.size()) {
3178fe6060f1SDimitry Andric TokError("Too many template arguments: " + utostr(ArgIndex + 1));
3179fe6060f1SDimitry Andric return true;
3180fe6060f1SDimitry Andric }
3181fe6060f1SDimitry Andric
318206c3fb27SDimitry Andric SMLoc ValueLoc = Lex.getLoc();
318306c3fb27SDimitry Andric // If we are parsing named argument, we don't need to know the argument name
318406c3fb27SDimitry Andric // and argument type will be resolved after we know the name.
318506c3fb27SDimitry Andric Init *Value = ParseValue(
318606c3fb27SDimitry Andric CurRec,
318706c3fb27SDimitry Andric HasNamedArg ? nullptr : ArgsRec->getValue(TArgs[ArgIndex])->getType());
3188fe6060f1SDimitry Andric if (!Value)
3189fe6060f1SDimitry Andric return true;
319006c3fb27SDimitry Andric
319106c3fb27SDimitry Andric // If we meet '=', then we are parsing named arguments.
319206c3fb27SDimitry Andric if (Lex.getCode() == tgtok::equal) {
319306c3fb27SDimitry Andric if (!isa<StringInit>(Value))
319406c3fb27SDimitry Andric return Error(ValueLoc,
319506c3fb27SDimitry Andric "The name of named argument should be a valid identifier");
319606c3fb27SDimitry Andric
319706c3fb27SDimitry Andric auto *Name = cast<StringInit>(Value);
31985f757f3fSDimitry Andric Init *QualifiedName = QualifyName(*ArgsRec, Name);
319906c3fb27SDimitry Andric auto *NamedArg = ArgsRec->getValue(QualifiedName);
320006c3fb27SDimitry Andric if (!NamedArg)
320106c3fb27SDimitry Andric return Error(ValueLoc,
320206c3fb27SDimitry Andric "Argument " + Name->getAsString() + " doesn't exist");
320306c3fb27SDimitry Andric
320406c3fb27SDimitry Andric Lex.Lex(); // eat the '='.
320506c3fb27SDimitry Andric ValueLoc = Lex.getLoc();
320606c3fb27SDimitry Andric Value = ParseValue(CurRec, NamedArg->getType());
320706c3fb27SDimitry Andric // Named value can't be uninitialized.
320806c3fb27SDimitry Andric if (isa<UnsetInit>(Value))
320906c3fb27SDimitry Andric return Error(ValueLoc,
321006c3fb27SDimitry Andric "The value of named argument should be initialized, "
321106c3fb27SDimitry Andric "but we got '" +
321206c3fb27SDimitry Andric Value->getAsString() + "'");
321306c3fb27SDimitry Andric
321406c3fb27SDimitry Andric Result.push_back(ArgumentInit::get(Value, QualifiedName));
321506c3fb27SDimitry Andric HasNamedArg = true;
321606c3fb27SDimitry Andric } else {
321706c3fb27SDimitry Andric // Positional arguments should be put before named arguments.
321806c3fb27SDimitry Andric if (HasNamedArg)
321906c3fb27SDimitry Andric return Error(ValueLoc,
322006c3fb27SDimitry Andric "Positional argument should be put before named argument");
322106c3fb27SDimitry Andric
322206c3fb27SDimitry Andric Result.push_back(ArgumentInit::get(Value, ArgIndex));
322306c3fb27SDimitry Andric }
3224fe6060f1SDimitry Andric
3225fe6060f1SDimitry Andric if (consume(tgtok::greater)) // end of argument list?
3226fe6060f1SDimitry Andric return false;
3227fe6060f1SDimitry Andric if (!consume(tgtok::comma))
3228fe6060f1SDimitry Andric return TokError("Expected comma before next argument");
3229fe6060f1SDimitry Andric ++ArgIndex;
3230fe6060f1SDimitry Andric }
3231fe6060f1SDimitry Andric }
3232fe6060f1SDimitry Andric
32330b57cec5SDimitry Andric /// ParseDeclaration - Read a declaration, returning the name of field ID, or an
3234fe6060f1SDimitry Andric /// empty string on error. This can happen in a number of different contexts,
3235fe6060f1SDimitry Andric /// including within a def or in the template args for a class (in which case
32360b57cec5SDimitry Andric /// CurRec will be non-null) and within the template args for a multiclass (in
32370b57cec5SDimitry Andric /// which case CurRec will be null, but CurMultiClass will be set). This can
32380b57cec5SDimitry Andric /// also happen within a def that is within a multiclass, which will set both
32390b57cec5SDimitry Andric /// CurRec and CurMultiClass.
32400b57cec5SDimitry Andric ///
32410b57cec5SDimitry Andric /// Declaration ::= FIELD? Type ID ('=' Value)?
32420b57cec5SDimitry Andric ///
ParseDeclaration(Record * CurRec,bool ParsingTemplateArgs)32430b57cec5SDimitry Andric Init *TGParser::ParseDeclaration(Record *CurRec,
32440b57cec5SDimitry Andric bool ParsingTemplateArgs) {
32450b57cec5SDimitry Andric // Read the field prefix if present.
32465ffd83dbSDimitry Andric bool HasField = consume(tgtok::Field);
32470b57cec5SDimitry Andric
32480b57cec5SDimitry Andric RecTy *Type = ParseType();
32490b57cec5SDimitry Andric if (!Type) return nullptr;
32500b57cec5SDimitry Andric
32510b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id) {
32520b57cec5SDimitry Andric TokError("Expected identifier in declaration");
32530b57cec5SDimitry Andric return nullptr;
32540b57cec5SDimitry Andric }
32550b57cec5SDimitry Andric
32560b57cec5SDimitry Andric std::string Str = Lex.getCurStrVal();
32570b57cec5SDimitry Andric if (Str == "NAME") {
32580b57cec5SDimitry Andric TokError("'" + Str + "' is a reserved variable name");
32590b57cec5SDimitry Andric return nullptr;
32600b57cec5SDimitry Andric }
32610b57cec5SDimitry Andric
326206c3fb27SDimitry Andric if (!ParsingTemplateArgs && CurScope->varAlreadyDefined(Str)) {
326306c3fb27SDimitry Andric TokError("local variable of this name already exists");
326406c3fb27SDimitry Andric return nullptr;
326506c3fb27SDimitry Andric }
326606c3fb27SDimitry Andric
32670b57cec5SDimitry Andric SMLoc IdLoc = Lex.getLoc();
326881ad6265SDimitry Andric Init *DeclName = StringInit::get(Records, Str);
32690b57cec5SDimitry Andric Lex.Lex();
32700b57cec5SDimitry Andric
3271fe6060f1SDimitry Andric bool BadField;
3272fe6060f1SDimitry Andric if (!ParsingTemplateArgs) { // def, possibly in a multiclass
3273fe6060f1SDimitry Andric BadField = AddValue(CurRec, IdLoc,
3274fe6060f1SDimitry Andric RecordVal(DeclName, IdLoc, Type,
3275e8d8bef9SDimitry Andric HasField ? RecordVal::FK_NonconcreteOK
3276fe6060f1SDimitry Andric : RecordVal::FK_Normal));
3277fe6060f1SDimitry Andric } else if (CurRec) { // class template argument
32785f757f3fSDimitry Andric DeclName = QualifyName(*CurRec, DeclName);
32795f757f3fSDimitry Andric BadField =
32805f757f3fSDimitry Andric AddValue(CurRec, IdLoc,
32815f757f3fSDimitry Andric RecordVal(DeclName, IdLoc, Type, RecordVal::FK_TemplateArg));
3282fe6060f1SDimitry Andric } else { // multiclass template argument
3283fe6060f1SDimitry Andric assert(CurMultiClass && "invalid context for template argument");
32845f757f3fSDimitry Andric DeclName = QualifyName(CurMultiClass, DeclName);
32855f757f3fSDimitry Andric BadField =
32865f757f3fSDimitry Andric AddValue(CurRec, IdLoc,
32875f757f3fSDimitry Andric RecordVal(DeclName, IdLoc, Type, RecordVal::FK_TemplateArg));
3288fe6060f1SDimitry Andric }
3289fe6060f1SDimitry Andric if (BadField)
32900b57cec5SDimitry Andric return nullptr;
32910b57cec5SDimitry Andric
3292fe6060f1SDimitry Andric // If a value is present, parse it and set new field's value.
32935ffd83dbSDimitry Andric if (consume(tgtok::equal)) {
32940b57cec5SDimitry Andric SMLoc ValLoc = Lex.getLoc();
32950b57cec5SDimitry Andric Init *Val = ParseValue(CurRec, Type);
32960b57cec5SDimitry Andric if (!Val ||
3297bdd1243dSDimitry Andric SetValue(CurRec, ValLoc, DeclName, std::nullopt, Val,
3298bdd1243dSDimitry Andric /*AllowSelfAssignment=*/false, /*OverrideDefLoc=*/false)) {
32990b57cec5SDimitry Andric // Return the name, even if an error is thrown. This is so that we can
33000b57cec5SDimitry Andric // continue to make some progress, even without the value having been
33010b57cec5SDimitry Andric // initialized.
33020b57cec5SDimitry Andric return DeclName;
33030b57cec5SDimitry Andric }
3304bdd1243dSDimitry Andric }
33050b57cec5SDimitry Andric
33060b57cec5SDimitry Andric return DeclName;
33070b57cec5SDimitry Andric }
33080b57cec5SDimitry Andric
33090b57cec5SDimitry Andric /// ParseForeachDeclaration - Read a foreach declaration, returning
33100b57cec5SDimitry Andric /// the name of the declared object or a NULL Init on error. Return
33110b57cec5SDimitry Andric /// the name of the parsed initializer list through ForeachListName.
33120b57cec5SDimitry Andric ///
33130b57cec5SDimitry Andric /// ForeachDeclaration ::= ID '=' '{' RangeList '}'
33140b57cec5SDimitry Andric /// ForeachDeclaration ::= ID '=' RangePiece
33150b57cec5SDimitry Andric /// ForeachDeclaration ::= ID '=' Value
33160b57cec5SDimitry Andric ///
ParseForeachDeclaration(Init * & ForeachListValue)33170b57cec5SDimitry Andric VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {
33180b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id) {
33190b57cec5SDimitry Andric TokError("Expected identifier in foreach declaration");
33200b57cec5SDimitry Andric return nullptr;
33210b57cec5SDimitry Andric }
33220b57cec5SDimitry Andric
332381ad6265SDimitry Andric Init *DeclName = StringInit::get(Records, Lex.getCurStrVal());
33240b57cec5SDimitry Andric Lex.Lex();
33250b57cec5SDimitry Andric
33260b57cec5SDimitry Andric // If a value is present, parse it.
33275ffd83dbSDimitry Andric if (!consume(tgtok::equal)) {
33280b57cec5SDimitry Andric TokError("Expected '=' in foreach declaration");
33290b57cec5SDimitry Andric return nullptr;
33300b57cec5SDimitry Andric }
33310b57cec5SDimitry Andric
33320b57cec5SDimitry Andric RecTy *IterType = nullptr;
33330b57cec5SDimitry Andric SmallVector<unsigned, 16> Ranges;
33340b57cec5SDimitry Andric
33350b57cec5SDimitry Andric switch (Lex.getCode()) {
33360b57cec5SDimitry Andric case tgtok::l_brace: { // '{' RangeList '}'
33370b57cec5SDimitry Andric Lex.Lex(); // eat the '{'
33380b57cec5SDimitry Andric ParseRangeList(Ranges);
33395ffd83dbSDimitry Andric if (!consume(tgtok::r_brace)) {
33400b57cec5SDimitry Andric TokError("expected '}' at end of bit range list");
33410b57cec5SDimitry Andric return nullptr;
33420b57cec5SDimitry Andric }
33430b57cec5SDimitry Andric break;
33440b57cec5SDimitry Andric }
33450b57cec5SDimitry Andric
33460b57cec5SDimitry Andric default: {
33470b57cec5SDimitry Andric SMLoc ValueLoc = Lex.getLoc();
33480b57cec5SDimitry Andric Init *I = ParseValue(nullptr);
33490b57cec5SDimitry Andric if (!I)
33500b57cec5SDimitry Andric return nullptr;
33510b57cec5SDimitry Andric
33520b57cec5SDimitry Andric TypedInit *TI = dyn_cast<TypedInit>(I);
33530b57cec5SDimitry Andric if (TI && isa<ListRecTy>(TI->getType())) {
33540b57cec5SDimitry Andric ForeachListValue = I;
33550b57cec5SDimitry Andric IterType = cast<ListRecTy>(TI->getType())->getElementType();
33560b57cec5SDimitry Andric break;
33570b57cec5SDimitry Andric }
33580b57cec5SDimitry Andric
33590b57cec5SDimitry Andric if (TI) {
33600b57cec5SDimitry Andric if (ParseRangePiece(Ranges, TI))
33610b57cec5SDimitry Andric return nullptr;
33620b57cec5SDimitry Andric break;
33630b57cec5SDimitry Andric }
33640b57cec5SDimitry Andric
3365fe6060f1SDimitry Andric Error(ValueLoc, "expected a list, got '" + I->getAsString() + "'");
33660b57cec5SDimitry Andric if (CurMultiClass) {
33670b57cec5SDimitry Andric PrintNote({}, "references to multiclass template arguments cannot be "
33680b57cec5SDimitry Andric "resolved at this time");
33690b57cec5SDimitry Andric }
33700b57cec5SDimitry Andric return nullptr;
33710b57cec5SDimitry Andric }
33720b57cec5SDimitry Andric }
33730b57cec5SDimitry Andric
33740b57cec5SDimitry Andric
33750b57cec5SDimitry Andric if (!Ranges.empty()) {
33760b57cec5SDimitry Andric assert(!IterType && "Type already initialized?");
337781ad6265SDimitry Andric IterType = IntRecTy::get(Records);
33780b57cec5SDimitry Andric std::vector<Init *> Values;
33790b57cec5SDimitry Andric for (unsigned R : Ranges)
338081ad6265SDimitry Andric Values.push_back(IntInit::get(Records, R));
33810b57cec5SDimitry Andric ForeachListValue = ListInit::get(Values, IterType);
33820b57cec5SDimitry Andric }
33830b57cec5SDimitry Andric
33840b57cec5SDimitry Andric if (!IterType)
33850b57cec5SDimitry Andric return nullptr;
33860b57cec5SDimitry Andric
33870b57cec5SDimitry Andric return VarInit::get(DeclName, IterType);
33880b57cec5SDimitry Andric }
33890b57cec5SDimitry Andric
33900b57cec5SDimitry Andric /// ParseTemplateArgList - Read a template argument list, which is a non-empty
33910b57cec5SDimitry Andric /// sequence of template-declarations in <>'s. If CurRec is non-null, these are
3392fe6060f1SDimitry Andric /// template args for a class. If null, these are the template args for a
3393fe6060f1SDimitry Andric /// multiclass.
33940b57cec5SDimitry Andric ///
33950b57cec5SDimitry Andric /// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'
33960b57cec5SDimitry Andric ///
ParseTemplateArgList(Record * CurRec)33970b57cec5SDimitry Andric bool TGParser::ParseTemplateArgList(Record *CurRec) {
33980b57cec5SDimitry Andric assert(Lex.getCode() == tgtok::less && "Not a template arg list!");
33990b57cec5SDimitry Andric Lex.Lex(); // eat the '<'
34000b57cec5SDimitry Andric
34010b57cec5SDimitry Andric Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;
34020b57cec5SDimitry Andric
34030b57cec5SDimitry Andric // Read the first declaration.
34040b57cec5SDimitry Andric Init *TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
34050b57cec5SDimitry Andric if (!TemplArg)
34060b57cec5SDimitry Andric return true;
34070b57cec5SDimitry Andric
34080b57cec5SDimitry Andric TheRecToAddTo->addTemplateArg(TemplArg);
34090b57cec5SDimitry Andric
34105ffd83dbSDimitry Andric while (consume(tgtok::comma)) {
34110b57cec5SDimitry Andric // Read the following declarations.
34120b57cec5SDimitry Andric SMLoc Loc = Lex.getLoc();
34130b57cec5SDimitry Andric TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
34140b57cec5SDimitry Andric if (!TemplArg)
34150b57cec5SDimitry Andric return true;
34160b57cec5SDimitry Andric
34170b57cec5SDimitry Andric if (TheRecToAddTo->isTemplateArg(TemplArg))
34180b57cec5SDimitry Andric return Error(Loc, "template argument with the same name has already been "
34190b57cec5SDimitry Andric "defined");
34200b57cec5SDimitry Andric
34210b57cec5SDimitry Andric TheRecToAddTo->addTemplateArg(TemplArg);
34220b57cec5SDimitry Andric }
34230b57cec5SDimitry Andric
34245ffd83dbSDimitry Andric if (!consume(tgtok::greater))
34250b57cec5SDimitry Andric return TokError("expected '>' at end of template argument list");
34260b57cec5SDimitry Andric return false;
34270b57cec5SDimitry Andric }
34280b57cec5SDimitry Andric
3429e8d8bef9SDimitry Andric /// ParseBodyItem - Parse a single item within the body of a def or class.
34300b57cec5SDimitry Andric ///
34310b57cec5SDimitry Andric /// BodyItem ::= Declaration ';'
34320b57cec5SDimitry Andric /// BodyItem ::= LET ID OptionalBitList '=' Value ';'
3433480093f4SDimitry Andric /// BodyItem ::= Defvar
34345f757f3fSDimitry Andric /// BodyItem ::= Dump
3435e8d8bef9SDimitry Andric /// BodyItem ::= Assert
3436fe6060f1SDimitry Andric ///
ParseBodyItem(Record * CurRec)34370b57cec5SDimitry Andric bool TGParser::ParseBodyItem(Record *CurRec) {
3438e8d8bef9SDimitry Andric if (Lex.getCode() == tgtok::Assert)
3439e8d8bef9SDimitry Andric return ParseAssert(nullptr, CurRec);
3440e8d8bef9SDimitry Andric
3441480093f4SDimitry Andric if (Lex.getCode() == tgtok::Defvar)
344206c3fb27SDimitry Andric return ParseDefvar(CurRec);
3443480093f4SDimitry Andric
34445f757f3fSDimitry Andric if (Lex.getCode() == tgtok::Dump)
34455f757f3fSDimitry Andric return ParseDump(nullptr, CurRec);
34465f757f3fSDimitry Andric
34470b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Let) {
34480b57cec5SDimitry Andric if (!ParseDeclaration(CurRec, false))
34490b57cec5SDimitry Andric return true;
34500b57cec5SDimitry Andric
34515ffd83dbSDimitry Andric if (!consume(tgtok::semi))
34520b57cec5SDimitry Andric return TokError("expected ';' after declaration");
34530b57cec5SDimitry Andric return false;
34540b57cec5SDimitry Andric }
34550b57cec5SDimitry Andric
34560b57cec5SDimitry Andric // LET ID OptionalRangeList '=' Value ';'
34570b57cec5SDimitry Andric if (Lex.Lex() != tgtok::Id)
34580b57cec5SDimitry Andric return TokError("expected field identifier after let");
34590b57cec5SDimitry Andric
34600b57cec5SDimitry Andric SMLoc IdLoc = Lex.getLoc();
346181ad6265SDimitry Andric StringInit *FieldName = StringInit::get(Records, Lex.getCurStrVal());
34620b57cec5SDimitry Andric Lex.Lex(); // eat the field name.
34630b57cec5SDimitry Andric
34640b57cec5SDimitry Andric SmallVector<unsigned, 16> BitList;
34650b57cec5SDimitry Andric if (ParseOptionalBitList(BitList))
34660b57cec5SDimitry Andric return true;
34670b57cec5SDimitry Andric std::reverse(BitList.begin(), BitList.end());
34680b57cec5SDimitry Andric
34695ffd83dbSDimitry Andric if (!consume(tgtok::equal))
34700b57cec5SDimitry Andric return TokError("expected '=' in let expression");
34710b57cec5SDimitry Andric
34720b57cec5SDimitry Andric RecordVal *Field = CurRec->getValue(FieldName);
34730b57cec5SDimitry Andric if (!Field)
34740b57cec5SDimitry Andric return TokError("Value '" + FieldName->getValue() + "' unknown!");
34750b57cec5SDimitry Andric
34760b57cec5SDimitry Andric RecTy *Type = Field->getType();
34775ffd83dbSDimitry Andric if (!BitList.empty() && isa<BitsRecTy>(Type)) {
34785ffd83dbSDimitry Andric // When assigning to a subset of a 'bits' object, expect the RHS to have
34795ffd83dbSDimitry Andric // the type of that subset instead of the type of the whole object.
348081ad6265SDimitry Andric Type = BitsRecTy::get(Records, BitList.size());
34815ffd83dbSDimitry Andric }
34820b57cec5SDimitry Andric
34830b57cec5SDimitry Andric Init *Val = ParseValue(CurRec, Type);
34840b57cec5SDimitry Andric if (!Val) return true;
34850b57cec5SDimitry Andric
34865ffd83dbSDimitry Andric if (!consume(tgtok::semi))
34870b57cec5SDimitry Andric return TokError("expected ';' after let expression");
34880b57cec5SDimitry Andric
34890b57cec5SDimitry Andric return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
34900b57cec5SDimitry Andric }
34910b57cec5SDimitry Andric
34920b57cec5SDimitry Andric /// ParseBody - Read the body of a class or def. Return true on error, false on
34930b57cec5SDimitry Andric /// success.
34940b57cec5SDimitry Andric ///
34950b57cec5SDimitry Andric /// Body ::= ';'
34960b57cec5SDimitry Andric /// Body ::= '{' BodyList '}'
34970b57cec5SDimitry Andric /// BodyList BodyItem*
34980b57cec5SDimitry Andric ///
ParseBody(Record * CurRec)34990b57cec5SDimitry Andric bool TGParser::ParseBody(Record *CurRec) {
35000b57cec5SDimitry Andric // If this is a null definition, just eat the semi and return.
35015ffd83dbSDimitry Andric if (consume(tgtok::semi))
35020b57cec5SDimitry Andric return false;
35030b57cec5SDimitry Andric
35045ffd83dbSDimitry Andric if (!consume(tgtok::l_brace))
3505e8d8bef9SDimitry Andric return TokError("Expected '{' to start body or ';' for declaration only");
35060b57cec5SDimitry Andric
35070b57cec5SDimitry Andric while (Lex.getCode() != tgtok::r_brace)
35080b57cec5SDimitry Andric if (ParseBodyItem(CurRec))
35090b57cec5SDimitry Andric return true;
35100b57cec5SDimitry Andric
35110b57cec5SDimitry Andric // Eat the '}'.
35120b57cec5SDimitry Andric Lex.Lex();
3513e8d8bef9SDimitry Andric
3514e8d8bef9SDimitry Andric // If we have a semicolon, print a gentle error.
3515e8d8bef9SDimitry Andric SMLoc SemiLoc = Lex.getLoc();
3516e8d8bef9SDimitry Andric if (consume(tgtok::semi)) {
3517e8d8bef9SDimitry Andric PrintError(SemiLoc, "A class or def body should not end with a semicolon");
3518e8d8bef9SDimitry Andric PrintNote("Semicolon ignored; remove to eliminate this error");
3519e8d8bef9SDimitry Andric }
3520e8d8bef9SDimitry Andric
35210b57cec5SDimitry Andric return false;
35220b57cec5SDimitry Andric }
35230b57cec5SDimitry Andric
35240b57cec5SDimitry Andric /// Apply the current let bindings to \a CurRec.
35250b57cec5SDimitry Andric /// \returns true on error, false otherwise.
ApplyLetStack(Record * CurRec)35260b57cec5SDimitry Andric bool TGParser::ApplyLetStack(Record *CurRec) {
35270b57cec5SDimitry Andric for (SmallVectorImpl<LetRecord> &LetInfo : LetStack)
35280b57cec5SDimitry Andric for (LetRecord &LR : LetInfo)
35290b57cec5SDimitry Andric if (SetValue(CurRec, LR.Loc, LR.Name, LR.Bits, LR.Value))
35300b57cec5SDimitry Andric return true;
35310b57cec5SDimitry Andric return false;
35320b57cec5SDimitry Andric }
35330b57cec5SDimitry Andric
3534fe6060f1SDimitry Andric /// Apply the current let bindings to the RecordsEntry.
ApplyLetStack(RecordsEntry & Entry)35350b57cec5SDimitry Andric bool TGParser::ApplyLetStack(RecordsEntry &Entry) {
35360b57cec5SDimitry Andric if (Entry.Rec)
35370b57cec5SDimitry Andric return ApplyLetStack(Entry.Rec.get());
35380b57cec5SDimitry Andric
3539fe6060f1SDimitry Andric // Let bindings are not applied to assertions.
3540fe6060f1SDimitry Andric if (Entry.Assertion)
3541fe6060f1SDimitry Andric return false;
3542fe6060f1SDimitry Andric
35435f757f3fSDimitry Andric // Let bindings are not applied to dumps.
35445f757f3fSDimitry Andric if (Entry.Dump)
35455f757f3fSDimitry Andric return false;
35465f757f3fSDimitry Andric
35470b57cec5SDimitry Andric for (auto &E : Entry.Loop->Entries) {
35480b57cec5SDimitry Andric if (ApplyLetStack(E))
35490b57cec5SDimitry Andric return true;
35500b57cec5SDimitry Andric }
35510b57cec5SDimitry Andric
35520b57cec5SDimitry Andric return false;
35530b57cec5SDimitry Andric }
35540b57cec5SDimitry Andric
35550b57cec5SDimitry Andric /// ParseObjectBody - Parse the body of a def or class. This consists of an
35560b57cec5SDimitry Andric /// optional ClassList followed by a Body. CurRec is the current def or class
35570b57cec5SDimitry Andric /// that is being parsed.
35580b57cec5SDimitry Andric ///
35590b57cec5SDimitry Andric /// ObjectBody ::= BaseClassList Body
35600b57cec5SDimitry Andric /// BaseClassList ::= /*empty*/
35610b57cec5SDimitry Andric /// BaseClassList ::= ':' BaseClassListNE
35620b57cec5SDimitry Andric /// BaseClassListNE ::= SubClassRef (',' SubClassRef)*
35630b57cec5SDimitry Andric ///
ParseObjectBody(Record * CurRec)35640b57cec5SDimitry Andric bool TGParser::ParseObjectBody(Record *CurRec) {
356506c3fb27SDimitry Andric // An object body introduces a new scope for local variables.
356606c3fb27SDimitry Andric TGVarScope *ObjectScope = PushScope(CurRec);
35670b57cec5SDimitry Andric // If there is a baseclass list, read it.
35685ffd83dbSDimitry Andric if (consume(tgtok::colon)) {
35690b57cec5SDimitry Andric
35700b57cec5SDimitry Andric // Read all of the subclasses.
35710b57cec5SDimitry Andric SubClassReference SubClass = ParseSubClassReference(CurRec, false);
35720b57cec5SDimitry Andric while (true) {
35730b57cec5SDimitry Andric // Check for error.
35740b57cec5SDimitry Andric if (!SubClass.Rec) return true;
35750b57cec5SDimitry Andric
35760b57cec5SDimitry Andric // Add it.
35770b57cec5SDimitry Andric if (AddSubClass(CurRec, SubClass))
35780b57cec5SDimitry Andric return true;
35790b57cec5SDimitry Andric
35805ffd83dbSDimitry Andric if (!consume(tgtok::comma))
35815ffd83dbSDimitry Andric break;
35820b57cec5SDimitry Andric SubClass = ParseSubClassReference(CurRec, false);
35830b57cec5SDimitry Andric }
35840b57cec5SDimitry Andric }
35850b57cec5SDimitry Andric
35860b57cec5SDimitry Andric if (ApplyLetStack(CurRec))
35870b57cec5SDimitry Andric return true;
35880b57cec5SDimitry Andric
358906c3fb27SDimitry Andric bool Result = ParseBody(CurRec);
359006c3fb27SDimitry Andric PopScope(ObjectScope);
359106c3fb27SDimitry Andric return Result;
35920b57cec5SDimitry Andric }
35930b57cec5SDimitry Andric
3594fe6060f1SDimitry Andric /// ParseDef - Parse and return a top level or multiclass record definition.
3595fe6060f1SDimitry Andric /// Return false if okay, true if error.
35960b57cec5SDimitry Andric ///
35970b57cec5SDimitry Andric /// DefInst ::= DEF ObjectName ObjectBody
35980b57cec5SDimitry Andric ///
ParseDef(MultiClass * CurMultiClass)35990b57cec5SDimitry Andric bool TGParser::ParseDef(MultiClass *CurMultiClass) {
36000b57cec5SDimitry Andric SMLoc DefLoc = Lex.getLoc();
36010b57cec5SDimitry Andric assert(Lex.getCode() == tgtok::Def && "Unknown tok");
36020b57cec5SDimitry Andric Lex.Lex(); // Eat the 'def' token.
36030b57cec5SDimitry Andric
3604bdd1243dSDimitry Andric // If the name of the def is an Id token, use that for the location.
3605bdd1243dSDimitry Andric // Otherwise, the name is more complex and we use the location of the 'def'
3606bdd1243dSDimitry Andric // token.
3607bdd1243dSDimitry Andric SMLoc NameLoc = Lex.getCode() == tgtok::Id ? Lex.getLoc() : DefLoc;
3608bdd1243dSDimitry Andric
36090b57cec5SDimitry Andric // Parse ObjectName and make a record for it.
36100b57cec5SDimitry Andric std::unique_ptr<Record> CurRec;
36110b57cec5SDimitry Andric Init *Name = ParseObjectName(CurMultiClass);
36120b57cec5SDimitry Andric if (!Name)
36130b57cec5SDimitry Andric return true;
36140b57cec5SDimitry Andric
3615bdd1243dSDimitry Andric if (isa<UnsetInit>(Name)) {
36165f757f3fSDimitry Andric CurRec = std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc,
36175f757f3fSDimitry Andric Records, Record::RK_AnonymousDef);
3618bdd1243dSDimitry Andric } else {
3619bdd1243dSDimitry Andric CurRec = std::make_unique<Record>(Name, NameLoc, Records);
3620bdd1243dSDimitry Andric }
36210b57cec5SDimitry Andric
36220b57cec5SDimitry Andric if (ParseObjectBody(CurRec.get()))
36230b57cec5SDimitry Andric return true;
36240b57cec5SDimitry Andric
36250b57cec5SDimitry Andric return addEntry(std::move(CurRec));
36260b57cec5SDimitry Andric }
36270b57cec5SDimitry Andric
36280b57cec5SDimitry Andric /// ParseDefset - Parse a defset statement.
36290b57cec5SDimitry Andric ///
36300b57cec5SDimitry Andric /// Defset ::= DEFSET Type Id '=' '{' ObjectList '}'
36310b57cec5SDimitry Andric ///
ParseDefset()36320b57cec5SDimitry Andric bool TGParser::ParseDefset() {
36330b57cec5SDimitry Andric assert(Lex.getCode() == tgtok::Defset);
36340b57cec5SDimitry Andric Lex.Lex(); // Eat the 'defset' token
36350b57cec5SDimitry Andric
36360b57cec5SDimitry Andric DefsetRecord Defset;
36370b57cec5SDimitry Andric Defset.Loc = Lex.getLoc();
36380b57cec5SDimitry Andric RecTy *Type = ParseType();
36390b57cec5SDimitry Andric if (!Type)
36400b57cec5SDimitry Andric return true;
36410b57cec5SDimitry Andric if (!isa<ListRecTy>(Type))
36420b57cec5SDimitry Andric return Error(Defset.Loc, "expected list type");
36430b57cec5SDimitry Andric Defset.EltTy = cast<ListRecTy>(Type)->getElementType();
36440b57cec5SDimitry Andric
36450b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id)
36460b57cec5SDimitry Andric return TokError("expected identifier");
364781ad6265SDimitry Andric StringInit *DeclName = StringInit::get(Records, Lex.getCurStrVal());
36480b57cec5SDimitry Andric if (Records.getGlobal(DeclName->getValue()))
36490b57cec5SDimitry Andric return TokError("def or global variable of this name already exists");
36500b57cec5SDimitry Andric
36510b57cec5SDimitry Andric if (Lex.Lex() != tgtok::equal) // Eat the identifier
36520b57cec5SDimitry Andric return TokError("expected '='");
36530b57cec5SDimitry Andric if (Lex.Lex() != tgtok::l_brace) // Eat the '='
36540b57cec5SDimitry Andric return TokError("expected '{'");
36550b57cec5SDimitry Andric SMLoc BraceLoc = Lex.getLoc();
36560b57cec5SDimitry Andric Lex.Lex(); // Eat the '{'
36570b57cec5SDimitry Andric
36580b57cec5SDimitry Andric Defsets.push_back(&Defset);
36590b57cec5SDimitry Andric bool Err = ParseObjectList(nullptr);
36600b57cec5SDimitry Andric Defsets.pop_back();
36610b57cec5SDimitry Andric if (Err)
36620b57cec5SDimitry Andric return true;
36630b57cec5SDimitry Andric
36645ffd83dbSDimitry Andric if (!consume(tgtok::r_brace)) {
36650b57cec5SDimitry Andric TokError("expected '}' at end of defset");
36660b57cec5SDimitry Andric return Error(BraceLoc, "to match this '{'");
36670b57cec5SDimitry Andric }
36680b57cec5SDimitry Andric
36690b57cec5SDimitry Andric Records.addExtraGlobal(DeclName->getValue(),
36700b57cec5SDimitry Andric ListInit::get(Defset.Elements, Defset.EltTy));
36710b57cec5SDimitry Andric return false;
36720b57cec5SDimitry Andric }
36730b57cec5SDimitry Andric
3674*0fca6ea1SDimitry Andric /// ParseDeftype - Parse a defvar statement.
3675*0fca6ea1SDimitry Andric ///
3676*0fca6ea1SDimitry Andric /// Deftype ::= DEFTYPE Id '=' Type ';'
3677*0fca6ea1SDimitry Andric ///
ParseDeftype()3678*0fca6ea1SDimitry Andric bool TGParser::ParseDeftype() {
3679*0fca6ea1SDimitry Andric assert(Lex.getCode() == tgtok::Deftype);
3680*0fca6ea1SDimitry Andric Lex.Lex(); // Eat the 'deftype' token
3681*0fca6ea1SDimitry Andric
3682*0fca6ea1SDimitry Andric if (Lex.getCode() != tgtok::Id)
3683*0fca6ea1SDimitry Andric return TokError("expected identifier");
3684*0fca6ea1SDimitry Andric
3685*0fca6ea1SDimitry Andric const std::string TypeName = Lex.getCurStrVal();
3686*0fca6ea1SDimitry Andric if (TypeAliases.count(TypeName) || Records.getClass(TypeName))
3687*0fca6ea1SDimitry Andric return TokError("type of this name '" + TypeName + "' already exists");
3688*0fca6ea1SDimitry Andric
3689*0fca6ea1SDimitry Andric Lex.Lex();
3690*0fca6ea1SDimitry Andric if (!consume(tgtok::equal))
3691*0fca6ea1SDimitry Andric return TokError("expected '='");
3692*0fca6ea1SDimitry Andric
3693*0fca6ea1SDimitry Andric SMLoc Loc = Lex.getLoc();
3694*0fca6ea1SDimitry Andric RecTy *Type = ParseType();
3695*0fca6ea1SDimitry Andric if (!Type)
3696*0fca6ea1SDimitry Andric return true;
3697*0fca6ea1SDimitry Andric
3698*0fca6ea1SDimitry Andric if (Type->getRecTyKind() == RecTy::RecordRecTyKind)
3699*0fca6ea1SDimitry Andric return Error(Loc, "cannot define type alias for class type '" +
3700*0fca6ea1SDimitry Andric Type->getAsString() + "'");
3701*0fca6ea1SDimitry Andric
3702*0fca6ea1SDimitry Andric TypeAliases[TypeName] = Type;
3703*0fca6ea1SDimitry Andric
3704*0fca6ea1SDimitry Andric if (!consume(tgtok::semi))
3705*0fca6ea1SDimitry Andric return TokError("expected ';'");
3706*0fca6ea1SDimitry Andric
3707*0fca6ea1SDimitry Andric return false;
3708*0fca6ea1SDimitry Andric }
3709*0fca6ea1SDimitry Andric
3710480093f4SDimitry Andric /// ParseDefvar - Parse a defvar statement.
3711480093f4SDimitry Andric ///
3712480093f4SDimitry Andric /// Defvar ::= DEFVAR Id '=' Value ';'
3713480093f4SDimitry Andric ///
ParseDefvar(Record * CurRec)371406c3fb27SDimitry Andric bool TGParser::ParseDefvar(Record *CurRec) {
3715480093f4SDimitry Andric assert(Lex.getCode() == tgtok::Defvar);
3716480093f4SDimitry Andric Lex.Lex(); // Eat the 'defvar' token
3717480093f4SDimitry Andric
3718480093f4SDimitry Andric if (Lex.getCode() != tgtok::Id)
3719480093f4SDimitry Andric return TokError("expected identifier");
372081ad6265SDimitry Andric StringInit *DeclName = StringInit::get(Records, Lex.getCurStrVal());
372106c3fb27SDimitry Andric if (CurScope->varAlreadyDefined(DeclName->getValue()))
3722480093f4SDimitry Andric return TokError("local variable of this name already exists");
372306c3fb27SDimitry Andric
372406c3fb27SDimitry Andric // The name should not be conflicted with existed field names.
372506c3fb27SDimitry Andric if (CurRec) {
372606c3fb27SDimitry Andric auto *V = CurRec->getValue(DeclName->getValue());
372706c3fb27SDimitry Andric if (V && !V->isTemplateArg())
372806c3fb27SDimitry Andric return TokError("field of this name already exists");
3729480093f4SDimitry Andric }
3730480093f4SDimitry Andric
373106c3fb27SDimitry Andric // If this defvar is in the top level, the name should not be conflicted
373206c3fb27SDimitry Andric // with existed global names.
373306c3fb27SDimitry Andric if (CurScope->isOutermost() && Records.getGlobal(DeclName->getValue()))
373406c3fb27SDimitry Andric return TokError("def or global variable of this name already exists");
373506c3fb27SDimitry Andric
37365ffd83dbSDimitry Andric Lex.Lex();
37375ffd83dbSDimitry Andric if (!consume(tgtok::equal))
3738480093f4SDimitry Andric return TokError("expected '='");
3739480093f4SDimitry Andric
374006c3fb27SDimitry Andric Init *Value = ParseValue(CurRec);
3741480093f4SDimitry Andric if (!Value)
3742480093f4SDimitry Andric return true;
3743480093f4SDimitry Andric
37445ffd83dbSDimitry Andric if (!consume(tgtok::semi))
3745480093f4SDimitry Andric return TokError("expected ';'");
3746480093f4SDimitry Andric
374706c3fb27SDimitry Andric if (!CurScope->isOutermost())
374806c3fb27SDimitry Andric CurScope->addVar(DeclName->getValue(), Value);
3749480093f4SDimitry Andric else
3750480093f4SDimitry Andric Records.addExtraGlobal(DeclName->getValue(), Value);
3751480093f4SDimitry Andric
3752480093f4SDimitry Andric return false;
3753480093f4SDimitry Andric }
3754480093f4SDimitry Andric
37550b57cec5SDimitry Andric /// ParseForeach - Parse a for statement. Return the record corresponding
37560b57cec5SDimitry Andric /// to it. This returns true on error.
37570b57cec5SDimitry Andric ///
37580b57cec5SDimitry Andric /// Foreach ::= FOREACH Declaration IN '{ ObjectList '}'
37590b57cec5SDimitry Andric /// Foreach ::= FOREACH Declaration IN Object
37600b57cec5SDimitry Andric ///
ParseForeach(MultiClass * CurMultiClass)37610b57cec5SDimitry Andric bool TGParser::ParseForeach(MultiClass *CurMultiClass) {
37620b57cec5SDimitry Andric SMLoc Loc = Lex.getLoc();
37630b57cec5SDimitry Andric assert(Lex.getCode() == tgtok::Foreach && "Unknown tok");
37640b57cec5SDimitry Andric Lex.Lex(); // Eat the 'for' token.
37650b57cec5SDimitry Andric
37660b57cec5SDimitry Andric // Make a temporary object to record items associated with the for
37670b57cec5SDimitry Andric // loop.
37680b57cec5SDimitry Andric Init *ListValue = nullptr;
37690b57cec5SDimitry Andric VarInit *IterName = ParseForeachDeclaration(ListValue);
37700b57cec5SDimitry Andric if (!IterName)
37710b57cec5SDimitry Andric return TokError("expected declaration in for");
37720b57cec5SDimitry Andric
37735ffd83dbSDimitry Andric if (!consume(tgtok::In))
37740b57cec5SDimitry Andric return TokError("Unknown tok");
37750b57cec5SDimitry Andric
37760b57cec5SDimitry Andric // Create a loop object and remember it.
377706c3fb27SDimitry Andric auto TheLoop = std::make_unique<ForeachLoop>(Loc, IterName, ListValue);
3778480093f4SDimitry Andric // A foreach loop introduces a new scope for local variables.
377906c3fb27SDimitry Andric TGVarScope *ForeachScope = PushScope(TheLoop.get());
378006c3fb27SDimitry Andric Loops.push_back(std::move(TheLoop));
3781480093f4SDimitry Andric
37820b57cec5SDimitry Andric if (Lex.getCode() != tgtok::l_brace) {
37830b57cec5SDimitry Andric // FOREACH Declaration IN Object
37840b57cec5SDimitry Andric if (ParseObject(CurMultiClass))
37850b57cec5SDimitry Andric return true;
37860b57cec5SDimitry Andric } else {
37870b57cec5SDimitry Andric SMLoc BraceLoc = Lex.getLoc();
37880b57cec5SDimitry Andric // Otherwise, this is a group foreach.
37890b57cec5SDimitry Andric Lex.Lex(); // eat the '{'.
37900b57cec5SDimitry Andric
37910b57cec5SDimitry Andric // Parse the object list.
37920b57cec5SDimitry Andric if (ParseObjectList(CurMultiClass))
37930b57cec5SDimitry Andric return true;
37940b57cec5SDimitry Andric
37955ffd83dbSDimitry Andric if (!consume(tgtok::r_brace)) {
37960b57cec5SDimitry Andric TokError("expected '}' at end of foreach command");
37970b57cec5SDimitry Andric return Error(BraceLoc, "to match this '{'");
37980b57cec5SDimitry Andric }
37990b57cec5SDimitry Andric }
38000b57cec5SDimitry Andric
380106c3fb27SDimitry Andric PopScope(ForeachScope);
3802480093f4SDimitry Andric
38030b57cec5SDimitry Andric // Resolve the loop or store it for later resolution.
38040b57cec5SDimitry Andric std::unique_ptr<ForeachLoop> Loop = std::move(Loops.back());
38050b57cec5SDimitry Andric Loops.pop_back();
38060b57cec5SDimitry Andric
38070b57cec5SDimitry Andric return addEntry(std::move(Loop));
38080b57cec5SDimitry Andric }
38090b57cec5SDimitry Andric
3810480093f4SDimitry Andric /// ParseIf - Parse an if statement.
3811480093f4SDimitry Andric ///
3812480093f4SDimitry Andric /// If ::= IF Value THEN IfBody
3813480093f4SDimitry Andric /// If ::= IF Value THEN IfBody ELSE IfBody
3814480093f4SDimitry Andric ///
ParseIf(MultiClass * CurMultiClass)3815480093f4SDimitry Andric bool TGParser::ParseIf(MultiClass *CurMultiClass) {
3816480093f4SDimitry Andric SMLoc Loc = Lex.getLoc();
3817480093f4SDimitry Andric assert(Lex.getCode() == tgtok::If && "Unknown tok");
3818480093f4SDimitry Andric Lex.Lex(); // Eat the 'if' token.
3819480093f4SDimitry Andric
3820480093f4SDimitry Andric // Make a temporary object to record items associated with the for
3821480093f4SDimitry Andric // loop.
3822480093f4SDimitry Andric Init *Condition = ParseValue(nullptr);
3823480093f4SDimitry Andric if (!Condition)
3824480093f4SDimitry Andric return true;
3825480093f4SDimitry Andric
38265ffd83dbSDimitry Andric if (!consume(tgtok::Then))
3827480093f4SDimitry Andric return TokError("Unknown tok");
3828480093f4SDimitry Andric
3829480093f4SDimitry Andric // We have to be able to save if statements to execute later, and they have
3830480093f4SDimitry Andric // to live on the same stack as foreach loops. The simplest implementation
3831480093f4SDimitry Andric // technique is to convert each 'then' or 'else' clause *into* a foreach
3832480093f4SDimitry Andric // loop, over a list of length 0 or 1 depending on the condition, and with no
3833480093f4SDimitry Andric // iteration variable being assigned.
3834480093f4SDimitry Andric
383581ad6265SDimitry Andric ListInit *EmptyList = ListInit::get({}, BitRecTy::get(Records));
383604eeddc0SDimitry Andric ListInit *SingletonList =
383781ad6265SDimitry Andric ListInit::get({BitInit::get(Records, true)}, BitRecTy::get(Records));
383881ad6265SDimitry Andric RecTy *BitListTy = ListRecTy::get(BitRecTy::get(Records));
3839480093f4SDimitry Andric
3840480093f4SDimitry Andric // The foreach containing the then-clause selects SingletonList if
3841480093f4SDimitry Andric // the condition is true.
3842480093f4SDimitry Andric Init *ThenClauseList =
3843480093f4SDimitry Andric TernOpInit::get(TernOpInit::IF, Condition, SingletonList, EmptyList,
3844480093f4SDimitry Andric BitListTy)
3845480093f4SDimitry Andric ->Fold(nullptr);
3846480093f4SDimitry Andric Loops.push_back(std::make_unique<ForeachLoop>(Loc, nullptr, ThenClauseList));
3847480093f4SDimitry Andric
3848480093f4SDimitry Andric if (ParseIfBody(CurMultiClass, "then"))
3849480093f4SDimitry Andric return true;
3850480093f4SDimitry Andric
3851480093f4SDimitry Andric std::unique_ptr<ForeachLoop> Loop = std::move(Loops.back());
3852480093f4SDimitry Andric Loops.pop_back();
3853480093f4SDimitry Andric
3854480093f4SDimitry Andric if (addEntry(std::move(Loop)))
3855480093f4SDimitry Andric return true;
3856480093f4SDimitry Andric
3857480093f4SDimitry Andric // Now look for an optional else clause. The if-else syntax has the usual
3858480093f4SDimitry Andric // dangling-else ambiguity, and by greedily matching an else here if we can,
3859480093f4SDimitry Andric // we implement the usual resolution of pairing with the innermost unmatched
3860480093f4SDimitry Andric // if.
38615ffd83dbSDimitry Andric if (consume(tgtok::ElseKW)) {
3862480093f4SDimitry Andric // The foreach containing the else-clause uses the same pair of lists as
3863480093f4SDimitry Andric // above, but this time, selects SingletonList if the condition is *false*.
3864480093f4SDimitry Andric Init *ElseClauseList =
3865480093f4SDimitry Andric TernOpInit::get(TernOpInit::IF, Condition, EmptyList, SingletonList,
3866480093f4SDimitry Andric BitListTy)
3867480093f4SDimitry Andric ->Fold(nullptr);
3868480093f4SDimitry Andric Loops.push_back(
3869480093f4SDimitry Andric std::make_unique<ForeachLoop>(Loc, nullptr, ElseClauseList));
3870480093f4SDimitry Andric
3871480093f4SDimitry Andric if (ParseIfBody(CurMultiClass, "else"))
3872480093f4SDimitry Andric return true;
3873480093f4SDimitry Andric
3874480093f4SDimitry Andric Loop = std::move(Loops.back());
3875480093f4SDimitry Andric Loops.pop_back();
3876480093f4SDimitry Andric
3877480093f4SDimitry Andric if (addEntry(std::move(Loop)))
3878480093f4SDimitry Andric return true;
3879480093f4SDimitry Andric }
3880480093f4SDimitry Andric
3881480093f4SDimitry Andric return false;
3882480093f4SDimitry Andric }
3883480093f4SDimitry Andric
3884480093f4SDimitry Andric /// ParseIfBody - Parse the then-clause or else-clause of an if statement.
3885480093f4SDimitry Andric ///
3886480093f4SDimitry Andric /// IfBody ::= Object
3887480093f4SDimitry Andric /// IfBody ::= '{' ObjectList '}'
3888480093f4SDimitry Andric ///
ParseIfBody(MultiClass * CurMultiClass,StringRef Kind)3889480093f4SDimitry Andric bool TGParser::ParseIfBody(MultiClass *CurMultiClass, StringRef Kind) {
389006c3fb27SDimitry Andric // An if-statement introduces a new scope for local variables.
389106c3fb27SDimitry Andric TGVarScope *BodyScope = PushScope();
3892480093f4SDimitry Andric
3893480093f4SDimitry Andric if (Lex.getCode() != tgtok::l_brace) {
3894480093f4SDimitry Andric // A single object.
3895480093f4SDimitry Andric if (ParseObject(CurMultiClass))
3896480093f4SDimitry Andric return true;
3897480093f4SDimitry Andric } else {
3898480093f4SDimitry Andric SMLoc BraceLoc = Lex.getLoc();
3899480093f4SDimitry Andric // A braced block.
3900480093f4SDimitry Andric Lex.Lex(); // eat the '{'.
3901480093f4SDimitry Andric
3902480093f4SDimitry Andric // Parse the object list.
3903480093f4SDimitry Andric if (ParseObjectList(CurMultiClass))
3904480093f4SDimitry Andric return true;
3905480093f4SDimitry Andric
39065ffd83dbSDimitry Andric if (!consume(tgtok::r_brace)) {
3907480093f4SDimitry Andric TokError("expected '}' at end of '" + Kind + "' clause");
3908480093f4SDimitry Andric return Error(BraceLoc, "to match this '{'");
3909480093f4SDimitry Andric }
3910480093f4SDimitry Andric }
3911480093f4SDimitry Andric
391206c3fb27SDimitry Andric PopScope(BodyScope);
3913480093f4SDimitry Andric return false;
3914480093f4SDimitry Andric }
3915480093f4SDimitry Andric
3916e8d8bef9SDimitry Andric /// ParseAssert - Parse an assert statement.
3917e8d8bef9SDimitry Andric ///
3918e8d8bef9SDimitry Andric /// Assert ::= ASSERT condition , message ;
ParseAssert(MultiClass * CurMultiClass,Record * CurRec)3919e8d8bef9SDimitry Andric bool TGParser::ParseAssert(MultiClass *CurMultiClass, Record *CurRec) {
3920e8d8bef9SDimitry Andric assert(Lex.getCode() == tgtok::Assert && "Unknown tok");
3921e8d8bef9SDimitry Andric Lex.Lex(); // Eat the 'assert' token.
3922e8d8bef9SDimitry Andric
3923e8d8bef9SDimitry Andric SMLoc ConditionLoc = Lex.getLoc();
3924e8d8bef9SDimitry Andric Init *Condition = ParseValue(CurRec);
3925e8d8bef9SDimitry Andric if (!Condition)
3926e8d8bef9SDimitry Andric return true;
3927e8d8bef9SDimitry Andric
3928e8d8bef9SDimitry Andric if (!consume(tgtok::comma)) {
3929e8d8bef9SDimitry Andric TokError("expected ',' in assert statement");
3930e8d8bef9SDimitry Andric return true;
3931e8d8bef9SDimitry Andric }
3932e8d8bef9SDimitry Andric
3933e8d8bef9SDimitry Andric Init *Message = ParseValue(CurRec);
3934e8d8bef9SDimitry Andric if (!Message)
3935e8d8bef9SDimitry Andric return true;
3936e8d8bef9SDimitry Andric
3937e8d8bef9SDimitry Andric if (!consume(tgtok::semi))
3938e8d8bef9SDimitry Andric return TokError("expected ';'");
3939e8d8bef9SDimitry Andric
3940fe6060f1SDimitry Andric if (CurRec)
3941e8d8bef9SDimitry Andric CurRec->addAssertion(ConditionLoc, Condition, Message);
3942fe6060f1SDimitry Andric else
3943fe6060f1SDimitry Andric addEntry(std::make_unique<Record::AssertionInfo>(ConditionLoc, Condition,
3944fe6060f1SDimitry Andric Message));
3945e8d8bef9SDimitry Andric return false;
3946e8d8bef9SDimitry Andric }
3947e8d8bef9SDimitry Andric
39480b57cec5SDimitry Andric /// ParseClass - Parse a tblgen class definition.
39490b57cec5SDimitry Andric ///
39500b57cec5SDimitry Andric /// ClassInst ::= CLASS ID TemplateArgList? ObjectBody
39510b57cec5SDimitry Andric ///
ParseClass()39520b57cec5SDimitry Andric bool TGParser::ParseClass() {
39530b57cec5SDimitry Andric assert(Lex.getCode() == tgtok::Class && "Unexpected token!");
39540b57cec5SDimitry Andric Lex.Lex();
39550b57cec5SDimitry Andric
39560b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id)
39570b57cec5SDimitry Andric return TokError("expected class name after 'class' keyword");
39580b57cec5SDimitry Andric
3959*0fca6ea1SDimitry Andric const std::string &Name = Lex.getCurStrVal();
3960*0fca6ea1SDimitry Andric Record *CurRec = Records.getClass(Name);
39610b57cec5SDimitry Andric if (CurRec) {
39620b57cec5SDimitry Andric // If the body was previously defined, this is an error.
39630b57cec5SDimitry Andric if (!CurRec->getValues().empty() ||
39640b57cec5SDimitry Andric !CurRec->getSuperClasses().empty() ||
39650b57cec5SDimitry Andric !CurRec->getTemplateArgs().empty())
39660b57cec5SDimitry Andric return TokError("Class '" + CurRec->getNameInitAsString() +
39670b57cec5SDimitry Andric "' already defined");
3968fcaf7f86SDimitry Andric
3969fcaf7f86SDimitry Andric CurRec->updateClassLoc(Lex.getLoc());
39700b57cec5SDimitry Andric } else {
39710b57cec5SDimitry Andric // If this is the first reference to this class, create and add it.
39725f757f3fSDimitry Andric auto NewRec = std::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(),
39735f757f3fSDimitry Andric Records, Record::RK_Class);
39740b57cec5SDimitry Andric CurRec = NewRec.get();
39750b57cec5SDimitry Andric Records.addClass(std::move(NewRec));
39760b57cec5SDimitry Andric }
3977*0fca6ea1SDimitry Andric
3978*0fca6ea1SDimitry Andric if (TypeAliases.count(Name))
3979*0fca6ea1SDimitry Andric return TokError("there is already a defined type alias '" + Name + "'");
3980*0fca6ea1SDimitry Andric
39810b57cec5SDimitry Andric Lex.Lex(); // eat the name.
39820b57cec5SDimitry Andric
398306c3fb27SDimitry Andric // A class definition introduces a new scope.
398406c3fb27SDimitry Andric TGVarScope *ClassScope = PushScope(CurRec);
39850b57cec5SDimitry Andric // If there are template args, parse them.
39860b57cec5SDimitry Andric if (Lex.getCode() == tgtok::less)
39870b57cec5SDimitry Andric if (ParseTemplateArgList(CurRec))
39880b57cec5SDimitry Andric return true;
39890b57cec5SDimitry Andric
3990349cc55cSDimitry Andric if (ParseObjectBody(CurRec))
3991349cc55cSDimitry Andric return true;
3992349cc55cSDimitry Andric
3993349cc55cSDimitry Andric if (!NoWarnOnUnusedTemplateArgs)
3994349cc55cSDimitry Andric CurRec->checkUnusedTemplateArgs();
399506c3fb27SDimitry Andric
399606c3fb27SDimitry Andric PopScope(ClassScope);
3997349cc55cSDimitry Andric return false;
39980b57cec5SDimitry Andric }
39990b57cec5SDimitry Andric
40000b57cec5SDimitry Andric /// ParseLetList - Parse a non-empty list of assignment expressions into a list
40010b57cec5SDimitry Andric /// of LetRecords.
40020b57cec5SDimitry Andric ///
40030b57cec5SDimitry Andric /// LetList ::= LetItem (',' LetItem)*
40040b57cec5SDimitry Andric /// LetItem ::= ID OptionalRangeList '=' Value
40050b57cec5SDimitry Andric ///
ParseLetList(SmallVectorImpl<LetRecord> & Result)40060b57cec5SDimitry Andric void TGParser::ParseLetList(SmallVectorImpl<LetRecord> &Result) {
40075ffd83dbSDimitry Andric do {
40080b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id) {
40090b57cec5SDimitry Andric TokError("expected identifier in let definition");
40100b57cec5SDimitry Andric Result.clear();
40110b57cec5SDimitry Andric return;
40120b57cec5SDimitry Andric }
40130b57cec5SDimitry Andric
401481ad6265SDimitry Andric StringInit *Name = StringInit::get(Records, Lex.getCurStrVal());
40150b57cec5SDimitry Andric SMLoc NameLoc = Lex.getLoc();
40160b57cec5SDimitry Andric Lex.Lex(); // Eat the identifier.
40170b57cec5SDimitry Andric
40180b57cec5SDimitry Andric // Check for an optional RangeList.
40190b57cec5SDimitry Andric SmallVector<unsigned, 16> Bits;
40200b57cec5SDimitry Andric if (ParseOptionalRangeList(Bits)) {
40210b57cec5SDimitry Andric Result.clear();
40220b57cec5SDimitry Andric return;
40230b57cec5SDimitry Andric }
40240b57cec5SDimitry Andric std::reverse(Bits.begin(), Bits.end());
40250b57cec5SDimitry Andric
40265ffd83dbSDimitry Andric if (!consume(tgtok::equal)) {
40270b57cec5SDimitry Andric TokError("expected '=' in let expression");
40280b57cec5SDimitry Andric Result.clear();
40290b57cec5SDimitry Andric return;
40300b57cec5SDimitry Andric }
40310b57cec5SDimitry Andric
40320b57cec5SDimitry Andric Init *Val = ParseValue(nullptr);
40330b57cec5SDimitry Andric if (!Val) {
40340b57cec5SDimitry Andric Result.clear();
40350b57cec5SDimitry Andric return;
40360b57cec5SDimitry Andric }
40370b57cec5SDimitry Andric
40380b57cec5SDimitry Andric // Now that we have everything, add the record.
40390b57cec5SDimitry Andric Result.emplace_back(Name, Bits, Val, NameLoc);
40405ffd83dbSDimitry Andric } while (consume(tgtok::comma));
40410b57cec5SDimitry Andric }
40420b57cec5SDimitry Andric
40430b57cec5SDimitry Andric /// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
40440b57cec5SDimitry Andric /// different related productions. This works inside multiclasses too.
40450b57cec5SDimitry Andric ///
40460b57cec5SDimitry Andric /// Object ::= LET LetList IN '{' ObjectList '}'
40470b57cec5SDimitry Andric /// Object ::= LET LetList IN Object
40480b57cec5SDimitry Andric ///
ParseTopLevelLet(MultiClass * CurMultiClass)40490b57cec5SDimitry Andric bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
40500b57cec5SDimitry Andric assert(Lex.getCode() == tgtok::Let && "Unexpected token");
40510b57cec5SDimitry Andric Lex.Lex();
40520b57cec5SDimitry Andric
40530b57cec5SDimitry Andric // Add this entry to the let stack.
40540b57cec5SDimitry Andric SmallVector<LetRecord, 8> LetInfo;
40550b57cec5SDimitry Andric ParseLetList(LetInfo);
40560b57cec5SDimitry Andric if (LetInfo.empty()) return true;
40570b57cec5SDimitry Andric LetStack.push_back(std::move(LetInfo));
40580b57cec5SDimitry Andric
40595ffd83dbSDimitry Andric if (!consume(tgtok::In))
40600b57cec5SDimitry Andric return TokError("expected 'in' at end of top-level 'let'");
40610b57cec5SDimitry Andric
40620b57cec5SDimitry Andric // If this is a scalar let, just handle it now
40630b57cec5SDimitry Andric if (Lex.getCode() != tgtok::l_brace) {
40640b57cec5SDimitry Andric // LET LetList IN Object
40650b57cec5SDimitry Andric if (ParseObject(CurMultiClass))
40660b57cec5SDimitry Andric return true;
40670b57cec5SDimitry Andric } else { // Object ::= LETCommand '{' ObjectList '}'
40680b57cec5SDimitry Andric SMLoc BraceLoc = Lex.getLoc();
40690b57cec5SDimitry Andric // Otherwise, this is a group let.
40700b57cec5SDimitry Andric Lex.Lex(); // eat the '{'.
40710b57cec5SDimitry Andric
407206c3fb27SDimitry Andric // A group let introduces a new scope for local variables.
407306c3fb27SDimitry Andric TGVarScope *LetScope = PushScope();
407406c3fb27SDimitry Andric
40750b57cec5SDimitry Andric // Parse the object list.
40760b57cec5SDimitry Andric if (ParseObjectList(CurMultiClass))
40770b57cec5SDimitry Andric return true;
40780b57cec5SDimitry Andric
40795ffd83dbSDimitry Andric if (!consume(tgtok::r_brace)) {
40800b57cec5SDimitry Andric TokError("expected '}' at end of top level let command");
40810b57cec5SDimitry Andric return Error(BraceLoc, "to match this '{'");
40820b57cec5SDimitry Andric }
40830b57cec5SDimitry Andric
408406c3fb27SDimitry Andric PopScope(LetScope);
408506c3fb27SDimitry Andric }
4086480093f4SDimitry Andric
40870b57cec5SDimitry Andric // Outside this let scope, this let block is not active.
40880b57cec5SDimitry Andric LetStack.pop_back();
40890b57cec5SDimitry Andric return false;
40900b57cec5SDimitry Andric }
40910b57cec5SDimitry Andric
40920b57cec5SDimitry Andric /// ParseMultiClass - Parse a multiclass definition.
40930b57cec5SDimitry Andric ///
40940b57cec5SDimitry Andric /// MultiClassInst ::= MULTICLASS ID TemplateArgList?
40950b57cec5SDimitry Andric /// ':' BaseMultiClassList '{' MultiClassObject+ '}'
4096fe6060f1SDimitry Andric /// MultiClassObject ::= Assert
40970b57cec5SDimitry Andric /// MultiClassObject ::= DefInst
40980b57cec5SDimitry Andric /// MultiClassObject ::= DefMInst
4099fe6060f1SDimitry Andric /// MultiClassObject ::= Defvar
4100fe6060f1SDimitry Andric /// MultiClassObject ::= Foreach
4101fe6060f1SDimitry Andric /// MultiClassObject ::= If
41020b57cec5SDimitry Andric /// MultiClassObject ::= LETCommand '{' ObjectList '}'
41030b57cec5SDimitry Andric /// MultiClassObject ::= LETCommand Object
41040b57cec5SDimitry Andric ///
ParseMultiClass()41050b57cec5SDimitry Andric bool TGParser::ParseMultiClass() {
41060b57cec5SDimitry Andric assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
41070b57cec5SDimitry Andric Lex.Lex(); // Eat the multiclass token.
41080b57cec5SDimitry Andric
41090b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id)
41100b57cec5SDimitry Andric return TokError("expected identifier after multiclass for name");
41110b57cec5SDimitry Andric std::string Name = Lex.getCurStrVal();
41120b57cec5SDimitry Andric
41130b57cec5SDimitry Andric auto Result =
41140b57cec5SDimitry Andric MultiClasses.insert(std::make_pair(Name,
41158bcb0991SDimitry Andric std::make_unique<MultiClass>(Name, Lex.getLoc(),Records)));
41160b57cec5SDimitry Andric
41170b57cec5SDimitry Andric if (!Result.second)
41180b57cec5SDimitry Andric return TokError("multiclass '" + Name + "' already defined");
41190b57cec5SDimitry Andric
41200b57cec5SDimitry Andric CurMultiClass = Result.first->second.get();
41210b57cec5SDimitry Andric Lex.Lex(); // Eat the identifier.
41220b57cec5SDimitry Andric
412306c3fb27SDimitry Andric // A multiclass body introduces a new scope for local variables.
412406c3fb27SDimitry Andric TGVarScope *MulticlassScope = PushScope(CurMultiClass);
412506c3fb27SDimitry Andric
41260b57cec5SDimitry Andric // If there are template args, parse them.
41270b57cec5SDimitry Andric if (Lex.getCode() == tgtok::less)
41280b57cec5SDimitry Andric if (ParseTemplateArgList(nullptr))
41290b57cec5SDimitry Andric return true;
41300b57cec5SDimitry Andric
41310b57cec5SDimitry Andric bool inherits = false;
41320b57cec5SDimitry Andric
41330b57cec5SDimitry Andric // If there are submulticlasses, parse them.
41345ffd83dbSDimitry Andric if (consume(tgtok::colon)) {
41350b57cec5SDimitry Andric inherits = true;
41360b57cec5SDimitry Andric
41370b57cec5SDimitry Andric // Read all of the submulticlasses.
41380b57cec5SDimitry Andric SubMultiClassReference SubMultiClass =
41390b57cec5SDimitry Andric ParseSubMultiClassReference(CurMultiClass);
41400b57cec5SDimitry Andric while (true) {
41410b57cec5SDimitry Andric // Check for error.
41420b57cec5SDimitry Andric if (!SubMultiClass.MC) return true;
41430b57cec5SDimitry Andric
41440b57cec5SDimitry Andric // Add it.
41450b57cec5SDimitry Andric if (AddSubMultiClass(CurMultiClass, SubMultiClass))
41460b57cec5SDimitry Andric return true;
41470b57cec5SDimitry Andric
41485ffd83dbSDimitry Andric if (!consume(tgtok::comma))
41495ffd83dbSDimitry Andric break;
41500b57cec5SDimitry Andric SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
41510b57cec5SDimitry Andric }
41520b57cec5SDimitry Andric }
41530b57cec5SDimitry Andric
41540b57cec5SDimitry Andric if (Lex.getCode() != tgtok::l_brace) {
41550b57cec5SDimitry Andric if (!inherits)
41560b57cec5SDimitry Andric return TokError("expected '{' in multiclass definition");
41575ffd83dbSDimitry Andric if (!consume(tgtok::semi))
41580b57cec5SDimitry Andric return TokError("expected ';' in multiclass definition");
41590b57cec5SDimitry Andric } else {
41600b57cec5SDimitry Andric if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
41610b57cec5SDimitry Andric return TokError("multiclass must contain at least one def");
41620b57cec5SDimitry Andric
41630b57cec5SDimitry Andric while (Lex.getCode() != tgtok::r_brace) {
41640b57cec5SDimitry Andric switch (Lex.getCode()) {
41650b57cec5SDimitry Andric default:
41665f757f3fSDimitry Andric return TokError("expected 'assert', 'def', 'defm', 'defvar', 'dump', "
4167e8d8bef9SDimitry Andric "'foreach', 'if', or 'let' in multiclass body");
4168e8d8bef9SDimitry Andric
4169fe6060f1SDimitry Andric case tgtok::Assert:
41700b57cec5SDimitry Andric case tgtok::Def:
41710b57cec5SDimitry Andric case tgtok::Defm:
4172480093f4SDimitry Andric case tgtok::Defvar:
41735f757f3fSDimitry Andric case tgtok::Dump:
41740b57cec5SDimitry Andric case tgtok::Foreach:
4175480093f4SDimitry Andric case tgtok::If:
4176e8d8bef9SDimitry Andric case tgtok::Let:
41770b57cec5SDimitry Andric if (ParseObject(CurMultiClass))
41780b57cec5SDimitry Andric return true;
41790b57cec5SDimitry Andric break;
41800b57cec5SDimitry Andric }
41810b57cec5SDimitry Andric }
41820b57cec5SDimitry Andric Lex.Lex(); // eat the '}'.
4183480093f4SDimitry Andric
4184e8d8bef9SDimitry Andric // If we have a semicolon, print a gentle error.
4185e8d8bef9SDimitry Andric SMLoc SemiLoc = Lex.getLoc();
4186e8d8bef9SDimitry Andric if (consume(tgtok::semi)) {
4187e8d8bef9SDimitry Andric PrintError(SemiLoc, "A multiclass body should not end with a semicolon");
4188e8d8bef9SDimitry Andric PrintNote("Semicolon ignored; remove to eliminate this error");
4189e8d8bef9SDimitry Andric }
41900b57cec5SDimitry Andric }
41910b57cec5SDimitry Andric
4192349cc55cSDimitry Andric if (!NoWarnOnUnusedTemplateArgs)
4193349cc55cSDimitry Andric CurMultiClass->Rec.checkUnusedTemplateArgs();
4194349cc55cSDimitry Andric
419506c3fb27SDimitry Andric PopScope(MulticlassScope);
41960b57cec5SDimitry Andric CurMultiClass = nullptr;
41970b57cec5SDimitry Andric return false;
41980b57cec5SDimitry Andric }
41990b57cec5SDimitry Andric
42000b57cec5SDimitry Andric /// ParseDefm - Parse the instantiation of a multiclass.
42010b57cec5SDimitry Andric ///
42020b57cec5SDimitry Andric /// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
42030b57cec5SDimitry Andric ///
ParseDefm(MultiClass * CurMultiClass)42040b57cec5SDimitry Andric bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
42050b57cec5SDimitry Andric assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
42060b57cec5SDimitry Andric Lex.Lex(); // eat the defm
42070b57cec5SDimitry Andric
42080b57cec5SDimitry Andric Init *DefmName = ParseObjectName(CurMultiClass);
42090b57cec5SDimitry Andric if (!DefmName)
42100b57cec5SDimitry Andric return true;
42110b57cec5SDimitry Andric if (isa<UnsetInit>(DefmName)) {
42120b57cec5SDimitry Andric DefmName = Records.getNewAnonymousName();
42130b57cec5SDimitry Andric if (CurMultiClass)
42140b57cec5SDimitry Andric DefmName = BinOpInit::getStrConcat(
42150b57cec5SDimitry Andric VarInit::get(QualifiedNameOfImplicitName(CurMultiClass),
421681ad6265SDimitry Andric StringRecTy::get(Records)),
42170b57cec5SDimitry Andric DefmName);
42180b57cec5SDimitry Andric }
42190b57cec5SDimitry Andric
42200b57cec5SDimitry Andric if (Lex.getCode() != tgtok::colon)
42210b57cec5SDimitry Andric return TokError("expected ':' after defm identifier");
42220b57cec5SDimitry Andric
42230b57cec5SDimitry Andric // Keep track of the new generated record definitions.
42240b57cec5SDimitry Andric std::vector<RecordsEntry> NewEntries;
42250b57cec5SDimitry Andric
42260b57cec5SDimitry Andric // This record also inherits from a regular class (non-multiclass)?
42270b57cec5SDimitry Andric bool InheritFromClass = false;
42280b57cec5SDimitry Andric
42290b57cec5SDimitry Andric // eat the colon.
42300b57cec5SDimitry Andric Lex.Lex();
42310b57cec5SDimitry Andric
42320b57cec5SDimitry Andric SMLoc SubClassLoc = Lex.getLoc();
42330b57cec5SDimitry Andric SubClassReference Ref = ParseSubClassReference(nullptr, true);
42340b57cec5SDimitry Andric
42350b57cec5SDimitry Andric while (true) {
42360b57cec5SDimitry Andric if (!Ref.Rec) return true;
42370b57cec5SDimitry Andric
4238fe6060f1SDimitry Andric // To instantiate a multiclass, we get the multiclass and then loop
4239fe6060f1SDimitry Andric // through its template argument names. Substs contains a substitution
4240fe6060f1SDimitry Andric // value for each argument, either the value specified or the default.
4241fe6060f1SDimitry Andric // Then we can resolve the template arguments.
42425ffd83dbSDimitry Andric MultiClass *MC = MultiClasses[std::string(Ref.Rec->getName())].get();
42430b57cec5SDimitry Andric assert(MC && "Didn't lookup multiclass correctly?");
4244fe6060f1SDimitry Andric
42450b57cec5SDimitry Andric SubstStack Substs;
424606c3fb27SDimitry Andric if (resolveArgumentsOfMultiClass(Substs, MC, Ref.TemplateArgs, DefmName,
424706c3fb27SDimitry Andric SubClassLoc))
424806c3fb27SDimitry Andric return true;
42490b57cec5SDimitry Andric
4250fe6060f1SDimitry Andric if (resolve(MC->Entries, Substs, !CurMultiClass && Loops.empty(),
4251fe6060f1SDimitry Andric &NewEntries, &SubClassLoc))
42520b57cec5SDimitry Andric return true;
42530b57cec5SDimitry Andric
42545ffd83dbSDimitry Andric if (!consume(tgtok::comma))
42555ffd83dbSDimitry Andric break;
42560b57cec5SDimitry Andric
42570b57cec5SDimitry Andric if (Lex.getCode() != tgtok::Id)
42580b57cec5SDimitry Andric return TokError("expected identifier");
42590b57cec5SDimitry Andric
42600b57cec5SDimitry Andric SubClassLoc = Lex.getLoc();
42610b57cec5SDimitry Andric
4262fe6060f1SDimitry Andric // A defm can inherit from regular classes (non-multiclasses) as
42630b57cec5SDimitry Andric // long as they come in the end of the inheritance list.
42640b57cec5SDimitry Andric InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != nullptr);
42650b57cec5SDimitry Andric
42660b57cec5SDimitry Andric if (InheritFromClass)
42670b57cec5SDimitry Andric break;
42680b57cec5SDimitry Andric
42690b57cec5SDimitry Andric Ref = ParseSubClassReference(nullptr, true);
42700b57cec5SDimitry Andric }
42710b57cec5SDimitry Andric
42720b57cec5SDimitry Andric if (InheritFromClass) {
42730b57cec5SDimitry Andric // Process all the classes to inherit as if they were part of a
42740b57cec5SDimitry Andric // regular 'def' and inherit all record values.
42750b57cec5SDimitry Andric SubClassReference SubClass = ParseSubClassReference(nullptr, false);
42760b57cec5SDimitry Andric while (true) {
42770b57cec5SDimitry Andric // Check for error.
42780b57cec5SDimitry Andric if (!SubClass.Rec) return true;
42790b57cec5SDimitry Andric
42800b57cec5SDimitry Andric // Get the expanded definition prototypes and teach them about
42810b57cec5SDimitry Andric // the record values the current class to inherit has
42820b57cec5SDimitry Andric for (auto &E : NewEntries) {
42830b57cec5SDimitry Andric // Add it.
42840b57cec5SDimitry Andric if (AddSubClass(E, SubClass))
42850b57cec5SDimitry Andric return true;
42860b57cec5SDimitry Andric }
42870b57cec5SDimitry Andric
42885ffd83dbSDimitry Andric if (!consume(tgtok::comma))
42895ffd83dbSDimitry Andric break;
42900b57cec5SDimitry Andric SubClass = ParseSubClassReference(nullptr, false);
42910b57cec5SDimitry Andric }
42920b57cec5SDimitry Andric }
42930b57cec5SDimitry Andric
42940b57cec5SDimitry Andric for (auto &E : NewEntries) {
42950b57cec5SDimitry Andric if (ApplyLetStack(E))
42960b57cec5SDimitry Andric return true;
42970b57cec5SDimitry Andric
42980b57cec5SDimitry Andric addEntry(std::move(E));
42990b57cec5SDimitry Andric }
43000b57cec5SDimitry Andric
43015ffd83dbSDimitry Andric if (!consume(tgtok::semi))
43020b57cec5SDimitry Andric return TokError("expected ';' at end of defm");
43030b57cec5SDimitry Andric
43040b57cec5SDimitry Andric return false;
43050b57cec5SDimitry Andric }
43060b57cec5SDimitry Andric
43070b57cec5SDimitry Andric /// ParseObject
43080b57cec5SDimitry Andric /// Object ::= ClassInst
43090b57cec5SDimitry Andric /// Object ::= DefInst
43100b57cec5SDimitry Andric /// Object ::= MultiClassInst
43110b57cec5SDimitry Andric /// Object ::= DefMInst
43120b57cec5SDimitry Andric /// Object ::= LETCommand '{' ObjectList '}'
43130b57cec5SDimitry Andric /// Object ::= LETCommand Object
4314480093f4SDimitry Andric /// Object ::= Defset
4315*0fca6ea1SDimitry Andric /// Object ::= Deftype
4316480093f4SDimitry Andric /// Object ::= Defvar
4317e8d8bef9SDimitry Andric /// Object ::= Assert
43185f757f3fSDimitry Andric /// Object ::= Dump
ParseObject(MultiClass * MC)43190b57cec5SDimitry Andric bool TGParser::ParseObject(MultiClass *MC) {
43200b57cec5SDimitry Andric switch (Lex.getCode()) {
43210b57cec5SDimitry Andric default:
4322e8d8bef9SDimitry Andric return TokError(
43235f757f3fSDimitry Andric "Expected assert, class, def, defm, defset, dump, foreach, if, or let");
4324fe6060f1SDimitry Andric case tgtok::Assert: return ParseAssert(MC);
43250b57cec5SDimitry Andric case tgtok::Def: return ParseDef(MC);
4326e8d8bef9SDimitry Andric case tgtok::Defm: return ParseDefm(MC);
4327*0fca6ea1SDimitry Andric case tgtok::Deftype:
4328*0fca6ea1SDimitry Andric return ParseDeftype();
4329e8d8bef9SDimitry Andric case tgtok::Defvar: return ParseDefvar();
43305f757f3fSDimitry Andric case tgtok::Dump:
43315f757f3fSDimitry Andric return ParseDump(MC);
43320b57cec5SDimitry Andric case tgtok::Foreach: return ParseForeach(MC);
4333480093f4SDimitry Andric case tgtok::If: return ParseIf(MC);
4334e8d8bef9SDimitry Andric case tgtok::Let: return ParseTopLevelLet(MC);
43350b57cec5SDimitry Andric case tgtok::Defset:
43360b57cec5SDimitry Andric if (MC)
43370b57cec5SDimitry Andric return TokError("defset is not allowed inside multiclass");
43380b57cec5SDimitry Andric return ParseDefset();
43390b57cec5SDimitry Andric case tgtok::Class:
43400b57cec5SDimitry Andric if (MC)
43410b57cec5SDimitry Andric return TokError("class is not allowed inside multiclass");
43420b57cec5SDimitry Andric if (!Loops.empty())
43430b57cec5SDimitry Andric return TokError("class is not allowed inside foreach loop");
43440b57cec5SDimitry Andric return ParseClass();
43450b57cec5SDimitry Andric case tgtok::MultiClass:
43460b57cec5SDimitry Andric if (!Loops.empty())
43470b57cec5SDimitry Andric return TokError("multiclass is not allowed inside foreach loop");
43480b57cec5SDimitry Andric return ParseMultiClass();
43490b57cec5SDimitry Andric }
43500b57cec5SDimitry Andric }
43510b57cec5SDimitry Andric
43520b57cec5SDimitry Andric /// ParseObjectList
43530b57cec5SDimitry Andric /// ObjectList :== Object*
ParseObjectList(MultiClass * MC)43540b57cec5SDimitry Andric bool TGParser::ParseObjectList(MultiClass *MC) {
43555f757f3fSDimitry Andric while (tgtok::isObjectStart(Lex.getCode())) {
43560b57cec5SDimitry Andric if (ParseObject(MC))
43570b57cec5SDimitry Andric return true;
43580b57cec5SDimitry Andric }
43590b57cec5SDimitry Andric return false;
43600b57cec5SDimitry Andric }
43610b57cec5SDimitry Andric
ParseFile()43620b57cec5SDimitry Andric bool TGParser::ParseFile() {
43630b57cec5SDimitry Andric Lex.Lex(); // Prime the lexer.
436406c3fb27SDimitry Andric TGVarScope *GlobalScope = PushScope();
436506c3fb27SDimitry Andric if (ParseObjectList())
436606c3fb27SDimitry Andric return true;
436706c3fb27SDimitry Andric PopScope(GlobalScope);
43680b57cec5SDimitry Andric
43690b57cec5SDimitry Andric // If we have unread input at the end of the file, report it.
43700b57cec5SDimitry Andric if (Lex.getCode() == tgtok::Eof)
43710b57cec5SDimitry Andric return false;
43720b57cec5SDimitry Andric
4373e8d8bef9SDimitry Andric return TokError("Unexpected token at top level");
4374e8d8bef9SDimitry Andric }
4375e8d8bef9SDimitry Andric
4376fe6060f1SDimitry Andric // Check the types of the template argument values for a class
4377fe6060f1SDimitry Andric // inheritance, multiclass invocation, or anonymous class invocation.
4378fe6060f1SDimitry Andric // If necessary, replace an argument with a cast to the required type.
4379fe6060f1SDimitry Andric // The argument count has already been checked.
CheckTemplateArgValues(SmallVectorImpl<llvm::ArgumentInit * > & Values,SMLoc Loc,Record * ArgsRec)438006c3fb27SDimitry Andric bool TGParser::CheckTemplateArgValues(
438106c3fb27SDimitry Andric SmallVectorImpl<llvm::ArgumentInit *> &Values, SMLoc Loc, Record *ArgsRec) {
4382fe6060f1SDimitry Andric ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs();
4383fe6060f1SDimitry Andric
4384*0fca6ea1SDimitry Andric for (llvm::ArgumentInit *&Value : Values) {
438506c3fb27SDimitry Andric Init *ArgName = nullptr;
438606c3fb27SDimitry Andric if (Value->isPositional())
438706c3fb27SDimitry Andric ArgName = TArgs[Value->getIndex()];
438806c3fb27SDimitry Andric if (Value->isNamed())
438906c3fb27SDimitry Andric ArgName = Value->getName();
4390fe6060f1SDimitry Andric
439106c3fb27SDimitry Andric RecordVal *Arg = ArgsRec->getValue(ArgName);
439206c3fb27SDimitry Andric RecTy *ArgType = Arg->getType();
439306c3fb27SDimitry Andric
439406c3fb27SDimitry Andric if (TypedInit *ArgValue = dyn_cast<TypedInit>(Value->getValue())) {
4395fe6060f1SDimitry Andric auto *CastValue = ArgValue->getCastTo(ArgType);
4396fe6060f1SDimitry Andric if (CastValue) {
4397fe6060f1SDimitry Andric assert((!isa<TypedInit>(CastValue) ||
4398fe6060f1SDimitry Andric cast<TypedInit>(CastValue)->getType()->typeIsA(ArgType)) &&
4399fe6060f1SDimitry Andric "result of template arg value cast has wrong type");
4400*0fca6ea1SDimitry Andric Value = Value->cloneWithValue(CastValue);
4401e8d8bef9SDimitry Andric } else {
440206c3fb27SDimitry Andric PrintFatalError(Loc, "Value specified for template argument '" +
440306c3fb27SDimitry Andric Arg->getNameInitAsString() + "' is of type " +
440406c3fb27SDimitry Andric ArgValue->getType()->getAsString() +
440506c3fb27SDimitry Andric "; expected type " + ArgType->getAsString() +
440606c3fb27SDimitry Andric ": " + ArgValue->getAsString());
4407fe6060f1SDimitry Andric }
4408e8d8bef9SDimitry Andric }
4409e8d8bef9SDimitry Andric }
4410e8d8bef9SDimitry Andric
4411fe6060f1SDimitry Andric return false;
44120b57cec5SDimitry Andric }
44130b57cec5SDimitry Andric
44140b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const44150b57cec5SDimitry Andric LLVM_DUMP_METHOD void RecordsEntry::dump() const {
44160b57cec5SDimitry Andric if (Loop)
44170b57cec5SDimitry Andric Loop->dump();
44180b57cec5SDimitry Andric if (Rec)
44190b57cec5SDimitry Andric Rec->dump();
44200b57cec5SDimitry Andric }
44210b57cec5SDimitry Andric
dump() const44220b57cec5SDimitry Andric LLVM_DUMP_METHOD void ForeachLoop::dump() const {
44230b57cec5SDimitry Andric errs() << "foreach " << IterVar->getAsString() << " = "
44240b57cec5SDimitry Andric << ListValue->getAsString() << " in {\n";
44250b57cec5SDimitry Andric
44260b57cec5SDimitry Andric for (const auto &E : Entries)
44270b57cec5SDimitry Andric E.dump();
44280b57cec5SDimitry Andric
44290b57cec5SDimitry Andric errs() << "}\n";
44300b57cec5SDimitry Andric }
44310b57cec5SDimitry Andric
dump() const44320b57cec5SDimitry Andric LLVM_DUMP_METHOD void MultiClass::dump() const {
44330b57cec5SDimitry Andric errs() << "Record:\n";
44340b57cec5SDimitry Andric Rec.dump();
44350b57cec5SDimitry Andric
44360b57cec5SDimitry Andric errs() << "Defs:\n";
44370b57cec5SDimitry Andric for (const auto &E : Entries)
44380b57cec5SDimitry Andric E.dump();
44390b57cec5SDimitry Andric }
44400b57cec5SDimitry Andric #endif
44415f757f3fSDimitry Andric
ParseDump(MultiClass * CurMultiClass,Record * CurRec)44425f757f3fSDimitry Andric bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) {
44435f757f3fSDimitry Andric // Location of the `dump` statement.
44445f757f3fSDimitry Andric SMLoc Loc = Lex.getLoc();
44455f757f3fSDimitry Andric assert(Lex.getCode() == tgtok::Dump && "Unknown tok");
44465f757f3fSDimitry Andric Lex.Lex(); // eat the operation
44475f757f3fSDimitry Andric
44485f757f3fSDimitry Andric Init *Message = ParseValue(CurRec);
44495f757f3fSDimitry Andric if (!Message)
44505f757f3fSDimitry Andric return true;
44515f757f3fSDimitry Andric
44525f757f3fSDimitry Andric // Allow to use dump directly on `defvar` and `def`, by wrapping
44535f757f3fSDimitry Andric // them with a `!repl`.
44545f757f3fSDimitry Andric if (isa<DefInit>(Message))
44555f757f3fSDimitry Andric Message = UnOpInit::get(UnOpInit::REPR, Message, StringRecTy::get(Records))
44565f757f3fSDimitry Andric ->Fold(CurRec);
44575f757f3fSDimitry Andric
44585f757f3fSDimitry Andric if (!consume(tgtok::semi))
44595f757f3fSDimitry Andric return TokError("expected ';'");
44605f757f3fSDimitry Andric
44615f757f3fSDimitry Andric if (CurRec)
44625f757f3fSDimitry Andric CurRec->addDump(Loc, Message);
44635f757f3fSDimitry Andric else
44645f757f3fSDimitry Andric addEntry(std::make_unique<Record::DumpInfo>(Loc, Message));
44655f757f3fSDimitry Andric
44665f757f3fSDimitry Andric return false;
44675f757f3fSDimitry Andric }
4468