diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html
index 36798c8b8b8..08838caf464 100644
--- a/docs/TableGenFundamentals.html
+++ b/docs/TableGenFundamentals.html
@@ -417,6 +417,8 @@ class. This operation is analogous to $(foreach) in GNU make.
The 2nd-N elements of list 'a.'
!null(a)
An integer {0,1} indicating whether list 'a' is empty.
+!if(a,b,c)
+ 'b' if the result of integer operator 'a' is nonzero, 'c' otherwise.
Note that all of the values have rules specifying how they convert to values
diff --git a/test/TableGen/if.td b/test/TableGen/if.td
new file mode 100644
index 00000000000..3c45d95eb20
--- /dev/null
+++ b/test/TableGen/if.td
@@ -0,0 +1,20 @@
+// RUN: tblgen %s | grep {1, 2, 3} | count 4
+// RUN: tblgen %s | grep {4, 5, 6} | count 2
+
+class A> vals> {
+ list first = vals[0];
+ list rest = !if(!null(!cdr(vals)), vals[0], vals[1]);
+}
+
+def One : A<[[1,2,3]]>;
+def Two : A<[[1,2,3],[4,5,6]]>;
+
+class B v> {
+ list vals = v;
+}
+
+class BB> vals> : B;
+class BBB> vals> : BB;
+
+def OneB : BBB<[[1,2,3]]>;
+def TwoB : BBB<[[1,2,3],[4,5,6]]>;
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
index ae2c2f3ea40..fc2de1c135a 100644
--- a/utils/TableGen/Record.cpp
+++ b/utils/TableGen/Record.cpp
@@ -912,6 +912,19 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
}
break;
}
+
+ case IF: {
+ IntInit *LHSi = dynamic_cast(LHS);
+ if (LHSi) {
+ if (LHSi->getValue()) {
+ return MHS;
+ }
+ else {
+ return RHS;
+ }
+ }
+ break;
+ }
}
return this;
@@ -932,6 +945,7 @@ std::string TernOpInit::getAsString() const {
switch (Opc) {
case SUBST: Result = "!subst"; break;
case FOREACH: Result = "!foreach"; break;
+ case IF: Result = "!if"; break;
}
return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", "
+ RHS->getAsString() + ")";
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index c2549dab73a..2153a54c95a 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -843,7 +843,7 @@ public:
///
class TernOpInit : public OpInit {
public:
- enum TernaryOp { SUBST, FOREACH };
+ enum TernaryOp { SUBST, FOREACH, IF };
private:
TernaryOp Opc;
Init *LHS, *MHS, *RHS;
diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp
index faf1e75a684..758d499a8b5 100644
--- a/utils/TableGen/TGLexer.cpp
+++ b/utils/TableGen/TGLexer.cpp
@@ -453,6 +453,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar;
if (Len == 3 && !memcmp(Start, "cdr", 3)) return tgtok::XCdr;
if (Len == 4 && !memcmp(Start, "null", 4)) return tgtok::XNull;
+ if (Len == 2 && !memcmp(Start, "if", 2)) return tgtok::XIf;
return ReturnError(Start-1, "Unknown operator");
}
diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h
index 3d27e5e8edb..ac3b9840039 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, XCar, XCdr, XNull,
+ XForEach, XCar, XCdr, XNull, XIf,
// Integer value.
IntVal,
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
index 8ff25a6186b..fc6f29fd9f1 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -862,6 +862,7 @@ Init *TGParser::ParseOperation(Record *CurRec) {
return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass);
}
+ case tgtok::XIf:
case tgtok::XForEach:
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
TernOpInit::TernaryOp Code;
@@ -872,6 +873,9 @@ Init *TGParser::ParseOperation(Record *CurRec) {
Lex.Lex(); // eat the operation
switch (LexCode) {
default: assert(0 && "Unhandled code!");
+ case tgtok::XIf:
+ Code = TernOpInit::IF;
+ break;
case tgtok::XForEach:
Code = TernOpInit::FOREACH;
break;
@@ -914,6 +918,25 @@ Init *TGParser::ParseOperation(Record *CurRec) {
switch (LexCode) {
default: assert(0 && "Unhandled code!");
+ case tgtok::XIf: {
+ TypedInit *MHSt = dynamic_cast(MHS);
+ TypedInit *RHSt = dynamic_cast(RHS);
+ if (MHSt == 0 || RHSt == 0) {
+ TokError("could not get type for !if");
+ return 0;
+ }
+ if (MHSt->getType()->typeIsConvertibleTo(RHSt->getType())) {
+ Type = RHSt->getType();
+ }
+ else if (RHSt->getType()->typeIsConvertibleTo(MHSt->getType())) {
+ Type = MHSt->getType();
+ }
+ else {
+ TokError("inconsistent types for !if");
+ return 0;
+ }
+ break;
+ }
case tgtok::XForEach: {
TypedInit *MHSt = dynamic_cast(MHS);
if (MHSt == 0) {
@@ -1152,6 +1175,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec) {
case tgtok::XSHL:
case tgtok::XStrConcat:
case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')'
+ case tgtok::XIf:
case tgtok::XForEach:
case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
return ParseOperation(CurRec);