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 420b57cec5SDimitry 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 520b57cec5SDimitry 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) 570b57cec5SDimitry 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 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 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. 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 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. 1305f757f3fSDimitry Andric static Init *QualifiedNameOfImplicitName(Record &Rec) { 1315f757f3fSDimitry Andric return QualifyName(Rec, StringInit::get(Rec.getRecords(), "NAME")); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric static Init *QualifiedNameOfImplicitName(MultiClass *MC) { 1355f757f3fSDimitry Andric return QualifiedNameOfImplicitName(MC->Rec); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 13806c3fb27SDimitry 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 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. 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. 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 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. 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. 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. 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. 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. 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 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. 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. 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 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 /// 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 /// 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 /// 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:: 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:: 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 /// 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 /// 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. 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 /// 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*/ 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*/ 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 /// 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 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 /// 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 /// 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 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 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> 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 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 /// 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 /// 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 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 /// 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}*] 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 /// 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 /// 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 /// 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 /// 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 /// 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. 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. 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 /// 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 /// 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 /// 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 /// 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 /// 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 /// 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 /// 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 /// 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 ; 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 /// 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 /// 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 /// 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 /// 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 /// 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 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* 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 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. 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) 44150b57cec5SDimitry 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 44220b57cec5SDimitry 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 44320b57cec5SDimitry 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 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