Alignment.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- llvm/Support/Alignment.h - Useful alignment functions ---*- 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 contains types to represent alignments.
  15. // They are instrumented to guarantee some invariants are preserved and prevent
  16. // invalid manipulations.
  17. //
  18. // - Align represents an alignment in bytes, it is always set and always a valid
  19. // power of two, its minimum value is 1 which means no alignment requirements.
  20. //
  21. // - MaybeAlign is an optional type, it may be undefined or set. When it's set
  22. // you can get the underlying Align type by using the getValue() method.
  23. //
  24. //===----------------------------------------------------------------------===//
  25. #ifndef LLVM_SUPPORT_ALIGNMENT_H_
  26. #define LLVM_SUPPORT_ALIGNMENT_H_
  27. #include "llvm/Support/MathExtras.h"
  28. #include <cassert>
  29. #include <optional>
  30. #ifndef NDEBUG
  31. #include <string>
  32. #endif // NDEBUG
  33. namespace llvm {
  34. #define ALIGN_CHECK_ISPOSITIVE(decl) \
  35. assert(decl > 0 && (#decl " should be defined"))
  36. /// This struct is a compact representation of a valid (non-zero power of two)
  37. /// alignment.
  38. /// It is suitable for use as static global constants.
  39. struct Align {
  40. private:
  41. uint8_t ShiftValue = 0; /// The log2 of the required alignment.
  42. /// ShiftValue is less than 64 by construction.
  43. friend struct MaybeAlign;
  44. friend unsigned Log2(Align);
  45. friend bool operator==(Align Lhs, Align Rhs);
  46. friend bool operator!=(Align Lhs, Align Rhs);
  47. friend bool operator<=(Align Lhs, Align Rhs);
  48. friend bool operator>=(Align Lhs, Align Rhs);
  49. friend bool operator<(Align Lhs, Align Rhs);
  50. friend bool operator>(Align Lhs, Align Rhs);
  51. friend unsigned encode(struct MaybeAlign A);
  52. friend struct MaybeAlign decodeMaybeAlign(unsigned Value);
  53. /// A trivial type to allow construction of constexpr Align.
  54. /// This is currently needed to workaround a bug in GCC 5.3 which prevents
  55. /// definition of constexpr assign operators.
  56. /// https://stackoverflow.com/questions/46756288/explicitly-defaulted-function-cannot-be-declared-as-constexpr-because-the-implic
  57. /// FIXME: Remove this, make all assign operators constexpr and introduce user
  58. /// defined literals when we don't have to support GCC 5.3 anymore.
  59. /// https://llvm.org/docs/GettingStarted.html#getting-a-modern-host-c-toolchain
  60. struct LogValue {
  61. uint8_t Log;
  62. };
  63. public:
  64. /// Default is byte-aligned.
  65. constexpr Align() = default;
  66. /// Do not perform checks in case of copy/move construct/assign, because the
  67. /// checks have been performed when building `Other`.
  68. constexpr Align(const Align &Other) = default;
  69. constexpr Align(Align &&Other) = default;
  70. Align &operator=(const Align &Other) = default;
  71. Align &operator=(Align &&Other) = default;
  72. explicit Align(uint64_t Value) {
  73. assert(Value > 0 && "Value must not be 0");
  74. assert(llvm::isPowerOf2_64(Value) && "Alignment is not a power of 2");
  75. ShiftValue = Log2_64(Value);
  76. assert(ShiftValue < 64 && "Broken invariant");
  77. }
  78. /// This is a hole in the type system and should not be abused.
  79. /// Needed to interact with C for instance.
  80. uint64_t value() const { return uint64_t(1) << ShiftValue; }
  81. // Returns the previous alignment.
  82. Align previous() const {
  83. assert(ShiftValue != 0 && "Undefined operation");
  84. Align Out;
  85. Out.ShiftValue = ShiftValue - 1;
  86. return Out;
  87. }
  88. /// Allow constructions of constexpr Align.
  89. template <size_t kValue> constexpr static Align Constant() {
  90. return LogValue{static_cast<uint8_t>(CTLog2<kValue>())};
  91. }
  92. /// Allow constructions of constexpr Align from types.
  93. /// Compile time equivalent to Align(alignof(T)).
  94. template <typename T> constexpr static Align Of() {
  95. return Constant<std::alignment_of<T>::value>();
  96. }
  97. /// Constexpr constructor from LogValue type.
  98. constexpr Align(LogValue CA) : ShiftValue(CA.Log) {}
  99. };
  100. /// Treats the value 0 as a 1, so Align is always at least 1.
  101. inline Align assumeAligned(uint64_t Value) {
  102. return Value ? Align(Value) : Align();
  103. }
  104. /// This struct is a compact representation of a valid (power of two) or
  105. /// undefined (0) alignment.
  106. struct MaybeAlign : public std::optional<Align> {
  107. private:
  108. using UP = std::optional<Align>;
  109. public:
  110. /// Default is undefined.
  111. MaybeAlign() = default;
  112. /// Do not perform checks in case of copy/move construct/assign, because the
  113. /// checks have been performed when building `Other`.
  114. MaybeAlign(const MaybeAlign &Other) = default;
  115. MaybeAlign &operator=(const MaybeAlign &Other) = default;
  116. MaybeAlign(MaybeAlign &&Other) = default;
  117. MaybeAlign &operator=(MaybeAlign &&Other) = default;
  118. constexpr MaybeAlign(std::nullopt_t None) : UP(None) {}
  119. constexpr MaybeAlign(Align Value) : UP(Value) {}
  120. explicit MaybeAlign(uint64_t Value) {
  121. assert((Value == 0 || llvm::isPowerOf2_64(Value)) &&
  122. "Alignment is neither 0 nor a power of 2");
  123. if (Value)
  124. emplace(Value);
  125. }
  126. /// For convenience, returns a valid alignment or 1 if undefined.
  127. Align valueOrOne() const { return value_or(Align()); }
  128. };
  129. /// Checks that SizeInBytes is a multiple of the alignment.
  130. inline bool isAligned(Align Lhs, uint64_t SizeInBytes) {
  131. return SizeInBytes % Lhs.value() == 0;
  132. }
  133. /// Checks that Addr is a multiple of the alignment.
  134. inline bool isAddrAligned(Align Lhs, const void *Addr) {
  135. return isAligned(Lhs, reinterpret_cast<uintptr_t>(Addr));
  136. }
  137. /// Returns a multiple of A needed to store `Size` bytes.
  138. inline uint64_t alignTo(uint64_t Size, Align A) {
  139. const uint64_t Value = A.value();
  140. // The following line is equivalent to `(Size + Value - 1) / Value * Value`.
  141. // The division followed by a multiplication can be thought of as a right
  142. // shift followed by a left shift which zeros out the extra bits produced in
  143. // the bump; `~(Value - 1)` is a mask where all those bits being zeroed out
  144. // are just zero.
  145. // Most compilers can generate this code but the pattern may be missed when
  146. // multiple functions gets inlined.
  147. return (Size + Value - 1) & ~(Value - 1U);
  148. }
  149. /// If non-zero \p Skew is specified, the return value will be a minimal integer
  150. /// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
  151. /// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
  152. /// Skew mod \p A'.
  153. ///
  154. /// Examples:
  155. /// \code
  156. /// alignTo(5, Align(8), 7) = 7
  157. /// alignTo(17, Align(8), 1) = 17
  158. /// alignTo(~0LL, Align(8), 3) = 3
  159. /// \endcode
  160. inline uint64_t alignTo(uint64_t Size, Align A, uint64_t Skew) {
  161. const uint64_t Value = A.value();
  162. Skew %= Value;
  163. return alignTo(Size - Skew, A) + Skew;
  164. }
  165. /// Aligns `Addr` to `Alignment` bytes, rounding up.
  166. inline uintptr_t alignAddr(const void *Addr, Align Alignment) {
  167. uintptr_t ArithAddr = reinterpret_cast<uintptr_t>(Addr);
  168. assert(static_cast<uintptr_t>(ArithAddr + Alignment.value() - 1) >=
  169. ArithAddr &&
  170. "Overflow");
  171. return alignTo(ArithAddr, Alignment);
  172. }
  173. /// Returns the offset to the next integer (mod 2**64) that is greater than
  174. /// or equal to \p Value and is a multiple of \p Align.
  175. inline uint64_t offsetToAlignment(uint64_t Value, Align Alignment) {
  176. return alignTo(Value, Alignment) - Value;
  177. }
  178. /// Returns the necessary adjustment for aligning `Addr` to `Alignment`
  179. /// bytes, rounding up.
  180. inline uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment) {
  181. return offsetToAlignment(reinterpret_cast<uintptr_t>(Addr), Alignment);
  182. }
  183. /// Returns the log2 of the alignment.
  184. inline unsigned Log2(Align A) { return A.ShiftValue; }
  185. /// Returns the alignment that satisfies both alignments.
  186. /// Same semantic as MinAlign.
  187. inline Align commonAlignment(Align A, uint64_t Offset) {
  188. return Align(MinAlign(A.value(), Offset));
  189. }
  190. /// Returns a representation of the alignment that encodes undefined as 0.
  191. inline unsigned encode(MaybeAlign A) { return A ? A->ShiftValue + 1 : 0; }
  192. /// Dual operation of the encode function above.
  193. inline MaybeAlign decodeMaybeAlign(unsigned Value) {
  194. if (Value == 0)
  195. return MaybeAlign();
  196. Align Out;
  197. Out.ShiftValue = Value - 1;
  198. return Out;
  199. }
  200. /// Returns a representation of the alignment, the encoded value is positive by
  201. /// definition.
  202. inline unsigned encode(Align A) { return encode(MaybeAlign(A)); }
  203. /// Comparisons between Align and scalars. Rhs must be positive.
  204. inline bool operator==(Align Lhs, uint64_t Rhs) {
  205. ALIGN_CHECK_ISPOSITIVE(Rhs);
  206. return Lhs.value() == Rhs;
  207. }
  208. inline bool operator!=(Align Lhs, uint64_t Rhs) {
  209. ALIGN_CHECK_ISPOSITIVE(Rhs);
  210. return Lhs.value() != Rhs;
  211. }
  212. inline bool operator<=(Align Lhs, uint64_t Rhs) {
  213. ALIGN_CHECK_ISPOSITIVE(Rhs);
  214. return Lhs.value() <= Rhs;
  215. }
  216. inline bool operator>=(Align Lhs, uint64_t Rhs) {
  217. ALIGN_CHECK_ISPOSITIVE(Rhs);
  218. return Lhs.value() >= Rhs;
  219. }
  220. inline bool operator<(Align Lhs, uint64_t Rhs) {
  221. ALIGN_CHECK_ISPOSITIVE(Rhs);
  222. return Lhs.value() < Rhs;
  223. }
  224. inline bool operator>(Align Lhs, uint64_t Rhs) {
  225. ALIGN_CHECK_ISPOSITIVE(Rhs);
  226. return Lhs.value() > Rhs;
  227. }
  228. /// Comparisons operators between Align.
  229. inline bool operator==(Align Lhs, Align Rhs) {
  230. return Lhs.ShiftValue == Rhs.ShiftValue;
  231. }
  232. inline bool operator!=(Align Lhs, Align Rhs) {
  233. return Lhs.ShiftValue != Rhs.ShiftValue;
  234. }
  235. inline bool operator<=(Align Lhs, Align Rhs) {
  236. return Lhs.ShiftValue <= Rhs.ShiftValue;
  237. }
  238. inline bool operator>=(Align Lhs, Align Rhs) {
  239. return Lhs.ShiftValue >= Rhs.ShiftValue;
  240. }
  241. inline bool operator<(Align Lhs, Align Rhs) {
  242. return Lhs.ShiftValue < Rhs.ShiftValue;
  243. }
  244. inline bool operator>(Align Lhs, Align Rhs) {
  245. return Lhs.ShiftValue > Rhs.ShiftValue;
  246. }
  247. // Don't allow relational comparisons with MaybeAlign.
  248. bool operator<=(Align Lhs, MaybeAlign Rhs) = delete;
  249. bool operator>=(Align Lhs, MaybeAlign Rhs) = delete;
  250. bool operator<(Align Lhs, MaybeAlign Rhs) = delete;
  251. bool operator>(Align Lhs, MaybeAlign Rhs) = delete;
  252. bool operator<=(MaybeAlign Lhs, Align Rhs) = delete;
  253. bool operator>=(MaybeAlign Lhs, Align Rhs) = delete;
  254. bool operator<(MaybeAlign Lhs, Align Rhs) = delete;
  255. bool operator>(MaybeAlign Lhs, Align Rhs) = delete;
  256. bool operator<=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
  257. bool operator>=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
  258. bool operator<(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
  259. bool operator>(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
  260. // Allow equality comparisons between Align and MaybeAlign.
  261. inline bool operator==(MaybeAlign Lhs, Align Rhs) { return Lhs && *Lhs == Rhs; }
  262. inline bool operator!=(MaybeAlign Lhs, Align Rhs) { return !(Lhs == Rhs); }
  263. inline bool operator==(Align Lhs, MaybeAlign Rhs) { return Rhs == Lhs; }
  264. inline bool operator!=(Align Lhs, MaybeAlign Rhs) { return !(Rhs == Lhs); }
  265. // Allow equality comparisons with MaybeAlign.
  266. inline bool operator==(MaybeAlign Lhs, MaybeAlign Rhs) {
  267. return (Lhs && Rhs && (*Lhs == *Rhs)) || (!Lhs && !Rhs);
  268. }
  269. inline bool operator!=(MaybeAlign Lhs, MaybeAlign Rhs) { return !(Lhs == Rhs); }
  270. // Allow equality comparisons with std::nullopt.
  271. inline bool operator==(MaybeAlign Lhs, std::nullopt_t) { return !bool(Lhs); }
  272. inline bool operator!=(MaybeAlign Lhs, std::nullopt_t) { return bool(Lhs); }
  273. inline bool operator==(std::nullopt_t, MaybeAlign Rhs) { return !bool(Rhs); }
  274. inline bool operator!=(std::nullopt_t, MaybeAlign Rhs) { return bool(Rhs); }
  275. #ifndef NDEBUG
  276. // For usage in LLVM_DEBUG macros.
  277. inline std::string DebugStr(const Align &A) {
  278. return std::to_string(A.value());
  279. }
  280. // For usage in LLVM_DEBUG macros.
  281. inline std::string DebugStr(const MaybeAlign &MA) {
  282. if (MA)
  283. return std::to_string(MA->value());
  284. return "None";
  285. }
  286. #endif // NDEBUG
  287. #undef ALIGN_CHECK_ISPOSITIVE
  288. } // namespace llvm
  289. #endif // LLVM_SUPPORT_ALIGNMENT_H_
  290. #ifdef __GNUC__
  291. #pragma GCC diagnostic pop
  292. #endif