diff options
Diffstat (limited to 'llvm/lib/TableGen')
| -rw-r--r-- | llvm/lib/TableGen/Error.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/TableGen/JSONBackend.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/TableGen/Main.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/TableGen/Record.cpp | 86 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGLexer.cpp | 147 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGLexer.h | 90 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 394 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TGParser.h | 9 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TableGenBackend.cpp | 12 | ||||
| -rw-r--r-- | llvm/lib/TableGen/TableGenBackendSkeleton.cpp | 1 |
10 files changed, 461 insertions, 287 deletions
diff --git a/llvm/lib/TableGen/Error.cpp b/llvm/lib/TableGen/Error.cpp index ebe9129ebaeb..dabb265ef80c 100644 --- a/llvm/lib/TableGen/Error.cpp +++ b/llvm/lib/TableGen/Error.cpp @@ -170,4 +170,11 @@ void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) { } } +// Dump a message to stderr. +void dumpMessage(SMLoc Loc, Init *Message) { + auto *MessageInit = dyn_cast<StringInit>(Message); + assert(MessageInit && "no debug message to print"); + PrintNote(Loc, MessageInit->getValue()); +} + } // end namespace llvm diff --git a/llvm/lib/TableGen/JSONBackend.cpp b/llvm/lib/TableGen/JSONBackend.cpp index a9dc30d7f59b..2a3f522a9c0e 100644 --- a/llvm/lib/TableGen/JSONBackend.cpp +++ b/llvm/lib/TableGen/JSONBackend.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" diff --git a/llvm/lib/TableGen/Main.cpp b/llvm/lib/TableGen/Main.cpp index 9aee1f8fecd2..c6e2e6c89fd2 100644 --- a/llvm/lib/TableGen/Main.cpp +++ b/llvm/lib/TableGen/Main.cpp @@ -34,7 +34,6 @@ #include <string> #include <system_error> #include <utility> -#include <vector> using namespace llvm; static cl::opt<std::string> diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index 20db470855a1..aa981fdab4b3 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -797,6 +797,25 @@ void UnOpInit::Profile(FoldingSetNodeID &ID) const { Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const { RecordKeeper &RK = getRecordKeeper(); switch (getOpcode()) { + case REPR: + if (LHS->isConcrete()) { + // If it is a Record, print the full content. + if (const auto *Def = dyn_cast<DefInit>(LHS)) { + std::string S; + raw_string_ostream OS(S); + OS << *Def->getDef(); + OS.flush(); + return StringInit::get(RK, S); + } else { + // Otherwise, print the value of the variable. + // + // NOTE: we could recursively !repr the elements of a list, + // but that could produce a lot of output when printing a + // defset. + return StringInit::get(RK, LHS->getAsString()); + } + } + break; case TOLOWER: if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) return StringInit::get(RK, LHSs->getValue().lower()); @@ -957,6 +976,9 @@ std::string UnOpInit::getAsString() const { case EMPTY: Result = "!empty"; break; case GETDAGOP: Result = "!getdagop"; break; case LOG2 : Result = "!logtwo"; break; + case REPR: + Result = "!repr"; + break; case TOLOWER: Result = "!tolower"; break; @@ -1287,7 +1309,6 @@ Init *BinOpInit::Fold(Record *CurRec) const { } return ListInit::get(Args, TheList->getElementType()); } - case RANGE: case RANGEC: { auto *LHSi = dyn_cast<IntInit>(LHS); auto *RHSi = dyn_cast<IntInit>(RHS); @@ -1487,8 +1508,9 @@ std::string BinOpInit::getAsString() const { case GT: Result = "!gt"; break; case LISTCONCAT: Result = "!listconcat"; break; case LISTSPLAT: Result = "!listsplat"; break; - case LISTREMOVE: Result = "!listremove"; break; - case RANGE: Result = "!range"; break; + case LISTREMOVE: + Result = "!listremove"; + break; case STRCONCAT: Result = "!strconcat"; break; case INTERLEAVE: Result = "!interleave"; break; case SETDAGOP: Result = "!setdagop"; break; @@ -1704,6 +1726,34 @@ Init *TernOpInit::Fold(Record *CurRec) const { break; } + case RANGE: { + auto *LHSi = dyn_cast<IntInit>(LHS); + auto *MHSi = dyn_cast<IntInit>(MHS); + auto *RHSi = dyn_cast<IntInit>(RHS); + if (!LHSi || !MHSi || !RHSi) + break; + + auto Start = LHSi->getValue(); + auto End = MHSi->getValue(); + auto Step = RHSi->getValue(); + if (Step == 0) + PrintError(CurRec->getLoc(), "Step of !range can't be 0"); + + SmallVector<Init *, 8> Args; + if (Start < End && Step > 0) { + Args.reserve((End - Start) / Step); + for (auto I = Start; I < End; I += Step) + Args.push_back(IntInit::get(getRecordKeeper(), I)); + } else if (Start > End && Step < 0) { + Args.reserve((Start - End) / -Step); + for (auto I = Start; I > End; I += Step) + Args.push_back(IntInit::get(getRecordKeeper(), I)); + } else { + // Empty set + } + return ListInit::get(Args, LHSi->getType()); + } + case SUBSTR: { StringInit *LHSs = dyn_cast<StringInit>(LHS); IntInit *MHSi = dyn_cast<IntInit>(MHS); @@ -1823,6 +1873,9 @@ std::string TernOpInit::getAsString() const { case FILTER: Result = "!filter"; UnquotedLHS = true; break; case FOREACH: Result = "!foreach"; UnquotedLHS = true; break; case IF: Result = "!if"; break; + case RANGE: + Result = "!range"; + break; case SUBST: Result = "!subst"; break; case SUBSTR: Result = "!substr"; break; case FIND: Result = "!find"; break; @@ -2210,9 +2263,9 @@ void VarDefInit::Profile(FoldingSetNodeID &ID) const { DefInit *VarDefInit::instantiate() { if (!Def) { RecordKeeper &Records = Class->getRecords(); - auto NewRecOwner = std::make_unique<Record>(Records.getNewAnonymousName(), - Class->getLoc(), Records, - /*IsAnonymous=*/true); + auto NewRecOwner = + std::make_unique<Record>(Records.getNewAnonymousName(), Class->getLoc(), + Records, Record::RK_AnonymousDef); Record *NewRec = NewRecOwner.get(); // Copy values from class to instance @@ -2222,6 +2275,9 @@ DefInit *VarDefInit::instantiate() { // Copy assertions from class to instance. NewRec->appendAssertions(Class); + // Copy dumps from class to instance. + NewRec->appendDumps(Class); + // Substitute and resolve template arguments ArrayRef<Init *> TArgs = Class->getTemplateArgs(); MapResolver R(NewRec); @@ -2256,6 +2312,9 @@ DefInit *VarDefInit::instantiate() { // Check the assertions. NewRec->checkRecordAssertions(); + // Check the assertions. + NewRec->emitRecordDumps(); + Def = DefInit::get(NewRec); } @@ -2813,6 +2872,11 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) { Value = Assertion.Message->resolveReferences(R); Assertion.Message = Value; } + // Resolve the dump expressions. + for (auto &Dump : Dumps) { + Init *Value = Dump.Message->resolveReferences(R); + Dump.Message = Value; + } } void Record::resolveReferences(Init *NewName) { @@ -3069,6 +3133,16 @@ void Record::checkRecordAssertions() { } } +void Record::emitRecordDumps() { + RecordResolver R(*this); + R.setFinal(true); + + for (const auto &Dump : getDumps()) { + Init *Message = Dump.Message->resolveReferences(R); + dumpMessage(Dump.Loc, Message); + } +} + // Report a warning if the record has unused template arguments. void Record::checkUnusedTemplateArgs() { for (const Init *TA : getTemplateArgs()) { diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp index 98f0e8c1149c..c811a67d930d 100644 --- a/llvm/lib/TableGen/TGLexer.cpp +++ b/llvm/lib/TableGen/TGLexer.cpp @@ -346,31 +346,32 @@ tgtok::TokKind TGLexer::LexIdentifier() { StringRef Str(IdentStart, CurPtr-IdentStart); tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(Str) - .Case("int", tgtok::Int) - .Case("bit", tgtok::Bit) - .Case("bits", tgtok::Bits) - .Case("string", tgtok::String) - .Case("list", tgtok::List) - .Case("code", tgtok::Code) - .Case("dag", tgtok::Dag) - .Case("class", tgtok::Class) - .Case("def", tgtok::Def) - .Case("true", tgtok::TrueVal) - .Case("false", tgtok::FalseVal) - .Case("foreach", tgtok::Foreach) - .Case("defm", tgtok::Defm) - .Case("defset", tgtok::Defset) - .Case("multiclass", tgtok::MultiClass) - .Case("field", tgtok::Field) - .Case("let", tgtok::Let) - .Case("in", tgtok::In) - .Case("defvar", tgtok::Defvar) - .Case("include", tgtok::Include) - .Case("if", tgtok::If) - .Case("then", tgtok::Then) - .Case("else", tgtok::ElseKW) - .Case("assert", tgtok::Assert) - .Default(tgtok::Id); + .Case("int", tgtok::Int) + .Case("bit", tgtok::Bit) + .Case("bits", tgtok::Bits) + .Case("string", tgtok::String) + .Case("list", tgtok::List) + .Case("code", tgtok::Code) + .Case("dag", tgtok::Dag) + .Case("class", tgtok::Class) + .Case("def", tgtok::Def) + .Case("true", tgtok::TrueVal) + .Case("false", tgtok::FalseVal) + .Case("foreach", tgtok::Foreach) + .Case("defm", tgtok::Defm) + .Case("defset", tgtok::Defset) + .Case("multiclass", tgtok::MultiClass) + .Case("field", tgtok::Field) + .Case("let", tgtok::Let) + .Case("in", tgtok::In) + .Case("defvar", tgtok::Defvar) + .Case("include", tgtok::Include) + .Case("if", tgtok::If) + .Case("then", tgtok::Then) + .Case("else", tgtok::ElseKW) + .Case("assert", tgtok::Assert) + .Case("dump", tgtok::Dump) + .Default(tgtok::Id); // A couple of tokens require special processing. switch (Kind) { @@ -462,56 +463,62 @@ bool TGLexer::SkipCComment() { /// 0x[0-9a-fA-F]+ /// 0b[01]+ tgtok::TokKind TGLexer::LexNumber() { + unsigned Base = 0; + const char *NumStart; + + // Check if it's a hex or a binary value. if (CurPtr[-1] == '0') { + NumStart = CurPtr + 1; if (CurPtr[0] == 'x') { - ++CurPtr; - const char *NumStart = CurPtr; - while (isxdigit(CurPtr[0])) + Base = 16; + do ++CurPtr; - - // Requires at least one hex digit. - if (CurPtr == NumStart) - return ReturnError(TokStart, "Invalid hexadecimal number"); - - errno = 0; - CurIntVal = strtoll(NumStart, nullptr, 16); - if (errno == EINVAL) - return ReturnError(TokStart, "Invalid hexadecimal number"); - if (errno == ERANGE) { - errno = 0; - CurIntVal = (int64_t)strtoull(NumStart, nullptr, 16); - if (errno == EINVAL) - return ReturnError(TokStart, "Invalid hexadecimal number"); - if (errno == ERANGE) - return ReturnError(TokStart, "Hexadecimal number out of range"); - } - return tgtok::IntVal; + while (isxdigit(CurPtr[0])); } else if (CurPtr[0] == 'b') { - ++CurPtr; - const char *NumStart = CurPtr; - while (CurPtr[0] == '0' || CurPtr[0] == '1') + Base = 2; + do ++CurPtr; - - // Requires at least one binary digit. - if (CurPtr == NumStart) - return ReturnError(CurPtr-2, "Invalid binary number"); - CurIntVal = strtoll(NumStart, nullptr, 2); - return tgtok::BinaryIntVal; + while (CurPtr[0] == '0' || CurPtr[0] == '1'); } } - // Check for a sign without a digit. - if (!isdigit(CurPtr[0])) { - if (CurPtr[-1] == '-') - return tgtok::minus; - else if (CurPtr[-1] == '+') - return tgtok::plus; + // For a hex or binary value, we always convert it to an unsigned value. + bool IsMinus = false; + + // Check if it's a decimal value. + if (Base == 0) { + // Check for a sign without a digit. + if (!isdigit(CurPtr[0])) { + if (CurPtr[-1] == '-') + return tgtok::minus; + else if (CurPtr[-1] == '+') + return tgtok::plus; + } + + Base = 10; + NumStart = TokStart; + IsMinus = CurPtr[-1] == '-'; + + while (isdigit(CurPtr[0])) + ++CurPtr; } - while (isdigit(CurPtr[0])) - ++CurPtr; - CurIntVal = strtoll(TokStart, nullptr, 10); - return tgtok::IntVal; + // Requires at least one digit. + if (CurPtr == NumStart) + return ReturnError(TokStart, "Invalid number"); + + errno = 0; + if (IsMinus) + CurIntVal = strtoll(NumStart, nullptr, Base); + else + CurIntVal = strtoull(NumStart, nullptr, Base); + + if (errno == EINVAL) + return ReturnError(TokStart, "Invalid number"); + if (errno == ERANGE) + return ReturnError(TokStart, "Number out of range"); + + return Base == 2 ? tgtok::BinaryIntVal : tgtok::IntVal; } /// LexBracket - We just read '['. If this is a code block, return it, @@ -599,6 +606,7 @@ tgtok::TokKind TGLexer::LexExclaim() { .Case("exists", tgtok::XExists) .Case("tolower", tgtok::XToLower) .Case("toupper", tgtok::XToUpper) + .Case("repr", tgtok::XRepr) .Default(tgtok::Error); return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator"); @@ -717,16 +725,15 @@ tgtok::TokKind TGLexer::lexPreprocessor( bool MacroIsDefined = DefinedMacros.count(MacroName) != 0; - // Canonicalize ifndef to ifdef equivalent - if (Kind == tgtok::Ifndef) { + // Canonicalize ifndef's MacroIsDefined to its ifdef equivalent. + if (Kind == tgtok::Ifndef) MacroIsDefined = !MacroIsDefined; - Kind = tgtok::Ifdef; - } // Regardless of whether we are processing tokens or not, // we put the #ifdef control on stack. + // Note that MacroIsDefined has been canonicalized against ifdef. PrepIncludeStack.back()->push_back( - {Kind, MacroIsDefined, SMLoc::getFromPointer(TokStart)}); + {tgtok::Ifdef, MacroIsDefined, SMLoc::getFromPointer(TokStart)}); if (!prepSkipDirectiveEnd()) return ReturnError(CurPtr, "Only comments are supported after " + diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h index c9bba98971d0..2e2aa59f3440 100644 --- a/llvm/lib/TableGen/TGLexer.h +++ b/llvm/lib/TableGen/TGLexer.h @@ -54,35 +54,60 @@ enum TokKind { paste, // # dotdotdot, // ... + // Boolean literals. + TrueVal, + FalseVal, + + // Integer value. + IntVal, + + // Binary constant. Note that these are sized according to the number of + // bits given. + BinaryIntVal, + + // Preprocessing tokens for internal usage by the lexer. + // They are never returned as a result of Lex(). + Ifdef, + Ifndef, + Else, + Endif, + Define, + // Reserved keywords. ('ElseKW' is named to distinguish it from the // existing 'Else' that means the preprocessor #else.) - Assert, Bit, Bits, - Class, Code, Dag, - Def, - Defm, - Defset, - Defvar, ElseKW, FalseKW, Field, - Foreach, - If, In, Include, Int, - Let, List, - MultiClass, String, Then, TrueKW, + // Object start tokens. + OBJECT_START_FIRST, + Assert = OBJECT_START_FIRST, + Class, + Def, + Defm, + Defset, + Defvar, + Dump, + Foreach, + If, + Let, + MultiClass, + OBJECT_START_LAST = MultiClass, + // Bang operators. - XConcat, + BANG_OPERATOR_FIRST, + XConcat = BANG_OPERATOR_FIRST, XADD, XSUB, XMUL, @@ -131,33 +156,33 @@ enum TokKind { XGetDagName, XSetDagArg, XSetDagName, - - // Boolean literals. - TrueVal, - FalseVal, - - // Integer value. - IntVal, - - // Binary constant. Note that these are sized according to the number of - // bits given. - BinaryIntVal, + XRepr, + BANG_OPERATOR_LAST = XRepr, // String valued tokens. - Id, + STRING_VALUE_FIRST, + Id = STRING_VALUE_FIRST, StrVal, VarName, CodeFragment, - - // Preprocessing tokens for internal usage by the lexer. - // They are never returned as a result of Lex(). - Ifdef, - Ifndef, - Else, - Endif, - Define + STRING_VALUE_LAST = CodeFragment, }; + +/// isBangOperator - Return true if this is a bang operator. +static inline bool isBangOperator(tgtok::TokKind Kind) { + return tgtok::BANG_OPERATOR_FIRST <= Kind && Kind <= BANG_OPERATOR_LAST; +} + +/// isObjectStart - Return true if this is a valid first token for a statement. +static inline bool isObjectStart(tgtok::TokKind Kind) { + return tgtok::OBJECT_START_FIRST <= Kind && Kind <= OBJECT_START_LAST; +} + +/// isStringValue - Return true if this is a string value. +static inline bool isStringValue(tgtok::TokKind Kind) { + return tgtok::STRING_VALUE_FIRST <= Kind && Kind <= STRING_VALUE_LAST; } +} // namespace tgtok /// TGLexer - TableGen Lexer class. class TGLexer { @@ -197,8 +222,7 @@ public: tgtok::TokKind getCode() const { return CurCode; } const std::string &getCurStrVal() const { - assert((CurCode == tgtok::Id || CurCode == tgtok::StrVal || - CurCode == tgtok::VarName || CurCode == tgtok::CodeFragment) && + assert(tgtok::isStringValue(CurCode) && "This token doesn't have a string value"); return CurStrVal; } diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index 759e15f4c443..e7dcb91ba20a 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "TGParser.h" -#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" @@ -35,20 +34,20 @@ namespace llvm { struct SubClassReference { SMRange RefRange; - Record *Rec; + Record *Rec = nullptr; SmallVector<ArgumentInit *, 4> TemplateArgs; - SubClassReference() : Rec(nullptr) {} + SubClassReference() = default; bool isInvalid() const { return Rec == nullptr; } }; struct SubMultiClassReference { SMRange RefRange; - MultiClass *MC; + MultiClass *MC = nullptr; SmallVector<ArgumentInit *, 4> TemplateArgs; - SubMultiClassReference() : MC(nullptr) {} + SubMultiClassReference() = default; bool isInvalid() const { return MC == nullptr; } void dump() const; @@ -111,11 +110,11 @@ static void checkConcrete(Record &R) { /// Return an Init with a qualifier prefix referring /// to CurRec's name. -static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass, Init *Name, - StringRef Scoper) { +static Init *QualifyName(Record &CurRec, Init *Name) { RecordKeeper &RK = CurRec.getRecords(); - Init *NewName = BinOpInit::getStrConcat(CurRec.getNameInit(), - StringInit::get(RK, Scoper)); + Init *NewName = BinOpInit::getStrConcat( + CurRec.getNameInit(), + StringInit::get(RK, CurRec.isMultiClass() ? "::" : ":")); NewName = BinOpInit::getStrConcat(NewName, Name); if (BinOpInit *BinOp = dyn_cast<BinOpInit>(NewName)) @@ -123,18 +122,20 @@ static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass, Init *Name, return NewName; } +static Init *QualifyName(MultiClass *MC, Init *Name) { + return QualifyName(MC->Rec, Name); +} + /// Return the qualified version of the implicit 'NAME' template argument. -static Init *QualifiedNameOfImplicitName(Record &Rec, - MultiClass *MC = nullptr) { - return QualifyName(Rec, MC, StringInit::get(Rec.getRecords(), "NAME"), - MC ? "::" : ":"); +static Init *QualifiedNameOfImplicitName(Record &Rec) { + return QualifyName(Rec, StringInit::get(Rec.getRecords(), "NAME")); } static Init *QualifiedNameOfImplicitName(MultiClass *MC) { - return QualifiedNameOfImplicitName(MC->Rec, MC); + return QualifiedNameOfImplicitName(MC->Rec); } -Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass* ParsingMultiClass, +Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass *ParsingMultiClass, StringInit *Name, SMRange NameLoc, bool TrackReferenceLocs) const { // First, we search in local variables. @@ -142,11 +143,10 @@ Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass* ParsingMultiClass, if (It != Vars.end()) return It->second; - std::function<Init *(Record *, StringInit *, StringRef)> FindValueInArgs = - [&](Record *Rec, StringInit *Name, StringRef Scoper) -> Init * { + auto FindValueInArgs = [&](Record *Rec, StringInit *Name) -> Init * { if (!Rec) return nullptr; - Init *ArgName = QualifyName(*Rec, ParsingMultiClass, Name, Scoper); + Init *ArgName = QualifyName(*Rec, Name); if (Rec->isTemplateArg(ArgName)) { RecordVal *RV = Rec->getValue(ArgName); assert(RV && "Template arg doesn't exist??"); @@ -176,7 +176,7 @@ Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass* ParsingMultiClass, // The variable is a class template argument? if (CurRec->isClass()) - if (auto *V = FindValueInArgs(CurRec, Name, ":")) + if (auto *V = FindValueInArgs(CurRec, Name)) return V; } break; @@ -193,7 +193,7 @@ Init *TGVarScope::getVar(RecordKeeper &Records, MultiClass* ParsingMultiClass, case SK_MultiClass: { // The variable is a multiclass template argument? if (CurMultiClass) - if (auto *V = FindValueInArgs(&CurMultiClass->Rec, Name, "::")) + if (auto *V = FindValueInArgs(&CurMultiClass->Rec, Name)) return V; break; } @@ -313,6 +313,9 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { // Copy the subclass record's assertions to the new record. CurRec->appendAssertions(SC); + // Copy the subclass record's dumps to the new record. + CurRec->appendDumps(SC); + Init *Name; if (CurRec->isClass()) Name = VarInit::get(QualifiedNameOfImplicitName(*CurRec), @@ -376,7 +379,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC, /// Add a record, foreach loop, or assertion to the current context. bool TGParser::addEntry(RecordsEntry E) { - assert((!!E.Rec + !!E.Loop + !!E.Assertion) == 1 && + assert((!!E.Rec + !!E.Loop + !!E.Assertion + !!E.Dump) == 1 && "RecordsEntry has invalid number of items"); // If we are parsing a loop, add it to the loop's entries. @@ -404,6 +407,11 @@ bool TGParser::addEntry(RecordsEntry E) { return false; } + if (E.Dump) { + dumpMessage(E.Dump->Loc, E.Dump->Message); + return false; + } + // It must be a record, so finish it off. return addDefOne(std::move(E.Rec)); } @@ -498,6 +506,18 @@ bool TGParser::resolve(const std::vector<RecordsEntry> &Source, else CheckAssert(E.Assertion->Loc, Condition, Message); + } else if (E.Dump) { + MapResolver R; + for (const auto &S : Substs) + R.set(S.first, S.second); + Init *Message = E.Dump->Message->resolveReferences(R); + + if (Dest) + Dest->push_back( + std::make_unique<Record::DumpInfo>(E.Dump->Loc, Message)); + else + dumpMessage(E.Dump->Loc, Message); + } else { auto Rec = std::make_unique<Record>(*E.Rec); if (Loc) @@ -545,6 +565,9 @@ bool TGParser::addDefOne(std::unique_ptr<Record> Rec) { // Check the assertions. Rec->checkRecordAssertions(); + // Run the dumps. + Rec->emitRecordDumps(); + // If ObjectBody has template arguments, it's an error. assert(Rec->getTemplateArgs().empty() && "How'd this get template args?"); @@ -586,17 +609,18 @@ bool TGParser::resolveArguments(Record *Rec, ArrayRef<ArgumentInit *> ArgValues, ArgName->getAsUnquotedString() + "' once"); ArgValueHandler(ArgName, ArgValue); - llvm::erase_value(UnsolvedArgNames, ArgName); + llvm::erase(UnsolvedArgNames, ArgName); } // For unsolved arguments, if there is no default value, complain. for (auto *UnsolvedArgName : UnsolvedArgNames) { Init *Default = Rec->getValue(UnsolvedArgName)->getValue(); if (!Default->isComplete()) { - return Error(Loc, "value not specified for template argument (" + - UnsolvedArgName->getAsUnquotedString() + - ") of multiclass '" + Rec->getNameInitAsString() + - "'"); + std::string Name = UnsolvedArgName->getAsUnquotedString(); + Error(Loc, "value not specified for template argument '" + Name + "'"); + PrintNote(Rec->getFieldLoc(Name), + "declared in '" + Rec->getNameInitAsString() + "'"); + return true; } ArgValueHandler(UnsolvedArgName, Default); } @@ -629,14 +653,6 @@ bool TGParser::resolveArgumentsOfMultiClass(SubstStack &Substs, MultiClass *MC, // Parser Code //===----------------------------------------------------------------------===// -/// isObjectStart - Return true if this is a valid first token for a statement. -static bool isObjectStart(tgtok::TokKind K) { - return K == tgtok::Assert || K == tgtok::Class || K == tgtok::Def || - K == tgtok::Defm || K == tgtok::Defset || K == tgtok::Defvar || - K == tgtok::Foreach || K == tgtok::If || K == tgtok::Let || - K == tgtok::MultiClass; -} - bool TGParser::consume(tgtok::TokKind K) { if (Lex.getCode() == K) { Lex.Lex(); @@ -755,8 +771,7 @@ ParseSubClassReference(Record *CurRec, bool isDefm) { return Result; } - if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec, - isDefm)) { + if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec)) { Result.Rec = nullptr; // Error parsing value list. return Result; } @@ -793,7 +808,7 @@ ParseSubMultiClassReference(MultiClass *CurMC) { } if (ParseTemplateArgValueList(Result.TemplateArgs, &CurMC->Rec, - &Result.MC->Rec, true)) { + &Result.MC->Rec)) { Result.MC = nullptr; // Error parsing value list. return Result; } @@ -1175,6 +1190,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XSize: case tgtok::XEmpty: case tgtok::XCast: + case tgtok::XRepr: case tgtok::XGetDagOp: { // Value ::= !unop '(' Value ')' UnOpInit::UnaryOp Code; RecTy *Type = nullptr; @@ -1193,6 +1209,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { } break; + case tgtok::XRepr: + Lex.Lex(); // eat the operation + Code = UnOpInit::REPR; + Type = StringRecTy::get(Records); + break; case tgtok::XToLower: Lex.Lex(); // eat the operation Code = UnOpInit::TOLOWER; @@ -1415,7 +1436,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XListConcat: case tgtok::XListSplat: case tgtok::XListRemove: - case tgtok::XRange: case tgtok::XStrConcat: case tgtok::XInterleave: case tgtok::XGetDagArg: @@ -1447,8 +1467,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XGt: Code = BinOpInit::GT; break; case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break; case tgtok::XListSplat: Code = BinOpInit::LISTSPLAT; break; - case tgtok::XListRemove: Code = BinOpInit::LISTREMOVE; break; - case tgtok::XRange: Code = BinOpInit::RANGE; break; + case tgtok::XListRemove: + Code = BinOpInit::LISTREMOVE; + break; case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; case tgtok::XInterleave: Code = BinOpInit::INTERLEAVE; break; case tgtok::XSetDagOp: Code = BinOpInit::SETDAGOP; break; @@ -1515,10 +1536,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { // We don't know the list type until we parse the first argument. ArgType = ItemType; break; - case tgtok::XRange: - Type = IntRecTy::get(Records)->getListTy(); - // ArgType may be either Int or List. - break; case tgtok::XStrConcat: Type = StringRecTy::get(Records); ArgType = StringRecTy::get(Records); @@ -1603,27 +1620,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { return nullptr; } break; - case BinOpInit::RANGE: - if (InitList.size() == 1) { - if (isa<ListRecTy>(ArgType)) { - ArgType = nullptr; // Detect error if 2nd arg were present. - } else if (isa<IntRecTy>(ArgType)) { - // Assume 2nd arg should be IntRecTy - } else { - Error(InitLoc, - Twine("expected list or int, got value of type '") + - ArgType->getAsString() + "'"); - return nullptr; - } - } else { - // Don't come here unless 1st arg is ListRecTy. - assert(isa<ListRecTy>(cast<TypedInit>(InitList[0])->getType())); - Error(InitLoc, - Twine("expected one list, got extra value of type '") + - ArgType->getAsString() + "'"); - return nullptr; - } - break; case BinOpInit::EQ: case BinOpInit::NE: if (!ArgType->typeIsConvertibleTo(IntRecTy::get(Records)) && @@ -1733,37 +1729,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { if (Code == BinOpInit::LISTREMOVE) Type = ArgType; - if (Code == BinOpInit::RANGE) { - Init *LHS, *RHS; - auto ArgCount = InitList.size(); - assert(ArgCount >= 1); - auto *Arg0 = cast<TypedInit>(InitList[0]); - auto *Arg0Ty = Arg0->getType(); - if (ArgCount == 1) { - if (isa<ListRecTy>(Arg0Ty)) { - // (0, !size(arg)) - LHS = IntInit::get(Records, 0); - RHS = UnOpInit::get(UnOpInit::SIZE, Arg0, IntRecTy::get(Records)) - ->Fold(CurRec); - } else { - assert(isa<IntRecTy>(Arg0Ty)); - // (0, arg) - LHS = IntInit::get(Records, 0); - RHS = Arg0; - } - } else if (ArgCount == 2) { - assert(isa<IntRecTy>(Arg0Ty)); - auto *Arg1 = cast<TypedInit>(InitList[1]); - assert(isa<IntRecTy>(Arg1->getType())); - LHS = Arg0; - RHS = Arg1; - } else { - Error(OpLoc, "expected at most two values of integer"); - return nullptr; - } - return BinOpInit::get(Code, LHS, RHS, Type)->Fold(CurRec); - } - // We allow multiple operands to associative operators like !strconcat as // shorthand for nesting them. if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT || @@ -1790,6 +1755,105 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { return ParseOperationForEachFilter(CurRec, ItemType); } + case tgtok::XRange: { + SMLoc OpLoc = Lex.getLoc(); + Lex.Lex(); // eat the operation + + if (!consume(tgtok::l_paren)) { + TokError("expected '(' after !range operator"); + return nullptr; + } + + SmallVector<Init *, 2> Args; + bool FirstArgIsList = false; + for (;;) { + if (Args.size() >= 3) { + TokError("expected at most three values of integer"); + return nullptr; + } + + SMLoc InitLoc = Lex.getLoc(); + Args.push_back(ParseValue(CurRec)); + if (!Args.back()) + return nullptr; + + TypedInit *ArgBack = dyn_cast<TypedInit>(Args.back()); + if (!ArgBack) { + Error(OpLoc, Twine("expected value to be a typed value, got '" + + Args.back()->getAsString() + "'")); + return nullptr; + } + + RecTy *ArgBackType = ArgBack->getType(); + if (!FirstArgIsList || Args.size() == 1) { + if (Args.size() == 1 && isa<ListRecTy>(ArgBackType)) { + FirstArgIsList = true; // Detect error if 2nd arg were present. + } else if (isa<IntRecTy>(ArgBackType)) { + // Assume 2nd arg should be IntRecTy + } else { + if (Args.size() != 1) + Error(InitLoc, Twine("expected value of type 'int', got '" + + ArgBackType->getAsString() + "'")); + else + Error(InitLoc, Twine("expected list or int, got value of type '") + + ArgBackType->getAsString() + "'"); + return nullptr; + } + } else { + // Don't come here unless 1st arg is ListRecTy. + assert(isa<ListRecTy>(cast<TypedInit>(Args[0])->getType())); + Error(InitLoc, Twine("expected one list, got extra value of type '") + + ArgBackType->getAsString() + "'"); + return nullptr; + } + if (!consume(tgtok::comma)) + break; + } + + if (!consume(tgtok::r_paren)) { + TokError("expected ')' in operator"); + return nullptr; + } + + Init *LHS, *MHS, *RHS; + auto ArgCount = Args.size(); + assert(ArgCount >= 1); + auto *Arg0 = cast<TypedInit>(Args[0]); + auto *Arg0Ty = Arg0->getType(); + if (ArgCount == 1) { + if (isa<ListRecTy>(Arg0Ty)) { + // (0, !size(arg), 1) + LHS = IntInit::get(Records, 0); + MHS = UnOpInit::get(UnOpInit::SIZE, Arg0, IntRecTy::get(Records)) + ->Fold(CurRec); + RHS = IntInit::get(Records, 1); + } else { + assert(isa<IntRecTy>(Arg0Ty)); + // (0, arg, 1) + LHS = IntInit::get(Records, 0); + MHS = Arg0; + RHS = IntInit::get(Records, 1); + } + } else { + assert(isa<IntRecTy>(Arg0Ty)); + auto *Arg1 = cast<TypedInit>(Args[1]); + assert(isa<IntRecTy>(Arg1->getType())); + LHS = Arg0; + MHS = Arg1; + if (ArgCount == 3) { + // (start, end, step) + auto *Arg2 = cast<TypedInit>(Args[2]); + assert(isa<IntRecTy>(Arg2->getType())); + RHS = Arg2; + } else + // (start, end, 1) + RHS = IntInit::get(Records, 1); + } + return TernOpInit::get(TernOpInit::RANGE, LHS, MHS, RHS, + IntRecTy::get(Records)->getListTy()) + ->Fold(CurRec); + } + case tgtok::XSetDagArg: case tgtok::XSetDagName: case tgtok::XDag: @@ -2541,13 +2605,20 @@ Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) { /// SimpleValue ::= LISTREMOVETOK '(' Value ',' Value ')' /// SimpleValue ::= RANGE '(' Value ')' /// SimpleValue ::= RANGE '(' Value ',' Value ')' +/// SimpleValue ::= RANGE '(' Value ',' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' /// SimpleValue ::= COND '(' [Value ':' Value,]+ ')' /// Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) { Init *R = nullptr; - switch (Lex.getCode()) { + tgtok::TokKind Code = Lex.getCode(); + + // Parse bang operators. + if (tgtok::isBangOperator(Code)) + return ParseOperation(CurRec, ItemType); + + switch (Code) { default: TokError("Unknown or reserved token when parsing a value"); break; case tgtok::TrueVal: @@ -2802,58 +2873,6 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, return DagInit::get(Operator, OperatorName, DagArgs); } - - case tgtok::XHead: - case tgtok::XTail: - case tgtok::XSize: - case tgtok::XEmpty: - case tgtok::XCast: - case tgtok::XToLower: - case tgtok::XToUpper: - case tgtok::XGetDagOp: // Value ::= !unop '(' Value ')' - case tgtok::XExists: - case tgtok::XIsA: - case tgtok::XConcat: - case tgtok::XDag: - case tgtok::XADD: - case tgtok::XSUB: - case tgtok::XMUL: - case tgtok::XDIV: - case tgtok::XNOT: - case tgtok::XLOG2: - case tgtok::XAND: - case tgtok::XOR: - case tgtok::XXOR: - case tgtok::XSRA: - case tgtok::XSRL: - case tgtok::XSHL: - case tgtok::XEq: - case tgtok::XNe: - case tgtok::XLe: - case tgtok::XLt: - case tgtok::XGe: - case tgtok::XGt: - case tgtok::XListConcat: - case tgtok::XListSplat: - case tgtok::XListRemove: - case tgtok::XRange: - case tgtok::XStrConcat: - case tgtok::XInterleave: - case tgtok::XGetDagArg: - case tgtok::XGetDagName: - case tgtok::XSetDagOp: // Value ::= !binop '(' Value ',' Value ')' - case tgtok::XSetDagArg: - case tgtok::XSetDagName: - case tgtok::XIf: - case tgtok::XCond: - case tgtok::XFoldl: - case tgtok::XForEach: - case tgtok::XFilter: - case tgtok::XSubst: - case tgtok::XSubstr: - case tgtok::XFind: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' - return ParseOperation(CurRec, ItemType); - } } return R; @@ -3139,8 +3158,7 @@ void TGParser::ParseValueList(SmallVectorImpl<Init *> &Result, Record *CurRec, // PostionalArgValueList ::= [Value {',' Value}*] // NamedArgValueList ::= [NameValue '=' Value {',' NameValue '=' Value}*] bool TGParser::ParseTemplateArgValueList( - SmallVectorImpl<ArgumentInit *> &Result, Record *CurRec, Record *ArgsRec, - bool IsDefm) { + SmallVectorImpl<ArgumentInit *> &Result, Record *CurRec, Record *ArgsRec) { assert(Result.empty() && "Result vector is not empty"); ArrayRef<Init *> TArgs = ArgsRec->getTemplateArgs(); @@ -3171,8 +3189,7 @@ bool TGParser::ParseTemplateArgValueList( "The name of named argument should be a valid identifier"); auto *Name = cast<StringInit>(Value); - Init *QualifiedName = - QualifyName(*ArgsRec, CurMultiClass, Name, IsDefm ? "::" : ":"); + Init *QualifiedName = QualifyName(*ArgsRec, Name); auto *NamedArg = ArgsRec->getValue(QualifiedName); if (!NamedArg) return Error(ValueLoc, @@ -3251,17 +3268,17 @@ Init *TGParser::ParseDeclaration(Record *CurRec, RecordVal(DeclName, IdLoc, Type, HasField ? RecordVal::FK_NonconcreteOK : RecordVal::FK_Normal)); - } else if (CurRec) { // class template argument - DeclName = QualifyName(*CurRec, CurMultiClass, DeclName, ":"); - BadField = AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type, - RecordVal::FK_TemplateArg)); - + DeclName = QualifyName(*CurRec, DeclName); + BadField = + AddValue(CurRec, IdLoc, + RecordVal(DeclName, IdLoc, Type, RecordVal::FK_TemplateArg)); } else { // multiclass template argument assert(CurMultiClass && "invalid context for template argument"); - DeclName = QualifyName(CurMultiClass->Rec, CurMultiClass, DeclName, "::"); - BadField = AddValue(CurRec, IdLoc, RecordVal(DeclName, IdLoc, Type, - RecordVal::FK_TemplateArg)); + DeclName = QualifyName(CurMultiClass, DeclName); + BadField = + AddValue(CurRec, IdLoc, + RecordVal(DeclName, IdLoc, Type, RecordVal::FK_TemplateArg)); } if (BadField) return nullptr; @@ -3408,6 +3425,7 @@ bool TGParser::ParseTemplateArgList(Record *CurRec) { /// BodyItem ::= Declaration ';' /// BodyItem ::= LET ID OptionalBitList '=' Value ';' /// BodyItem ::= Defvar +/// BodyItem ::= Dump /// BodyItem ::= Assert /// bool TGParser::ParseBodyItem(Record *CurRec) { @@ -3417,6 +3435,9 @@ bool TGParser::ParseBodyItem(Record *CurRec) { if (Lex.getCode() == tgtok::Defvar) return ParseDefvar(CurRec); + if (Lex.getCode() == tgtok::Dump) + return ParseDump(nullptr, CurRec); + if (Lex.getCode() != tgtok::Let) { if (!ParseDeclaration(CurRec, false)) return true; @@ -3513,6 +3534,10 @@ bool TGParser::ApplyLetStack(RecordsEntry &Entry) { if (Entry.Assertion) return false; + // Let bindings are not applied to dumps. + if (Entry.Dump) + return false; + for (auto &E : Entry.Loop->Entries) { if (ApplyLetStack(E)) return true; @@ -3582,9 +3607,8 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { return true; if (isa<UnsetInit>(Name)) { - CurRec = - std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc, Records, - /*Anonymous=*/true); + CurRec = std::make_unique<Record>(Records.getNewAnonymousName(), DefLoc, + Records, Record::RK_AnonymousDef); } else { CurRec = std::make_unique<Record>(Name, NameLoc, Records); } @@ -3902,9 +3926,8 @@ bool TGParser::ParseClass() { CurRec->updateClassLoc(Lex.getLoc()); } else { // If this is the first reference to this class, create and add it. - auto NewRec = - std::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(), Records, - /*Class=*/true); + auto NewRec = std::make_unique<Record>(Lex.getCurStrVal(), Lex.getLoc(), + Records, Record::RK_Class); CurRec = NewRec.get(); Records.addClass(std::move(NewRec)); } @@ -4093,13 +4116,14 @@ bool TGParser::ParseMultiClass() { while (Lex.getCode() != tgtok::r_brace) { switch (Lex.getCode()) { default: - return TokError("expected 'assert', 'def', 'defm', 'defvar', " + return TokError("expected 'assert', 'def', 'defm', 'defvar', 'dump', " "'foreach', 'if', or 'let' in multiclass body"); case tgtok::Assert: case tgtok::Def: case tgtok::Defm: case tgtok::Defvar: + case tgtok::Dump: case tgtok::Foreach: case tgtok::If: case tgtok::Let: @@ -4243,15 +4267,18 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { /// Object ::= Defset /// Object ::= Defvar /// Object ::= Assert +/// Object ::= Dump bool TGParser::ParseObject(MultiClass *MC) { switch (Lex.getCode()) { default: return TokError( - "Expected assert, class, def, defm, defset, foreach, if, or let"); + "Expected assert, class, def, defm, defset, dump, foreach, if, or let"); case tgtok::Assert: return ParseAssert(MC); case tgtok::Def: return ParseDef(MC); case tgtok::Defm: return ParseDefm(MC); case tgtok::Defvar: return ParseDefvar(); + case tgtok::Dump: + return ParseDump(MC); case tgtok::Foreach: return ParseForeach(MC); case tgtok::If: return ParseIf(MC); case tgtok::Let: return ParseTopLevelLet(MC); @@ -4275,7 +4302,7 @@ bool TGParser::ParseObject(MultiClass *MC) { /// ParseObjectList /// ObjectList :== Object* bool TGParser::ParseObjectList(MultiClass *MC) { - while (isObjectStart(Lex.getCode())) { + while (tgtok::isObjectStart(Lex.getCode())) { if (ParseObject(MC)) return true; } @@ -4362,3 +4389,30 @@ LLVM_DUMP_METHOD void MultiClass::dump() const { E.dump(); } #endif + +bool TGParser::ParseDump(MultiClass *CurMultiClass, Record *CurRec) { + // Location of the `dump` statement. + SMLoc Loc = Lex.getLoc(); + assert(Lex.getCode() == tgtok::Dump && "Unknown tok"); + Lex.Lex(); // eat the operation + + Init *Message = ParseValue(CurRec); + if (!Message) + return true; + + // Allow to use dump directly on `defvar` and `def`, by wrapping + // them with a `!repl`. + if (isa<DefInit>(Message)) + Message = UnOpInit::get(UnOpInit::REPR, Message, StringRecTy::get(Records)) + ->Fold(CurRec); + + if (!consume(tgtok::semi)) + return TokError("expected ';'"); + + if (CurRec) + CurRec->addDump(Loc, Message); + else + addEntry(std::make_unique<Record::DumpInfo>(Loc, Message)); + + return false; +} diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h index d42cdad88a84..0929154fed3d 100644 --- a/llvm/lib/TableGen/TGParser.h +++ b/llvm/lib/TableGen/TGParser.h @@ -41,6 +41,7 @@ struct RecordsEntry { std::unique_ptr<Record> Rec; std::unique_ptr<ForeachLoop> Loop; std::unique_ptr<Record::AssertionInfo> Assertion; + std::unique_ptr<Record::DumpInfo> Dump; void dump() const; @@ -49,6 +50,8 @@ struct RecordsEntry { RecordsEntry(std::unique_ptr<ForeachLoop> Loop) : Loop(std::move(Loop)) {} RecordsEntry(std::unique_ptr<Record::AssertionInfo> Assertion) : Assertion(std::move(Assertion)) {} + RecordsEntry(std::unique_ptr<Record::DumpInfo> Dump) + : Dump(std::move(Dump)) {} }; /// ForeachLoop - Record the iteration state associated with a for loop. @@ -82,7 +85,7 @@ struct MultiClass { void dump() const; MultiClass(StringRef Name, SMLoc Loc, RecordKeeper &Records) - : Rec(Name, Loc, Records) {} + : Rec(Name, Loc, Records, Record::RK_MultiClass) {} }; class TGVarScope { @@ -262,6 +265,7 @@ private: // Parser methods. bool ParseDef(MultiClass *CurMultiClass); bool ParseDefset(); bool ParseDefvar(Record *CurRec = nullptr); + bool ParseDump(MultiClass *CurMultiClass, Record *CurRec = nullptr); bool ParseForeach(MultiClass *CurMultiClass); bool ParseIf(MultiClass *CurMultiClass); bool ParseIfBody(MultiClass *CurMultiClass, StringRef Kind); @@ -289,8 +293,7 @@ private: // Parser methods. void ParseValueList(SmallVectorImpl<llvm::Init*> &Result, Record *CurRec, RecTy *ItemType = nullptr); bool ParseTemplateArgValueList(SmallVectorImpl<llvm::ArgumentInit *> &Result, - Record *CurRec, Record *ArgsRec, - bool IsDefm = false); + Record *CurRec, Record *ArgsRec); void ParseDagArgList( SmallVectorImpl<std::pair<llvm::Init*, StringInit*>> &Result, Record *CurRec); diff --git a/llvm/lib/TableGen/TableGenBackend.cpp b/llvm/lib/TableGen/TableGenBackend.cpp index 135ec643bc3a..035abe936e11 100644 --- a/llvm/lib/TableGen/TableGenBackend.cpp +++ b/llvm/lib/TableGen/TableGenBackend.cpp @@ -12,6 +12,7 @@ #include "llvm/TableGen/TableGenBackend.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -40,7 +41,8 @@ static void printLine(raw_ostream &OS, const Twine &Prefix, char Fill, OS << Suffix << '\n'; } -void llvm::emitSourceFileHeader(StringRef Desc, raw_ostream &OS) { +void llvm::emitSourceFileHeader(StringRef Desc, raw_ostream &OS, + const RecordKeeper &Record) { printLine(OS, "/*===- TableGen'erated file ", '-', "*- C++ -*-===*\\"); StringRef Prefix("|* "); StringRef Suffix(" *|"); @@ -55,7 +57,13 @@ void llvm::emitSourceFileHeader(StringRef Desc, raw_ostream &OS) { } while (Pos < Desc.size()); printLine(OS, Prefix, ' ', Suffix); printLine(OS, Prefix + "Automatically generated file, do not edit!", ' ', - Suffix); + Suffix); + + // Print the filename of source file + if (!Record.getInputFilename().empty()) + printLine( + OS, Prefix + "From: " + sys::path::filename(Record.getInputFilename()), + ' ', Suffix); printLine(OS, Prefix, ' ', Suffix); printLine(OS, "\\*===", '-', "===*/"); OS << '\n'; diff --git a/llvm/lib/TableGen/TableGenBackendSkeleton.cpp b/llvm/lib/TableGen/TableGenBackendSkeleton.cpp index 2fde4a66727b..8e65b7a5b300 100644 --- a/llvm/lib/TableGen/TableGenBackendSkeleton.cpp +++ b/llvm/lib/TableGen/TableGenBackendSkeleton.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/StringRef.h" #include "llvm/TableGen/TableGenBackend.h" |
