X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTableGen%2FTGParser.cpp;h=10e80fb9190cc978ad6bdd84de2c7f3e680342a1;hp=072e3ef5909a01eba191ca61851ac16234a91850;hb=ae62636ef881aa040e9c550cccb8404a4598a957;hpb=64a334da36da748426904701bfc56c3bf5d064fe diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp index 072e3ef5909..10e80fb9190 100644 --- a/lib/TableGen/TGParser.cpp +++ b/lib/TableGen/TGParser.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "TGParser.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" @@ -50,12 +51,8 @@ void SubMultiClassReference::dump() const { MC->dump(); errs() << "Template args:\n"; - for (std::vector::const_iterator i = TemplateArgs.begin(), - iend = TemplateArgs.end(); - i != iend; - ++i) { - (*i)->dump(); - } + for (Init *TA : TemplateArgs) + TA->dump(); } } // end namespace llvm @@ -80,22 +77,23 @@ bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) { /// SetValue - /// Return true on error, false on success. bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, - const std::vector &BitList, Init *V) { + const std::vector &BitList, Init *V, + bool AllowSelfAssignment) { if (!V) return false; if (!CurRec) CurRec = &CurMultiClass->Rec; RecordVal *RV = CurRec->getValue(ValName); if (!RV) - return Error(Loc, "Value '" + ValName->getAsUnquotedString() - + "' unknown!"); + return Error(Loc, "Value '" + ValName->getAsUnquotedString() + + "' unknown!"); // Do not allow assignments like 'X = X'. This will just cause infinite loops // in the resolution machinery. if (BitList.empty()) if (VarInit *VI = dyn_cast(V)) - if (VI->getNameInit() == ValName) - return false; + if (VI->getNameInit() == ValName && !AllowSelfAssignment) + return true; // If we are assigning to a subset of the bits in the value... then we must be // assigning to a field of BitsRecTy, which must have a BitsInit @@ -104,18 +102,16 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, if (!BitList.empty()) { BitsInit *CurVal = dyn_cast(RV->getValue()); if (!CurVal) - return Error(Loc, "Value '" + ValName->getAsUnquotedString() - + "' is not a bits type"); + return Error(Loc, "Value '" + ValName->getAsUnquotedString() + + "' is not a bits type"); // Convert the incoming value to a bits type of the appropriate size... Init *BI = V->convertInitializerTo(BitsRecTy::get(BitList.size())); - if (!BI) { + if (!BI) return Error(Loc, "Initializer is not compatible with bit range"); - } // We should have a BitsInit type now. - BitsInit *BInit = dyn_cast(BI); - assert(BInit != nullptr); + BitsInit *BInit = cast(BI); SmallVector NewBits(CurVal->getNumBits()); @@ -123,7 +119,7 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, for (unsigned i = 0, e = BitList.size(); i != e; ++i) { unsigned Bit = BitList[i]; if (NewBits[Bit]) - return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" + + return Error(Loc, "Cannot set bit #" + Twine(Bit) + " of value '" + ValName->getAsUnquotedString() + "' more than once"); NewBits[Bit] = BInit->getBit(i); } @@ -137,15 +133,13 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, if (RV->setValue(V)) { std::string InitType = ""; - if (BitsInit *BI = dyn_cast(V)) { + if (BitsInit *BI = dyn_cast(V)) InitType = (Twine("' of type bit initializer with length ") + Twine(BI->getNumBits())).str(); - } - return Error(Loc, "Value '" + ValName->getAsUnquotedString() + "' of type '" - + RV->getType()->getAsString() + - "' is incompatible with initializer '" + V->getAsString() - + InitType - + "'"); + return Error(Loc, "Value '" + ValName->getAsUnquotedString() + + "' of type '" + RV->getType()->getAsString() + + "' is incompatible with initializer '" + V->getAsString() + + InitType + "'"); } return false; } @@ -155,12 +149,11 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, Init *ValName, bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { Record *SC = SubClass.Rec; // Add all of the values in the subclass into the current class. - const std::vector &Vals = SC->getValues(); - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - if (AddValue(CurRec, SubClass.RefRange.Start, Vals[i])) + for (const RecordVal &Val : SC->getValues()) + if (AddValue(CurRec, SubClass.RefRange.Start, Val)) return true; - const std::vector &TArgs = SC->getTemplateArgs(); + ArrayRef TArgs = SC->getTemplateArgs(); // Ensure that an appropriate number of template arguments are specified. if (TArgs.size() < SubClass.TemplateArgs.size()) @@ -184,15 +177,15 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { return Error(SubClass.RefRange.Start, - "Value not specified for template argument #" - + utostr(i) + " (" + TArgs[i]->getAsUnquotedString() - + ") of subclass '" + SC->getNameInitAsString() + "'!"); + "Value not specified for template argument #" + + Twine(i) + " (" + TArgs[i]->getAsUnquotedString() + + ") of subclass '" + SC->getNameInitAsString() + "'!"); } } // Since everything went well, we can now set the "superclass" list for the // current record. - const std::vector &SCs = SC->getSuperClasses(); + ArrayRef SCs = SC->getSuperClasses(); ArrayRef SCRanges = SC->getSuperClassRanges(); for (unsigned i = 0, e = SCs.size(); i != e; ++i) { if (CurRec->isSubClassOf(SCs[i])) @@ -216,33 +209,27 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, MultiClass *SMC = SubMultiClass.MC; Record *CurRec = &CurMC->Rec; - const std::vector &MCVals = CurRec->getValues(); - // Add all of the values in the subclass into the current class. - const std::vector &SMCVals = SMC->Rec.getValues(); - for (unsigned i = 0, e = SMCVals.size(); i != e; ++i) - if (AddValue(CurRec, SubMultiClass.RefRange.Start, SMCVals[i])) + for (const auto &SMCVal : SMC->Rec.getValues()) + if (AddValue(CurRec, SubMultiClass.RefRange.Start, SMCVal)) return true; - int newDefStart = CurMC->DefPrototypes.size(); + unsigned newDefStart = CurMC->DefPrototypes.size(); // Add all of the defs in the subclass into the current multiclass. - for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(), - iend = SMC->DefPrototypes.end(); - i != iend; - ++i) { + for (const std::unique_ptr &R : SMC->DefPrototypes) { // Clone the def and add it to the current multiclass - Record *NewDef = new Record(**i); + auto NewDef = make_unique(*R); // Add all of the values in the superclass into the current def. - for (unsigned i = 0, e = MCVals.size(); i != e; ++i) - if (AddValue(NewDef, SubMultiClass.RefRange.Start, MCVals[i])) + for (const auto &MCVal : CurRec->getValues()) + if (AddValue(NewDef.get(), SubMultiClass.RefRange.Start, MCVal)) return true; - CurMC->DefPrototypes.push_back(NewDef); + CurMC->DefPrototypes.push_back(std::move(NewDef)); } - const std::vector &SMCTArgs = SMC->Rec.getTemplateArgs(); + ArrayRef SMCTArgs = SMC->Rec.getTemplateArgs(); // Ensure that an appropriate number of template arguments are // specified. @@ -269,14 +256,9 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, // If a value is specified for this template arg, set it in the // new defs now. - for (MultiClass::RecordVector::iterator j = - CurMC->DefPrototypes.begin() + newDefStart, - jend = CurMC->DefPrototypes.end(); - j != jend; - ++j) { - Record *Def = *j; - - if (SetValue(Def, SubMultiClass.RefRange.Start, SMCTArgs[i], + for (const auto &Def : + makeArrayRef(CurMC->DefPrototypes).slice(newDefStart)) { + if (SetValue(Def.get(), SubMultiClass.RefRange.Start, SMCTArgs[i], std::vector(), SubMultiClass.TemplateArgs[i])) return true; @@ -289,9 +271,9 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, } } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) { return Error(SubMultiClass.RefRange.Start, - "Value not specified for template argument #" - + utostr(i) + " (" + SMCTArgs[i]->getAsUnquotedString() - + ") of subclass '" + SMC->Rec.getNameInitAsString() + "'!"); + "Value not specified for template argument #" + + Twine(i) + " (" + SMCTArgs[i]->getAsUnquotedString() + + ") of subclass '" + SMC->Rec.getNameInitAsString() + "'!"); } } @@ -327,7 +309,7 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){ } // Process each value. - for (int64_t i = 0; i < List->getSize(); ++i) { + for (unsigned i = 0; i < List->size(); ++i) { Init *ItemVal = List->resolveListElementReference(*CurRec, nullptr, i); IterVals.push_back(IterRecord(CurLoop.IterVar, ItemVal)); if (ProcessForeachDefs(CurRec, Loc, IterVals)) @@ -340,24 +322,20 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){ // This is the bottom of the recursion. We have all of the iterator values // for this point in the iteration space. Instantiate a new record to // reflect this combination of values. - Record *IterRec = new Record(*CurRec); + auto IterRec = make_unique(*CurRec); // Set the iterator values now. - for (unsigned i = 0, e = IterVals.size(); i != e; ++i) { - VarInit *IterVar = IterVals[i].IterVar; - TypedInit *IVal = dyn_cast(IterVals[i].IterValue); - if (!IVal) { - Error(Loc, "foreach iterator value is untyped"); - return true; - } + for (IterRecord &IR : IterVals) { + VarInit *IterVar = IR.IterVar; + TypedInit *IVal = dyn_cast(IR.IterValue); + if (!IVal) + return Error(Loc, "foreach iterator value is untyped"); IterRec->addValue(RecordVal(IterVar->getName(), IVal->getType(), false)); - if (SetValue(IterRec, Loc, IterVar->getName(), - std::vector(), IVal)) { - Error(Loc, "when instantiating this def"); - return true; - } + if (SetValue(IterRec.get(), Loc, IterVar->getName(), + std::vector(), IVal)) + return Error(Loc, "when instantiating this def"); // Resolve it next. IterRec->resolveReferencesTo(IterRec->getValue(IterVar->getName())); @@ -368,16 +346,15 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){ if (Records.getDef(IterRec->getNameInitAsString())) { // If this record is anonymous, it's no problem, just generate a new name - if (IterRec->isAnonymous()) - IterRec->setName(GetNewAnonymousName()); - else { - Error(Loc, "def already exists: " + IterRec->getNameInitAsString()); - return true; - } + if (!IterRec->isAnonymous()) + return Error(Loc, "def already exists: " +IterRec->getNameInitAsString()); + + IterRec->setName(GetNewAnonymousName()); } - Records.addDef(IterRec); - IterRec->resolveReferences(); + Record *IterRecSave = IterRec.get(); // Keep a copy before release. + Records.addDef(std::move(IterRec)); + IterRecSave->resolveReferences(); return false; } @@ -395,8 +372,7 @@ static bool isObjectStart(tgtok::TokKind K) { /// GetNewAnonymousName - Generate a unique anonymous name that can be used as /// an identifier. std::string TGParser::GetNewAnonymousName() { - unsigned Tmp = AnonCounter++; // MSVC2012 ICEs without this. - return "anonymous_" + utostr(Tmp); + return "anonymous_" + utostr(AnonCounter++); } /// ParseObjectName - If an object name is specified, return it. Otherwise, @@ -464,7 +440,7 @@ MultiClass *TGParser::ParseMultiClassID() { return nullptr; } - MultiClass *Result = MultiClasses[Lex.getCurStrVal()]; + MultiClass *Result = MultiClasses[Lex.getCurStrVal()].get(); if (!Result) TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'"); @@ -601,13 +577,12 @@ bool TGParser::ParseRangePiece(std::vector &Ranges) { Lex.Lex(); // Add to the range. - if (Start < End) { + if (Start < End) for (; Start <= End; ++Start) Ranges.push_back(Start); - } else { + else for (; Start >= End; --Start) Ranges.push_back(Start); - } return false; } @@ -768,10 +743,8 @@ Init *TGParser::ParseIDValue(Record *CurRec, } // If this is in a foreach loop, make sure it's not a loop iterator - for (LoopVector::iterator i = Loops.begin(), iend = Loops.end(); - i != iend; - ++i) { - VarInit *IterVar = dyn_cast(i->IterVar); + for (const auto &L : Loops) { + VarInit *IterVar = dyn_cast(L.IterVar); if (IterVar && IterVar->getName() == Name) return IterVar; } @@ -786,7 +759,7 @@ Init *TGParser::ParseIDValue(Record *CurRec, Error(NameLoc, "Variable not defined: '" + Name + "'"); return nullptr; } - + return StringInit::get(Name); } @@ -843,9 +816,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { Init *LHS = ParseValue(CurRec); if (!LHS) return nullptr; - if (Code == UnOpInit::HEAD - || Code == UnOpInit::TAIL - || Code == UnOpInit::EMPTY) { + if (Code == UnOpInit::HEAD || + Code == UnOpInit::TAIL || + Code == UnOpInit::EMPTY) { ListInit *LHSl = dyn_cast(LHS); StringInit *LHSs = dyn_cast(LHS); TypedInit *LHSt = dyn_cast(LHS); @@ -862,14 +835,13 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { } } - if (Code == UnOpInit::HEAD - || Code == UnOpInit::TAIL) { + if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) { if (!LHSl && !LHSt) { TokError("expected list type argument in unary operator"); return nullptr; } - if (LHSl && LHSl->getSize() == 0) { + if (LHSl && LHSl->empty()) { TokError("empty list argument in unary operator"); return nullptr; } @@ -880,11 +852,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { TokError("untyped list element in unary operator"); return nullptr; } - if (Code == UnOpInit::HEAD) { - Type = Itemt->getType(); - } else { - Type = ListRecTy::get(Itemt->getType()); - } + Type = (Code == UnOpInit::HEAD) ? Itemt->getType() + : ListRecTy::get(Itemt->getType()); } else { assert(LHSt && "expected list type argument in unary operator"); ListRecTy *LType = dyn_cast(LHSt->getType()); @@ -892,11 +861,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { TokError("expected list type argument in unary operator"); return nullptr; } - if (Code == UnOpInit::HEAD) { - Type = LType->getElementType(); - } else { - Type = LType; - } + Type = (Code == UnOpInit::HEAD) ? LType->getElementType() : LType; } } } @@ -1186,7 +1151,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, auto BinaryVal = Lex.getCurBinaryIntVal(); SmallVector Bits(BinaryVal.second); for (unsigned i = 0, e = BinaryVal.second; i != e; ++i) - Bits[i] = BitInit::get(BinaryVal.first & (1 << i)); + Bits[i] = BitInit::get(BinaryVal.first & (1LL << i)); R = BitsInit::get(Bits); Lex.Lex(); break; @@ -1244,8 +1209,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, SMLoc EndLoc = Lex.getLoc(); // Create the new record, set it as CurRec temporarily. - Record *NewRec = new Record(GetNewAnonymousName(), NameLoc, Records, - /*IsAnonymous=*/true); + auto NewRecOwner = llvm::make_unique(GetNewAnonymousName(), NameLoc, + Records, /*IsAnonymous=*/true); + Record *NewRec = NewRecOwner.get(); // Keep a copy since we may release. SubClassReference SCRef; SCRef.RefRange = SMRange(NameLoc, EndLoc); SCRef.Rec = Class; @@ -1253,19 +1219,20 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, // Add info about the subclass to NewRec. if (AddSubClass(NewRec, SCRef)) return nullptr; + if (!CurMultiClass) { NewRec->resolveReferences(); - Records.addDef(NewRec); + Records.addDef(std::move(NewRecOwner)); } else { + // This needs to get resolved once the multiclass template arguments are + // known before any use. + NewRec->setResolveFirst(true); // Otherwise, we're inside a multiclass, add it to the multiclass. - CurMultiClass->DefPrototypes.push_back(NewRec); + CurMultiClass->DefPrototypes.push_back(std::move(NewRecOwner)); // Copy the template arguments for the multiclass into the def. - const std::vector &TArgs = - CurMultiClass->Rec.getTemplateArgs(); - - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]); + for (Init *TArg : CurMultiClass->Rec.getTemplateArgs()) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TArg); assert(RV && "Template arg doesn't exist?"); NewRec->addValue(*RV); } @@ -1308,16 +1275,28 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, // first. We'll first read everything in to a vector, then we can reverse // it to get the bits in the correct order for the BitsInit value. for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + // FIXME: The following two loops would not be duplicated + // if the API was a little more orthogonal. + // bits values are allowed to initialize n bits. if (BitsInit *BI = dyn_cast(Vals[i])) { for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) NewBits.push_back(BI->getBit((e - i) - 1)); continue; } + // bits can also come from variable initializers. + if (VarInit *VI = dyn_cast(Vals[i])) { + if (BitsRecTy *BitsRec = dyn_cast(VI->getType())) { + for (unsigned i = 0, e = BitsRec->getNumBits(); i != e; ++i) + NewBits.push_back(VI->getBit((e - i) - 1)); + continue; + } + // Fallthrough to try convert this to a bit. + } // All other values must be convertible to just a single bit. Init *Bit = Vals[i]->convertInitializerTo(BitRecTy::get()); if (!Bit) { - Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+ + Error(BraceLoc, "Element #" + Twine(i) + " (" + Vals[i]->getAsString() + ") is not convertable to a bit"); return nullptr; } @@ -1336,11 +1315,8 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, if (ItemType) { ListRecTy *ListType = dyn_cast(ItemType); if (!ListType) { - std::string s; - raw_string_ostream ss(s); - ss << "Type mismatch for list, expected list type, got " - << ItemType->getAsString(); - TokError(ss.str()); + TokError(Twine("Type mismatch for list, expected list type, got ") + + ItemType->getAsString()); return nullptr; } GivenListTy = ListType; @@ -1377,10 +1353,8 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, // Check elements RecTy *EltTy = nullptr; - for (std::vector::iterator i = Vals.begin(), ie = Vals.end(); - i != ie; - ++i) { - TypedInit *TArg = dyn_cast(*i); + for (Init *V : Vals) { + TypedInit *TArg = dyn_cast(V); if (!TArg) { TokError("Untyped list element"); return nullptr; @@ -1571,7 +1545,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { Error(PasteLoc, "LHS of paste is not typed!"); return nullptr; } - + if (LHS->getType() != StringRecTy::get()) { LHS = UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get()); } @@ -1586,7 +1560,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { // These are all of the tokens that can begin an object body. // Some of these can also begin values but we disallow those cases // because they are unlikely to be useful. - + // Trailing paste, concat with an empty string. RHS = StringInit::get(""); break; @@ -1602,7 +1576,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { if (RHS->getType() != StringRecTy::get()) { RHS = UnOpInit::get(UnOpInit::CAST, RHS, StringRecTy::get()); } - + break; } @@ -1627,7 +1601,7 @@ TGParser::ParseDagArgList(Record *CurRec) { // DagArg ::= VARNAME if (Lex.getCode() == tgtok::VarName) { // A missing value is treated like '?'. - Result.push_back(std::make_pair(UnsetInit::get(), Lex.getCurStrVal())); + Result.emplace_back(UnsetInit::get(), Lex.getCurStrVal()); Lex.Lex(); } else { // DagArg ::= Value (':' VARNAME)? @@ -1668,8 +1642,8 @@ std::vector TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, RecTy *ItemType = EltTy; unsigned int ArgN = 0; if (ArgsRec && !EltTy) { - const std::vector &TArgs = ArgsRec->getTemplateArgs(); - if (!TArgs.size()) { + ArrayRef TArgs = ArgsRec->getTemplateArgs(); + if (TArgs.empty()) { TokError("template argument provided to non-template class"); return std::vector(); } @@ -1689,7 +1663,7 @@ std::vector TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, Lex.Lex(); // Eat the comma if (ArgsRec && !EltTy) { - const std::vector &TArgs = ArgsRec->getTemplateArgs(); + ArrayRef TArgs = ArgsRec->getTemplateArgs(); if (ArgN >= TArgs.size()) { TokError("too many template arguments"); return std::vector(); @@ -1736,11 +1710,10 @@ Init *TGParser::ParseDeclaration(Record *CurRec, Lex.Lex(); if (ParsingTemplateArgs) { - if (CurRec) { + if (CurRec) DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":"); - } else { + else assert(CurMultiClass); - } if (CurMultiClass) DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, "::"); @@ -1834,8 +1807,8 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) { assert(!IterType && "Type already initialized?"); IterType = IntRecTy::get(); std::vector Values; - for (unsigned i = 0, e = Ranges.size(); i != e; ++i) - Values.push_back(IntInit::get(Ranges[i])); + for (unsigned R : Ranges) + Values.push_back(IntInit::get(R)); ForeachListValue = ListInit::get(Values, IterType); } @@ -1961,10 +1934,9 @@ bool TGParser::ParseBody(Record *CurRec) { /// \brief Apply the current let bindings to \a CurRec. /// \returns true on error, false otherwise. bool TGParser::ApplyLetStack(Record *CurRec) { - for (unsigned i = 0, e = LetStack.size(); i != e; ++i) - for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) - if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, - LetStack[i][j].Bits, LetStack[i][j].Value)) + for (std::vector &LetInfo : LetStack) + for (LetRecord &LR : LetInfo) + if (SetValue(CurRec, LR.Loc, LR.Name, LR.Bits, LR.Value)) return true; return false; } @@ -2016,24 +1988,23 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { Lex.Lex(); // Eat the 'def' token. // Parse ObjectName and make a record for it. - Record *CurRec; + std::unique_ptr CurRecOwner; Init *Name = ParseObjectName(CurMultiClass); if (Name) - CurRec = new Record(Name, DefLoc, Records); + CurRecOwner = make_unique(Name, DefLoc, Records); else - CurRec = new Record(GetNewAnonymousName(), DefLoc, Records, - /*IsAnonymous=*/true); + CurRecOwner = llvm::make_unique(GetNewAnonymousName(), DefLoc, + Records, /*IsAnonymous=*/true); + Record *CurRec = CurRecOwner.get(); // Keep a copy since we may release. if (!CurMultiClass && Loops.empty()) { // Top-level def definition. // Ensure redefinition doesn't happen. - if (Records.getDef(CurRec->getNameInitAsString())) { - Error(DefLoc, "def '" + CurRec->getNameInitAsString() - + "' already defined"); - return true; - } - Records.addDef(CurRec); + if (Records.getDef(CurRec->getNameInitAsString())) + return Error(DefLoc, "def '" + CurRec->getNameInitAsString()+ + "' already defined"); + Records.addDef(std::move(CurRecOwner)); if (ParseObjectBody(CurRec)) return true; @@ -2047,16 +2018,14 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { return true; // Otherwise, a def inside a multiclass, add it to the multiclass. - for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i) - if (CurMultiClass->DefPrototypes[i]->getNameInit() - == CurRec->getNameInit()) { - Error(DefLoc, "def '" + CurRec->getNameInitAsString() + - "' already defined in this multiclass!"); - return true; - } - CurMultiClass->DefPrototypes.push_back(CurRec); - } else if (ParseObjectBody(CurRec)) + for (const auto &Proto : CurMultiClass->DefPrototypes) + if (Proto->getNameInit() == CurRec->getNameInit()) + return Error(DefLoc, "def '" + CurRec->getNameInitAsString() + + "' already defined in this multiclass!"); + CurMultiClass->DefPrototypes.push_back(std::move(CurRecOwner)); + } else if (ParseObjectBody(CurRec)) { return true; + } if (!CurMultiClass) // Def's in multiclasses aren't really defs. // See Record::setName(). This resolve step will see any new name @@ -2069,21 +2038,16 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { if (CurMultiClass) { // Copy the template arguments for the multiclass into the def. - const std::vector &TArgs = - CurMultiClass->Rec.getTemplateArgs(); - - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]); + for (Init *TArg : CurMultiClass->Rec.getTemplateArgs()) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TArg); assert(RV && "Template arg doesn't exist?"); CurRec->addValue(*RV); } } - if (ProcessForeachDefs(CurRec, DefLoc)) { - Error(DefLoc, - "Could not process loops for def" + CurRec->getNameInitAsString()); - return true; - } + if (ProcessForeachDefs(CurRec, DefLoc)) + return Error(DefLoc, "Could not process loops for def" + + CurRec->getNameInitAsString()); return false; } @@ -2116,8 +2080,7 @@ bool TGParser::ParseForeach(MultiClass *CurMultiClass) { // FOREACH Declaration IN Object if (ParseObject(CurMultiClass)) return true; - } - else { + } else { SMLoc BraceLoc = Lex.getLoc(); // Otherwise, this is a group foreach. Lex.Lex(); // eat the '{'. @@ -2156,12 +2119,14 @@ bool TGParser::ParseClass() { if (CurRec->getValues().size() > 1 || // Account for NAME. !CurRec->getSuperClasses().empty() || !CurRec->getTemplateArgs().empty()) - return TokError("Class '" + CurRec->getNameInitAsString() - + "' already defined"); + return TokError("Class '" + CurRec->getNameInitAsString() + + "' already defined"); } else { // If this is the first reference to this class, create and add it. - CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records); - Records.addClass(CurRec); + auto NewRec = + llvm::make_unique(Lex.getCurStrVal(), Lex.getLoc(), Records); + CurRec = NewRec.get(); + Records.addClass(std::move(NewRec)); } Lex.Lex(); // eat the name. @@ -2208,7 +2173,7 @@ std::vector TGParser::ParseLetList() { if (!Val) return std::vector(); // Now that we have everything, add the record. - Result.push_back(LetRecord(Name, Bits, Val, NameLoc)); + Result.emplace_back(std::move(Name), std::move(Bits), Val, NameLoc); if (Lex.getCode() != tgtok::comma) return Result; @@ -2229,7 +2194,7 @@ bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) { // Add this entry to the let stack. std::vector LetInfo = ParseLetList(); if (LetInfo.empty()) return true; - LetStack.push_back(LetInfo); + LetStack.push_back(std::move(LetInfo)); if (Lex.getCode() != tgtok::In) return TokError("expected 'in' at end of top-level 'let'"); @@ -2279,11 +2244,14 @@ bool TGParser::ParseMultiClass() { return TokError("expected identifier after multiclass for name"); std::string Name = Lex.getCurStrVal(); - if (MultiClasses.count(Name)) + auto Result = + MultiClasses.insert(std::make_pair(Name, + llvm::make_unique(Name, Lex.getLoc(),Records))); + + if (!Result.second) return TokError("multiclass '" + Name + "' already defined"); - CurMultiClass = MultiClasses[Name] = new MultiClass(Name, - Lex.getLoc(), Records); + CurMultiClass = Result.first->second.get(); Lex.Lex(); // Eat the identifier. // If there are template args, parse them. @@ -2319,25 +2287,24 @@ bool TGParser::ParseMultiClass() { if (Lex.getCode() != tgtok::l_brace) { if (!inherits) return TokError("expected '{' in multiclass definition"); - else if (Lex.getCode() != tgtok::semi) + if (Lex.getCode() != tgtok::semi) return TokError("expected ';' in multiclass definition"); - else - Lex.Lex(); // eat the ';'. + Lex.Lex(); // eat the ';'. } else { if (Lex.Lex() == tgtok::r_brace) // eat the '{'. return TokError("multiclass must contain at least one def"); while (Lex.getCode() != tgtok::r_brace) { switch (Lex.getCode()) { - default: - return TokError("expected 'let', 'def' or 'defm' in multiclass body"); - case tgtok::Let: - case tgtok::Def: - case tgtok::Defm: - case tgtok::Foreach: - if (ParseObject(CurMultiClass)) - return true; - break; + default: + return TokError("expected 'let', 'def' or 'defm' in multiclass body"); + case tgtok::Let: + case tgtok::Def: + case tgtok::Defm: + case tgtok::Foreach: + if (ParseObject(CurMultiClass)) + return true; + break; } } Lex.Lex(); // eat the '}'. @@ -2347,11 +2314,11 @@ bool TGParser::ParseMultiClass() { return false; } -Record *TGParser:: -InstantiateMulticlassDef(MultiClass &MC, - Record *DefProto, - Init *&DefmPrefix, - SMRange DefmPrefixRange) { +Record *TGParser::InstantiateMulticlassDef(MultiClass &MC, Record *DefProto, + Init *&DefmPrefix, + SMRange DefmPrefixRange, + ArrayRef TArgs, + std::vector &TemplateVals) { // We need to preserve DefProto so it can be reused for later // instantiations, so create a new Record to inherit from it. @@ -2367,7 +2334,6 @@ InstantiateMulticlassDef(MultiClass &MC, } Init *DefName = DefProto->getNameInit(); - StringInit *DefNameString = dyn_cast(DefName); if (DefNameString) { @@ -2383,21 +2349,22 @@ InstantiateMulticlassDef(MultiClass &MC, // Make a trail of SMLocs from the multiclass instantiations. SmallVector Locs(1, DefmPrefixRange.Start); Locs.append(DefProto->getLoc().begin(), DefProto->getLoc().end()); - Record *CurRec = new Record(DefName, Locs, Records, IsAnonymous); + auto CurRec = make_unique(DefName, Locs, Records, IsAnonymous); SubClassReference Ref; Ref.RefRange = DefmPrefixRange; Ref.Rec = DefProto; - AddSubClass(CurRec, Ref); + AddSubClass(CurRec.get(), Ref); // Set the value for NAME. We don't resolve references to it 'til later, // though, so that uses in nested multiclass names don't get // confused. - if (SetValue(CurRec, Ref.RefRange.Start, "NAME", std::vector(), - DefmPrefix)) { - Error(DefmPrefixRange.Start, "Could not resolve " - + CurRec->getNameInitAsString() + ":NAME to '" - + DefmPrefix->getAsUnquotedString() + "'"); + if (SetValue(CurRec.get(), Ref.RefRange.Start, "NAME", + std::vector(), DefmPrefix, + /*AllowSelfAssignment*/true)) { + Error(DefmPrefixRange.Start, "Could not resolve " + + CurRec->getNameInitAsString() + ":NAME to '" + + DefmPrefix->getAsUnquotedString() + "'"); return nullptr; } @@ -2415,12 +2382,40 @@ InstantiateMulticlassDef(MultiClass &MC, RecordVal *DefNameRV = CurRec->getValue("NAME"); CurRec->resolveReferencesTo(DefNameRV); + // Check if the name is a complex pattern. + // If so, resolve it. + DefName = CurRec->getNameInit(); + DefNameString = dyn_cast(DefName); + + // OK the pattern is more complex than simply using NAME. + // Let's use the heavy weaponery. + if (!DefNameString) { + ResolveMulticlassDefArgs(MC, CurRec.get(), DefmPrefixRange.Start, + Lex.getLoc(), TArgs, TemplateVals, + false/*Delete args*/); + DefName = CurRec->getNameInit(); + DefNameString = dyn_cast(DefName); + + if (!DefNameString) + DefName = DefName->convertInitializerTo(StringRecTy::get()); + + // We ran out of options here... + DefNameString = dyn_cast(DefName); + if (!DefNameString) { + PrintFatalError(CurRec->getLoc()[CurRec->getLoc().size() - 1], + DefName->getAsUnquotedString() + " is not a string."); + return nullptr; + } + + CurRec->setName(DefName); + } + // Now that NAME references are resolved and we're at the top level of // any multiclass expansions, add the record to the RecordKeeper. If we are // currently in a multiclass, it means this defm appears inside a // multiclass and its name won't be fully resolvable until we see - // the top-level defm. Therefore, we don't add this to the - // RecordKeeper at this point. If we did we could get duplicate + // the top-level defm. Therefore, we don't add this to the + // RecordKeeper at this point. If we did we could get duplicate // defs as more than one probably refers to NAME or some other // common internal placeholder. @@ -2432,17 +2427,19 @@ InstantiateMulticlassDef(MultiClass &MC, return nullptr; } - Records.addDef(CurRec); + Record *CurRecSave = CurRec.get(); // Keep a copy before we release. + Records.addDef(std::move(CurRec)); + return CurRecSave; } - return CurRec; + // FIXME This is bad but the ownership transfer to caller is pretty messy. + // The unique_ptr in this function at least protects the exits above. + return CurRec.release(); } -bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC, - Record *CurRec, - SMLoc DefmPrefixLoc, - SMLoc SubClassLoc, - const std::vector &TArgs, +bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC, Record *CurRec, + SMLoc DefmPrefixLoc, SMLoc SubClassLoc, + ArrayRef TArgs, std::vector &TemplateVals, bool DeleteArgs) { // Loop over all of the template arguments, setting them to the specified @@ -2454,19 +2451,19 @@ bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC, if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(), TemplateVals[i])) return true; - + // Resolve it next. CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); if (DeleteArgs) // Now remove it. CurRec->removeValue(TArgs[i]); - + } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { - return Error(SubClassLoc, "value not specified for template argument #"+ - utostr(i) + " (" + TArgs[i]->getAsUnquotedString() - + ") of multiclassclass '" + MC.Rec.getNameInitAsString() - + "'"); + return Error(SubClassLoc, "value not specified for template argument #" + + Twine(i) + " (" + TArgs[i]->getAsUnquotedString() + + ") of multiclassclass '" + MC.Rec.getNameInitAsString() + + "'"); } } return false; @@ -2485,20 +2482,15 @@ bool TGParser::ResolveMulticlassDef(MultiClass &MC, // with the new created definition. if (!CurMultiClass) return false; - for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); - i != e; ++i) - if (CurMultiClass->DefPrototypes[i]->getNameInit() - == CurRec->getNameInit()) + for (const auto &Proto : CurMultiClass->DefPrototypes) + if (Proto->getNameInit() == CurRec->getNameInit()) return Error(DefmPrefixLoc, "defm '" + CurRec->getNameInitAsString() + "' already defined in this multiclass!"); - CurMultiClass->DefPrototypes.push_back(CurRec); + CurMultiClass->DefPrototypes.push_back(std::unique_ptr(CurRec)); // Copy the template arguments for the multiclass into the new def. - const std::vector &TA = - CurMultiClass->Rec.getTemplateArgs(); - - for (unsigned i = 0, e = TA.size(); i != e; ++i) { - const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]); + for (Init * TA : CurMultiClass->Rec.getTemplateArgs()) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TA); assert(RV && "Template arg doesn't exist?"); CurRec->addValue(*RV); } @@ -2541,33 +2533,44 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { // To instantiate a multiclass, we need to first get the multiclass, then // instantiate each def contained in the multiclass with the SubClassRef // template parameters. - MultiClass *MC = MultiClasses[Ref.Rec->getName()]; + MultiClass *MC = MultiClasses[Ref.Rec->getName()].get(); assert(MC && "Didn't lookup multiclass correctly?"); std::vector &TemplateVals = Ref.TemplateArgs; // Verify that the correct number of template arguments were specified. - const std::vector &TArgs = MC->Rec.getTemplateArgs(); + ArrayRef TArgs = MC->Rec.getTemplateArgs(); if (TArgs.size() < TemplateVals.size()) return Error(SubClassLoc, "more template args specified than multiclass expects"); // Loop over all the def's in the multiclass, instantiating each one. - for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { - Record *DefProto = MC->DefPrototypes[i]; - - Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix, + for (const std::unique_ptr &DefProto : MC->DefPrototypes) { + // The record name construction goes as follow: + // - If the def name is a string, prepend the prefix. + // - If the def name is a more complex pattern, use that pattern. + // As a result, the record is instanciated before resolving + // arguments, as it would make its name a string. + Record *CurRec = InstantiateMulticlassDef(*MC, DefProto.get(), DefmPrefix, SMRange(DefmLoc, - DefmPrefixEndLoc)); + DefmPrefixEndLoc), + TArgs, TemplateVals); if (!CurRec) return true; + // Now that the record is instanciated, we can resolve arguments. if (ResolveMulticlassDefArgs(*MC, CurRec, DefmLoc, SubClassLoc, TArgs, TemplateVals, true/*Delete args*/)) return Error(SubClassLoc, "could not instantiate def"); - if (ResolveMulticlassDef(*MC, CurRec, DefProto, DefmLoc)) + if (ResolveMulticlassDef(*MC, CurRec, DefProto.get(), DefmLoc)) return Error(SubClassLoc, "could not instantiate def"); + // Defs that can be used by other definitions should be fully resolved + // before any use. + if (DefProto->isResolveFirst() && !CurMultiClass) { + CurRec->resolveReferences(); + CurRec->setResolveFirst(false); + } NewRecDefs.push_back(CurRec); } @@ -2600,9 +2603,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { // Get the expanded definition prototypes and teach them about // the record values the current class to inherit has - for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) { - Record *CurRec = NewRecDefs[i]; - + for (Record *CurRec : NewRecDefs) { // Add it. if (AddSubClass(CurRec, SubClass)) return true; @@ -2618,11 +2619,11 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { } if (!CurMultiClass) - for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) + for (Record *CurRec : NewRecDefs) // See Record::setName(). This resolve step will see any new // name for the def that might have been created when resolving // inheritance, values and arguments above. - NewRecDefs[i]->resolveReferences(); + CurRec->resolveReferences(); if (Lex.getCode() != tgtok::semi) return TokError("expected ';' at end of defm");