summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/docs/TableGen/LangIntro.rst3
-rw-r--r--llvm/docs/TableGen/LangRef.rst2
-rw-r--r--llvm/include/llvm/TableGen/Record.h2
-rw-r--r--llvm/lib/TableGen/Record.cpp6
-rw-r--r--llvm/lib/TableGen/TGLexer.cpp1
-rw-r--r--llvm/lib/TableGen/TGLexer.h2
-rw-r--r--llvm/lib/TableGen/TGParser.cpp12
-rw-r--r--llvm/test/TableGen/size.td34
8 files changed, 58 insertions, 4 deletions
diff --git a/llvm/docs/TableGen/LangIntro.rst b/llvm/docs/TableGen/LangIntro.rst
index 460ff9067f2..534597b041b 100644
--- a/llvm/docs/TableGen/LangIntro.rst
+++ b/llvm/docs/TableGen/LangIntro.rst
@@ -205,6 +205,9 @@ supported include:
``!empty(a)``
An integer {0,1} indicating whether list 'a' is empty.
+``!size(a)``
+ An integer indicating the number of elements in list 'a'.
+
``!if(a,b,c)``
'b' if the result of 'int' or 'bit' operator 'a' is nonzero, 'c' otherwise.
diff --git a/llvm/docs/TableGen/LangRef.rst b/llvm/docs/TableGen/LangRef.rst
index 285572fa481..5f7917a5b4b 100644
--- a/llvm/docs/TableGen/LangRef.rst
+++ b/llvm/docs/TableGen/LangRef.rst
@@ -98,7 +98,7 @@ wide variety of meanings:
:!eq !if !head !tail !con
:!add !shl !sra !srl !and
:!or !empty !subst !foreach !strconcat
- :!cast !listconcat
+ :!cast !listconcat !size
Syntax
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index 0c27f395cfb..a94f76d852f 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -759,7 +759,7 @@ public:
///
class UnOpInit : public OpInit, public FoldingSetNode {
public:
- enum UnaryOp : uint8_t { CAST, HEAD, TAIL, EMPTY };
+ enum UnaryOp : uint8_t { CAST, HEAD, TAIL, SIZE, EMPTY };
private:
Init *LHS;
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index f447b3b1b47..80c0973644b 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -722,6 +722,11 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
}
break;
+ case SIZE:
+ if (ListInit *LHSl = dyn_cast<ListInit>(LHS))
+ return IntInit::get(LHSl->size());
+ break;
+
case EMPTY:
if (ListInit *LHSl = dyn_cast<ListInit>(LHS))
return IntInit::get(LHSl->empty());
@@ -746,6 +751,7 @@ std::string UnOpInit::getAsString() const {
case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
case HEAD: Result = "!head"; break;
case TAIL: Result = "!tail"; break;
+ case SIZE: Result = "!size"; break;
case EMPTY: Result = "!empty"; break;
}
return Result + "(" + LHS->getAsString() + ")";
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index 5d6f7c23e0b..bc03055eb23 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -469,6 +469,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("if", tgtok::XIf)
.Case("head", tgtok::XHead)
.Case("tail", tgtok::XTail)
+ .Case("size", tgtok::XSize)
.Case("con", tgtok::XConcat)
.Case("add", tgtok::XADD)
.Case("and", tgtok::XAND)
diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index b5b58161878..342eb76fc0f 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, XEmpty, XIf, XEq,
+ XSubst, XForEach, XHead, XTail, XSize, XEmpty, XIf, XEq,
// Integer value.
IntVal,
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 17c2c2ee613..72ab8d3838d 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -781,6 +781,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
return nullptr;
case tgtok::XHead:
case tgtok::XTail:
+ case tgtok::XSize:
case tgtok::XEmpty:
case tgtok::XCast: { // Value ::= !unop '(' Value ')'
UnOpInit::UnaryOp Code;
@@ -808,6 +809,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
Lex.Lex(); // eat the operation
Code = UnOpInit::TAIL;
break;
+ case tgtok::XSize:
+ Lex.Lex();
+ Code = UnOpInit::SIZE;
+ Type = IntRecTy::get();
+ break;
case tgtok::XEmpty:
Lex.Lex(); // eat the operation
Code = UnOpInit::EMPTY;
@@ -842,12 +848,15 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
}
}
- if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) {
+ if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL ||
+ Code == UnOpInit::SIZE) {
if (!LHSl && !LHSt) {
TokError("expected list type argument in unary operator");
return nullptr;
}
+ }
+ if (Code == UnOpInit::HEAD || Code == UnOpInit::TAIL) {
if (LHSl && LHSl->empty()) {
TokError("empty list argument in unary operator");
return nullptr;
@@ -1453,6 +1462,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
case tgtok::XHead:
case tgtok::XTail:
+ case tgtok::XSize:
case tgtok::XEmpty:
case tgtok::XCast: // Value ::= !unop '(' Value ')'
case tgtok::XConcat:
diff --git a/llvm/test/TableGen/size.td b/llvm/test/TableGen/size.td
new file mode 100644
index 00000000000..f7061e11079
--- /dev/null
+++ b/llvm/test/TableGen/size.td
@@ -0,0 +1,34 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+// CHECK: --- Defs ---
+
+// CHECK: def A1 {
+// CHECK: int Val = 0;
+// CHECK: }
+
+// CHECK: def A2 {
+// CHECK: int Val = 3;
+// CHECK: }
+
+// CHECK: def B1 {
+// CHECK: int Val = 0;
+// CHECK: }
+
+// CHECK: def B2 {
+// CHECK: int Val = 2;
+// CHECK: }
+
+class A<list<int> L> {
+ int Val = !size(L);
+}
+
+class B<list<string> L> {
+ int Val = !size(L);
+}
+
+def A1 : A<[]>;
+def A2 : A<[1, 1, 2]>;
+
+def B1 : B<[]>;
+def B2 : B<["a", "b"]>;
OpenPOWER on IntegriCloud