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