1*700637cbSDimitry Andric //===--- Boolean.h - Wrapper for boolean types for the VM -------*- C++ -*-===// 2*700637cbSDimitry Andric // 3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*700637cbSDimitry Andric // 7*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 8*700637cbSDimitry Andric 9*700637cbSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_BOOLEAN_H 10*700637cbSDimitry Andric #define LLVM_CLANG_AST_INTERP_BOOLEAN_H 11*700637cbSDimitry Andric 12*700637cbSDimitry Andric #include "Integral.h" 13*700637cbSDimitry Andric #include "clang/AST/APValue.h" 14*700637cbSDimitry Andric #include "clang/AST/ComparisonCategories.h" 15*700637cbSDimitry Andric #include "llvm/ADT/APSInt.h" 16*700637cbSDimitry Andric #include "llvm/Support/MathExtras.h" 17*700637cbSDimitry Andric #include "llvm/Support/raw_ostream.h" 18*700637cbSDimitry Andric #include <cstddef> 19*700637cbSDimitry Andric #include <cstdint> 20*700637cbSDimitry Andric 21*700637cbSDimitry Andric namespace clang { 22*700637cbSDimitry Andric namespace interp { 23*700637cbSDimitry Andric 24*700637cbSDimitry Andric /// Wrapper around boolean types. 25*700637cbSDimitry Andric class Boolean final { 26*700637cbSDimitry Andric private: 27*700637cbSDimitry Andric /// Underlying boolean. 28*700637cbSDimitry Andric bool V; 29*700637cbSDimitry Andric 30*700637cbSDimitry Andric public: 31*700637cbSDimitry Andric /// Zero-initializes a boolean. Boolean()32*700637cbSDimitry Andric Boolean() : V(false) {} Boolean(bool V)33*700637cbSDimitry Andric explicit Boolean(bool V) : V(V) {} 34*700637cbSDimitry Andric 35*700637cbSDimitry Andric bool operator<(Boolean RHS) const { return V < RHS.V; } 36*700637cbSDimitry Andric bool operator>(Boolean RHS) const { return V > RHS.V; } 37*700637cbSDimitry Andric bool operator>(unsigned RHS) const { return static_cast<unsigned>(V) > RHS; } 38*700637cbSDimitry Andric 39*700637cbSDimitry Andric Boolean operator-() const { return Boolean(V); } 40*700637cbSDimitry Andric Boolean operator-(const Boolean &Other) const { return Boolean(V - Other.V); } 41*700637cbSDimitry Andric Boolean operator~() const { return Boolean(true); } 42*700637cbSDimitry Andric Boolean operator!() const { return Boolean(!V); } 43*700637cbSDimitry Andric 44*700637cbSDimitry Andric template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>> Ty()45*700637cbSDimitry Andric explicit operator Ty() const { 46*700637cbSDimitry Andric return V; 47*700637cbSDimitry Andric } 48*700637cbSDimitry Andric toAPSInt()49*700637cbSDimitry Andric APSInt toAPSInt() const { 50*700637cbSDimitry Andric return APSInt(APInt(1, static_cast<uint64_t>(V), false), true); 51*700637cbSDimitry Andric } toAPSInt(unsigned NumBits)52*700637cbSDimitry Andric APSInt toAPSInt(unsigned NumBits) const { 53*700637cbSDimitry Andric return APSInt(toAPSInt().zextOrTrunc(NumBits), true); 54*700637cbSDimitry Andric } toAPValue(const ASTContext &)55*700637cbSDimitry Andric APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); } 56*700637cbSDimitry Andric toUnsigned()57*700637cbSDimitry Andric Boolean toUnsigned() const { return *this; } 58*700637cbSDimitry Andric bitWidth()59*700637cbSDimitry Andric constexpr static unsigned bitWidth() { return 1; } isZero()60*700637cbSDimitry Andric bool isZero() const { return !V; } isMin()61*700637cbSDimitry Andric bool isMin() const { return isZero(); } 62*700637cbSDimitry Andric isMinusOne()63*700637cbSDimitry Andric constexpr static bool isMinusOne() { return false; } 64*700637cbSDimitry Andric isSigned()65*700637cbSDimitry Andric constexpr static bool isSigned() { return false; } 66*700637cbSDimitry Andric isNegative()67*700637cbSDimitry Andric constexpr static bool isNegative() { return false; } isPositive()68*700637cbSDimitry Andric constexpr static bool isPositive() { return !isNegative(); } 69*700637cbSDimitry Andric compare(const Boolean & RHS)70*700637cbSDimitry Andric ComparisonCategoryResult compare(const Boolean &RHS) const { 71*700637cbSDimitry Andric return Compare(V, RHS.V); 72*700637cbSDimitry Andric } 73*700637cbSDimitry Andric countLeadingZeros()74*700637cbSDimitry Andric unsigned countLeadingZeros() const { return V ? 0 : 1; } 75*700637cbSDimitry Andric truncate(unsigned TruncBits)76*700637cbSDimitry Andric Boolean truncate(unsigned TruncBits) const { return *this; } 77*700637cbSDimitry Andric bitcastFromMemory(const std::byte * Buff,unsigned BitWidth)78*700637cbSDimitry Andric static Boolean bitcastFromMemory(const std::byte *Buff, unsigned BitWidth) { 79*700637cbSDimitry Andric // Just load the first byte. 80*700637cbSDimitry Andric bool Val = static_cast<bool>(*Buff); 81*700637cbSDimitry Andric return Boolean(Val); 82*700637cbSDimitry Andric } 83*700637cbSDimitry Andric bitcastToMemory(std::byte * Buff)84*700637cbSDimitry Andric void bitcastToMemory(std::byte *Buff) { std::memcpy(Buff, &V, sizeof(V)); } 85*700637cbSDimitry Andric print(llvm::raw_ostream & OS)86*700637cbSDimitry Andric void print(llvm::raw_ostream &OS) const { OS << (V ? "true" : "false"); } toDiagnosticString(const ASTContext & Ctx)87*700637cbSDimitry Andric std::string toDiagnosticString(const ASTContext &Ctx) const { 88*700637cbSDimitry Andric std::string NameStr; 89*700637cbSDimitry Andric llvm::raw_string_ostream OS(NameStr); 90*700637cbSDimitry Andric print(OS); 91*700637cbSDimitry Andric return NameStr; 92*700637cbSDimitry Andric } 93*700637cbSDimitry Andric min(unsigned NumBits)94*700637cbSDimitry Andric static Boolean min(unsigned NumBits) { return Boolean(false); } max(unsigned NumBits)95*700637cbSDimitry Andric static Boolean max(unsigned NumBits) { return Boolean(true); } 96*700637cbSDimitry Andric from(T Value)97*700637cbSDimitry Andric template <typename T> static Boolean from(T Value) { 98*700637cbSDimitry Andric if constexpr (std::is_integral<T>::value) 99*700637cbSDimitry Andric return Boolean(Value != 0); 100*700637cbSDimitry Andric return Boolean(static_cast<decltype(Boolean::V)>(Value) != 0); 101*700637cbSDimitry Andric } 102*700637cbSDimitry Andric 103*700637cbSDimitry Andric template <unsigned SrcBits, bool SrcSign> 104*700637cbSDimitry Andric static std::enable_if_t<SrcBits != 0, Boolean> from(Integral<SrcBits,SrcSign> Value)105*700637cbSDimitry Andric from(Integral<SrcBits, SrcSign> Value) { 106*700637cbSDimitry Andric return Boolean(!Value.isZero()); 107*700637cbSDimitry Andric } 108*700637cbSDimitry Andric zero()109*700637cbSDimitry Andric static Boolean zero() { return from(false); } 110*700637cbSDimitry Andric from(T Value,unsigned NumBits)111*700637cbSDimitry Andric template <typename T> static Boolean from(T Value, unsigned NumBits) { 112*700637cbSDimitry Andric return Boolean(Value); 113*700637cbSDimitry Andric } 114*700637cbSDimitry Andric inRange(int64_t Value,unsigned NumBits)115*700637cbSDimitry Andric static bool inRange(int64_t Value, unsigned NumBits) { 116*700637cbSDimitry Andric return Value == 0 || Value == 1; 117*700637cbSDimitry Andric } 118*700637cbSDimitry Andric increment(Boolean A,Boolean * R)119*700637cbSDimitry Andric static bool increment(Boolean A, Boolean *R) { 120*700637cbSDimitry Andric *R = Boolean(true); 121*700637cbSDimitry Andric return false; 122*700637cbSDimitry Andric } 123*700637cbSDimitry Andric decrement(Boolean A,Boolean * R)124*700637cbSDimitry Andric static bool decrement(Boolean A, Boolean *R) { 125*700637cbSDimitry Andric llvm_unreachable("Cannot decrement booleans"); 126*700637cbSDimitry Andric } 127*700637cbSDimitry Andric add(Boolean A,Boolean B,unsigned OpBits,Boolean * R)128*700637cbSDimitry Andric static bool add(Boolean A, Boolean B, unsigned OpBits, Boolean *R) { 129*700637cbSDimitry Andric *R = Boolean(A.V || B.V); 130*700637cbSDimitry Andric return false; 131*700637cbSDimitry Andric } 132*700637cbSDimitry Andric sub(Boolean A,Boolean B,unsigned OpBits,Boolean * R)133*700637cbSDimitry Andric static bool sub(Boolean A, Boolean B, unsigned OpBits, Boolean *R) { 134*700637cbSDimitry Andric *R = Boolean(A.V ^ B.V); 135*700637cbSDimitry Andric return false; 136*700637cbSDimitry Andric } 137*700637cbSDimitry Andric mul(Boolean A,Boolean B,unsigned OpBits,Boolean * R)138*700637cbSDimitry Andric static bool mul(Boolean A, Boolean B, unsigned OpBits, Boolean *R) { 139*700637cbSDimitry Andric *R = Boolean(A.V && B.V); 140*700637cbSDimitry Andric return false; 141*700637cbSDimitry Andric } 142*700637cbSDimitry Andric inv(Boolean A,Boolean * R)143*700637cbSDimitry Andric static bool inv(Boolean A, Boolean *R) { 144*700637cbSDimitry Andric *R = Boolean(!A.V); 145*700637cbSDimitry Andric return false; 146*700637cbSDimitry Andric } 147*700637cbSDimitry Andric neg(Boolean A,Boolean * R)148*700637cbSDimitry Andric static bool neg(Boolean A, Boolean *R) { 149*700637cbSDimitry Andric *R = Boolean(A.V); 150*700637cbSDimitry Andric return false; 151*700637cbSDimitry Andric } 152*700637cbSDimitry Andric }; 153*700637cbSDimitry Andric 154*700637cbSDimitry Andric inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Boolean &B) { 155*700637cbSDimitry Andric B.print(OS); 156*700637cbSDimitry Andric return OS; 157*700637cbSDimitry Andric } 158*700637cbSDimitry Andric 159*700637cbSDimitry Andric } // namespace interp 160*700637cbSDimitry Andric } // namespace clang 161*700637cbSDimitry Andric 162*700637cbSDimitry Andric #endif 163