clang 17.0.0git
Integral.h
Go to the documentation of this file.
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.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_INTEGRAL_H
14#define LLVM_CLANG_AST_INTERP_INTEGRAL_H
15
17#include "clang/AST/APValue.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>
23
24#include "Primitives.h"
25
26namespace clang {
27namespace interp {
28
29using APInt = llvm::APInt;
30using APSInt = llvm::APSInt;
31
32// Helper structure to select the representation.
33template <unsigned Bits, bool Signed> struct Repr;
34template <> struct Repr<8, false> { using Type = uint8_t; };
35template <> struct Repr<16, false> { using Type = uint16_t; };
36template <> struct Repr<32, false> { using Type = uint32_t; };
37template <> struct Repr<64, false> { using Type = uint64_t; };
38template <> struct Repr<8, true> { using Type = int8_t; };
39template <> struct Repr<16, true> { using Type = int16_t; };
40template <> struct Repr<32, true> { using Type = int32_t; };
41template <> struct Repr<64, true> { using Type = int64_t; };
42
43/// Wrapper around numeric types.
44///
45/// These wrappers are required to shared an interface between APSint and
46/// builtin primitive numeral types, while optimising for storage and
47/// allowing methods operating on primitive type to compile to fast code.
48template <unsigned Bits, bool Signed> class Integral final {
49private:
50 template <unsigned OtherBits, bool OtherSigned> friend class Integral;
51
52 // The primitive representing the integral.
53 using ReprT = typename Repr<Bits, Signed>::Type;
54 ReprT V;
55
56 /// Primitive representing limits.
57 static const auto Min = std::numeric_limits<ReprT>::min();
58 static const auto Max = std::numeric_limits<ReprT>::max();
59
60 /// Construct an integral from anything that is convertible to storage.
61 template <typename T> explicit Integral(T V) : V(V) {}
62
63public:
64 /// Zero-initializes an integral.
65 Integral() : V(0) {}
66
67 /// Constructs an integral from another integral.
68 template <unsigned SrcBits, bool SrcSign>
70
71 /// Construct an integral from a value based on signedness.
72 explicit Integral(const APSInt &V)
73 : V(V.isSigned() ? V.getSExtValue() : V.getZExtValue()) {}
74
75 bool operator<(Integral RHS) const { return V < RHS.V; }
76 bool operator>(Integral RHS) const { return V > RHS.V; }
77 bool operator<=(Integral RHS) const { return V <= RHS.V; }
78 bool operator>=(Integral RHS) const { return V >= RHS.V; }
79 bool operator==(Integral RHS) const { return V == RHS.V; }
80 bool operator!=(Integral RHS) const { return V != RHS.V; }
81
82 bool operator>(unsigned RHS) const {
83 return V >= 0 && static_cast<unsigned>(V) > RHS;
84 }
85
86 Integral operator-() const { return Integral(-V); }
87 Integral operator~() const { return Integral(~V); }
88
89 template <unsigned DstBits, bool DstSign>
90 explicit operator Integral<DstBits, DstSign>() const {
92 }
93
94 explicit operator unsigned() const { return V; }
95 explicit operator int64_t() const { return V; }
96 explicit operator uint64_t() const { return V; }
97
98 APSInt toAPSInt() const {
99 return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed);
100 }
101 APSInt toAPSInt(unsigned NumBits) const {
102 if constexpr (Signed)
103 return APSInt(toAPSInt().sextOrTrunc(NumBits), !Signed);
104 else
105 return APSInt(toAPSInt().zextOrTrunc(NumBits), !Signed);
106 }
107 APValue toAPValue() const { return APValue(toAPSInt()); }
108
110 return Integral<Bits, false>(*this);
111 }
112
113 constexpr static unsigned bitWidth() { return Bits; }
114
115 bool isZero() const { return !V; }
116
117 bool isMin() const { return *this == min(bitWidth()); }
118
119 bool isMinusOne() const { return Signed && V == ReprT(-1); }
120
121 constexpr static bool isSigned() { return Signed; }
122
123 bool isNegative() const { return V < ReprT(0); }
124 bool isPositive() const { return !isNegative(); }
125
127 return Compare(V, RHS.V);
128 }
129
130 unsigned countLeadingZeros() const { return llvm::countl_zero<ReprT>(V); }
131
132 Integral truncate(unsigned TruncBits) const {
133 if (TruncBits >= Bits)
134 return *this;
135 const ReprT BitMask = (ReprT(1) << ReprT(TruncBits)) - 1;
136 const ReprT SignBit = ReprT(1) << (TruncBits - 1);
137 const ReprT ExtMask = ~BitMask;
138 return Integral((V & BitMask) | (Signed && (V & SignBit) ? ExtMask : 0));
139 }
140
141 void print(llvm::raw_ostream &OS) const { OS << V; }
142
143 static Integral min(unsigned NumBits) {
144 return Integral(Min);
145 }
146 static Integral max(unsigned NumBits) {
147 return Integral(Max);
148 }
149
150 template <typename ValT> static Integral from(ValT Value) {
151 if constexpr (std::is_integral<ValT>::value)
152 return Integral(Value);
153 else
154 return Integral::from(static_cast<Integral::ReprT>(Value));
155 }
156
157 template <unsigned SrcBits, bool SrcSign>
158 static std::enable_if_t<SrcBits != 0, Integral>
160 return Integral(Value.V);
161 }
162
163 template <bool SrcSign> static Integral from(Integral<0, SrcSign> Value) {
164 if constexpr (SrcSign)
165 return Integral(Value.V.getSExtValue());
166 else
167 return Integral(Value.V.getZExtValue());
168 }
169
170 static Integral zero() { return from(0); }
171
172 template <typename T> static Integral from(T Value, unsigned NumBits) {
173 return Integral(Value);
174 }
175
176 static bool inRange(int64_t Value, unsigned NumBits) {
177 return CheckRange<ReprT, Min, Max>(Value);
178 }
179
180 static bool increment(Integral A, Integral *R) {
181 return add(A, Integral(ReprT(1)), A.bitWidth(), R);
182 }
183
184 static bool decrement(Integral A, Integral *R) {
185 return sub(A, Integral(ReprT(1)), A.bitWidth(), R);
186 }
187
188 static bool add(Integral A, Integral B, unsigned OpBits, Integral *R) {
189 return CheckAddUB(A.V, B.V, R->V);
190 }
191
192 static bool sub(Integral A, Integral B, unsigned OpBits, Integral *R) {
193 return CheckSubUB(A.V, B.V, R->V);
194 }
195
196 static bool mul(Integral A, Integral B, unsigned OpBits, Integral *R) {
197 return CheckMulUB(A.V, B.V, R->V);
198 }
199
200 static bool rem(Integral A, Integral B, unsigned OpBits, Integral *R) {
201 *R = Integral(A.V % B.V);
202 return false;
203 }
204
205 static bool div(Integral A, Integral B, unsigned OpBits, Integral *R) {
206 *R = Integral(A.V / B.V);
207 return false;
208 }
209
210 static bool bitAnd(Integral A, Integral B, unsigned OpBits, Integral *R) {
211 *R = Integral(A.V & B.V);
212 return false;
213 }
214
215 static bool bitOr(Integral A, Integral B, unsigned OpBits, Integral *R) {
216 *R = Integral(A.V | B.V);
217 return false;
218 }
219
220 static bool bitXor(Integral A, Integral B, unsigned OpBits, Integral *R) {
221 *R = Integral(A.V ^ B.V);
222 return false;
223 }
224
225 static bool neg(Integral A, Integral *R) {
226 *R = -A;
227 return false;
228 }
229
230 static bool comp(Integral A, Integral *R) {
231 *R = Integral(~A.V);
232 return false;
233 }
234
235 template <unsigned RHSBits, bool RHSSign>
236 static void shiftLeft(const Integral A, const Integral<RHSBits, RHSSign> B,
237 unsigned OpBits, Integral *R) {
238 *R = Integral::from(A.V << B.V, OpBits);
239 }
240
241 template <unsigned RHSBits, bool RHSSign>
242 static void shiftRight(const Integral A, const Integral<RHSBits, RHSSign> B,
243 unsigned OpBits, Integral *R) {
244 *R = Integral::from(A.V >> B.V, OpBits);
245 }
246
247private:
248 template <typename T> static bool CheckAddUB(T A, T B, T &R) {
249 if constexpr (std::is_signed_v<T>) {
250 return llvm::AddOverflow<T>(A, B, R);
251 } else {
252 R = A + B;
253 return false;
254 }
255 }
256
257 template <typename T> static bool CheckSubUB(T A, T B, T &R) {
258 if constexpr (std::is_signed_v<T>) {
259 return llvm::SubOverflow<T>(A, B, R);
260 } else {
261 R = A - B;
262 return false;
263 }
264 }
265
266 template <typename T> static bool CheckMulUB(T A, T B, T &R) {
267 if constexpr (std::is_signed_v<T>) {
268 return llvm::MulOverflow<T>(A, B, R);
269 } else {
270 R = A * B;
271 return false;
272 }
273 }
274 template <typename T, T Min, T Max> static bool CheckRange(int64_t V) {
275 if constexpr (std::is_signed_v<T>) {
276 return Min <= V && V <= Max;
277 } else {
278 return V >= 0 && static_cast<uint64_t>(V) <= Max;
279 }
280 }
281};
282
283template <unsigned Bits, bool Signed>
284llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Integral<Bits, Signed> I) {
285 I.print(OS);
286 return OS;
287}
288
289} // namespace interp
290} // namespace clang
291
292#endif
#define V(N, I)
Definition: ASTContext.h:3217
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
Wrapper around numeric types.
Definition: Integral.h:48
Integral< Bits, false > toUnsigned() const
Definition: Integral.h:109
bool isMinusOne() const
Definition: Integral.h:119
bool isNegative() const
Definition: Integral.h:123
APValue toAPValue() const
Definition: Integral.h:107
static Integral max(unsigned NumBits)
Definition: Integral.h:146
Integral()
Zero-initializes an integral.
Definition: Integral.h:65
static bool mul(Integral A, Integral B, unsigned OpBits, Integral *R)
Definition: Integral.h:196
bool operator>=(Integral RHS) const
Definition: Integral.h:78
friend class Integral
Definition: Integral.h:50
void print(llvm::raw_ostream &OS) const
Definition: Integral.h:141
static bool sub(Integral A, Integral B, unsigned OpBits, Integral *R)
Definition: Integral.h:192
static constexpr unsigned bitWidth()
Definition: Integral.h:113
APSInt toAPSInt() const
Definition: Integral.h:98
static void shiftRight(const Integral A, const Integral< RHSBits, RHSSign > B, unsigned OpBits, Integral *R)
Definition: Integral.h:242
bool operator>(Integral RHS) const
Definition: Integral.h:76
bool operator>(unsigned RHS) const
Definition: Integral.h:82
bool isZero() const
Definition: Integral.h:115
unsigned countLeadingZeros() const
Definition: Integral.h:130
Integral operator~() const
Definition: Integral.h:87
Integral truncate(unsigned TruncBits) const
Definition: Integral.h:132
bool operator<(Integral RHS) const
Definition: Integral.h:75
ComparisonCategoryResult compare(const Integral &RHS) const
Definition: Integral.h:126
static Integral from(ValT Value)
Definition: Integral.h:150
bool isMin() const
Definition: Integral.h:117
static bool neg(Integral A, Integral *R)
Definition: Integral.h:225
bool operator!=(Integral RHS) const
Definition: Integral.h:80
static bool decrement(Integral A, Integral *R)
Definition: Integral.h:184
static bool comp(Integral A, Integral *R)
Definition: Integral.h:230
Integral(Integral< SrcBits, SrcSign > V)
Constructs an integral from another integral.
Definition: Integral.h:69
static Integral from(T Value, unsigned NumBits)
Definition: Integral.h:172
bool operator<=(Integral RHS) const
Definition: Integral.h:77
static bool div(Integral A, Integral B, unsigned OpBits, Integral *R)
Definition: Integral.h:205
static bool inRange(int64_t Value, unsigned NumBits)
Definition: Integral.h:176
APSInt toAPSInt(unsigned NumBits) const
Definition: Integral.h:101
static bool bitXor(Integral A, Integral B, unsigned OpBits, Integral *R)
Definition: Integral.h:220
static bool rem(Integral A, Integral B, unsigned OpBits, Integral *R)
Definition: Integral.h:200
bool operator==(Integral RHS) const
Definition: Integral.h:79
Integral(const APSInt &V)
Construct an integral from a value based on signedness.
Definition: Integral.h:72
static Integral min(unsigned NumBits)
Definition: Integral.h:143
static Integral zero()
Definition: Integral.h:170
static Integral from(Integral< 0, SrcSign > Value)
Definition: Integral.h:163
static constexpr bool isSigned()
Definition: Integral.h:121
static void shiftLeft(const Integral A, const Integral< RHSBits, RHSSign > B, unsigned OpBits, Integral *R)
Definition: Integral.h:236
static bool bitOr(Integral A, Integral B, unsigned OpBits, Integral *R)
Definition: Integral.h:215
Integral operator-() const
Definition: Integral.h:86
bool isPositive() const
Definition: Integral.h:124
static std::enable_if_t< SrcBits !=0, Integral > from(Integral< SrcBits, SrcSign > Value)
Definition: Integral.h:159
static bool add(Integral A, Integral B, unsigned OpBits, Integral *R)
Definition: Integral.h:188
static bool increment(Integral A, Integral *R)
Definition: Integral.h:180
static bool bitAnd(Integral A, Integral B, unsigned OpBits, Integral *R)
Definition: Integral.h:210
llvm::APInt APInt
Definition: Integral.h:29
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const Boolean &B)
Definition: Boolean.h:154
ComparisonCategoryResult Compare(const T &X, const T &Y)
Helper to compare two comparable types.
Definition: Primitives.h:25
llvm::APSInt APSInt
Definition: Floating.h:24
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
unsigned long uint64_t
#define true
Definition: stdbool.h:21
#define false
Definition: stdbool.h:22