summaryrefslogtreecommitdiffstats
path: root/llvm/lib/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/TableGen')
-rw-r--r--llvm/lib/TableGen/TGLexer.cpp1
-rw-r--r--llvm/lib/TableGen/TGLexer.h2
-rw-r--r--llvm/lib/TableGen/TGParser.cpp92
-rw-r--r--llvm/lib/TableGen/TGParser.h11
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);
OpenPOWER on IntegriCloud