[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / lib / AST / Interp / IntegralAP.h
blob9aefea6d0c47ed96fb372100ca3c2ccb3274755f
1 //===--- Integral.h - Wrapper for numeric 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 // Defines the VM types and helpers operating on types.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_INTERP_INTEGRAL_AP_H
14 #define LLVM_CLANG_AST_INTERP_INTEGRAL_AP_H
16 #include "clang/AST/APValue.h"
17 #include "clang/AST/ComparisonCategories.h"
18 #include "llvm/ADT/APSInt.h"
19 #include "llvm/Support/MathExtras.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include <cstddef>
22 #include <cstdint>
24 #include "Primitives.h"
26 namespace clang {
27 namespace interp {
29 using APInt = llvm::APInt;
30 using APSInt = llvm::APSInt;
31 template <unsigned Bits, bool Signed> class Integral;
33 template <bool Signed> class IntegralAP final {
34 private:
35 friend IntegralAP<!Signed>;
36 APInt V;
38 template <typename T, bool InputSigned>
39 static T truncateCast(const APInt &V) {
40 constexpr unsigned BitSize = sizeof(T) * 8;
41 if (BitSize >= V.getBitWidth()) {
42 APInt Extended;
43 if constexpr (InputSigned)
44 Extended = V.sext(BitSize);
45 else
46 Extended = V.zext(BitSize);
47 return std::is_signed_v<T> ? Extended.getSExtValue()
48 : Extended.getZExtValue();
51 return std::is_signed_v<T> ? V.trunc(BitSize).getSExtValue()
52 : V.trunc(BitSize).getZExtValue();
55 public:
56 using AsUnsigned = IntegralAP<false>;
58 template <typename T>
59 IntegralAP(T Value, unsigned BitWidth)
60 : V(APInt(BitWidth, static_cast<uint64_t>(Value), Signed)) {}
62 IntegralAP(APInt V) : V(V) {}
63 /// Arbitrary value for uninitialized variables.
64 IntegralAP() : IntegralAP(-1, 1024) {}
66 IntegralAP operator-() const { return IntegralAP(-V); }
67 IntegralAP operator-(const IntegralAP &Other) const {
68 return IntegralAP(V - Other.V);
70 bool operator>(const IntegralAP &RHS) const {
71 if constexpr (Signed)
72 return V.ugt(RHS.V);
73 return V.sgt(RHS.V);
75 bool operator>=(IntegralAP RHS) const {
76 if constexpr (Signed)
77 return V.uge(RHS.V);
78 return V.sge(RHS.V);
80 bool operator<(IntegralAP RHS) const {
81 if constexpr (Signed)
82 return V.slt(RHS.V);
83 return V.slt(RHS.V);
85 bool operator<=(IntegralAP RHS) const {
86 if constexpr (Signed)
87 return V.ult(RHS.V);
88 return V.ult(RHS.V);
91 template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
92 explicit operator Ty() const {
93 return truncateCast<Ty, Signed>(V);
96 template <typename T> static IntegralAP from(T Value, unsigned NumBits = 0) {
97 assert(NumBits > 0);
98 APInt Copy = APInt(NumBits, static_cast<uint64_t>(Value), Signed);
100 return IntegralAP<Signed>(Copy);
103 template <bool InputSigned>
104 static IntegralAP from(IntegralAP<InputSigned> V, unsigned NumBits = 0) {
105 return IntegralAP<Signed>(V.V);
108 template <unsigned Bits, bool InputSigned>
109 static IntegralAP from(Integral<Bits, InputSigned> I, unsigned BitWidth) {
110 APInt Copy = APInt(BitWidth, static_cast<uint64_t>(I), InputSigned);
112 return IntegralAP<Signed>(Copy);
115 static IntegralAP zero(int32_t BitWidth) {
116 APInt V = APInt(BitWidth, 0LL, Signed);
117 return IntegralAP(V);
120 constexpr unsigned bitWidth() const { return V.getBitWidth(); }
122 APSInt toAPSInt(unsigned Bits = 0) const { return APSInt(V, Signed); }
123 APValue toAPValue() const { return APValue(APSInt(V, Signed)); }
125 bool isZero() const { return V.isZero(); }
126 bool isPositive() const { return V.isNonNegative(); }
127 bool isNegative() const { return !V.isNonNegative(); }
128 bool isMin() const { return V.isMinValue(); }
129 bool isMax() const { return V.isMaxValue(); }
130 static constexpr bool isSigned() { return Signed; }
131 bool isMinusOne() const { return Signed && V == -1; }
133 unsigned countLeadingZeros() const { return V.countl_zero(); }
135 void print(llvm::raw_ostream &OS) const { OS << V; }
136 std::string toDiagnosticString(const ASTContext &Ctx) const {
137 std::string NameStr;
138 llvm::raw_string_ostream OS(NameStr);
139 print(OS);
140 return NameStr;
143 IntegralAP truncate(unsigned bitWidth) const {
144 assert(false);
145 return V;
148 IntegralAP<false> toUnsigned() const {
149 APInt Copy = V;
150 return IntegralAP<false>(Copy);
153 ComparisonCategoryResult compare(const IntegralAP &RHS) const {
154 assert(Signed == RHS.isSigned());
155 assert(bitWidth() == RHS.bitWidth());
156 if constexpr (Signed) {
157 if (V.slt(RHS.V))
158 return ComparisonCategoryResult::Less;
159 if (V.sgt(RHS.V))
160 return ComparisonCategoryResult::Greater;
161 return ComparisonCategoryResult::Equal;
164 assert(!Signed);
165 if (V.ult(RHS.V))
166 return ComparisonCategoryResult::Less;
167 if (V.ugt(RHS.V))
168 return ComparisonCategoryResult::Greater;
169 return ComparisonCategoryResult::Equal;
172 static bool increment(IntegralAP A, IntegralAP *R) {
173 // FIXME: Implement.
174 assert(false);
175 *R = IntegralAP(A.V - 1);
176 return false;
179 static bool decrement(IntegralAP A, IntegralAP *R) {
180 // FIXME: Implement.
181 assert(false);
182 *R = IntegralAP(A.V - 1);
183 return false;
186 static bool add(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
187 return CheckAddUB(A, B, OpBits, R);
190 static bool sub(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
191 /// FIXME: Gotta check if the result fits into OpBits bits.
192 return CheckSubUB(A, B, R);
195 static bool mul(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
196 // FIXME: Implement.
197 assert(false);
198 return false;
201 static bool rem(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
202 // FIXME: Implement.
203 assert(false);
204 return false;
207 static bool div(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
208 // FIXME: Implement.
209 assert(false);
210 return false;
213 static bool bitAnd(IntegralAP A, IntegralAP B, unsigned OpBits,
214 IntegralAP *R) {
215 // FIXME: Implement.
216 assert(false);
217 return false;
220 static bool bitOr(IntegralAP A, IntegralAP B, unsigned OpBits,
221 IntegralAP *R) {
222 assert(false);
223 return false;
226 static bool bitXor(IntegralAP A, IntegralAP B, unsigned OpBits,
227 IntegralAP *R) {
228 // FIXME: Implement.
229 assert(false);
230 return false;
233 static bool neg(const IntegralAP &A, IntegralAP *R) {
234 APInt AI = A.V;
235 AI.negate();
236 *R = IntegralAP(AI);
237 return false;
240 static bool comp(IntegralAP A, IntegralAP *R) {
241 *R = IntegralAP(~A.V);
242 return false;
245 static void shiftLeft(const IntegralAP A, const IntegralAP B, unsigned OpBits,
246 IntegralAP *R) {
247 *R = IntegralAP(A.V.shl(B.V.getZExtValue()));
250 static void shiftRight(const IntegralAP A, const IntegralAP B,
251 unsigned OpBits, IntegralAP *R) {
252 *R = IntegralAP(A.V.ashr(B.V.getZExtValue()));
255 private:
256 static bool CheckAddUB(const IntegralAP &A, const IntegralAP &B,
257 unsigned BitWidth, IntegralAP *R) {
258 if (!A.isSigned()) {
259 R->V = A.V + B.V;
260 return false;
263 const APSInt &LHS = APSInt(A.V, A.isSigned());
264 const APSInt &RHS = APSInt(B.V, B.isSigned());
266 APSInt Value(LHS.extend(BitWidth) + RHS.extend(BitWidth), false);
267 APSInt Result = Value.trunc(LHS.getBitWidth());
268 if (Result.extend(BitWidth) != Value)
269 return true;
271 R->V = Result;
272 return false;
274 static bool CheckSubUB(const IntegralAP &A, const IntegralAP &B,
275 IntegralAP *R) {
276 R->V = A.V - B.V;
277 return false; // Success!
281 template <bool Signed>
282 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
283 IntegralAP<Signed> I) {
284 I.print(OS);
285 return OS;
288 } // namespace interp
289 } // namespace clang
291 #endif