summaryrefslogtreecommitdiffstats
path: root/llvm/lib/TableGen
diff options
context:
space:
mode:
authorNicolai Haehnle <nhaehnle@gmail.com>2018-03-06 13:49:16 +0000
committerNicolai Haehnle <nhaehnle@gmail.com>2018-03-06 13:49:16 +0000
commitd34f6843aaffc6a8f6929cce5b589032fd55ede0 (patch)
tree4de1aaea018b4bc54a57c76241d3ac61d02e94d5 /llvm/lib/TableGen
parent616635022a7a15bf097e6c23fe2d2f5678491419 (diff)
downloadbcm5719-llvm-d34f6843aaffc6a8f6929cce5b589032fd55ede0.tar.gz
bcm5719-llvm-d34f6843aaffc6a8f6929cce5b589032fd55ede0.zip
TableGen: Add !foldl operation
Change-Id: I63d67bf6e0b315e2d3360e47e3b62c9517f38987 llvm-svn: 326790
Diffstat (limited to 'llvm/lib/TableGen')
-rw-r--r--llvm/lib/TableGen/Record.cpp71
-rw-r--r--llvm/lib/TableGen/TGLexer.cpp1
-rw-r--r--llvm/lib/TableGen/TGLexer.h2
-rw-r--r--llvm/lib/TableGen/TGParser.cpp122
4 files changed, 193 insertions, 3 deletions
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 2fe58dd61d0..c1344aea4eb 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -1160,6 +1160,77 @@ std::string TernOpInit::getAsString() const {
RHS->getAsString() + ")";
}
+static void ProfileFoldOpInit(FoldingSetNodeID &ID, Init *A, Init *B,
+ Init *Start, Init *List, Init *Expr,
+ RecTy *Type) {
+ ID.AddPointer(Start);
+ ID.AddPointer(List);
+ ID.AddPointer(A);
+ ID.AddPointer(B);
+ ID.AddPointer(Expr);
+ ID.AddPointer(Type);
+}
+
+FoldOpInit *FoldOpInit::get(Init *Start, Init *List, Init *A, Init *B,
+ Init *Expr, RecTy *Type) {
+ static FoldingSet<FoldOpInit> ThePool;
+
+ FoldingSetNodeID ID;
+ ProfileFoldOpInit(ID, Start, List, A, B, Expr, Type);
+
+ void *IP = nullptr;
+ if (FoldOpInit *I = ThePool.FindNodeOrInsertPos(ID, IP))
+ return I;
+
+ FoldOpInit *I = new (Allocator) FoldOpInit(Start, List, A, B, Expr, Type);
+ ThePool.InsertNode(I, IP);
+ return I;
+}
+
+void FoldOpInit::Profile(FoldingSetNodeID &ID) const {
+ ProfileFoldOpInit(ID, Start, List, A, B, Expr, getType());
+}
+
+Init *FoldOpInit::Fold(Record *CurRec) const {
+ if (ListInit *LI = dyn_cast<ListInit>(List)) {
+ Init *Accum = Start;
+ for (Init *Elt : *LI) {
+ MapResolver R(CurRec);
+ R.set(A, Accum);
+ R.set(B, Elt);
+ Accum = Expr->resolveReferences(R);
+ }
+ return Accum;
+ }
+ return const_cast<FoldOpInit *>(this);
+}
+
+Init *FoldOpInit::resolveReferences(Resolver &R) const {
+ Init *NewStart = Start->resolveReferences(R);
+ Init *NewList = List->resolveReferences(R);
+ ShadowResolver SR(R);
+ SR.addShadow(A);
+ SR.addShadow(B);
+ Init *NewExpr = Expr->resolveReferences(SR);
+
+ if (Start == NewStart && List == NewList && Expr == NewExpr)
+ return const_cast<FoldOpInit *>(this);
+
+ return get(NewStart, NewList, A, B, NewExpr, getType())
+ ->Fold(R.getCurrentRecord());
+}
+
+Init *FoldOpInit::getBit(unsigned Bit) const {
+ return VarBitInit::get(const_cast<FoldOpInit *>(this), Bit);
+}
+
+std::string FoldOpInit::getAsString() const {
+ return (Twine("!foldl(") + Start->getAsString() + ", " + List->getAsString() +
+ ", " + A->getAsUnquotedString() + ", " + B->getAsUnquotedString() +
+ ", " + Expr->getAsString() + ")")
+ .str();
+}
+
RecTy *TypedInit::getFieldType(StringInit *FieldName) const {
if (RecordRecTy *RecordType = dyn_cast<RecordRecTy>(getType())) {
for (Record *Rec : RecordType->getClasses()) {
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index bc03055eb23..9d8d693f975 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -480,6 +480,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("cast", tgtok::XCast)
.Case("empty", tgtok::XEmpty)
.Case("subst", tgtok::XSubst)
+ .Case("foldl", tgtok::XFoldl)
.Case("foreach", tgtok::XForEach)
.Case("listconcat", tgtok::XListConcat)
.Case("strconcat", tgtok::XStrConcat)
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index 342eb76fc0f..cfed08ec4d4 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -48,7 +48,7 @@ namespace tgtok {
// !keywords.
XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast,
- XSubst, XForEach, XHead, XTail, XSize, XEmpty, XIf, XEq,
+ XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq,
// Integer value.
IntVal,
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 31b2c008ba4..488d1c8d82a 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -1232,6 +1232,123 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec,
CurMultiClass);
}
+
+ case tgtok::XFoldl: {
+ // Value ::= !foldl '(' Id ',' Id ',' Value ',' Value ',' Value ')'
+ Lex.Lex(); // eat the operation
+ if (Lex.getCode() != tgtok::l_paren) {
+ TokError("expected '(' after !foldl");
+ return nullptr;
+ }
+ Lex.Lex(); // eat the '('
+
+ Init *StartUntyped = ParseValue(CurRec);
+ if (!StartUntyped)
+ return nullptr;
+
+ TypedInit *Start = dyn_cast<TypedInit>(StartUntyped);
+ if (!Start) {
+ TokError(Twine("could not get type of !foldl start: '") +
+ StartUntyped->getAsString() + "'");
+ return nullptr;
+ }
+
+ if (Lex.getCode() != tgtok::comma) {
+ TokError("expected ',' in !foldl");
+ return nullptr;
+ }
+ Lex.Lex(); // eat the ','
+
+ Init *ListUntyped = ParseValue(CurRec);
+ if (!ListUntyped)
+ return nullptr;
+
+ TypedInit *List = dyn_cast<TypedInit>(ListUntyped);
+ if (!List) {
+ TokError(Twine("could not get type of !foldl list: '") +
+ ListUntyped->getAsString() + "'");
+ return nullptr;
+ }
+
+ ListRecTy *ListType = dyn_cast<ListRecTy>(List->getType());
+ if (!ListType) {
+ TokError(Twine("!foldl list must be a list, but is of type '") +
+ List->getType()->getAsString());
+ return nullptr;
+ }
+
+ if (Lex.getCode() != tgtok::comma) {
+ TokError("expected ',' in !foldl");
+ return nullptr;
+ }
+
+ if (Lex.Lex() != tgtok::Id) { // eat the ','
+ TokError("third argument of !foldl must be an identifier");
+ return nullptr;
+ }
+
+ Init *A = StringInit::get(Lex.getCurStrVal());
+ if (CurRec->getValue(A)) {
+ TokError((Twine("left !foldl variable '") + A->getAsString() +
+ "' already defined")
+ .str());
+ return nullptr;
+ }
+
+ if (Lex.Lex() != tgtok::comma) { // eat the id
+ TokError("expected ',' in !foldl");
+ return nullptr;
+ }
+
+ if (Lex.Lex() != tgtok::Id) { // eat the ','
+ TokError("fourth argument of !foldl must be an identifier");
+ return nullptr;
+ }
+
+ Init *B = StringInit::get(Lex.getCurStrVal());
+ if (CurRec->getValue(B)) {
+ TokError((Twine("right !foldl variable '") + B->getAsString() +
+ "' already defined")
+ .str());
+ return nullptr;
+ }
+
+ if (Lex.Lex() != tgtok::comma) { // eat the id
+ TokError("expected ',' in !foldl");
+ return nullptr;
+ }
+ Lex.Lex(); // eat the ','
+
+ CurRec->addValue(RecordVal(A, Start->getType(), false));
+ CurRec->addValue(RecordVal(B, ListType->getElementType(), false));
+ Init *ExprUntyped = ParseValue(CurRec);
+ CurRec->removeValue(A);
+ CurRec->removeValue(B);
+ if (!ExprUntyped)
+ return nullptr;
+
+ TypedInit *Expr = dyn_cast<TypedInit>(ExprUntyped);
+ if (!Expr) {
+ TokError("could not get type of !foldl expression");
+ return nullptr;
+ }
+
+ if (Expr->getType() != Start->getType()) {
+ TokError(Twine("!foldl expression must be of same type as start (") +
+ Start->getType()->getAsString() + "), but is of type " +
+ Expr->getType()->getAsString());
+ return nullptr;
+ }
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in fold operator");
+ return nullptr;
+ }
+ Lex.Lex(); // eat the ')'
+
+ return FoldOpInit::get(Start, List, A, B, Expr, Start->getType())
+ ->Fold(CurRec);
+ }
}
}
@@ -1590,6 +1707,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
case tgtok::XListConcat:
case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
case tgtok::XIf:
+ case tgtok::XFoldl:
case tgtok::XForEach:
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
return ParseOperation(CurRec, ItemType);
@@ -1697,7 +1815,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
TypedInit *RHS = nullptr;
Lex.Lex(); // Eat the '#'.
- switch (Lex.getCode()) {
+ switch (Lex.getCode()) {
case tgtok::colon:
case tgtok::semi:
case tgtok::l_brace:
@@ -2579,7 +2697,7 @@ Record *TGParser::InstantiateMulticlassDef(MultiClass &MC, Record *DefProto,
// Ensure redefinition doesn't happen.
if (Records.getDef(CurRec->getNameInitAsString())) {
Error(DefmPrefixRange.Start, "def '" + CurRec->getNameInitAsString() +
- "' already defined, instantiating defm with subdef '" +
+ "' already defined, instantiating defm with subdef '" +
DefProto->getNameInitAsString() + "'");
return nullptr;
}
OpenPOWER on IntegriCloud