Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- 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
/// \file
10
/// This file implements the APSInt class, which is a simple class that
11
/// represents an arbitrary sized integer that knows its signedness.
12
///
13
//===----------------------------------------------------------------------===//
14
 
15
#ifndef LLVM_ADT_APSINT_H
16
#define LLVM_ADT_APSINT_H
17
 
18
#include "llvm/ADT/APInt.h"
19
 
20
namespace llvm {
21
 
22
/// An arbitrary precision integer that knows its signedness.
23
class [[nodiscard]] APSInt : public APInt {
24
  bool IsUnsigned = false;
25
 
26
public:
27
  /// Default constructor that creates an uninitialized APInt.
28
  explicit APSInt() = default;
29
 
30
  /// Create an APSInt with the specified width, default to unsigned.
31
  explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
32
      : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
33
 
34
  explicit APSInt(APInt I, bool isUnsigned = true)
35
      : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
36
 
37
  /// Construct an APSInt from a string representation.
38
  ///
39
  /// This constructor interprets the string \p Str using the radix of 10.
40
  /// The interpretation stops at the end of the string. The bit width of the
41
  /// constructed APSInt is determined automatically.
42
  ///
43
  /// \param Str the string to be interpreted.
44
  explicit APSInt(StringRef Str);
45
 
46
  /// Determine sign of this APSInt.
47
  ///
48
  /// \returns true if this APSInt is negative, false otherwise
49
  bool isNegative() const { return isSigned() && APInt::isNegative(); }
50
 
51
  /// Determine if this APSInt Value is non-negative (>= 0)
52
  ///
53
  /// \returns true if this APSInt is non-negative, false otherwise
54
  bool isNonNegative() const { return !isNegative(); }
55
 
56
  /// Determine if this APSInt Value is positive.
57
  ///
58
  /// This tests if the value of this APSInt is positive (> 0). Note
59
  /// that 0 is not a positive value.
60
  ///
61
  /// \returns true if this APSInt is positive.
62
  bool isStrictlyPositive() const { return isNonNegative() && !isZero(); }
63
 
64
  APSInt &operator=(APInt RHS) {
65
    // Retain our current sign.
66
    APInt::operator=(std::move(RHS));
67
    return *this;
68
  }
69
 
70
  APSInt &operator=(uint64_t RHS) {
71
    // Retain our current sign.
72
    APInt::operator=(RHS);
73
    return *this;
74
  }
75
 
76
  // Query sign information.
77
  bool isSigned() const { return !IsUnsigned; }
78
  bool isUnsigned() const { return IsUnsigned; }
79
  void setIsUnsigned(bool Val) { IsUnsigned = Val; }
80
  void setIsSigned(bool Val) { IsUnsigned = !Val; }
81
 
82
  /// Append this APSInt to the specified SmallString.
83
  void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
84
    APInt::toString(Str, Radix, isSigned());
85
  }
86
  using APInt::toString;
87
 
88
  /// If this int is representable using an int64_t.
89
  bool isRepresentableByInt64() const {
90
    // For unsigned values with 64 active bits, they technically fit into a
91
    // int64_t, but the user may get negative numbers and has to manually cast
92
    // them to unsigned. Let's not bet the user has the sanity to do that and
93
    // not give them a vague value at the first place.
94
    return isSigned() ? isSignedIntN(64) : isIntN(63);
95
  }
96
 
97
  /// Get the correctly-extended \c int64_t value.
98
  int64_t getExtValue() const {
99
    assert(isRepresentableByInt64() && "Too many bits for int64_t");
100
    return isSigned() ? getSExtValue() : getZExtValue();
101
  }
102
 
103
  std::optional<int64_t> tryExtValue() const {
104
    return isRepresentableByInt64() ? std::optional<int64_t>(getExtValue())
105
                                    : std::nullopt;
106
  }
107
 
108
  APSInt trunc(uint32_t width) const {
109
    return APSInt(APInt::trunc(width), IsUnsigned);
110
  }
111
 
112
  APSInt extend(uint32_t width) const {
113
    if (IsUnsigned)
114
      return APSInt(zext(width), IsUnsigned);
115
    else
116
      return APSInt(sext(width), IsUnsigned);
117
  }
118
 
119
  APSInt extOrTrunc(uint32_t width) const {
120
    if (IsUnsigned)
121
      return APSInt(zextOrTrunc(width), IsUnsigned);
122
    else
123
      return APSInt(sextOrTrunc(width), IsUnsigned);
124
  }
125
 
126
  const APSInt &operator%=(const APSInt &RHS) {
127
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
128
    if (IsUnsigned)
129
      *this = urem(RHS);
130
    else
131
      *this = srem(RHS);
132
    return *this;
133
  }
134
  const APSInt &operator/=(const APSInt &RHS) {
135
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
136
    if (IsUnsigned)
137
      *this = udiv(RHS);
138
    else
139
      *this = sdiv(RHS);
140
    return *this;
141
  }
142
  APSInt operator%(const APSInt &RHS) const {
143
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
144
    return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
145
  }
146
  APSInt operator/(const APSInt &RHS) const {
147
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
148
    return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
149
  }
150
 
151
  APSInt operator>>(unsigned Amt) const {
152
    return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
153
  }
154
  APSInt &operator>>=(unsigned Amt) {
155
    if (IsUnsigned)
156
      lshrInPlace(Amt);
157
    else
158
      ashrInPlace(Amt);
159
    return *this;
160
  }
161
  APSInt relativeShr(unsigned Amt) const {
162
    return IsUnsigned ? APSInt(relativeLShr(Amt), true)
163
                      : APSInt(relativeAShr(Amt), false);
164
  }
165
 
166
  inline bool operator<(const APSInt &RHS) const {
167
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
168
    return IsUnsigned ? ult(RHS) : slt(RHS);
169
  }
170
  inline bool operator>(const APSInt &RHS) const {
171
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
172
    return IsUnsigned ? ugt(RHS) : sgt(RHS);
173
  }
174
  inline bool operator<=(const APSInt &RHS) const {
175
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
176
    return IsUnsigned ? ule(RHS) : sle(RHS);
177
  }
178
  inline bool operator>=(const APSInt &RHS) const {
179
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
180
    return IsUnsigned ? uge(RHS) : sge(RHS);
181
  }
182
  inline bool operator==(const APSInt &RHS) const {
183
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
184
    return eq(RHS);
185
  }
186
  inline bool operator!=(const APSInt &RHS) const { return !((*this) == RHS); }
187
 
188
  bool operator==(int64_t RHS) const {
189
    return compareValues(*this, get(RHS)) == 0;
190
  }
191
  bool operator!=(int64_t RHS) const {
192
    return compareValues(*this, get(RHS)) != 0;
193
  }
194
  bool operator<=(int64_t RHS) const {
195
    return compareValues(*this, get(RHS)) <= 0;
196
  }
197
  bool operator>=(int64_t RHS) const {
198
    return compareValues(*this, get(RHS)) >= 0;
199
  }
200
  bool operator<(int64_t RHS) const {
201
    return compareValues(*this, get(RHS)) < 0;
202
  }
203
  bool operator>(int64_t RHS) const {
204
    return compareValues(*this, get(RHS)) > 0;
205
  }
206
 
207
  // The remaining operators just wrap the logic of APInt, but retain the
208
  // signedness information.
209
 
210
  APSInt operator<<(unsigned Bits) const {
211
    return APSInt(static_cast<const APInt &>(*this) << Bits, IsUnsigned);
212
  }
213
  APSInt &operator<<=(unsigned Amt) {
214
    static_cast<APInt &>(*this) <<= Amt;
215
    return *this;
216
  }
217
  APSInt relativeShl(unsigned Amt) const {
218
    return IsUnsigned ? APSInt(relativeLShl(Amt), true)
219
                      : APSInt(relativeAShl(Amt), false);
220
  }
221
 
222
  APSInt &operator++() {
223
    ++(static_cast<APInt &>(*this));
224
    return *this;
225
  }
226
  APSInt &operator--() {
227
    --(static_cast<APInt &>(*this));
228
    return *this;
229
  }
230
  APSInt operator++(int) {
231
    return APSInt(++static_cast<APInt &>(*this), IsUnsigned);
232
  }
233
  APSInt operator--(int) {
234
    return APSInt(--static_cast<APInt &>(*this), IsUnsigned);
235
  }
236
  APSInt operator-() const {
237
    return APSInt(-static_cast<const APInt &>(*this), IsUnsigned);
238
  }
239
  APSInt &operator+=(const APSInt &RHS) {
240
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
241
    static_cast<APInt &>(*this) += RHS;
242
    return *this;
243
  }
244
  APSInt &operator-=(const APSInt &RHS) {
245
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
246
    static_cast<APInt &>(*this) -= RHS;
247
    return *this;
248
  }
249
  APSInt &operator*=(const APSInt &RHS) {
250
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
251
    static_cast<APInt &>(*this) *= RHS;
252
    return *this;
253
  }
254
  APSInt &operator&=(const APSInt &RHS) {
255
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
256
    static_cast<APInt &>(*this) &= RHS;
257
    return *this;
258
  }
259
  APSInt &operator|=(const APSInt &RHS) {
260
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
261
    static_cast<APInt &>(*this) |= RHS;
262
    return *this;
263
  }
264
  APSInt &operator^=(const APSInt &RHS) {
265
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
266
    static_cast<APInt &>(*this) ^= RHS;
267
    return *this;
268
  }
269
 
270
  APSInt operator&(const APSInt &RHS) const {
271
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
272
    return APSInt(static_cast<const APInt &>(*this) & RHS, IsUnsigned);
273
  }
274
 
275
  APSInt operator|(const APSInt &RHS) const {
276
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
277
    return APSInt(static_cast<const APInt &>(*this) | RHS, IsUnsigned);
278
  }
279
 
280
  APSInt operator^(const APSInt &RHS) const {
281
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
282
    return APSInt(static_cast<const APInt &>(*this) ^ RHS, IsUnsigned);
283
  }
284
 
285
  APSInt operator*(const APSInt &RHS) const {
286
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
287
    return APSInt(static_cast<const APInt &>(*this) * RHS, IsUnsigned);
288
  }
289
  APSInt operator+(const APSInt &RHS) const {
290
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
291
    return APSInt(static_cast<const APInt &>(*this) + RHS, IsUnsigned);
292
  }
293
  APSInt operator-(const APSInt &RHS) const {
294
    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
295
    return APSInt(static_cast<const APInt &>(*this) - RHS, IsUnsigned);
296
  }
297
  APSInt operator~() const {
298
    return APSInt(~static_cast<const APInt &>(*this), IsUnsigned);
299
  }
300
 
301
  /// Return the APSInt representing the maximum integer value with the given
302
  /// bit width and signedness.
303
  static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
304
    return APSInt(Unsigned ? APInt::getMaxValue(numBits)
305
                           : APInt::getSignedMaxValue(numBits),
306
                  Unsigned);
307
  }
308
 
309
  /// Return the APSInt representing the minimum integer value with the given
310
  /// bit width and signedness.
311
  static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
312
    return APSInt(Unsigned ? APInt::getMinValue(numBits)
313
                           : APInt::getSignedMinValue(numBits),
314
                  Unsigned);
315
  }
316
 
317
  /// Determine if two APSInts have the same value, zero- or
318
  /// sign-extending as needed.
319
  static bool isSameValue(const APSInt &I1, const APSInt &I2) {
320
    return !compareValues(I1, I2);
321
  }
322
 
323
  /// Compare underlying values of two numbers.
324
  static int compareValues(const APSInt &I1, const APSInt &I2) {
325
    if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
326
      return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
327
 
328
    // Check for a bit-width mismatch.
329
    if (I1.getBitWidth() > I2.getBitWidth())
330
      return compareValues(I1, I2.extend(I1.getBitWidth()));
331
    if (I2.getBitWidth() > I1.getBitWidth())
332
      return compareValues(I1.extend(I2.getBitWidth()), I2);
333
 
334
    // We have a signedness mismatch. Check for negative values and do an
335
    // unsigned compare if both are positive.
336
    if (I1.isSigned()) {
337
      assert(!I2.isSigned() && "Expected signed mismatch");
338
      if (I1.isNegative())
339
        return -1;
340
    } else {
341
      assert(I2.isSigned() && "Expected signed mismatch");
342
      if (I2.isNegative())
343
        return 1;
344
    }
345
 
346
    return I1.compare(I2);
347
  }
348
 
349
  static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
350
  static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
351
 
352
  /// Used to insert APSInt objects, or objects that contain APSInt objects,
353
  /// into FoldingSets.
354
  void Profile(FoldingSetNodeID &ID) const;
355
};
356
 
357
inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
358
inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
359
inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
360
inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
361
inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
362
inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
363
 
364
inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
365
  I.print(OS, I.isSigned());
366
  return OS;
367
}
368
 
369
/// Provide DenseMapInfo for APSInt, using the DenseMapInfo for APInt.
370
template <> struct DenseMapInfo<APSInt, void> {
371
  static inline APSInt getEmptyKey() {
372
    return APSInt(DenseMapInfo<APInt, void>::getEmptyKey());
373
  }
374
 
375
  static inline APSInt getTombstoneKey() {
376
    return APSInt(DenseMapInfo<APInt, void>::getTombstoneKey());
377
  }
378
 
379
  static unsigned getHashValue(const APSInt &Key) {
380
    return DenseMapInfo<APInt, void>::getHashValue(Key);
381
  }
382
 
383
  static bool isEqual(const APSInt &LHS, const APSInt &RHS) {
384
    return LHS.getBitWidth() == RHS.getBitWidth() &&
385
           LHS.isUnsigned() == RHS.isUnsigned() && LHS == RHS;
386
  }
387
};
388
 
389
} // end namespace llvm
390
 
391
#endif