summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorNicolai Haehnle <nhaehnle@gmail.com>2018-03-09 12:24:42 +0000
committerNicolai Haehnle <nhaehnle@gmail.com>2018-03-09 12:24:42 +0000
commitfcd6525a4516f0a4d83fd8dcaee25c81ac2c14cd (patch)
tree911a9e9413187f6d3c6c62d0aeba37d78d757f9e /llvm/lib
parent8aa9d5839dbb4d457616a935eb2167ceb0087dfa (diff)
downloadbcm5719-llvm-fcd6525a4516f0a4d83fd8dcaee25c81ac2c14cd.tar.gz
bcm5719-llvm-fcd6525a4516f0a4d83fd8dcaee25c81ac2c14cd.zip
TableGen: Add a defset statement
Allows capturing a list of concrete instantiated defs. This can be combined with foreach to create parallel sets of def instantiations with less repetition in the source. This purpose is largely also served by multiclasses, but in some cases multiclasses can't be used. The motivating example for this change is having a large set of intrinsics, which are generated from the IntrinsicsBackend.td file included by Intrinsics.td, and a corresponding set of instruction selection patterns, which are generated via the backend's .td files. Multiclasses cannot be used to eliminate the redundancy in this case, because a multiclass cannot span both LLVM's common .td files and the backend .td files at the same time. Change-Id: I879e35042dceea542a5e6776fad23c5e0e69e76b Differential revision: https://reviews.llvm.org/D44109 llvm-svn: 327121
Diffstat (limited to 'llvm/lib')
-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