diff options
Diffstat (limited to 'llvm/lib/TableGen')
-rw-r--r-- | llvm/lib/TableGen/TGLexer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGLexer.h | 2 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 92 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGParser.h | 11 |
4 files changed, 97 insertions, 9 deletions
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp index 222aac25f9d..d3dd27cbbb3 100644 --- a/llvm/lib/TableGen/TGLexer.cpp +++ b/llvm/lib/TableGen/TGLexer.cpp @@ -276,6 +276,7 @@ tgtok::TokKind TGLexer::LexIdentifier() { .Case("def", tgtok::Def) .Case("foreach", tgtok::Foreach) .Case("defm", tgtok::Defm) + .Case("defset", tgtok::Defset) .Case("multiclass", tgtok::MultiClass) .Case("field", tgtok::Field) .Case("let", tgtok::Let) diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h index bebe3176d7b..c2222472195 100644 --- a/llvm/lib/TableGen/TGLexer.h +++ b/llvm/lib/TableGen/TGLexer.h @@ -44,7 +44,7 @@ namespace tgtok { // Keywords. Bit, Bits, Class, Code, Dag, Def, Foreach, Defm, Field, In, Int, Let, List, - MultiClass, String, + MultiClass, String, Defset, // !keywords. XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast, diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index a60fa90c190..5d87bfdf19d 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -413,6 +413,8 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){ Records.addDef(std::move(IterRec)); IterRecSave->resolveReferences(); checkConcrete(*IterRecSave); + if (addToDefsets(*IterRecSave)) + return true; return false; } @@ -422,9 +424,9 @@ bool TGParser::ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals){ /// isObjectStart - Return true if this is a valid first token for an Object. static bool isObjectStart(tgtok::TokKind K) { - return K == tgtok::Class || K == tgtok::Def || - K == tgtok::Defm || K == tgtok::Let || - K == tgtok::MultiClass || K == tgtok::Foreach; + return K == tgtok::Class || K == tgtok::Def || K == tgtok::Defm || + K == tgtok::Let || K == tgtok::MultiClass || K == tgtok::Foreach || + K == tgtok::Defset; } /// ParseObjectName - If an object name is specified, return it. Otherwise, @@ -724,6 +726,7 @@ RecTy *TGParser::ParseType() { case tgtok::Dag: Lex.Lex(); return DagRecTy::get(); case tgtok::Id: if (Record *R = ParseClassID()) return RecordRecTy::get(R); + TokError("unknown class name"); return nullptr; case tgtok::Bits: { if (Lex.Lex() != tgtok::less) { // Eat 'bits' @@ -805,8 +808,8 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc, if (Mode == ParseNameMode) return Name; - if (Record *D = Records.getDef(Name->getValue())) - return DefInit::get(D); + if (Init *I = Records.getGlobal(Name->getValue())) + return I; if (Mode == ParseValueMode) { Error(NameLoc, "Variable not defined: '" + Name->getValue() + "'"); @@ -2323,8 +2326,11 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { // for the def that might have been created when resolving // inheritance, values and arguments above. CurRec->resolveReferences(); - if (Loops.empty()) + if (Loops.empty()) { checkConcrete(*CurRec); + if (addToDefsets(*CurRec)) + return true; + } } // If ObjectBody has template arguments, it's an error. @@ -2346,6 +2352,68 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { return false; } +bool TGParser::addToDefsets(Record &R) { + for (DefsetRecord *Defset : Defsets) { + DefInit *I = R.getDefInit(); + if (!I->getType()->typeIsA(Defset->EltTy)) { + PrintError(R.getLoc(), + Twine("adding record of incompatible type '") + + I->getType()->getAsString() + "' to defset"); + PrintNote(Defset->Loc, "to this defset"); + return true; + } + Defset->Elements.push_back(I); + } + return false; +} + +/// ParseDefset - Parse a defset statement. +/// +/// Defset ::= DEFSET Type Id '=' '{' ObjectList '}' +/// +bool TGParser::ParseDefset() { + assert(Lex.getCode() == tgtok::Defset); + Lex.Lex(); // Eat the 'defset' token + + DefsetRecord Defset; + Defset.Loc = Lex.getLoc(); + RecTy *Type = ParseType(); + if (!Type) + return true; + if (!isa<ListRecTy>(Type)) + return Error(Defset.Loc, "expected list type"); + Defset.EltTy = cast<ListRecTy>(Type)->getElementType(); + + if (Lex.getCode() != tgtok::Id) + return TokError("expected identifier"); + StringInit *DeclName = StringInit::get(Lex.getCurStrVal()); + if (Records.getGlobal(DeclName->getValue())) + return TokError("def or global variable of this name already exists"); + + if (Lex.Lex() != tgtok::equal) // Eat the identifier + return TokError("expected '='"); + if (Lex.Lex() != tgtok::l_brace) // Eat the '=' + return TokError("expected '{'"); + SMLoc BraceLoc = Lex.getLoc(); + Lex.Lex(); // Eat the '{' + + Defsets.push_back(&Defset); + bool Err = ParseObjectList(nullptr); + Defsets.pop_back(); + if (Err) + return true; + + if (Lex.getCode() != tgtok::r_brace) { + TokError("expected '}' at end of defset"); + return Error(BraceLoc, "to match this '{'"); + } + Lex.Lex(); // Eat the '}' + + Records.addExtraGlobal(DeclName->getValue(), + ListInit::get(Defset.Elements, Defset.EltTy)); + return false; +} + /// ParseForeach - Parse a for statement. Return the record corresponding /// to it. This returns true on error. /// @@ -2598,7 +2666,8 @@ bool TGParser::ParseMultiClass() { while (Lex.getCode() != tgtok::r_brace) { switch (Lex.getCode()) { default: - return TokError("expected 'let', 'def' or 'defm' in multiclass body"); + return TokError("expected 'let', 'def', 'defm' or 'foreach' in " + "multiclass body"); case tgtok::Let: case tgtok::Def: case tgtok::Defm: @@ -2919,6 +2988,8 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { // inheritance, values and arguments above. CurRec->resolveReferences(); checkConcrete(*CurRec); + if (addToDefsets(*CurRec)) + return true; } } @@ -2939,11 +3010,16 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { bool TGParser::ParseObject(MultiClass *MC) { switch (Lex.getCode()) { default: - return TokError("Expected class, def, defm, multiclass or let definition"); + return TokError("Expected class, def, defm, defset, multiclass, let or " + "foreach"); case tgtok::Let: return ParseTopLevelLet(MC); case tgtok::Def: return ParseDef(MC); case tgtok::Foreach: return ParseForeach(MC); case tgtok::Defm: return ParseDefm(MC); + case tgtok::Defset: + if (MC) + return TokError("defset is not allowed inside multiclass"); + return ParseDefset(); case tgtok::Class: return ParseClass(); case tgtok::MultiClass: return ParseMultiClass(); } diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h index 03fbc14047e..d4ee5be5d98 100644 --- a/llvm/lib/TableGen/TGParser.h +++ b/llvm/lib/TableGen/TGParser.h @@ -51,6 +51,12 @@ namespace llvm { : IterVar(IVar), ListValue(LValue) {} }; + struct DefsetRecord { + SMLoc Loc; + RecTy *EltTy; + SmallVector<Init *, 16> Elements; + }; + class TGParser { TGLexer Lex; std::vector<SmallVector<LetRecord, 4>> LetStack; @@ -61,6 +67,8 @@ class TGParser { typedef std::vector<ForeachLoop> LoopVector; LoopVector Loops; + SmallVector<DefsetRecord *, 2> Defsets; + /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the /// current value. MultiClass *CurMultiClass; @@ -121,6 +129,8 @@ private: // Semantic analysis methods. bool ProcessForeachDefs(Record *CurRec, SMLoc Loc); bool ProcessForeachDefs(Record *CurRec, SMLoc Loc, IterSet &IterVals); + bool addToDefsets(Record &R); + private: // Parser methods. bool ParseObjectList(MultiClass *MC = nullptr); bool ParseObject(MultiClass *MC); @@ -140,6 +150,7 @@ private: // Parser methods. SMLoc DefmPrefixLoc); bool ParseDefm(MultiClass *CurMultiClass); bool ParseDef(MultiClass *CurMultiClass); + bool ParseDefset(); bool ParseForeach(MultiClass *CurMultiClass); bool ParseTopLevelLet(MultiClass *CurMultiClass); void ParseLetList(SmallVectorImpl<LetRecord> &Result); |