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