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 @@ -220,13 +220,13 @@ .. productionlist:: BangOperator: one of : !add !and !cast !con !dag - : !empty !eq !filter !find !foldl - : !foreach !ge !getdagop !gt !head - : !if !interleave !isa !le !listconcat - : !listsplat !lt !mul !ne !not - : !or !setdagop !shl !size !sra - : !srl !strconcat !sub !subst !substr - : !tail !xor + : !div !empty !eq !filter !find + : !foldl !foreach !ge !getdagop !gt + : !head !if !interleave !isa !le + : !listconcat !listsplat !lt !mul !ne + : !not !or !setdagop !shl !size + : !sra !srl !strconcat !sub !subst + : !substr !tail !xor The ``!cond`` operator has a slightly different syntax compared to other bang operators, so it is defined separately: @@ -1622,6 +1622,10 @@ Example: ``!dag(op, [a1, a2, ?], ["name1", "name2", "name3"])`` results in ``(op a1-value:$name1, a2-value:$name2, ?:$name3)``. +``!div(``\ *a*\ ``,`` *b*\ ``)`` + This operator preforms signed division of *a* by *b*, and produces the quotient. + Division by 0 produces an error. Division of INT64_MIN by -1 produces an error. + ``!empty(``\ *a*\ ``)`` 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. 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 @@ -833,9 +833,30 @@ /// !op (X, Y) - Combine two inits. class BinOpInit : public OpInit, public FoldingSetNode { public: - enum BinaryOp : uint8_t { ADD, SUB, MUL, AND, OR, XOR, SHL, SRA, SRL, LISTCONCAT, - LISTSPLAT, STRCONCAT, INTERLEAVE, CONCAT, EQ, - NE, LE, LT, GE, GT, SETDAGOP }; + enum BinaryOp : uint8_t { + ADD, + SUB, + MUL, + DIV, + AND, + OR, + XOR, + SHL, + SRA, + SRL, + LISTCONCAT, + LISTSPLAT, + STRCONCAT, + INTERLEAVE, + CONCAT, + EQ, + NE, + LE, + LT, + GE, + GT, + SETDAGOP + }; private: Init *LHS, *RHS; 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 @@ -1165,6 +1165,7 @@ case ADD: case SUB: case MUL: + case DIV: case AND: case OR: case XOR: @@ -1183,6 +1184,16 @@ case ADD: Result = LHSv + RHSv; break; case SUB: Result = LHSv - RHSv; break; case MUL: Result = LHSv * RHSv; break; + case DIV: + if (RHSv == 0) + PrintFatalError(CurRec->getLoc(), + "Illegal operation: division by zero"); + else if (LHSv == INT64_MIN && RHSv == -1) + PrintFatalError(CurRec->getLoc(), + "Illegal operation: INT64_MIN / -1"); + else + Result = LHSv / RHSv; + break; case AND: Result = LHSv & RHSv; break; case OR: Result = LHSv | RHSv; break; case XOR: Result = LHSv ^ RHSv; break; @@ -1215,6 +1226,7 @@ case ADD: Result = "!add"; break; case SUB: Result = "!sub"; break; case MUL: Result = "!mul"; break; + case DIV: Result = "!div"; break; case AND: Result = "!and"; break; case OR: Result = "!or"; break; case XOR: Result = "!xor"; break; 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 @@ -52,7 +52,7 @@ String, Then, TrueKW, // Bang operators. - XConcat, XADD, XSUB, XMUL, XNOT, XAND, XOR, XXOR, XSRA, XSRL, XSHL, + XConcat, XADD, XSUB, XMUL, XDIV, XNOT, 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, 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 @@ -563,6 +563,7 @@ .Case("add", tgtok::XADD) .Case("sub", tgtok::XSUB) .Case("mul", tgtok::XMUL) + .Case("div", tgtok::XDIV) .Case("not", tgtok::XNOT) .Case("and", tgtok::XAND) .Case("or", tgtok::XOR) 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 @@ -1146,6 +1146,7 @@ case tgtok::XADD: case tgtok::XSUB: case tgtok::XMUL: + case tgtok::XDIV: case tgtok::XAND: case tgtok::XOR: case tgtok::XXOR: @@ -1174,6 +1175,7 @@ case tgtok::XADD: Code = BinOpInit::ADD; break; case tgtok::XSUB: Code = BinOpInit::SUB; break; case tgtok::XMUL: Code = BinOpInit::MUL; break; + case tgtok::XDIV: Code = BinOpInit::DIV; break; case tgtok::XAND: Code = BinOpInit::AND; break; case tgtok::XOR: Code = BinOpInit::OR; break; case tgtok::XXOR: Code = BinOpInit::XOR; break; @@ -1212,6 +1214,7 @@ case tgtok::XADD: case tgtok::XSUB: case tgtok::XMUL: + case tgtok::XDIV: Type = IntRecTy::get(Records); ArgType = IntRecTy::get(Records); break; @@ -1371,7 +1374,7 @@ Code != BinOpInit::AND && Code != BinOpInit::OR && Code != BinOpInit::XOR && Code != BinOpInit::SRA && Code != BinOpInit::SRL && Code != BinOpInit::SHL && - Code != BinOpInit::MUL) + Code != BinOpInit::MUL && Code != BinOpInit::DIV) ArgType = Resolved; } @@ -2126,6 +2129,7 @@ /// SimpleValue ::= '(' IDValue DagArgList ')' /// SimpleValue ::= CONCATTOK '(' Value ',' Value ')' /// SimpleValue ::= ADDTOK '(' Value ',' Value ')' +/// SimpleValue ::= DIVTOK '(' Value ',' Value ')' /// SimpleValue ::= SUBTOK '(' Value ',' Value ')' /// SimpleValue ::= SHLTOK '(' Value ',' Value ')' /// SimpleValue ::= SRATOK '(' Value ',' Value ')' @@ -2411,6 +2415,7 @@ case tgtok::XADD: case tgtok::XSUB: case tgtok::XMUL: + case tgtok::XDIV: case tgtok::XNOT: case tgtok::XAND: case tgtok::XOR: diff --git a/llvm/test/TableGen/math.td b/llvm/test/TableGen/math.td --- a/llvm/test/TableGen/math.td +++ b/llvm/test/TableGen/math.td @@ -1,4 +1,6 @@ // RUN: llvm-tblgen %s | FileCheck %s +// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s +// RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s // XFAIL: vg_leak // CHECK: def shifts @@ -47,6 +49,36 @@ // CHECK: Value = 12 def v12 : Int; +// CHECK: def v13 +// CHECK: Value = 5 +def v13 : Int; + +// CHECK: def v14 +// CHECK: Value = 5 +def v14 : Int; + +// CHECK: def v15 +// CHECK: Value = 1 +def v15 : Int; + +// CHECK: def v16 +// CHECK: Value = 0 +def v16 : Int; + +// CHECK: def v17 +// CHECK: Value = -2 +def v17 : Int; + +#ifdef ERROR1 +// ERROR1: error: Illegal operation: division by zero +def v18 : Int; +#endif + +#ifdef ERROR2 +// ERROR2: error: Illegal operation: INT64_MIN / -1 +def v19 : Int; +#endif + // CHECK: def v1a // CHECK: Value = 1