Index: docs/TableGen/LangRef.rst =================================================================== --- docs/TableGen/LangRef.rst +++ docs/TableGen/LangRef.rst @@ -98,7 +98,7 @@ :!eq !if !head !tail !con :!add !shl !sra !srl !and :!or !empty !subst !foreach !strconcat - :!cast !listconcat + :!cast !listconcat !size Syntax Index: include/llvm/TableGen/Record.h =================================================================== --- include/llvm/TableGen/Record.h +++ include/llvm/TableGen/Record.h @@ -752,7 +752,7 @@ /// 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; Index: lib/TableGen/Record.cpp =================================================================== --- lib/TableGen/Record.cpp +++ lib/TableGen/Record.cpp @@ -705,6 +705,11 @@ } break; + case SIZE: + if (ListInit *LHSl = dyn_cast(LHS)) + return IntInit::get(LHSl->size()); + break; + case EMPTY: if (ListInit *LHSl = dyn_cast(LHS)) return IntInit::get(LHSl->empty()); @@ -729,6 +734,7 @@ 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() + ")"; Index: lib/TableGen/TGLexer.h =================================================================== --- lib/TableGen/TGLexer.h +++ lib/TableGen/TGLexer.h @@ -48,7 +48,7 @@ // !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, Index: lib/TableGen/TGLexer.cpp =================================================================== --- lib/TableGen/TGLexer.cpp +++ lib/TableGen/TGLexer.cpp @@ -469,6 +469,7 @@ .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) Index: lib/TableGen/TGParser.cpp =================================================================== --- lib/TableGen/TGParser.cpp +++ lib/TableGen/TGParser.cpp @@ -781,6 +781,7 @@ 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 @@ 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 @@ } } - 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; @@ -1447,6 +1456,7 @@ case tgtok::XHead: case tgtok::XTail: + case tgtok::XSize: case tgtok::XEmpty: case tgtok::XCast: // Value ::= !unop '(' Value ')' case tgtok::XConcat: Index: test/TableGen/size.td =================================================================== --- /dev/null +++ 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 L> { + int Val = !size(L); +} + +class B L> { + int Val = !size(L); +} + +def A1 : A<[]>; +def A2 : A<[1, 1, 2]>; + +def B1 : B<[]>; +def B2 : B<["a", "b"]>;