CharUnits.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- CharUnits.h - Character units for sizes and offsets ----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines the CharUnits class
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_CLANG_AST_CHARUNITS_H
  18. #define LLVM_CLANG_AST_CHARUNITS_H
  19. #include "llvm/ADT/DenseMapInfo.h"
  20. #include "llvm/Support/Alignment.h"
  21. #include "llvm/Support/DataTypes.h"
  22. #include "llvm/Support/MathExtras.h"
  23. namespace clang {
  24. /// CharUnits - This is an opaque type for sizes expressed in character units.
  25. /// Instances of this type represent a quantity as a multiple of the size
  26. /// of the standard C type, char, on the target architecture. As an opaque
  27. /// type, CharUnits protects you from accidentally combining operations on
  28. /// quantities in bit units and character units.
  29. ///
  30. /// In both C and C++, an object of type 'char', 'signed char', or 'unsigned
  31. /// char' occupies exactly one byte, so 'character unit' and 'byte' refer to
  32. /// the same quantity of storage. However, we use the term 'character unit'
  33. /// rather than 'byte' to avoid an implication that a character unit is
  34. /// exactly 8 bits.
  35. ///
  36. /// For portability, never assume that a target character is 8 bits wide. Use
  37. /// CharUnit values wherever you calculate sizes, offsets, or alignments
  38. /// in character units.
  39. class CharUnits {
  40. public:
  41. typedef int64_t QuantityType;
  42. private:
  43. QuantityType Quantity = 0;
  44. explicit CharUnits(QuantityType C) : Quantity(C) {}
  45. public:
  46. /// CharUnits - A default constructor.
  47. CharUnits() = default;
  48. /// Zero - Construct a CharUnits quantity of zero.
  49. static CharUnits Zero() {
  50. return CharUnits(0);
  51. }
  52. /// One - Construct a CharUnits quantity of one.
  53. static CharUnits One() {
  54. return CharUnits(1);
  55. }
  56. /// fromQuantity - Construct a CharUnits quantity from a raw integer type.
  57. static CharUnits fromQuantity(QuantityType Quantity) {
  58. return CharUnits(Quantity);
  59. }
  60. /// fromQuantity - Construct a CharUnits quantity from an llvm::Align
  61. /// quantity.
  62. static CharUnits fromQuantity(llvm::Align Quantity) {
  63. return CharUnits(Quantity.value());
  64. }
  65. // Compound assignment.
  66. CharUnits& operator+= (const CharUnits &Other) {
  67. Quantity += Other.Quantity;
  68. return *this;
  69. }
  70. CharUnits& operator++ () {
  71. ++Quantity;
  72. return *this;
  73. }
  74. CharUnits operator++ (int) {
  75. return CharUnits(Quantity++);
  76. }
  77. CharUnits& operator-= (const CharUnits &Other) {
  78. Quantity -= Other.Quantity;
  79. return *this;
  80. }
  81. CharUnits& operator-- () {
  82. --Quantity;
  83. return *this;
  84. }
  85. CharUnits operator-- (int) {
  86. return CharUnits(Quantity--);
  87. }
  88. // Comparison operators.
  89. bool operator== (const CharUnits &Other) const {
  90. return Quantity == Other.Quantity;
  91. }
  92. bool operator!= (const CharUnits &Other) const {
  93. return Quantity != Other.Quantity;
  94. }
  95. // Relational operators.
  96. bool operator< (const CharUnits &Other) const {
  97. return Quantity < Other.Quantity;
  98. }
  99. bool operator<= (const CharUnits &Other) const {
  100. return Quantity <= Other.Quantity;
  101. }
  102. bool operator> (const CharUnits &Other) const {
  103. return Quantity > Other.Quantity;
  104. }
  105. bool operator>= (const CharUnits &Other) const {
  106. return Quantity >= Other.Quantity;
  107. }
  108. // Other predicates.
  109. /// isZero - Test whether the quantity equals zero.
  110. bool isZero() const { return Quantity == 0; }
  111. /// isOne - Test whether the quantity equals one.
  112. bool isOne() const { return Quantity == 1; }
  113. /// isPositive - Test whether the quantity is greater than zero.
  114. bool isPositive() const { return Quantity > 0; }
  115. /// isNegative - Test whether the quantity is less than zero.
  116. bool isNegative() const { return Quantity < 0; }
  117. /// isPowerOfTwo - Test whether the quantity is a power of two.
  118. /// Zero is not a power of two.
  119. bool isPowerOfTwo() const {
  120. return (Quantity & -Quantity) == Quantity;
  121. }
  122. /// Test whether this is a multiple of the other value.
  123. ///
  124. /// Among other things, this promises that
  125. /// self.alignTo(N) will just return self.
  126. bool isMultipleOf(CharUnits N) const {
  127. return (*this % N) == 0;
  128. }
  129. // Arithmetic operators.
  130. CharUnits operator* (QuantityType N) const {
  131. return CharUnits(Quantity * N);
  132. }
  133. CharUnits &operator*= (QuantityType N) {
  134. Quantity *= N;
  135. return *this;
  136. }
  137. CharUnits operator/ (QuantityType N) const {
  138. return CharUnits(Quantity / N);
  139. }
  140. CharUnits &operator/= (QuantityType N) {
  141. Quantity /= N;
  142. return *this;
  143. }
  144. QuantityType operator/ (const CharUnits &Other) const {
  145. return Quantity / Other.Quantity;
  146. }
  147. CharUnits operator% (QuantityType N) const {
  148. return CharUnits(Quantity % N);
  149. }
  150. QuantityType operator% (const CharUnits &Other) const {
  151. return Quantity % Other.Quantity;
  152. }
  153. CharUnits operator+ (const CharUnits &Other) const {
  154. return CharUnits(Quantity + Other.Quantity);
  155. }
  156. CharUnits operator- (const CharUnits &Other) const {
  157. return CharUnits(Quantity - Other.Quantity);
  158. }
  159. CharUnits operator- () const {
  160. return CharUnits(-Quantity);
  161. }
  162. // Conversions.
  163. /// getQuantity - Get the raw integer representation of this quantity.
  164. QuantityType getQuantity() const { return Quantity; }
  165. /// getAsAlign - Returns Quantity as a valid llvm::Align,
  166. /// Beware llvm::Align assumes power of two 8-bit bytes.
  167. llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
  168. /// getAsMaybeAlign - Returns Quantity as a valid llvm::Align or
  169. /// std::nullopt, Beware llvm::MaybeAlign assumes power of two 8-bit
  170. /// bytes.
  171. llvm::MaybeAlign getAsMaybeAlign() const {
  172. return llvm::MaybeAlign(Quantity);
  173. }
  174. /// alignTo - Returns the next integer (mod 2**64) that is
  175. /// greater than or equal to this quantity and is a multiple of \p Align.
  176. /// Align must be non-zero.
  177. CharUnits alignTo(const CharUnits &Align) const {
  178. return CharUnits(llvm::alignTo(Quantity, Align.Quantity));
  179. }
  180. /// Given that this is a non-zero alignment value, what is the
  181. /// alignment at the given offset?
  182. CharUnits alignmentAtOffset(CharUnits offset) const {
  183. assert(Quantity != 0 && "offsetting from unknown alignment?");
  184. return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
  185. }
  186. /// Given that this is the alignment of the first element of an
  187. /// array, return the minimum alignment of any element in the array.
  188. CharUnits alignmentOfArrayElement(CharUnits elementSize) const {
  189. // Since we don't track offsetted alignments, the alignment of
  190. // the second element (or any odd element) will be minimally
  191. // aligned.
  192. return alignmentAtOffset(elementSize);
  193. }
  194. }; // class CharUnit
  195. } // namespace clang
  196. inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
  197. const clang::CharUnits &CU) {
  198. return CU * Scale;
  199. }
  200. namespace llvm {
  201. template<> struct DenseMapInfo<clang::CharUnits> {
  202. static clang::CharUnits getEmptyKey() {
  203. clang::CharUnits::QuantityType Quantity =
  204. DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
  205. return clang::CharUnits::fromQuantity(Quantity);
  206. }
  207. static clang::CharUnits getTombstoneKey() {
  208. clang::CharUnits::QuantityType Quantity =
  209. DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
  210. return clang::CharUnits::fromQuantity(Quantity);
  211. }
  212. static unsigned getHashValue(const clang::CharUnits &CU) {
  213. clang::CharUnits::QuantityType Quantity = CU.getQuantity();
  214. return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
  215. }
  216. static bool isEqual(const clang::CharUnits &LHS,
  217. const clang::CharUnits &RHS) {
  218. return LHS == RHS;
  219. }
  220. };
  221. } // end namespace llvm
  222. #endif // LLVM_CLANG_AST_CHARUNITS_H
  223. #ifdef __GNUC__
  224. #pragma GCC diagnostic pop
  225. #endif