tbaeder created this revision. tbaeder added reviewers: erichkeane, aaron.ballman. Herald added a project: All. tbaeder requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Implement inverting and negating values Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D132098 Files: clang/lib/AST/Interp/Boolean.h clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/Integral.h clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/test/AST/Interp/literals.cpp
Index: clang/test/AST/Interp/literals.cpp =================================================================== --- clang/test/AST/Interp/literals.cpp +++ clang/test/AST/Interp/literals.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++11 -verify %s +// RUN: %clang_cc1 -std=c++11 -verify %s -DREFERENCE static_assert(true, ""); static_assert(false, ""); // expected-error{{failed}} @@ -9,7 +10,25 @@ constexpr int number = 10; static_assert(number == 10, ""); static_assert(number != 10, ""); // expected-error{{failed}} +#ifdef REFERENCE + // expected-note@-2{{evaluates to}} +#endif constexpr bool getTrue() { return true; } constexpr bool getFalse() { return false; } constexpr void* getNull() { return nullptr; } + +constexpr int neg(int m) { return -m; } +constexpr bool inv(bool b) { return !b; } + +static_assert(12, ""); +static_assert(12 == -(-(12)), ""); +static_assert(!false, ""); +static_assert(!!true, ""); +static_assert(!!true == !false, ""); +static_assert(true == 1, ""); +static_assert(false == 0, ""); +static_assert(!5 == false, ""); +static_assert(!0, ""); +static_assert(-true, ""); +static_assert(-false, ""); //expected-error{{failed}} Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -73,6 +73,10 @@ let Types = [Ptr]; } +def BoolTypeClass : TypeClass { + let Types = [Bool]; +} + def AllTypeClass : TypeClass { let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types); } @@ -383,6 +387,25 @@ def Add : AluOpcode; def Mul : AluOpcode; + +//===----------------------------------------------------------------------===// +// Unary operators. +//===----------------------------------------------------------------------===// + + + +// [Real] -> [Real] +def Inv: Opcode { + let Types = [BoolTypeClass]; + let HasGroup = 1; +} + +// [Real] -> [Real] +def Neg: Opcode { + let Types = [AluTypeClass]; + let HasGroup = 1; +} + //===----------------------------------------------------------------------===// // Comparison opcodes. //===----------------------------------------------------------------------===// Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -154,6 +154,36 @@ return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS); } +//===----------------------------------------------------------------------===// +// Inv +//===----------------------------------------------------------------------===// + +template <PrimType Name, class T = typename PrimConv<Name>::T> +bool Inv(InterpState &S, CodePtr OpPC) { + using BoolT = PrimConv<PT_Bool>::T; + const T &Val = S.Stk.pop<T>(); + const unsigned Bits = Val.bitWidth(); + Boolean R; + Boolean::inv(BoolT::from(Val, Bits), &R); + + S.Stk.push<BoolT>(R); + return true; +} + +//===----------------------------------------------------------------------===// +// Neg +//===----------------------------------------------------------------------===// + +template <PrimType Name, class T = typename PrimConv<Name>::T> +bool Neg(InterpState &S, CodePtr OpPC) { + const T &Val = S.Stk.pop<T>(); + T Result; + T::neg(Val, &Result); + + S.Stk.push<T>(Val); + return true; +} + //===----------------------------------------------------------------------===// // EQ, NE, GT, GE, LT, LE //===----------------------------------------------------------------------===// Index: clang/lib/AST/Interp/Integral.h =================================================================== --- clang/lib/AST/Interp/Integral.h +++ clang/lib/AST/Interp/Integral.h @@ -203,6 +203,11 @@ return CheckMulUB(A.V, B.V, R->V); } + static bool neg(Integral A, Integral *R) { + *R = -A; + return false; + } + private: template <typename T> static std::enable_if_t<std::is_signed<T>::value, bool> CheckAddUB(T A, T B, Index: clang/lib/AST/Interp/ByteCodeExprGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -71,6 +71,7 @@ bool VisitBinaryOperator(const BinaryOperator *E); bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E); bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E); + bool VisitUnaryOperator(const UnaryOperator *E); protected: bool visitExpr(const Expr *E) override; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -114,15 +114,26 @@ case CK_NoOp: case CK_UserDefinedConversion: case CK_NullToPointer: + case CK_IntegralCast: return this->Visit(SubExpr); case CK_ToVoid: return discard(SubExpr); - default: { - // TODO: implement other casts. - return this->bail(CE); - } + case CK_IntegralToBoolean: + if (Optional<PrimType> T = classify(SubExpr->getType())) { + if (!this->Visit(SubExpr)) + return false; + + if (!this->emitConst(SubExpr, 0)) + return false; + + return this->emitNE(*T, SubExpr); + } + return false; + + default: + llvm_unreachable("Cast not implemented"); } } @@ -583,6 +594,40 @@ return this->emitNullPtr(E); } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) { + if (!this->Visit(E->getSubExpr())) + return false; + + switch (E->getOpcode()) { + case UO_PostInc: // x++ + case UO_PostDec: // x-- + case UO_PreInc: // --x + case UO_PreDec: // ++x + return false; + + case UO_LNot: // !x + return this->emitInvBool(E); + case UO_Minus: // -x + if (Optional<PrimType> T = classify(E->getType())) + return this->emitNeg(*T, E); + return false; + case UO_Plus: // +x + return true; // noop + + case UO_AddrOf: // &x + case UO_Deref: // *x + case UO_Not: // ~x + case UO_Real: // __real x + case UO_Imag: // __imag x + case UO_Extension: + case UO_Coawait: + llvm_unreachable("Unhandled opcode"); + } + + return false; +} + template <class Emitter> void ByteCodeExprGen<Emitter>::emitCleanup() { for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) Index: clang/lib/AST/Interp/Boolean.h =================================================================== --- clang/lib/AST/Interp/Boolean.h +++ clang/lib/AST/Interp/Boolean.h @@ -134,6 +134,16 @@ *R = Boolean(A.V && B.V); return false; } + + static bool inv(Boolean A, Boolean *R) { + *R = Boolean(!A.V); + return false; + } + + static bool neg(Boolean A, Boolean *R) { + *R = Boolean(A.V); + return false; + } }; inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Boolean &B) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits