1353942Sdim//===--- Boolean.h - Wrapper for boolean types for the VM -------*- C++ -*-===//
2353942Sdim//
3353942Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353942Sdim// See https://llvm.org/LICENSE.txt for license information.
5353942Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353942Sdim//
7353942Sdim//===----------------------------------------------------------------------===//
8353942Sdim
9353942Sdim#ifndef LLVM_CLANG_AST_INTERP_BOOLEAN_H
10353942Sdim#define LLVM_CLANG_AST_INTERP_BOOLEAN_H
11353942Sdim
12353942Sdim#include <cstddef>
13353942Sdim#include <cstdint>
14353942Sdim#include "Integral.h"
15353942Sdim#include "clang/AST/APValue.h"
16353942Sdim#include "clang/AST/ComparisonCategories.h"
17353942Sdim#include "llvm/ADT/APSInt.h"
18353942Sdim#include "llvm/Support/MathExtras.h"
19353942Sdim#include "llvm/Support/raw_ostream.h"
20353942Sdim
21353942Sdimnamespace clang {
22353942Sdimnamespace interp {
23353942Sdim
24353942Sdim/// Wrapper around boolean types.
25353942Sdimclass Boolean {
26353942Sdim private:
27353942Sdim  /// Underlying boolean.
28353942Sdim  bool V;
29353942Sdim
30353942Sdim  /// Construct a wrapper from a boolean.
31353942Sdim  explicit Boolean(bool V) : V(V) {}
32353942Sdim
33353942Sdim public:
34353942Sdim  /// Zero-initializes a boolean.
35353942Sdim  Boolean() : V(false) {}
36353942Sdim
37353942Sdim  bool operator<(Boolean RHS) const { return V < RHS.V; }
38353942Sdim  bool operator>(Boolean RHS) const { return V > RHS.V; }
39353942Sdim  bool operator<=(Boolean RHS) const { return V <= RHS.V; }
40353942Sdim  bool operator>=(Boolean RHS) const { return V >= RHS.V; }
41353942Sdim  bool operator==(Boolean RHS) const { return V == RHS.V; }
42353942Sdim  bool operator!=(Boolean RHS) const { return V != RHS.V; }
43353942Sdim
44353942Sdim  bool operator>(unsigned RHS) const { return static_cast<unsigned>(V) > RHS; }
45353942Sdim
46353942Sdim  Boolean operator-() const { return Boolean(V); }
47353942Sdim  Boolean operator~() const { return Boolean(true); }
48353942Sdim
49353942Sdim  explicit operator unsigned() const { return V; }
50353942Sdim  explicit operator int64_t() const { return V; }
51353942Sdim  explicit operator uint64_t() const { return V; }
52353942Sdim
53353942Sdim  APSInt toAPSInt() const {
54353942Sdim    return APSInt(APInt(1, static_cast<uint64_t>(V), false), true);
55353942Sdim  }
56353942Sdim  APSInt toAPSInt(unsigned NumBits) const {
57353942Sdim    return APSInt(toAPSInt().zextOrTrunc(NumBits), true);
58353942Sdim  }
59353942Sdim  APValue toAPValue() const { return APValue(toAPSInt()); }
60353942Sdim
61353942Sdim  Boolean toUnsigned() const { return *this; }
62353942Sdim
63353942Sdim  constexpr static unsigned bitWidth() { return true; }
64353942Sdim  bool isZero() const { return !V; }
65353942Sdim  bool isMin() const { return isZero(); }
66353942Sdim
67353942Sdim  constexpr static bool isMinusOne() { return false; }
68353942Sdim
69353942Sdim  constexpr static bool isSigned() { return false; }
70353942Sdim
71353942Sdim  constexpr static bool isNegative() { return false; }
72353942Sdim  constexpr static bool isPositive() { return !isNegative(); }
73353942Sdim
74353942Sdim  ComparisonCategoryResult compare(const Boolean &RHS) const {
75353942Sdim    return Compare(V, RHS.V);
76353942Sdim  }
77353942Sdim
78353942Sdim  unsigned countLeadingZeros() const { return V ? 0 : 1; }
79353942Sdim
80353942Sdim  Boolean truncate(unsigned TruncBits) const { return *this; }
81353942Sdim
82353942Sdim  void print(llvm::raw_ostream &OS) const { OS << (V ? "true" : "false"); }
83353942Sdim
84353942Sdim  static Boolean min(unsigned NumBits) { return Boolean(false); }
85353942Sdim  static Boolean max(unsigned NumBits) { return Boolean(true); }
86353942Sdim
87353942Sdim  template <typename T>
88353942Sdim  static typename std::enable_if<std::is_integral<T>::value, Boolean>::type
89353942Sdim  from(T Value) {
90353942Sdim    return Boolean(Value != 0);
91353942Sdim  }
92353942Sdim
93353942Sdim  template <unsigned SrcBits, bool SrcSign>
94353942Sdim  static typename std::enable_if<SrcBits != 0, Boolean>::type from(
95353942Sdim      Integral<SrcBits, SrcSign> Value) {
96353942Sdim    return Boolean(!Value.isZero());
97353942Sdim  }
98353942Sdim
99353942Sdim  template <bool SrcSign>
100353942Sdim  static Boolean from(Integral<0, SrcSign> Value) {
101353942Sdim    return Boolean(!Value.isZero());
102353942Sdim  }
103353942Sdim
104353942Sdim  static Boolean zero() { return from(false); }
105353942Sdim
106353942Sdim  template <typename T>
107353942Sdim  static Boolean from(T Value, unsigned NumBits) {
108353942Sdim    return Boolean(Value);
109353942Sdim  }
110353942Sdim
111353942Sdim  static bool inRange(int64_t Value, unsigned NumBits) {
112353942Sdim    return Value == 0 || Value == 1;
113353942Sdim  }
114353942Sdim
115353942Sdim  static bool increment(Boolean A, Boolean *R) {
116353942Sdim    *R = Boolean(true);
117353942Sdim    return false;
118353942Sdim  }
119353942Sdim
120353942Sdim  static bool decrement(Boolean A, Boolean *R) {
121353942Sdim    llvm_unreachable("Cannot decrement booleans");
122353942Sdim  }
123353942Sdim
124353942Sdim  static bool add(Boolean A, Boolean B, unsigned OpBits, Boolean *R) {
125353942Sdim    *R = Boolean(A.V || B.V);
126353942Sdim    return false;
127353942Sdim  }
128353942Sdim
129353942Sdim  static bool sub(Boolean A, Boolean B, unsigned OpBits, Boolean *R) {
130353942Sdim    *R = Boolean(A.V ^ B.V);
131353942Sdim    return false;
132353942Sdim  }
133353942Sdim
134353942Sdim  static bool mul(Boolean A, Boolean B, unsigned OpBits, Boolean *R) {
135353942Sdim    *R = Boolean(A.V && B.V);
136353942Sdim    return false;
137353942Sdim  }
138353942Sdim};
139353942Sdim
140353942Sdiminline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Boolean &B) {
141353942Sdim  B.print(OS);
142353942Sdim  return OS;
143353942Sdim}
144353942Sdim
145353942Sdim}  // namespace interp
146353942Sdim}  // namespace clang
147353942Sdim
148353942Sdim#endif
149