diff options
author | Nicolai Haehnle <nhaehnle@gmail.com> | 2018-03-05 15:21:04 +0000 |
---|---|---|
committer | Nicolai Haehnle <nhaehnle@gmail.com> | 2018-03-05 15:21:04 +0000 |
commit | 8ebf7e4dfa222ae04e063f1c1e0bb5c945331ac7 (patch) | |
tree | e2e97ea9e1484e355a5569bca9534813c4dee71e /llvm/lib/TableGen/TGParser.cpp | |
parent | 0b0eaf7ee2bc86108ae0628cb4fbdb5e52c25cfb (diff) | |
download | bcm5719-llvm-8ebf7e4dfa222ae04e063f1c1e0bb5c945331ac7.tar.gz bcm5719-llvm-8ebf7e4dfa222ae04e063f1c1e0bb5c945331ac7.zip |
TableGen: Reimplement !foreach using the resolving mechanism
Summary:
This changes the syntax of !foreach so that the first "parameter" is
a new syntactic variable: !foreach(x, lst, expr) will define the
variable x within the scope of expr, and evaluation of the !foreach
will substitute elements of the given list (or dag) for x in expr.
Aside from leading to a nicer syntax, this allows more complex
expressions where x is deeply nested, or even constant expressions
in which x does not occur at all.
!foreach is currently not actually used anywhere in trunk, but I
plan to use it in the AMDGPU backend. If out-of-tree targets are
using it, they can adjust to the new syntax very easily.
Change-Id: Ib966694d8ab6542279d6bc358b6f4d767945a805
Reviewers: arsenm, craig.topper, tra, MartinO
Subscribers: wdng, llvm-commits, tpr
Differential Revision: https://reviews.llvm.org/D43651
llvm-svn: 326705
Diffstat (limited to 'llvm/lib/TableGen/TGParser.cpp')
-rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 123 |
1 files changed, 102 insertions, 21 deletions
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index 3ef65938282..b42580c9cda 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -985,8 +985,109 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { return nullptr; } + case tgtok::XForEach: { // Value ::= !foreach '(' Id ',' Value ',' Value ')' + SMLoc OpLoc = Lex.getLoc(); + Lex.Lex(); // eat the operation + if (Lex.getCode() != tgtok::l_paren) { + TokError("expected '(' after !foreach"); + return nullptr; + } + + if (Lex.Lex() != tgtok::Id) { // eat the '(' + TokError("first argument of !foreach must be an identifier"); + return nullptr; + } + + Init *LHS = StringInit::get(Lex.getCurStrVal()); + + if (CurRec->getValue(LHS)) { + TokError((Twine("iteration variable '") + LHS->getAsString() + + "' already defined") + .str()); + return nullptr; + } + + if (Lex.Lex() != tgtok::comma) { // eat the id + TokError("expected ',' in ternary operator"); + return nullptr; + } + Lex.Lex(); // eat the ',' + + Init *MHS = ParseValue(CurRec); + if (!MHS) + return nullptr; + + if (Lex.getCode() != tgtok::comma) { + TokError("expected ',' in ternary operator"); + return nullptr; + } + Lex.Lex(); // eat the ',' + + TypedInit *MHSt = dyn_cast<TypedInit>(MHS); + if (!MHSt) { + TokError("could not get type of !foreach input"); + return nullptr; + } + + RecTy *InEltType = nullptr; + RecTy *OutEltType = nullptr; + bool IsDAG = false; + + if (ListRecTy *InListTy = dyn_cast<ListRecTy>(MHSt->getType())) { + InEltType = InListTy->getElementType(); + if (ItemType) { + if (ListRecTy *OutListTy = dyn_cast<ListRecTy>(ItemType)) { + OutEltType = OutListTy->getElementType(); + } else { + Error(OpLoc, + "expected value of type '" + Twine(ItemType->getAsString()) + + "', but got !foreach of list type"); + return nullptr; + } + } + } else if (DagRecTy *InDagTy = dyn_cast<DagRecTy>(MHSt->getType())) { + InEltType = InDagTy; + if (ItemType && !isa<DagRecTy>(ItemType)) { + Error(OpLoc, + "expected value of type '" + Twine(ItemType->getAsString()) + + "', but got !foreach of dag type"); + return nullptr; + } + IsDAG = true; + } else { + TokError("!foreach must have list or dag input"); + return nullptr; + } + + CurRec->addValue(RecordVal(LHS, InEltType, false)); + Init *RHS = ParseValue(CurRec, OutEltType); + CurRec->removeValue(LHS); + if (!RHS) + return nullptr; + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in binary operator"); + return nullptr; + } + Lex.Lex(); // eat the ')' + + RecTy *OutType; + if (IsDAG) { + OutType = InEltType; + } else { + TypedInit *RHSt = dyn_cast<TypedInit>(RHS); + if (!RHSt) { + TokError("could not get type of !foreach result"); + return nullptr; + } + OutType = RHSt->getType()->getListTy(); + } + + return (TernOpInit::get(TernOpInit::FOREACH, LHS, MHS, RHS, OutType)) + ->Fold(CurRec, CurMultiClass); + } + case tgtok::XIf: - case tgtok::XForEach: case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' TernOpInit::TernaryOp Code; RecTy *Type = nullptr; @@ -998,9 +1099,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XIf: Code = TernOpInit::IF; break; - case tgtok::XForEach: - Code = TernOpInit::FOREACH; - break; case tgtok::XSubst: Code = TernOpInit::SUBST; break; @@ -1081,23 +1179,6 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { } break; } - case tgtok::XForEach: { - TypedInit *MHSt = dyn_cast<TypedInit>(MHS); - if (!MHSt) { - TokError("could not get type for !foreach"); - return nullptr; - } - Type = MHSt->getType(); - if (isa<ListRecTy>(Type)) { - TypedInit *RHSt = dyn_cast<TypedInit>(RHS); - if (!RHSt) { - TokError("could not get type of !foreach list elements"); - return nullptr; - } - Type = RHSt->getType()->getListTy(); - } - break; - } case tgtok::XSubst: { TypedInit *RHSt = dyn_cast<TypedInit>(RHS); if (!RHSt) { |