diff options
Diffstat (limited to 'llvm/lib/TableGen/TGParser.cpp')
-rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 253 |
1 files changed, 107 insertions, 146 deletions
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index 223d1337322..a0ec4dbfdc7 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -110,6 +110,16 @@ static void checkConcrete(Record &R) { } } +/// Return the qualified version of the implicit 'NAME' template argument. +static Init *QualifiedNameOfImplicitName(Record &Rec, + MultiClass *MC = nullptr) { + return QualifyName(Rec, MC, StringInit::get("NAME"), MC ? "::" : ":"); +} + +static Init *QualifiedNameOfImplicitName(MultiClass *MC) { + return QualifiedNameOfImplicitName(MC->Rec, MC); +} + bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) { if (!CurRec) CurRec = &CurMultiClass->Rec; @@ -234,6 +244,14 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { CurRec->removeValue(TArgs[i]); } + Init *Name; + if (CurRec->isClass()) + Name = + VarInit::get(QualifiedNameOfImplicitName(*CurRec), StringRecTy::get()); + else + Name = CurRec->getNameInit(); + R.set(QualifiedNameOfImplicitName(*SC), Name); + CurRec->resolveReferences(R); // Since everything went well, we can now set the "superclass" list for the @@ -259,80 +277,45 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { bool TGParser::AddSubMultiClass(MultiClass *CurMC, SubMultiClassReference &SubMultiClass) { MultiClass *SMC = SubMultiClass.MC; - Record *CurRec = &CurMC->Rec; - - // Add all of the values in the subclass into the current class. - for (const auto &SMCVal : SMC->Rec.getValues()) - if (AddValue(CurRec, SubMultiClass.RefRange.Start, SMCVal)) - return true; - - unsigned newDefStart = CurMC->DefPrototypes.size(); - - // Add all of the defs in the subclass into the current multiclass. - for (const std::unique_ptr<Record> &R : SMC->DefPrototypes) { - // Clone the def and add it to the current multiclass - auto NewDef = make_unique<Record>(*R); - - // Add all of the values in the superclass into the current def. - for (const auto &MCVal : CurRec->getValues()) - if (AddValue(NewDef.get(), SubMultiClass.RefRange.Start, MCVal)) - return true; - - CurMC->DefPrototypes.push_back(std::move(NewDef)); - } ArrayRef<Init *> SMCTArgs = SMC->Rec.getTemplateArgs(); - - // Ensure that an appropriate number of template arguments are - // specified. if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size()) return Error(SubMultiClass.RefRange.Start, "More template args specified than expected"); - // Loop over all of the template arguments, setting them to the specified - // value or leaving them as the default if necessary. - MapResolver CurRecResolver(CurRec); - + // Prepare the mapping of template argument name to value, filling in default + // values if necessary. + SmallVector<std::pair<Init *, Init *>, 8> TemplateArgs; for (unsigned i = 0, e = SMCTArgs.size(); i != e; ++i) { if (i < SubMultiClass.TemplateArgs.size()) { - // If a value is specified for this template arg, set it in the - // superclass now. - if (SetValue(CurRec, SubMultiClass.RefRange.Start, SMCTArgs[i], - None, SubMultiClass.TemplateArgs[i])) - return true; - - // If a value is specified for this template arg, set it in the - // new defs now. - for (const auto &Def : - makeArrayRef(CurMC->DefPrototypes).slice(newDefStart)) { - if (SetValue(Def.get(), SubMultiClass.RefRange.Start, SMCTArgs[i], - None, SubMultiClass.TemplateArgs[i])) - return true; + TemplateArgs.emplace_back(SMCTArgs[i], SubMultiClass.TemplateArgs[i]); + } else { + Init *Default = SMC->Rec.getValue(SMCTArgs[i])->getValue(); + if (!Default->isComplete()) { + return Error(SubMultiClass.RefRange.Start, + "value not specified for template argument #" + Twine(i) + + " (" + SMCTArgs[i]->getAsUnquotedString() + + ") of multiclass '" + SMC->Rec.getNameInitAsString() + + "'"); } - } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) { - return Error(SubMultiClass.RefRange.Start, - "Value not specified for template argument #" + - Twine(i) + " (" + SMCTArgs[i]->getAsUnquotedString() + - ") of subclass '" + SMC->Rec.getNameInitAsString() + "'!"); + TemplateArgs.emplace_back(SMCTArgs[i], Default); } - - CurRecResolver.set(SMCTArgs[i], CurRec->getValue(SMCTArgs[i])->getValue()); - - CurRec->removeValue(SMCTArgs[i]); } - CurRec->resolveReferences(CurRecResolver); + TemplateArgs.emplace_back( + QualifiedNameOfImplicitName(SMC), + VarInit::get(QualifiedNameOfImplicitName(CurMC), StringRecTy::get())); - for (const auto &Def : - makeArrayRef(CurMC->DefPrototypes).slice(newDefStart)) { - MapResolver R(Def.get()); + // Add all of the defs in the subclass into the current multiclass. + for (const std::unique_ptr<Record> &Rec : SMC->DefPrototypes) { + auto NewDef = make_unique<Record>(*Rec); - for (Init *SMCTArg : SMCTArgs) { - R.set(SMCTArg, Def->getValue(SMCTArg)->getValue()); - Def->removeValue(SMCTArg); - } + MapResolver R(NewDef.get()); + for (const auto &TArg : TemplateArgs) + R.set(TArg.first, TArg.second); + NewDef->resolveReferences(R); - Def->resolveReferences(R); + CurMC->DefPrototypes.push_back(std::move(NewDef)); } return false; @@ -343,18 +326,18 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, /// /// Apply foreach loops, resolve internal variable references, and add to the /// current multi class or the global record keeper as appropriate. -bool TGParser::addDef(std::unique_ptr<Record> Rec, Init *DefmName) { +bool TGParser::addDef(std::unique_ptr<Record> Rec) { IterSet IterVals; if (Loops.empty()) - return addDefOne(std::move(Rec), DefmName, IterVals); + return addDefOne(std::move(Rec), IterVals); - return addDefForeach(Rec.get(), DefmName, IterVals); + return addDefForeach(Rec.get(), IterVals); } /// Recursive helper function for addDef/addDefOne to resolve references to /// foreach variables. -bool TGParser::addDefForeach(Record *Rec, Init *DefmName, IterSet &IterVals) { +bool TGParser::addDefForeach(Record *Rec, IterSet &IterVals) { if (IterVals.size() != Loops.size()) { assert(IterVals.size() < Loops.size()); ForeachLoop &CurLoop = Loops[IterVals.size()]; @@ -363,7 +346,7 @@ bool TGParser::addDefForeach(Record *Rec, Init *DefmName, IterSet &IterVals) { // Process each value. for (unsigned i = 0; i < List->size(); ++i) { IterVals.push_back(IterRecord(CurLoop.IterVar, List->getElement(i))); - if (addDefForeach(Rec, DefmName, IterVals)) + if (addDefForeach(Rec, IterVals)) return true; IterVals.pop_back(); } @@ -374,13 +357,12 @@ bool TGParser::addDefForeach(Record *Rec, Init *DefmName, IterSet &IterVals) { // for this point in the iteration space. Instantiate a new record to // reflect this combination of values. auto IterRec = make_unique<Record>(*Rec); - return addDefOne(std::move(IterRec), DefmName, IterVals); + return addDefOne(std::move(IterRec), IterVals); } /// After resolving foreach loops, add the record as a prototype to the /// current multiclass, or resolve fully and add to the record keeper. -bool TGParser::addDefOne(std::unique_ptr<Record> Rec, Init *DefmName, - IterSet &IterVals) { +bool TGParser::addDefOne(std::unique_ptr<Record> Rec, IterSet &IterVals) { MapResolver R(Rec.get()); for (IterRecord &IR : IterVals) @@ -389,32 +371,21 @@ bool TGParser::addDefOne(std::unique_ptr<Record> Rec, Init *DefmName, Rec->resolveReferences(R); if (CurMultiClass) { - for (const auto &Proto : CurMultiClass->DefPrototypes) { - if (Proto->getNameInit() == Rec->getNameInit()) { - if (!Rec->isAnonymous()) { + if (!Rec->isAnonymous()) { + for (const auto &Proto : CurMultiClass->DefPrototypes) { + if (Proto->getNameInit() == Rec->getNameInit()) { PrintError(Rec->getLoc(), Twine("def '") + Rec->getNameInitAsString() + "' already defined in this multiclass!"); PrintNote(Proto->getLoc(), "location of previous definition"); return true; } - Rec->setName(Records.getNewAnonymousName()); - break; } } CurMultiClass->DefPrototypes.emplace_back(std::move(Rec)); return false; } - // Name construction is an incoherent mess. Unfortunately, existing .td - // files rely on pretty much all the quirks and implementation details of - // this. - if (DefmName) { - MapResolver R(Rec.get()); - R.set(StringInit::get("NAME"), DefmName); - Rec->resolveReferences(R); - } - if (Record *Prev = Records.getDef(Rec->getNameInitAsString())) { if (!Rec->isAnonymous()) { PrintError(Rec->getLoc(), @@ -488,7 +459,20 @@ Init *TGParser::ParseObjectName(MultiClass *CurMultiClass) { if (CurMultiClass) CurRec = &CurMultiClass->Rec; - return ParseValue(CurRec, StringRecTy::get(), ParseNameMode); + Init *Name = ParseValue(CurRec, StringRecTy::get(), ParseNameMode); + if (!Name) + return nullptr; + + if (CurMultiClass) { + Init *NameStr = QualifiedNameOfImplicitName(CurMultiClass); + HasReferenceResolver R(NameStr); + Name->resolveReferences(R); + if (!R.found()) + Name = BinOpInit::getStrConcat(VarInit::get(NameStr, StringRecTy::get()), + Name); + } + + return Name; } /// ParseClassID - Parse and resolve a reference to a class name. This returns @@ -798,30 +782,23 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc, if (CurRec) { if (const RecordVal *RV = CurRec->getValue(Name)) return VarInit::get(Name, RV->getType()); - - Init *TemplateArgName = QualifyName(*CurRec, CurMultiClass, Name, ":"); - - if (CurMultiClass) - TemplateArgName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name, - "::"); - - if (CurRec->isTemplateArg(TemplateArgName)) { - const RecordVal *RV = CurRec->getValue(TemplateArgName); - assert(RV && "Template arg doesn't exist??"); - return VarInit::get(TemplateArgName, RV->getType()); - } } - if (CurMultiClass) { - if (Name->getValue() == "NAME") - return VarInit::get(Name, StringRecTy::get()); - - Init *MCName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name, "::"); + if ((CurRec && CurRec->isClass()) || CurMultiClass) { + Init *TemplateArgName; + if (CurMultiClass) { + TemplateArgName = + QualifyName(CurMultiClass->Rec, CurMultiClass, Name, "::"); + } else + TemplateArgName = QualifyName(*CurRec, CurMultiClass, Name, ":"); - if (CurMultiClass->Rec.isTemplateArg(MCName)) { - const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); + Record *TemplateRec = CurMultiClass ? &CurMultiClass->Rec : CurRec; + if (TemplateRec->isTemplateArg(TemplateArgName)) { + const RecordVal *RV = TemplateRec->getValue(TemplateArgName); assert(RV && "Template arg doesn't exist??"); - return VarInit::get(MCName, RV->getType()); + return VarInit::get(TemplateArgName, RV->getType()); + } else if (Name->getValue() == "NAME") { + return VarInit::get(TemplateArgName, StringRecTy::get()); } } @@ -840,15 +817,12 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc, // Allow self-references of concrete defs, but delay the lookup so that we // get the correct type. - if (CurRec && !CurMultiClass && CurRec->getNameInit() == Name) + if (CurRec && !CurRec->isClass() && !CurMultiClass && + CurRec->getNameInit() == Name) return UnOpInit::get(UnOpInit::CAST, Name, CurRec->getType()); - if (Mode == ParseValueMode) { - Error(NameLoc, "Variable not defined: '" + Name->getValue() + "'"); - return nullptr; - } - - return Name; + Error(NameLoc, "Variable not defined: '" + Name->getValue() + "'"); + return nullptr; } /// ParseOperation - Parse an operator. This returns null on error. @@ -2169,8 +2143,14 @@ Init *TGParser::ParseDeclaration(Record *CurRec, return nullptr; } + std::string Str = Lex.getCurStrVal(); + if (Str == "NAME") { + TokError("'" + Str + "' is a reserved variable name"); + return nullptr; + } + SMLoc IdLoc = Lex.getLoc(); - Init *DeclName = StringInit::get(Lex.getCurStrVal()); + Init *DeclName = StringInit::get(Str); Lex.Lex(); if (ParsingTemplateArgs) { @@ -2471,7 +2451,7 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { if (ParseObjectBody(CurRec.get())) return true; - return addDef(std::move(CurRec), nullptr); + return addDef(std::move(CurRec)); } /// ParseDefset - Parse a defset statement. @@ -2585,7 +2565,7 @@ bool TGParser::ParseClass() { Record *CurRec = Records.getClass(Lex.getCurStrVal()); if (CurRec) { // If the body was previously defined, this is an error. - if (CurRec->getValues().size() > 1 || // Account for NAME. + if (!CurRec->getValues().empty() || !CurRec->getSuperClasses().empty() || !CurRec->getTemplateArgs().empty()) return TokError("Class '" + CurRec->getNameInitAsString() + @@ -2593,7 +2573,8 @@ bool TGParser::ParseClass() { } else { // If this is the first reference to this class, create and add it. auto NewRec = - llvm::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(), Records); + llvm::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(), Records, + /*Class=*/true); CurRec = NewRec.get(); Records.addClass(std::move(NewRec)); } @@ -2604,7 +2585,6 @@ bool TGParser::ParseClass() { if (ParseTemplateArgList(CurRec)) return true; - // Finally, parse the object body. return ParseObjectBody(CurRec); } @@ -2802,8 +2782,14 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { Init *DefmName = ParseObjectName(CurMultiClass); if (!DefmName) return true; - if (isa<UnsetInit>(DefmName)) + if (isa<UnsetInit>(DefmName)) { DefmName = Records.getNewAnonymousName(); + if (CurMultiClass) + DefmName = BinOpInit::getStrConcat( + VarInit::get(QualifiedNameOfImplicitName(CurMultiClass), + StringRecTy::get()), + DefmName); + } if (Lex.getCode() != tgtok::colon) return TokError("expected ':' after defm identifier"); @@ -2836,10 +2822,10 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { return Error(SubClassLoc, "more template args specified than multiclass expects"); - DenseMap<Init *, Init *> TemplateArgs; + SmallVector<std::pair<Init *, Init *>, 8> TemplateArgs; for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { if (i < TemplateVals.size()) { - TemplateArgs.insert({TArgs[i], TemplateVals[i]}); + TemplateArgs.emplace_back(TArgs[i], TemplateVals[i]); } else { Init *Default = MC->Rec.getValue(TArgs[i])->getValue(); if (!Default->isComplete()) { @@ -2849,45 +2835,20 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { ") of multiclass '" + MC->Rec.getNameInitAsString() + "'"); } - TemplateArgs.insert({TArgs[i], Default}); + TemplateArgs.emplace_back(TArgs[i], Default); } } + TemplateArgs.emplace_back(QualifiedNameOfImplicitName(MC), DefmName); + // Loop over all the def's in the multiclass, instantiating each one. for (const std::unique_ptr<Record> &DefProto : MC->DefPrototypes) { - bool ResolveName = true; auto CurRec = make_unique<Record>(*DefProto); CurRec->appendLoc(SubClassLoc); - if (StringInit *NameString = - dyn_cast<StringInit>(CurRec->getNameInit())) { - // We have a fully expanded string so there are no operators to - // resolve. We should concatenate the given prefix and name. - // - // TODO: This MUST happen before template argument resolution. This - // does not make sense and should be changed, but at the time of - // writing, there are existing .td files which rely on this - // implementation detail. It's a bad idea and should be fixed. - // See test/TableGen/name-resolution-consistency.td for some - // examples. - CurRec->setName(BinOpInit::getStrConcat(DefmName, NameString)); - ResolveName = false; - } - MapResolver R(CurRec.get()); - - if (ResolveName) { - // If the proto's name wasn't resolved, we probably have a reference to - // NAME and need to replace it. - // - // TODO: Whether the name is resolved is basically determined by magic. - // Unfortunately, existing .td files depend on it. - R.set(StringInit::get("NAME"), DefmName); - } - for (const auto &TArg : TemplateArgs) R.set(TArg.first, TArg.second); - CurRec->resolveReferences(R); NewRecDefs.emplace_back(std::move(CurRec)); @@ -2937,7 +2898,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { if (ApplyLetStack(CurRec.get())) return true; - addDef(std::move(CurRec), DefmName); + addDef(std::move(CurRec)); } if (Lex.getCode() != tgtok::semi) |