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