xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/Boolean.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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