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