Author: Timm Bäder Date: 2022-10-14T12:57:57+02:00 New Revision: d704ba26b9144829f1c4905c168f6b6278c7a3e6
URL: https://github.com/llvm/llvm-project/commit/d704ba26b9144829f1c4905c168f6b6278c7a3e6 DIFF: https://github.com/llvm/llvm-project/commit/d704ba26b9144829f1c4905c168f6b6278c7a3e6.diff LOG: [clang][Interp] Implement div opcode Implement an opcode for division of two integrals. Differential Revision: https://reviews.llvm.org/D134749 Added: Modified: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/Integral.h clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/test/AST/Interp/literals.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 1574f8b6c6c8..107fd77c974d 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -214,6 +214,8 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { return Discard(this->emitMul(*T, BO)); case BO_Rem: return Discard(this->emitRem(*T, BO)); + case BO_Div: + return Discard(this->emitDiv(*T, BO)); case BO_Assign: if (!this->emitStore(*T, BO)) return false; diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h index c7e558965531..b50a567d18c7 100644 --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -212,6 +212,11 @@ template <unsigned Bits, bool Signed> class Integral final { return false; } + static bool div(Integral A, Integral B, unsigned OpBits, Integral *R) { + *R = Integral(A.V / B.V); + return false; + } + static bool neg(Integral A, Integral *R) { *R = -A; return false; diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 4d0c7f62f46c..6ad3a6aeaa31 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -186,6 +186,39 @@ bool Rem(InterpState &S, CodePtr OpPC) { return false; } +/// 1) Pops the RHS from the stack. +/// 2) Pops the LHS from the stack. +/// 3) Pushes 'LHS / RHS' on the stack +template <PrimType Name, class T = typename PrimConv<Name>::T> +bool Div(InterpState &S, CodePtr OpPC) { + const T &RHS = S.Stk.pop<T>(); + const T &LHS = S.Stk.pop<T>(); + + if (RHS.isZero()) { + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, diag::note_expr_divide_by_zero); + return false; + } + + if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) { + APSInt LHSInt = LHS.toAPSInt(); + SmallString<32> Trunc; + (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10); + const SourceInfo &Loc = S.Current->getSource(OpPC); + const Expr *E = S.Current->getExpr(OpPC); + S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType(); + return false; + } + + const unsigned Bits = RHS.bitWidth() * 2; + T Result; + if (!T::div(LHS, RHS, Bits, &Result)) { + S.Stk.push<T>(Result); + return true; + } + return false; +} + //===----------------------------------------------------------------------===// // Inv //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index 61f97337fd04..f47f6492fcd7 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -401,7 +401,10 @@ def Rem : Opcode { let Types = [NumberTypeClass]; let HasGroup = 1; } - +def Div : Opcode { + let Types = [NumberTypeClass]; + let HasGroup = 1; +} //===----------------------------------------------------------------------===// // Unary operators. diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 19c80f478d1a..cc868266e4a2 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -188,3 +188,25 @@ namespace rem { // expected-note {{value 2147483648 is outside the range}} \ }; + +namespace div { + constexpr int zero() { return 0; } + static_assert(12 / 3 == 4, ""); + static_assert(12 / zero() == 12, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{division by zero}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{division by zero}} + static_assert(12 / -3 == -4, ""); + static_assert(-12 / 3 == -4, ""); + + + constexpr int LHS = 12; + constexpr long unsigned RHS = 3; + static_assert(LHS / RHS == 4, ""); + + constexpr int x = INT_MIN / - 1; // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{value 2147483648 is outside the range}} \ + // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{value 2147483648 is outside the range}} \ + +}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits