summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/TableGenFundamentals.html4
-rw-r--r--test/TableGen/TargetInstrSpec.td97
-rw-r--r--test/TableGen/foreach.td31
-rw-r--r--utils/TableGen/Record.cpp280
-rw-r--r--utils/TableGen/Record.h118
-rw-r--r--utils/TableGen/TGLexer.cpp2
-rw-r--r--utils/TableGen/TGLexer.h2
-rw-r--r--utils/TableGen/TGParser.cpp28
8 files changed, 374 insertions, 188 deletions
diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html
index 0186453f36..9607f9ea9e 100644
--- a/docs/TableGenFundamentals.html
+++ b/docs/TableGenFundamentals.html
@@ -407,6 +407,10 @@ aborts with an error. </dd>
<dt><tt>!subst(a, b, c)</tt></dt>
<dd>If 'a' and 'b' are of string type or are symbol references, substitute
'b' for 'a' in 'c.' This operation is analogous to $(subst) in GNU make.</dd>
+<dt><tt>!foreach(a, b, c)</tt></dt>
+ <dd>For each member 'b' of dag or list 'a' apply operator 'c.' 'b' is a
+dummy variable that should be declared as a member variable of an instantiated
+class. This operation is analogous to $(foreach) in GNU make.</dd>
</dl>
<p>Note that all of the values have rules specifying how they convert to values
diff --git a/test/TableGen/TargetInstrSpec.td b/test/TableGen/TargetInstrSpec.td
new file mode 100644
index 0000000000..852551d1fe
--- /dev/null
+++ b/test/TableGen/TargetInstrSpec.td
@@ -0,0 +1,97 @@
+// RUN: tblgen %s | grep {[(set VR128:$dst, (int_x86_sse2_add_pd VR128:$src1, VR128:$src2))]} | count 1
+// RUN: tblgen %s | grep {[(set VR128:$dst, (int_x86_sse2_add_ps VR128:$src1, VR128:$src2))]} | count 2
+
+class ValueType<int size, int value> {
+ int Size = size;
+ int Value = value;
+}
+
+def v2i64 : ValueType<128, 22>; // 2 x i64 vector value
+def v2f64 : ValueType<128, 28>; // 2 x f64 vector value
+
+class Intrinsic<string name> {
+ string Name = name;
+}
+
+class Inst<bits<8> opcode, dag oopnds, dag iopnds, string asmstr,
+ list<dag> pattern> {
+ bits<8> Opcode = opcode;
+ dag OutOperands = oopnds;
+ dag InOperands = iopnds;
+ string AssemblyString = asmstr;
+ list<dag> Pattern = pattern;
+}
+
+def ops;
+def outs;
+def ins;
+
+def set;
+
+// Define registers
+class Register<string n> {
+ string Name = n;
+}
+
+class RegisterClass<list<ValueType> regTypes, list<Register> regList> {
+ list<ValueType> RegTypes = regTypes;
+ list<Register> MemberList = regList;
+}
+
+def XMM0: Register<"xmm0">;
+def XMM1: Register<"xmm1">;
+def XMM2: Register<"xmm2">;
+def XMM3: Register<"xmm3">;
+def XMM4: Register<"xmm4">;
+def XMM5: Register<"xmm5">;
+def XMM6: Register<"xmm6">;
+def XMM7: Register<"xmm7">;
+def XMM8: Register<"xmm8">;
+def XMM9: Register<"xmm9">;
+def XMM10: Register<"xmm10">;
+def XMM11: Register<"xmm11">;
+def XMM12: Register<"xmm12">;
+def XMM13: Register<"xmm13">;
+def XMM14: Register<"xmm14">;
+def XMM15: Register<"xmm15">;
+
+def VR128 : RegisterClass<[v2i64, v2f64],
+ [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
+ XMM8, XMM9, XMM10, XMM11,
+ XMM12, XMM13, XMM14, XMM15]>;
+
+// Dummy for subst
+def REGCLASS : RegisterClass<[], []>;
+
+class decls {
+ // Dummy for foreach
+ dag pattern;
+ int operand;
+}
+
+def Decls : decls;
+
+// Define intrinsics
+def int_x86_sse2_add_ps : Intrinsic<"addps">;
+def int_x86_sse2_add_pd : Intrinsic<"addpd">;
+def INTRINSIC : Intrinsic<"Dummy">;
+
+multiclass arith<bits<8> opcode, string asmstr, string intr, list<dag> patterns> {
+ def PS : Inst<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
+ !strconcat(asmstr, "\t$dst, $src1, $src2"),
+ !foreach(Decls.pattern, patterns,
+ !foreach(Decls.operand, Decls.pattern,
+ !subst(INTRINSIC, !cast<Intrinsic>(!subst("SUFFIX", "_ps", intr)),
+ !subst(REGCLASS, VR128, Decls.operand))))>;
+
+ def PD : Inst<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
+ !strconcat(asmstr, "\t$dst, $src1, $src2"),
+ !foreach(Decls.pattern, patterns,
+ !foreach(Decls.operand, Decls.pattern,
+ !subst(INTRINSIC, !cast<Intrinsic>(!subst("SUFFIX", "_pd", intr)),
+ !subst(REGCLASS, VR128, Decls.operand))))>;
+}
+
+defm ADD : arith<0x58, "add", "int_x86_sse2_addSUFFIX",
+ [(set REGCLASS:$dst, (INTRINSIC REGCLASS:$src1, REGCLASS:$src2))]>;
+
diff --git a/test/TableGen/foreach.td b/test/TableGen/foreach.td
new file mode 100644
index 0000000000..589520a6f0
--- /dev/null
+++ b/test/TableGen/foreach.td
@@ -0,0 +1,31 @@
+// RUN: tblgen %s | grep {Jr} | count 2
+// RUN: tblgen %s | grep {Sr} | count 2
+// RUN: tblgen %s | not grep {NAME}
+
+// Variables for foreach
+class decls {
+ string name;
+}
+
+def Decls : decls;
+
+class A<list<string> names> {
+ list<string> Names = names;
+}
+
+class B<list<string> names> : A<!foreach(Decls.name, names, !strconcat(Decls.name, ", Sr."))>;
+
+class C<list<string> names> : A<!foreach(Decls.name, names, !strconcat(Decls.name, ", Jr."))>;
+
+class D<list<string> names> : A<!foreach(Decls.name, names, !subst("NAME", "John Smith", Decls.name))>;
+
+class Names {
+ list<string> values = ["Ken Griffey", "Seymour Cray"];
+}
+
+def People : Names;
+
+def Seniors : B<People.values>;
+def Juniors : C<People.values>;
+def Smiths : D<["NAME", "Jane Smith"]>;
+def Unprocessed : D<People.values>;
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
index baff05c6ef..ade17026fb 100644
--- a/utils/TableGen/Record.cpp
+++ b/utils/TableGen/Record.cpp
@@ -678,6 +678,144 @@ std::string BinOpInit::getAsString() const {
return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
}
+static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
+ Record *CurRec, MultiClass *CurMultiClass);
+
+static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg,
+ RecTy *Type, Record *CurRec,
+ MultiClass *CurMultiClass) {
+ std::vector<Init *> NewOperands;
+
+ TypedInit *TArg = dynamic_cast<TypedInit*>(Arg);
+
+ // If this is a dag, recurse
+ if (TArg && TArg->getType()->getAsString() == "dag") {
+ Init *Result = ForeachHelper(LHS, Arg, RHSo, Type,
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ return Result;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ for (int i = 0; i < RHSo->getNumOperands(); ++i) {
+ OpInit *RHSoo = dynamic_cast<OpInit*>(RHSo->getOperand(i));
+
+ if (RHSoo) {
+ Init *Result = EvaluateOperation(RHSoo, LHS, Arg,
+ Type, CurRec, CurMultiClass);
+ if (Result != 0) {
+ NewOperands.push_back(Result);
+ }
+ else {
+ NewOperands.push_back(Arg);
+ }
+ }
+ else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
+ NewOperands.push_back(Arg);
+ }
+ else {
+ NewOperands.push_back(RHSo->getOperand(i));
+ }
+ }
+
+ // Now run the operator and use its result as the new leaf
+ OpInit *NewOp = RHSo->clone(NewOperands);
+ Init *NewVal = NewOp->Fold(CurRec, CurMultiClass);
+ if (NewVal != NewOp) {
+ delete NewOp;
+ return NewVal;
+ }
+ return 0;
+}
+
+static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
+ Record *CurRec, MultiClass *CurMultiClass) {
+ DagInit *MHSd = dynamic_cast<DagInit*>(MHS);
+ ListInit *MHSl = dynamic_cast<ListInit*>(MHS);
+
+ DagRecTy *DagType = dynamic_cast<DagRecTy*>(Type);
+ ListRecTy *ListType = dynamic_cast<ListRecTy*>(Type);
+
+ OpInit *RHSo = dynamic_cast<OpInit*>(RHS);
+
+ if (!RHSo) {
+ cerr << "!foreach requires an operator\n";
+ assert(0 && "No operator for !foreach");
+ }
+
+ TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
+
+ if (!LHSt) {
+ cerr << "!foreach requires typed variable\n";
+ assert(0 && "No typed variable for !foreach");
+ }
+
+ if (MHSd && DagType || MHSl && ListType) {
+ if (MHSd) {
+ Init *Val = MHSd->getOperator();
+ Init *Result = EvaluateOperation(RHSo, LHS, Val,
+ Type, CurRec, CurMultiClass);
+ if (Result != 0) {
+ Val = Result;
+ }
+
+ std::vector<std::pair<Init *, std::string> > args;
+ for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
+ Init *Arg;
+ std::string ArgName;
+ Arg = MHSd->getArg(i);
+ ArgName = MHSd->getArgName(i);
+
+ // Process args
+ Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type,
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ Arg = Result;
+ }
+
+ // TODO: Process arg names
+ args.push_back(std::make_pair(Arg, ArgName));
+ }
+
+ return new DagInit(Val, "", args);
+ }
+ if (MHSl) {
+ std::vector<Init *> NewOperands;
+ std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
+
+ for (ListInit::iterator li = NewList.begin(),
+ liend = NewList.end();
+ li != liend;
+ ++li) {
+ Init *Item = *li;
+ NewOperands.clear();
+ for(int i = 0; i < RHSo->getNumOperands(); ++i) {
+ // First, replace the foreach variable with the list item
+ if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
+ NewOperands.push_back(Item);
+ }
+ else {
+ NewOperands.push_back(RHSo->getOperand(i));
+ }
+ }
+
+ // Now run the operator and use its result as the new list item
+ OpInit *NewOp = RHSo->clone(NewOperands);
+ Init *NewItem = NewOp->Fold(CurRec, CurMultiClass);
+ if (NewItem != NewOp) {
+ *li = NewItem;
+ delete NewOp;
+ }
+ }
+ return new ListInit(NewList);
+ }
+ }
+ return 0;
+}
+
Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
switch (getOpcode()) {
default: assert(0 && "Unknown binop");
@@ -729,144 +867,10 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
}
case FOREACH: {
- DagInit *MHSd = dynamic_cast<DagInit*>(MHS);
- ListInit *MHSl = dynamic_cast<ListInit*>(MHS);
-
- DagRecTy *DagType = dynamic_cast<DagRecTy*>(getType());
- ListRecTy *ListType = dynamic_cast<ListRecTy*>(getType());
-
- OpInit *RHSo = dynamic_cast<OpInit*>(RHS);
-
- if (!RHSo) {
- cerr << "!foreach requires an operator\n";
- assert(0 && "No operator for !foreach");
- }
-
- TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
-
- if (!LHSt) {
- cerr << "!foreach requires typed variable\n";
- assert(0 && "No typed variable for !foreach");
- }
-
- if (MHSd && DagType || MHSl && ListType) {
- std::vector<Init *> NewOperands;
- if (MHSd) {
- Init *Val = MHSd->getOperator();
- TypedInit *TVal = dynamic_cast<TypedInit*>(Val);
-
- if (TVal && TVal->getType()->typeIsConvertibleTo(LHSt->getType())) {
-
- // First, replace the foreach variable with the DAG leaf
- for (int i = 0; i < RHSo->getNumOperands(); ++i) {
- if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
- NewOperands.push_back(Val);
- }
- else {
- NewOperands.push_back(RHSo->getOperand(i));
- }
- }
-
- // Now run the operator and use its result as the new leaf
- OpInit *NewOp = RHSo->clone(NewOperands);
- Val = NewOp->Fold(CurRec, CurMultiClass);
- if (Val != NewOp) {
- delete NewOp;
- }
- }
-
- std::vector<std::pair<Init *, std::string> > args;
- for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
- Init *Arg;
- std::string ArgName;
- Arg = MHSd->getArg(i);
- ArgName = MHSd->getArgName(i);
-
- TypedInit *TArg = dynamic_cast<TypedInit*>(Arg);
-
- if (TArg && TArg->getType()->typeIsConvertibleTo(LHSt->getType())) {
- NewOperands.clear();
-
- // First, replace the foreach variable with the DAG leaf
- for (int i = 0; i < RHSo->getNumOperands(); ++i) {
- if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
- NewOperands.push_back(Arg);
- }
- else {
- NewOperands.push_back(RHSo->getOperand(i));
- }
- }
-
- // Now run the operator and use its result as the new leaf
- OpInit *NewOp = RHSo->clone(NewOperands);
- Arg = NewOp->Fold(CurRec, CurMultiClass);
- if (Arg != NewOp) {
- delete NewOp;
- }
- }
-
- if (LHSt->getType()->getAsString() == "string") {
- NewOperands.clear();
-
- // First, replace the foreach variable with the DAG leaf
- for (int i = 0; i < RHSo->getNumOperands(); ++i) {
- if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
- NewOperands.push_back(new StringInit(ArgName));
- }
- else {
- NewOperands.push_back(RHSo->getOperand(i));
- }
- }
-
- // Now run the operator and use its result as the new leaf
- OpInit *NewOp = RHSo->clone(NewOperands);
- Init *ArgNameInit = NewOp->Fold(CurRec, CurMultiClass);
- StringInit *SArgNameInit = dynamic_cast<StringInit*>(ArgNameInit);
- if (SArgNameInit) {
- ArgName = SArgNameInit->getValue();
- }
- if (ArgNameInit != NewOp) {
- delete NewOp;
- }
- delete ArgNameInit;
- }
-
- args.push_back(std::make_pair(Arg, ArgName));
- }
-
- return new DagInit(Val, "", args);
- }
- if (MHSl) {
- std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
-
- for (ListInit::iterator li = NewList.begin(),
- liend = NewList.end();
- li != liend;
- ++li) {
- Init *Item = *li;
- TypedInit *TItem = dynamic_cast<TypedInit*>(Item);
- if (TItem && TItem->getType()->typeIsConvertibleTo(LHSt->getType())) {
- // First, replace the foreach variable with the list item
- for (int i = 0; i < RHSo->getNumOperands(); ++i) {
- if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
- NewOperands.push_back(Item);
- }
- else {
- NewOperands.push_back(RHSo->getOperand(i));
- }
- }
-
- // Now run the operator and use its result as the new list item
- OpInit *NewOp = RHSo->clone(NewOperands);
- *li = NewOp->Fold(CurRec, CurMultiClass);
- if (*li != NewOp) {
- delete NewOp;
- }
- }
- }
-
- return new ListInit(NewList);
- }
+ Init *Result = ForeachHelper(LHS, MHS, RHS, getType(),
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ return Result;
}
break;
}
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index 59b6348a36..c37f6e6207 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -517,6 +517,33 @@ inline std::ostream &operator<<(std::ostream &OS, const Init &I) {
I.print(OS); return OS;
}
+/// TypedInit - This is the common super-class of types that have a specific,
+/// explicit, type.
+///
+class TypedInit : public Init {
+ RecTy *Ty;
+public:
+ explicit TypedInit(RecTy *T) : Ty(T) {}
+
+ RecTy *getType() const { return Ty; }
+
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+ virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements);
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return null.
+ ///
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) = 0;
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) = 0;
+};
+
/// UnsetInit - ? - Represents an uninitialized value
///
@@ -609,10 +636,10 @@ public:
/// StringInit - "foo" - Represent an initialization by a string value.
///
-class StringInit : public Init {
+class StringInit : public TypedInit {
std::string Value;
public:
- explicit StringInit(const std::string &V) : Value(V) {}
+ explicit StringInit(const std::string &V) : TypedInit(new StringRecTy), Value(V) {}
const std::string &getValue() const { return Value; }
@@ -621,6 +648,25 @@ public:
}
virtual std::string getAsString() const { return "\"" + Value + "\""; }
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return null.
+ ///
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ assert(0 && "Illegal bit reference off string");
+ return 0;
+ }
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) {
+ assert(0 && "Illegal element reference off string");
+ return 0;
+ }
};
/// CodeInit - "[{...}]" - Represent a code fragment.
@@ -684,33 +730,6 @@ public:
};
-/// TypedInit - This is the common super-class of types that have a specific,
-/// explicit, type.
-///
-class TypedInit : public Init {
- RecTy *Ty;
-public:
- explicit TypedInit(RecTy *T) : Ty(T) {}
-
- RecTy *getType() const { return Ty; }
-
- virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
- virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements);
-
- /// resolveBitReference - This method is used to implement
- /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
- /// simply return the resolved value, otherwise we return null.
- ///
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) = 0;
-
- /// resolveListElementReference - This method is used to implement
- /// VarListElementInit::resolveReferences. If the list element is resolvable
- /// now, we return the resolved value, otherwise we return null.
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) = 0;
-};
-
/// OpInit - Base class for operators
///
class OpInit : public TypedInit {
@@ -957,10 +976,10 @@ public:
/// DefInit - AL - Represent a reference to a 'def' in the description
///
-class DefInit : public Init {
+class DefInit : public TypedInit {
Record *Def;
public:
- explicit DefInit(Record *D) : Def(D) {}
+ explicit DefInit(Record *D) : TypedInit(new RecordRecTy(D)), Def(D) {}
virtual Init *convertInitializerTo(RecTy *Ty) {
return Ty->convertValue(this);
@@ -974,6 +993,25 @@ public:
virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
virtual std::string getAsString() const;
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return null.
+ ///
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ assert(0 && "Illegal bit reference off def");
+ return 0;
+ }
+
+ /// resolveListElementReference - This method is used to implement
+ /// VarListElementInit::resolveReferences. If the list element is resolvable
+ /// now, we return the resolved value, otherwise we return null.
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) {
+ assert(0 && "Illegal element reference off def");
+ return 0;
+ }
};
@@ -1008,7 +1046,7 @@ public:
/// to have at least one value then a (possibly empty) list of arguments. Each
/// argument can have a name associated with it.
///
-class DagInit : public Init {
+class DagInit : public TypedInit {
Init *Val;
std::string ValName;
std::vector<Init*> Args;
@@ -1016,7 +1054,7 @@ class DagInit : public Init {
public:
DagInit(Init *V, std::string VN,
const std::vector<std::pair<Init*, std::string> > &args)
- : Val(V), ValName(VN) {
+ : TypedInit(new DagRecTy), Val(V), ValName(VN) {
Args.reserve(args.size());
ArgNames.reserve(args.size());
for (unsigned i = 0, e = args.size(); i != e; ++i) {
@@ -1026,7 +1064,7 @@ public:
}
DagInit(Init *V, std::string VN, const std::vector<Init*> &args,
const std::vector<std::string> &argNames)
- : Val(V), ValName(VN), Args(args), ArgNames(argNames) {
+ : TypedInit(new DagRecTy), Val(V), ValName(VN), Args(args), ArgNames(argNames) {
}
virtual Init *convertInitializerTo(RecTy *Ty) {
@@ -1077,6 +1115,18 @@ public:
inline size_t name_size () const { return ArgNames.size(); }
inline bool name_empty() const { return ArgNames.empty(); }
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) {
+ assert(0 && "Illegal bit reference off dag");
+ return 0;
+ }
+
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) {
+ assert(0 && "Illegal element reference off dag");
+ return 0;
+ }
+
};
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp
index 264be4b98b..6215a7267f 100644
--- a/utils/TableGen/TGLexer.cpp
+++ b/utils/TableGen/TGLexer.cpp
@@ -448,7 +448,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat;
if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
-// if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
+ if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
return ReturnError(Start-1, "Unknown operator");
diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h
index f152df0a2f..3993e89d64 100644
--- a/utils/TableGen/TGLexer.h
+++ b/utils/TableGen/TGLexer.h
@@ -46,7 +46,7 @@ namespace tgtok {
// !keywords.
XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst,
- //XForEach,
+ XForEach,
// Integer value.
IntVal,
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
index 967f5d0d5d..bc5d65eea5 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -792,7 +792,7 @@ Init *TGParser::ParseOperation(Record *CurRec) {
return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass);
}
-// case tgtok::XForEach:
+ case tgtok::XForEach:
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
TernOpInit::TernaryOp Code;
RecTy *Type = 0;
@@ -802,9 +802,9 @@ Init *TGParser::ParseOperation(Record *CurRec) {
Lex.Lex(); // eat the operation
switch (LexCode) {
default: assert(0 && "Unhandled code!");
- //case tgtok::XForEach:
- //Code = TernOpInit::FOREACH;
- //break;
+ case tgtok::XForEach:
+ Code = TernOpInit::FOREACH;
+ break;
case tgtok::XSubst:
Code = TernOpInit::SUBST;
break;
@@ -844,15 +844,15 @@ Init *TGParser::ParseOperation(Record *CurRec) {
switch (LexCode) {
default: assert(0 && "Unhandled code!");
- //case tgtok::XForEach: {
- //TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
- //if (MHSt == 0) {
- // TokError("could not get type for !foreach");
- // return 0;
- //}
- //Type = MHSt->getType();
- //break;
- //}
+ case tgtok::XForEach: {
+ TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
+ if (MHSt == 0) {
+ TokError("could not get type for !foreach");
+ return 0;
+ }
+ Type = MHSt->getType();
+ break;
+ }
case tgtok::XSubst: {
TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
if (RHSt == 0) {
@@ -1079,7 +1079,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
case tgtok::XSHL:
case tgtok::XStrConcat:
case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')'
- // case tgtok::XForEach:
+ case tgtok::XForEach:
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
return ParseOperation(CurRec);
break;