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