CIRCT  20.0.0git
FVInt.h
Go to the documentation of this file.
1 //===- FVInt.h - Four-valued integer ----------------------------*- 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 // This file implements a class to represent arbitrary precision integers where
10 // each bit can be one of four values. This corresponds to SystemVerilog's
11 // four-valued `logic` type (originally defined in IEEE 1364, later merged into
12 // IEEE 1800).
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef CIRCT_SUPPORT_FVINT_H
17 #define CIRCT_SUPPORT_FVINT_H
18 
19 #include "circt/Support/LLVM.h"
20 #include "llvm/ADT/APInt.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Support/raw_ostream.h"
24 
25 namespace circt {
26 
27 /// Four-valued arbitrary precision integers.
28 ///
29 /// Each bit of the integer can be 0, 1, X, or Z. Internally the bits are stored
30 /// in a pair of `APInt`s, one of which specifies the value of each bit (0/X or
31 /// 1/Z), and the other whether the bit is unknown (X or Z).
32 class FVInt {
33 public:
34  /// Default constructor that creates an zero-bit zero value.
35  explicit FVInt() : FVInt(0, 0) {}
36 
37  /// Construct an `FVInt` from a 64-bit value. The result has no X or Z bits.
38  FVInt(unsigned numBits, uint64_t value, bool isSigned = false)
39  : FVInt(APInt(numBits, value, isSigned)) {}
40 
41  /// Construct an `FVInt` from an `APInt`. The result has no X or Z bits.
42  FVInt(const APInt &value)
43  : value(value), unknown(APInt::getZero(value.getBitWidth())) {}
44 
45  /// Construct an `FVInt` from two `APInt`s used internally to store the bit
46  /// data. The first argument specifies whether each bit is 0/X or 1/Z. The
47  /// second argument specifies whether each bit is 0/1 or X/Z. Both `APInt`s
48  /// must have the same bitwidth. The two arguments correspond to the results
49  /// of `getRawValue()` and `getRawUnknown()`.
50  FVInt(APInt &&rawValue, APInt &&rawUnknown)
51  : value(rawValue), unknown(rawUnknown) {
52  assert(rawValue.getBitWidth() == rawUnknown.getBitWidth());
53  }
54 
55  /// Construct an `FVInt` with all bits set to 0.
56  static FVInt getZero(unsigned numBits) {
57  return FVInt(APInt::getZero(numBits));
58  }
59 
60  /// Construct an `FVInt` with all bits set to 1.
61  static FVInt getAllOnes(unsigned numBits) {
62  return FVInt(APInt::getAllOnes(numBits));
63  }
64 
65  /// Construct an `FVInt` with all bits set to X.
66  static FVInt getAllX(unsigned numBits) {
67  return FVInt(APInt::getZero(numBits), APInt::getAllOnes(numBits));
68  }
69 
70  /// Construct an `FVInt` with all bits set to Z.
71  static FVInt getAllZ(unsigned numBits) {
72  return FVInt(APInt::getAllOnes(numBits), APInt::getAllOnes(numBits));
73  }
74 
75  /// Return the number of bits this integer has.
76  unsigned getBitWidth() const { return value.getBitWidth(); }
77 
78  /// Compute the number of active bits in the value. This is the smallest bit
79  /// width to which the value can be truncated without losing information in
80  /// the most significant bits. Or put differently, the value truncated to its
81  /// active bits and zero-extended back to its original width produces the
82  /// original value.
83  unsigned getActiveBits() const {
84  return std::max(value.getActiveBits(), unknown.getActiveBits());
85  }
86 
87  /// Compute the minimum bit width necessary to accurately represent this
88  /// integer's value and sign. This is the smallest bit width to which the
89  /// value can be truncated without losing information in the most significant
90  /// bits and without flipping from negative to positive or vice versa. Or put
91  /// differently, the value truncated to its significant bits and sign-extended
92  /// back to its original width produces the original value.
93  unsigned getSignificantBits() const {
94  return std::max(value.getSignificantBits(), unknown.getSignificantBits());
95  }
96 
97  /// Return the underlying `APInt` used to store whether a bit is 0/X or 1/Z.
98  const APInt &getRawValue() const { return value; }
99 
100  /// Return the underlying `APInt` used to store whether a bit is unknown (X or
101  /// Z).
102  const APInt &getRawUnknown() const { return unknown; }
103 
104  /// Convert the four-valued `FVInt` to a two-valued `APInt` by mapping X and Z
105  /// bits to either 0 or 1.
106  APInt toAPInt(bool unknownBitMapping) const {
107  auto v = value;
108  if (unknownBitMapping)
109  v |= unknown; // set unknown bits to 1
110  else
111  v &= ~unknown; // set unknown bits to 0
112  return v;
113  }
114 
115  //===--------------------------------------------------------------------===//
116  // Resizing
117  //===--------------------------------------------------------------------===//
118 
119  /// Truncate the integer to a smaller bit width. This simply discards the
120  /// high-order bits. If the integer is truncated to a bit width less than its
121  /// "active bits", information will be lost and the resulting integer will
122  /// have a different value.
123  FVInt trunc(unsigned bitWidth) const {
124  assert(bitWidth <= getBitWidth());
125  return FVInt(value.trunc(bitWidth), unknown.trunc(bitWidth));
126  }
127 
128  /// Zero-extend the integer to a new bit width. The additional high-order bits
129  /// are filled in with zero.
130  FVInt zext(unsigned bitWidth) const {
131  assert(bitWidth >= getBitWidth());
132  return FVInt(value.zext(bitWidth), unknown.zext(bitWidth));
133  }
134 
135  /// Sign-extend the integer to a new bit width. The additional high-order bits
136  /// are filled in with the sign bit (top-most bit) of the original number,
137  /// also when that sign bit is X or Z. Zero-width integers are extended with
138  /// zeros.
139  FVInt sext(unsigned bitWidth) const {
140  assert(bitWidth >= getBitWidth());
141  return FVInt(value.sext(bitWidth), unknown.sext(bitWidth));
142  }
143 
144  /// Truncate or zero-extend to a target bit width.
145  FVInt zextOrTrunc(unsigned bitWidth) const {
146  return bitWidth > getBitWidth() ? zext(bitWidth) : trunc(bitWidth);
147  }
148 
149  /// Truncate or sign-extend to a target bit width.
150  FVInt sextOrTrunc(unsigned bitWidth) const {
151  return bitWidth > getBitWidth() ? sext(bitWidth) : trunc(bitWidth);
152  }
153 
154  //===--------------------------------------------------------------------===//
155  // Value Tests
156  //===--------------------------------------------------------------------===//
157 
158  /// Determine if any bits are X or Z.
159  bool hasUnknown() const { return !unknown.isZero(); }
160 
161  /// Determine if all bits are 0. This is true for zero-width values.
162  bool isZero() const { return value.isZero() && unknown.isZero(); }
163 
164  /// Determine if all bits are 1. This is true for zero-width values.
165  bool isAllOnes() const { return value.isAllOnes() && unknown.isZero(); }
166 
167  /// Determine if all bits are X. This is true for zero-width values.
168  bool isAllX() const { return value.isZero() && unknown.isAllOnes(); }
169 
170  /// Determine if all bits are Z. This is true for zero-width values.
171  bool isAllZ() const { return value.isAllOnes() && unknown.isAllOnes(); }
172 
173  /// Determine whether the integer interpreted as a signed number would be
174  /// negative. Returns true if the sign bit is 1, and false if it is 0, X, or
175  /// Z.
176  bool isNegative() const {
177  auto idx = getBitWidth() - 1;
178  return value[idx] && !unknown[idx];
179  }
180 
181  //===--------------------------------------------------------------------===//
182  // Bit Manipulation
183  //===--------------------------------------------------------------------===//
184 
185  /// The value of an individual bit. Can be 0, 1, X, or Z.
186  enum Bit { V0 = 0b00, V1 = 0b01, X = 0b10, Z = 0b11 };
187 
188  /// Get the value of an individual bit.
189  Bit getBit(unsigned index) const {
190  return static_cast<Bit>(value[index] | unknown[index] << 1);
191  }
192 
193  /// Set the value of an individual bit.
194  void setBit(unsigned index, Bit bit) {
195  value.setBitVal(index, (bit >> 0) & 1);
196  unknown.setBitVal(index, (bit >> 1) & 1);
197  }
198 
199  /// Compute a mask of all the 0 bits in this integer.
200  APInt getZeroBits() const { return ~value & ~unknown; }
201 
202  /// Compute a mask of all the 1 bits in this integer.
203  APInt getOneBits() const { return value & ~unknown; }
204 
205  /// Compute a mask of all the X bits in this integer.
206  APInt getXBits() const { return ~value & unknown; }
207 
208  /// Compute a mask of all the Z bits in this integer.
209  APInt getZBits() const { return value & unknown; }
210 
211  /// Compute a mask of all the X and Z bits in this integer.
212  APInt getUnknownBits() const { return unknown; }
213 
214  /// Set the value of all bits in the mask to 0.
215  template <typename T>
216  void setZeroBits(const T &mask) {
217  value &= ~mask;
218  unknown &= ~mask;
219  }
220 
221  /// Set the value of all bits in the mask to 1.
222  template <typename T>
223  void setOneBits(const T &mask) {
224  value |= mask;
225  unknown &= ~mask;
226  }
227 
228  /// Set the value of all bits in the mask to X.
229  template <typename T>
230  void setXBits(const T &mask) {
231  value &= ~mask;
232  unknown |= mask;
233  }
234 
235  /// Set the value of all bits in the mask to Z.
236  template <typename T>
237  void setZBits(const T &mask) {
238  value |= mask;
239  unknown |= mask;
240  }
241 
242  /// Set all bits to 0.
243  void setAllZero() {
244  value.clearAllBits();
245  unknown.clearAllBits();
246  }
247 
248  /// Set all bits to 1.
249  void setAllOne() {
250  value.setAllBits();
251  unknown.clearAllBits();
252  }
253 
254  /// Set all bits to X.
255  void setAllX() {
256  value.clearAllBits();
257  unknown.setAllBits();
258  }
259 
260  /// Set all bits to Z.
261  void setAllZ() {
262  value.setAllBits();
263  unknown.setAllBits();
264  }
265 
266  /// Replace all Z bits with X. This is useful since most logic operations will
267  /// treat X and Z bits the same way and produce an X bit in the output. By
268  /// mapping Z bits to X, these operations can then just handle 0, 1, and X
269  /// bits.
270  void replaceZWithX() {
271  // Z bits have value and unknown set to 1. X bits have value set to 0 and
272  // unknown set to 1. To convert between the two, make sure that value is 0
273  // wherever unknown is 1.
274  value &= ~unknown;
275  }
276 
277  /// If any bits are X or Z, set the entire integer to X.
279  if (hasUnknown())
280  setAllX();
281  }
282 
283  /// If any bits in this integer or another integer are X or Z, set the entire
284  /// integer to X. This is useful for binary operators which want to set their
285  /// result to X if either of the two inputs contained an X or Z bit.
286  void setAllXIfAnyUnknown(const FVInt &other) {
287  if (hasUnknown() || other.hasUnknown())
288  setAllX();
289  }
290 
291  //===--------------------------------------------------------------------===//
292  // Shift Operators
293  //===--------------------------------------------------------------------===//
294 
295  /// Perform a logical left-shift. If any bits in the shift amount are unknown,
296  /// the entire result is X.
297  FVInt &operator<<=(const FVInt &amount) {
298  if (amount.hasUnknown()) {
299  setAllX();
300  } else {
301  value <<= amount.value;
302  unknown <<= amount.value;
303  }
304  return *this;
305  }
306 
307  /// Perform a logical left-shift by a two-valued amount.
308  template <typename T>
309  FVInt &operator<<=(const T &amount) {
310  value <<= amount;
311  unknown <<= amount;
312  return *this;
313  }
314 
315  //===--------------------------------------------------------------------===//
316  // Logic Operators
317  //===--------------------------------------------------------------------===//
318 
319  /// Compute the logical NOT of this integer. This implements the following
320  /// bit-wise truth table:
321  /// ```
322  /// 0 | 1
323  /// 1 | 0
324  /// X | X
325  /// Z | X
326  /// ```
327  void flipAllBits() {
328  value = ~value;
329  replaceZWithX();
330  }
331 
332  /// Compute the logical NOT.
333  FVInt operator~() const {
334  auto v = *this;
335  v.flipAllBits();
336  return v;
337  }
338 
339  /// Compute the logical AND of this integer and another. This implements the
340  /// following bit-wise truth table:
341  /// ```
342  /// 0 1 X Z
343  /// +--------
344  /// 0 | 0 0 0 0
345  /// 1 | 0 1 X X
346  /// X | 0 X X X
347  /// Z | 0 X X X
348  /// ```
349  FVInt &operator&=(const FVInt &other) {
350  auto zeros = getZeroBits() | other.getZeroBits();
351  value &= other.value;
352  unknown |= other.unknown;
353  unknown &= ~zeros;
354  replaceZWithX();
355  return *this;
356  }
357 
358  /// Compute the logical AND of this integer and a two-valued integer.
359  template <typename T>
360  FVInt &operator&=(T other) {
361  value &= other;
362  unknown &= other; // make 0 bits known
363  replaceZWithX();
364  return *this;
365  }
366 
367  /// Compute the logical AND.
368  template <typename T>
369  FVInt operator&(const T &other) const {
370  auto v = *this;
371  v &= other;
372  return v;
373  }
374 
375  /// Compute the logical OR of this integer and another. This implements the
376  /// following bit-wise truth table:
377  /// ```
378  /// 0 1 X Z
379  /// +--------
380  /// 0 | 0 1 X X
381  /// 1 | 1 1 1 1
382  /// X | X 1 X X
383  /// Z | X 1 X X
384  /// ```
385  FVInt &operator|=(const FVInt &other) {
386  auto ones = getOneBits() | other.getOneBits();
387  value |= other.value;
388  unknown |= other.unknown;
389  unknown &= ~ones;
390  replaceZWithX();
391  return *this;
392  }
393 
394  /// Compute the logical OR of this integer and a two-valued integer.
395  template <typename T>
396  FVInt &operator|=(T other) {
397  value |= other;
398  unknown &= ~other; // make 1 bits known
399  replaceZWithX();
400  return *this;
401  }
402 
403  /// Compute the logical OR.
404  template <typename T>
405  FVInt operator|(const T &other) const {
406  auto v = *this;
407  v |= other;
408  return v;
409  }
410 
411  /// Compute the logical XOR of this integer and another. This implements the
412  /// following bit-wise truth table:
413  /// ```
414  /// 0 1 X Z
415  /// +--------
416  /// 0 | 0 1 X X
417  /// 1 | 1 0 X X
418  /// X | X X X X
419  /// Z | X X X X
420  /// ```
421  FVInt &operator^=(const FVInt &other) {
422  value ^= other.value;
423  unknown |= other.unknown;
424  replaceZWithX();
425  return *this;
426  }
427 
428  /// Compute the logical XOR of this integer and a two-valued integer.
429  template <typename T>
430  FVInt &operator^=(const T &other) {
431  value ^= other;
432  replaceZWithX();
433  return *this;
434  }
435 
436  /// Compute the logical XOR.
437  template <typename T>
438  FVInt operator^(const T &other) const {
439  auto v = *this;
440  v ^= other;
441  return v;
442  }
443 
444  //===--------------------------------------------------------------------===//
445  // Arithmetic Operators
446  //===--------------------------------------------------------------------===//
447 
448  /// Compute the negation of this integer. If any bits are unknown, the entire
449  /// result is X.
450  void negate() {
451  value.negate();
453  }
454 
455  /// Compute the negation of this integer.
456  FVInt operator-() const {
457  auto v = *this;
458  v.negate();
459  return v;
460  }
461 
462  /// Compute the addition of this integer and another. If any bits in either
463  /// integer are unknown, the entire result is X.
464  FVInt &operator+=(const FVInt &other) {
465  value += other.value;
466  setAllXIfAnyUnknown(other);
467  return *this;
468  }
469 
470  /// Compute the addition of this integer and a two-valued integer. If any bit
471  /// in the integer is unknown, the entire result is X.
472  template <typename T>
473  FVInt &operator+=(const T &other) {
474  value += other;
476  return *this;
477  }
478 
479  /// Compute an addition.
480  template <typename T>
481  FVInt operator+(const T &other) const {
482  auto v = *this;
483  v += other;
484  return v;
485  }
486 
487  /// Compute the subtraction of this integer and another. If any bits in either
488  /// integer are unknown, the entire result is X.
489  FVInt &operator-=(const FVInt &other) {
490  value -= other.value;
491  setAllXIfAnyUnknown(other);
492  return *this;
493  }
494 
495  /// Compute the subtraction of this integer and a two-valued integer. If any
496  /// bit in the integer is unknown, the entire result is X.
497  template <typename T>
498  FVInt &operator-=(const T &other) {
499  value -= other;
501  return *this;
502  }
503 
504  /// Compute an subtraction.
505  template <typename T>
506  FVInt operator-(const T &other) const {
507  auto v = *this;
508  v -= other;
509  return v;
510  }
511 
512  /// Compute the multiplication of this integer and another. If any bits in
513  /// either integer are unknown, the entire result is X.
514  FVInt &operator*=(const FVInt &other) {
515  value *= other.value;
516  setAllXIfAnyUnknown(other);
517  return *this;
518  }
519 
520  /// Compute the multiplication of this integer and a two-valued integer. If
521  /// any bit in the integer is unknown, the entire result is X.
522  template <typename T>
523  FVInt &operator*=(const T &other) {
524  value *= other;
526  return *this;
527  }
528 
529  /// Compute a multiplication.
530  template <typename T>
531  FVInt operator*(const T &other) const {
532  auto v = *this;
533  v *= other;
534  return v;
535  }
536 
537  //===--------------------------------------------------------------------===//
538  // Comparison
539  //===--------------------------------------------------------------------===//
540 
541  /// Determine whether this integer is equal to another. Note that this
542  /// corresponds to SystemVerilog's `===` operator. Returns false if the two
543  /// integers have different bit width.
544  bool operator==(const FVInt &other) const {
545  if (getBitWidth() != other.getBitWidth())
546  return false;
547  return value == other.value && unknown == other.unknown;
548  }
549 
550  /// Determine whether this integer is equal to a two-valued integer. Note that
551  /// this corresponds to SystemVerilog's `===` operator.
552  template <typename T>
553  bool operator==(const T &other) const {
554  return value == other && !hasUnknown();
555  }
556 
557  /// Determine whether this integer is not equal to another. Returns true if
558  /// the two integers have different bit width.
559  bool operator!=(const FVInt &other) const { return !((*this) == other); }
560 
561  /// Determine whether this integer is not equal to a two-valued integer.
562  template <typename T>
563  bool operator!=(const T &other) const {
564  return !((*this) == other);
565  }
566 
567  //===--------------------------------------------------------------------===//
568  // String Conversion
569  //===--------------------------------------------------------------------===//
570 
571  /// Convert a string into an `FVInt`.
572  ///
573  /// The radix can be 2, 8, 10, or 16. For radix 2, the input string may
574  /// contain the characters `x` or `X` to indicate an unknown X bit, and `z` or
575  /// `Z` to indicate an unknown Z bit. For radix 8, each X or Z counts as 3
576  /// bits. For radix 16, each X and Z counts as 4 bits. When radix is 10 the
577  /// input cannot contain any X or Z.
578  ///
579  /// Returns the parsed integer if the string is non-empty and a well-formed
580  /// number, otherwise returns none.
581  static std::optional<FVInt> tryFromString(StringRef str, unsigned radix = 10);
582 
583  /// Convert a string into an `FVInt`. Same as `tryFromString`, but aborts if
584  /// the string is malformed.
585  static FVInt fromString(StringRef str, unsigned radix = 10) {
586  auto v = tryFromString(str, radix);
587  assert(v.has_value() && "string is not a well-formed FVInt");
588  return *v;
589  }
590 
591  /// Convert an `FVInt` to a string.
592  ///
593  /// The radix can be 2, 8, 10, or 16. For radix 8 or 16, the integer can only
594  /// contain unknown bits in groups of 3 or 4, respectively, such that a `X` or
595  /// `Z` can be printed for the entire group of bits. For radix 10, the integer
596  /// cannot contain any unknown bits. In case the output contains letters,
597  /// `uppercase` specifies whether they are printed as uppercase letters.
598  ///
599  /// Appends the output characters to `str` and returns true if the integer
600  /// could be printed with the given configuration. Otherwise returns false and
601  /// leaves `str` in its original state. Always succeeds for radix 2.
602  bool tryToString(SmallVectorImpl<char> &str, unsigned radix = 10,
603  bool uppercase = true) const;
604 
605  /// Convert an `FVInt` to a string. Same as `tryToString`, but directly
606  /// returns the string and aborts if the conversion is unsuccessful.
607  SmallString<16> toString(unsigned radix = 10, bool uppercase = true) const {
608  SmallString<16> str;
609  bool success = tryToString(str, radix, uppercase);
610  assert(success && "radix cannot represent FVInt");
611  return str;
612  }
613 
614  /// Print an `FVInt` to an output stream.
615  void print(raw_ostream &os) const;
616 
617 private:
618  APInt value;
619  APInt unknown;
620 };
621 
622 inline FVInt operator&(uint64_t a, const FVInt &b) { return b & a; }
623 inline FVInt operator|(uint64_t a, const FVInt &b) { return b | a; }
624 inline FVInt operator^(uint64_t a, const FVInt &b) { return b ^ a; }
625 inline FVInt operator+(uint64_t a, const FVInt &b) { return b + a; }
626 inline FVInt operator*(uint64_t a, const FVInt &b) { return b * a; }
627 
628 inline FVInt operator&(const APInt &a, const FVInt &b) { return b & a; }
629 inline FVInt operator|(const APInt &a, const FVInt &b) { return b | a; }
630 inline FVInt operator^(const APInt &a, const FVInt &b) { return b ^ a; }
631 inline FVInt operator+(const APInt &a, const FVInt &b) { return b + a; }
632 inline FVInt operator*(const APInt &a, const FVInt &b) { return b * a; }
633 
634 inline FVInt operator-(uint64_t a, const FVInt &b) {
635  return FVInt(b.getBitWidth(), a) - b;
636 }
637 
638 inline FVInt operator-(const APInt &a, const FVInt &b) { return FVInt(a) - b; }
639 
640 inline bool operator==(uint64_t a, const FVInt &b) { return b == a; }
641 inline bool operator!=(uint64_t a, const FVInt &b) { return b != a; }
642 
643 inline raw_ostream &operator<<(raw_ostream &os, const FVInt &value) {
644  value.print(os);
645  return os;
646 }
647 
648 llvm::hash_code hash_value(const FVInt &a);
649 
650 /// Print a four-valued integer usign an `AsmPrinter`. This produces the
651 /// following output formats:
652 ///
653 /// - Decimal notation if the integer has no unknown bits. The sign bit is used
654 /// to determine whether the value is printed as negative number or not.
655 /// - Hexadecimal notation with a leading `h` if the integer the bits in each
656 /// hex digit are either all known, all X, or all Z.
657 /// - Binary notation with a leading `b` in all other cases.
658 void printFVInt(AsmPrinter &p, const FVInt &value);
659 
660 /// Parse a four-valued integer using an `AsmParser`. This accepts the following
661 /// formats:
662 ///
663 /// - `42`/`-42`: positive or negative integer in decimal notation. The sign bit
664 /// of the result indicates whether the value was negative. Cannot contain
665 /// unknown X or Z digits.
666 /// - `h123456789ABCDEF0XZ`: signless integer in hexadecimal notation. Can
667 /// contain unknown X or Z digits.
668 /// - `b10XZ`: signless integer in binary notation. Can contain unknown X or Z
669 /// digits.
670 ///
671 /// The result has enough bits to fully represent the parsed integer, and to
672 /// have the sign bit encode whether the integer was written as a negative
673 /// number in the input. The result's bit width may be larger than the minimum
674 /// number of bits required to represent its value.
675 ParseResult parseFVInt(AsmParser &p, FVInt &result);
676 
677 } // namespace circt
678 
679 #endif // CIRCT_SUPPORT_FVINT_H
assert(baseType &&"element must be base type")
Four-valued arbitrary precision integers.
Definition: FVInt.h:32
void setAllXIfAnyUnknown()
If any bits are X or Z, set the entire integer to X.
Definition: FVInt.h:278
void setAllOne()
Set all bits to 1.
Definition: FVInt.h:249
FVInt & operator^=(const FVInt &other)
Compute the logical XOR of this integer and another.
Definition: FVInt.h:421
FVInt(APInt &&rawValue, APInt &&rawUnknown)
Construct an FVInt from two APInts used internally to store the bit data.
Definition: FVInt.h:50
static FVInt getZero(unsigned numBits)
Construct an FVInt with all bits set to 0.
Definition: FVInt.h:56
FVInt & operator|=(T other)
Compute the logical OR of this integer and a two-valued integer.
Definition: FVInt.h:396
FVInt & operator<<=(const T &amount)
Perform a logical left-shift by a two-valued amount.
Definition: FVInt.h:309
FVInt operator&(const T &other) const
Compute the logical AND.
Definition: FVInt.h:369
void negate()
Compute the negation of this integer.
Definition: FVInt.h:450
Bit
The value of an individual bit. Can be 0, 1, X, or Z.
Definition: FVInt.h:186
void setAllZ()
Set all bits to Z.
Definition: FVInt.h:261
FVInt(const APInt &value)
Construct an FVInt from an APInt. The result has no X or Z bits.
Definition: FVInt.h:42
FVInt & operator&=(T other)
Compute the logical AND of this integer and a two-valued integer.
Definition: FVInt.h:360
APInt value
Definition: FVInt.h:618
bool operator==(const T &other) const
Determine whether this integer is equal to a two-valued integer.
Definition: FVInt.h:553
APInt getOneBits() const
Compute a mask of all the 1 bits in this integer.
Definition: FVInt.h:203
Bit getBit(unsigned index) const
Get the value of an individual bit.
Definition: FVInt.h:189
FVInt & operator+=(const T &other)
Compute the addition of this integer and a two-valued integer.
Definition: FVInt.h:473
FVInt()
Default constructor that creates an zero-bit zero value.
Definition: FVInt.h:35
FVInt & operator-=(const FVInt &other)
Compute the subtraction of this integer and another.
Definition: FVInt.h:489
APInt getXBits() const
Compute a mask of all the X bits in this integer.
Definition: FVInt.h:206
static FVInt getAllZ(unsigned numBits)
Construct an FVInt with all bits set to Z.
Definition: FVInt.h:71
FVInt sextOrTrunc(unsigned bitWidth) const
Truncate or sign-extend to a target bit width.
Definition: FVInt.h:150
void setAllXIfAnyUnknown(const FVInt &other)
If any bits in this integer or another integer are X or Z, set the entire integer to X.
Definition: FVInt.h:286
bool operator==(const FVInt &other) const
Determine whether this integer is equal to another.
Definition: FVInt.h:544
void setAllZero()
Set all bits to 0.
Definition: FVInt.h:243
FVInt zextOrTrunc(unsigned bitWidth) const
Truncate or zero-extend to a target bit width.
Definition: FVInt.h:145
APInt getZeroBits() const
Compute a mask of all the 0 bits in this integer.
Definition: FVInt.h:200
FVInt operator|(const T &other) const
Compute the logical OR.
Definition: FVInt.h:405
bool isNegative() const
Determine whether the integer interpreted as a signed number would be negative.
Definition: FVInt.h:176
FVInt & operator<<=(const FVInt &amount)
Perform a logical left-shift.
Definition: FVInt.h:297
FVInt & operator*=(const T &other)
Compute the multiplication of this integer and a two-valued integer.
Definition: FVInt.h:523
FVInt operator*(const T &other) const
Compute a multiplication.
Definition: FVInt.h:531
FVInt operator-() const
Compute the negation of this integer.
Definition: FVInt.h:456
FVInt operator^(const T &other) const
Compute the logical XOR.
Definition: FVInt.h:438
void setZeroBits(const T &mask)
Set the value of all bits in the mask to 0.
Definition: FVInt.h:216
FVInt & operator+=(const FVInt &other)
Compute the addition of this integer and another.
Definition: FVInt.h:464
bool isAllZ() const
Determine if all bits are Z. This is true for zero-width values.
Definition: FVInt.h:171
FVInt & operator|=(const FVInt &other)
Compute the logical OR of this integer and another.
Definition: FVInt.h:385
void setAllX()
Set all bits to X.
Definition: FVInt.h:255
void replaceZWithX()
Replace all Z bits with X.
Definition: FVInt.h:270
FVInt & operator&=(const FVInt &other)
Compute the logical AND of this integer and another.
Definition: FVInt.h:349
void setOneBits(const T &mask)
Set the value of all bits in the mask to 1.
Definition: FVInt.h:223
APInt unknown
Definition: FVInt.h:619
static std::optional< FVInt > tryFromString(StringRef str, unsigned radix=10)
Convert a string into an FVInt.
Definition: FVInt.cpp:17
FVInt & operator*=(const FVInt &other)
Compute the multiplication of this integer and another.
Definition: FVInt.h:514
bool isAllX() const
Determine if all bits are X. This is true for zero-width values.
Definition: FVInt.h:168
FVInt operator-(const T &other) const
Compute an subtraction.
Definition: FVInt.h:506
APInt getZBits() const
Compute a mask of all the Z bits in this integer.
Definition: FVInt.h:209
static FVInt fromString(StringRef str, unsigned radix=10)
Convert a string into an FVInt.
Definition: FVInt.h:585
static FVInt getAllOnes(unsigned numBits)
Construct an FVInt with all bits set to 1.
Definition: FVInt.h:61
FVInt operator+(const T &other) const
Compute an addition.
Definition: FVInt.h:481
const APInt & getRawUnknown() const
Return the underlying APInt used to store whether a bit is unknown (X or Z).
Definition: FVInt.h:102
bool operator!=(const T &other) const
Determine whether this integer is not equal to a two-valued integer.
Definition: FVInt.h:563
FVInt sext(unsigned bitWidth) const
Sign-extend the integer to a new bit width.
Definition: FVInt.h:139
unsigned getSignificantBits() const
Compute the minimum bit width necessary to accurately represent this integer's value and sign.
Definition: FVInt.h:93
void flipAllBits()
Compute the logical NOT of this integer.
Definition: FVInt.h:327
SmallString< 16 > toString(unsigned radix=10, bool uppercase=true) const
Convert an FVInt to a string.
Definition: FVInt.h:607
void setXBits(const T &mask)
Set the value of all bits in the mask to X.
Definition: FVInt.h:230
static FVInt getAllX(unsigned numBits)
Construct an FVInt with all bits set to X.
Definition: FVInt.h:66
void print(raw_ostream &os) const
Print an FVInt to an output stream.
Definition: FVInt.cpp:135
void setBit(unsigned index, Bit bit)
Set the value of an individual bit.
Definition: FVInt.h:194
bool hasUnknown() const
Determine if any bits are X or Z.
Definition: FVInt.h:159
APInt toAPInt(bool unknownBitMapping) const
Convert the four-valued FVInt to a two-valued APInt by mapping X and Z bits to either 0 or 1.
Definition: FVInt.h:106
FVInt & operator^=(const T &other)
Compute the logical XOR of this integer and a two-valued integer.
Definition: FVInt.h:430
unsigned getActiveBits() const
Compute the number of active bits in the value.
Definition: FVInt.h:83
bool isAllOnes() const
Determine if all bits are 1. This is true for zero-width values.
Definition: FVInt.h:165
FVInt operator~() const
Compute the logical NOT.
Definition: FVInt.h:333
FVInt zext(unsigned bitWidth) const
Zero-extend the integer to a new bit width.
Definition: FVInt.h:130
FVInt & operator-=(const T &other)
Compute the subtraction of this integer and a two-valued integer.
Definition: FVInt.h:498
APInt getUnknownBits() const
Compute a mask of all the X and Z bits in this integer.
Definition: FVInt.h:212
unsigned getBitWidth() const
Return the number of bits this integer has.
Definition: FVInt.h:76
bool isZero() const
Determine if all bits are 0. This is true for zero-width values.
Definition: FVInt.h:162
FVInt(unsigned numBits, uint64_t value, bool isSigned=false)
Construct an FVInt from a 64-bit value. The result has no X or Z bits.
Definition: FVInt.h:38
void setZBits(const T &mask)
Set the value of all bits in the mask to Z.
Definition: FVInt.h:237
const APInt & getRawValue() const
Return the underlying APInt used to store whether a bit is 0/X or 1/Z.
Definition: FVInt.h:98
bool tryToString(SmallVectorImpl< char > &str, unsigned radix=10, bool uppercase=true) const
Convert an FVInt to a string.
Definition: FVInt.cpp:68
bool operator!=(const FVInt &other) const
Determine whether this integer is not equal to another.
Definition: FVInt.h:559
FVInt trunc(unsigned bitWidth) const
Truncate the integer to a smaller bit width.
Definition: FVInt.h:123
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
FVInt operator^(uint64_t a, const FVInt &b)
Definition: FVInt.h:624
FVInt operator|(uint64_t a, const FVInt &b)
Definition: FVInt.h:623
inline ::llvm::hash_code hash_value(const FieldRef &fieldRef)
Get a hash code for a FieldRef.
Definition: FieldRef.h:92
FVInt operator*(uint64_t a, const FVInt &b)
Definition: FVInt.h:626
void printFVInt(AsmPrinter &p, const FVInt &value)
Print a four-valued integer usign an AsmPrinter.
Definition: FVInt.cpp:147
ParseResult parseFVInt(AsmParser &p, FVInt &result)
Parse a four-valued integer using an AsmParser.
Definition: FVInt.cpp:162
FVInt operator&(uint64_t a, const FVInt &b)
Definition: FVInt.h:622
FVInt operator-(uint64_t a, const FVInt &b)
Definition: FVInt.h:634
bool operator==(uint64_t a, const FVInt &b)
Definition: FVInt.h:640
bool operator!=(uint64_t a, const FVInt &b)
Definition: FVInt.h:641
raw_ostream & operator<<(raw_ostream &os, const FVInt &value)
Definition: FVInt.h:643
FVInt operator+(uint64_t a, const FVInt &b)
Definition: FVInt.h:625