diff options
author | Nicolai Haehnle <nhaehnle@gmail.com> | 2018-03-06 13:49:16 +0000 |
---|---|---|
committer | Nicolai Haehnle <nhaehnle@gmail.com> | 2018-03-06 13:49:16 +0000 |
commit | d34f6843aaffc6a8f6929cce5b589032fd55ede0 (patch) | |
tree | 4de1aaea018b4bc54a57c76241d3ac61d02e94d5 /llvm/lib/TableGen | |
parent | 616635022a7a15bf097e6c23fe2d2f5678491419 (diff) | |
download | bcm5719-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.cpp | 71 | ||||
-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 | 122 |
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; } |