diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst --- a/llvm/docs/TableGen/ProgRef.rst +++ b/llvm/docs/TableGen/ProgRef.rst @@ -1630,6 +1630,12 @@ This operator produces 1 if the string, list, or DAG *a* is empty; 0 otherwise. A dag is empty if it has no arguments; the operator does not count. +``!lower(``\ *a*\ ``)`` + This operator converts a to lower case. + +``!upper(``\ *a*\ ``)`` + This operator converts a to upper case. + ``!eq(`` *a*\ `,` *b*\ ``)`` This operator produces 1 if *a* is equal to *b*; 0 otherwise. The arguments must be ``bit``, ``bits``, ``int``, ``string``, or diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -785,7 +785,18 @@ /// class UnOpInit : public OpInit, public FoldingSetNode { public: - enum UnaryOp : uint8_t { CAST, NOT, HEAD, TAIL, SIZE, EMPTY, GETDAGOP, LOG2 }; + enum UnaryOp : uint8_t { + LOWER, + UPPER, + CAST, + NOT, + HEAD, + TAIL, + SIZE, + EMPTY, + GETDAGOP, + LOG2 + }; private: Init *LHS; diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -778,6 +778,14 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const { RecordKeeper &RK = getRecordKeeper(); switch (getOpcode()) { + case LOWER: + if (StringInit *LHSs = dyn_cast(LHS)) + return StringInit::get(RK, LHSs->getValue().lower()); + break; + case UPPER: + if (StringInit *LHSs = dyn_cast(LHS)) + return StringInit::get(RK, LHSs->getValue().upper()); + break; case CAST: if (isa(getType())) { if (StringInit *LHSs = dyn_cast(LHS)) @@ -927,6 +935,12 @@ case EMPTY: Result = "!empty"; break; case GETDAGOP: Result = "!getdagop"; break; case LOG2 : Result = "!logtwo"; break; + case LOWER: + Result = "!lower"; + break; + case UPPER: + Result = "!upper"; + break; } return Result + "(" + LHS->getAsString() + ")"; } diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h --- a/llvm/lib/TableGen/TGLexer.h +++ b/llvm/lib/TableGen/TGLexer.h @@ -29,11 +29,11 @@ class Twine; namespace tgtok { - enum TokKind { - // Markers +enum TokKind { + // Markers Eof, Error, - // Tokens with no info. + // Tokens with no info. minus, plus, // - + l_square, r_square, // [ ] l_brace, r_brace, // { } @@ -45,36 +45,36 @@ paste, // # dotdotdot, // ... - // Reserved keywords. ('ElseKW' is named to distinguish it from the - // existing 'Else' that means the preprocessor #else.) + // Reserved keywords. ('ElseKW' is named to distinguish it from the + // existing 'Else' that means the preprocessor #else.) Assert, Bit, Bits, Class, Code, Dag, Def, Defm, Defset, Defvar, ElseKW, FalseKW, Field, Foreach, If, In, Include, Int, Let, List, MultiClass, String, Then, TrueKW, - // Bang operators. + // Bang operators. XConcat, XADD, XSUB, XMUL, XDIV, XNOT, XLOG2, XAND, XOR, XXOR, XSRA, XSRL, XSHL, XListConcat, XListSplat, XStrConcat, XInterleave, XSubstr, XFind, XCast, XSubst, XForEach, XFilter, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag, XNe, XLe, XLt, XGe, XGt, XSetDagOp, XGetDagOp, - XExists, XListRemove, + XExists, XListRemove, XLower, XUpper, - // Boolean literals. + // Boolean literals. TrueVal, FalseVal, - // Integer value. - IntVal, + // Integer value. + IntVal, - // Binary constant. Note that these are sized according to the number of - // bits given. - BinaryIntVal, + // Binary constant. Note that these are sized according to the number of + // bits given. + BinaryIntVal, - // String valued tokens. + // String valued tokens. Id, StrVal, VarName, CodeFragment, - // Preprocessing tokens for internal usage by the lexer. - // They are never returned as a result of Lex(). + // Preprocessing tokens for internal usage by the lexer. + // They are never returned as a result of Lex(). Ifdef, Ifndef, Else, Endif, Define - }; +}; } /// TGLexer - TableGen Lexer class. diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp --- a/llvm/lib/TableGen/TGLexer.cpp +++ b/llvm/lib/TableGen/TGLexer.cpp @@ -549,50 +549,52 @@ // Check to see which operator this is. tgtok::TokKind Kind = - StringSwitch(StringRef(Start, CurPtr - Start)) - .Case("eq", tgtok::XEq) - .Case("ne", tgtok::XNe) - .Case("le", tgtok::XLe) - .Case("lt", tgtok::XLt) - .Case("ge", tgtok::XGe) - .Case("gt", tgtok::XGt) - .Case("if", tgtok::XIf) - .Case("cond", tgtok::XCond) - .Case("isa", tgtok::XIsA) - .Case("head", tgtok::XHead) - .Case("tail", tgtok::XTail) - .Case("size", tgtok::XSize) - .Case("con", tgtok::XConcat) - .Case("dag", tgtok::XDag) - .Case("add", tgtok::XADD) - .Case("sub", tgtok::XSUB) - .Case("mul", tgtok::XMUL) - .Case("div", tgtok::XDIV) - .Case("not", tgtok::XNOT) - .Case("logtwo", tgtok::XLOG2) - .Case("and", tgtok::XAND) - .Case("or", tgtok::XOR) - .Case("xor", tgtok::XXOR) - .Case("shl", tgtok::XSHL) - .Case("sra", tgtok::XSRA) - .Case("srl", tgtok::XSRL) - .Case("cast", tgtok::XCast) - .Case("empty", tgtok::XEmpty) - .Case("subst", tgtok::XSubst) - .Case("foldl", tgtok::XFoldl) - .Case("foreach", tgtok::XForEach) - .Case("filter", tgtok::XFilter) - .Case("listconcat", tgtok::XListConcat) - .Case("listsplat", tgtok::XListSplat) - .Case("listremove", tgtok::XListRemove) - .Case("strconcat", tgtok::XStrConcat) - .Case("interleave", tgtok::XInterleave) - .Case("substr", tgtok::XSubstr) - .Case("find", tgtok::XFind) - .Cases("setdagop", "setop", tgtok::XSetDagOp) // !setop is deprecated. - .Cases("getdagop", "getop", tgtok::XGetDagOp) // !getop is deprecated. - .Case("exists", tgtok::XExists) - .Default(tgtok::Error); + StringSwitch(StringRef(Start, CurPtr - Start)) + .Case("eq", tgtok::XEq) + .Case("ne", tgtok::XNe) + .Case("le", tgtok::XLe) + .Case("lt", tgtok::XLt) + .Case("ge", tgtok::XGe) + .Case("gt", tgtok::XGt) + .Case("if", tgtok::XIf) + .Case("cond", tgtok::XCond) + .Case("isa", tgtok::XIsA) + .Case("head", tgtok::XHead) + .Case("tail", tgtok::XTail) + .Case("size", tgtok::XSize) + .Case("con", tgtok::XConcat) + .Case("dag", tgtok::XDag) + .Case("add", tgtok::XADD) + .Case("sub", tgtok::XSUB) + .Case("mul", tgtok::XMUL) + .Case("div", tgtok::XDIV) + .Case("not", tgtok::XNOT) + .Case("logtwo", tgtok::XLOG2) + .Case("and", tgtok::XAND) + .Case("or", tgtok::XOR) + .Case("xor", tgtok::XXOR) + .Case("shl", tgtok::XSHL) + .Case("sra", tgtok::XSRA) + .Case("srl", tgtok::XSRL) + .Case("cast", tgtok::XCast) + .Case("empty", tgtok::XEmpty) + .Case("subst", tgtok::XSubst) + .Case("foldl", tgtok::XFoldl) + .Case("foreach", tgtok::XForEach) + .Case("filter", tgtok::XFilter) + .Case("listconcat", tgtok::XListConcat) + .Case("listsplat", tgtok::XListSplat) + .Case("listremove", tgtok::XListRemove) + .Case("strconcat", tgtok::XStrConcat) + .Case("interleave", tgtok::XInterleave) + .Case("substr", tgtok::XSubstr) + .Case("find", tgtok::XFind) + .Cases("setdagop", "setop", tgtok::XSetDagOp) // !setop is deprecated. + .Cases("getdagop", "getop", tgtok::XGetDagOp) // !getop is deprecated. + .Case("exists", tgtok::XExists) + .Case("lower", tgtok::XLower) + .Case("upper", tgtok::XUpper) + .Default(tgtok::Error); return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator"); } diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -944,6 +944,8 @@ TokError("unknown bang operator"); return nullptr; case tgtok::XNOT: + case tgtok::XLower: + case tgtok::XUpper: case tgtok::XLOG2: case tgtok::XHead: case tgtok::XTail: @@ -967,6 +969,16 @@ return nullptr; } + break; + case tgtok::XLower: + Lex.Lex(); // eat the operation + Code = UnOpInit::LOWER; + Type = StringRecTy::get(Records); + break; + case tgtok::XUpper: + Lex.Lex(); // eat the operation + Code = UnOpInit::UPPER; + Type = StringRecTy::get(Records); break; case tgtok::XNOT: Lex.Lex(); // eat the operation @@ -2445,6 +2457,8 @@ case tgtok::XSize: case tgtok::XEmpty: case tgtok::XCast: + case tgtok::XLower: + case tgtok::XUpper: case tgtok::XGetDagOp: // Value ::= !unop '(' Value ')' case tgtok::XExists: case tgtok::XIsA: diff --git a/llvm/test/TableGen/string_ops.td b/llvm/test/TableGen/string_ops.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/string_ops.td @@ -0,0 +1,44 @@ +// RUN: llvm-tblgen %s | FileCheck %s + +// CHECK-LABEL: def LOWER1 { +// CHECK: int Value = 1; +// CHECK: } + +// CHECK-LABEL: def LOWER2 { +// CHECK: int Value = 1; +// CHECK: } + +// CHECK-LABEL: def LOWER3 { +// CHECK: int Value = 1; +// CHECK: } + +// CHECK-LABEL: def UPPER1 { +// CHECK: int Value = 1; +// CHECK: } + +// CHECK-LABEL: def UPPER2 { +// CHECK: int Value = 1; +// CHECK: } + +// CHECK-LABEL: def UPPER3 { +// CHECK: int Value = 1; +// CHECK: } + +class Base { + int Value = V; +} + +class Derived : + Base; + + +class Derived2 : + Base; + +def LOWER1 : Derived<"Str">; +def LOWER2 : Derived<"STr">; +def LOWER3 : Derived<"STR">; + +def UPPER1 : Derived2<"str">; +def UPPER2 : Derived2<"sTr">; +def UPPER3 : Derived2<"sTR">; diff --git a/llvm/utils/kate/llvm-tablegen.xml b/llvm/utils/kate/llvm-tablegen.xml --- a/llvm/utils/kate/llvm-tablegen.xml +++ b/llvm/utils/kate/llvm-tablegen.xml @@ -42,6 +42,8 @@ !ge !gt !ne + !lower + !upper class