Alignment.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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/ADT/Optional.h"
  28. #include "llvm/Support/MathExtras.h"
  29. #include <cassert>
  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. /// Allow constructions of constexpr Align.
  82. template <size_t kValue> constexpr static LogValue Constant() {
  83. return LogValue{static_cast<uint8_t>(CTLog2<kValue>())};
  84. }
  85. /// Allow constructions of constexpr Align from types.
  86. /// Compile time equivalent to Align(alignof(T)).
  87. template <typename T> constexpr static LogValue Of() {
  88. return Constant<std::alignment_of<T>::value>();
  89. }
  90. /// Constexpr constructor from LogValue type.
  91. constexpr Align(LogValue CA) : ShiftValue(CA.Log) {}
  92. };
  93. /// Treats the value 0 as a 1, so Align is always at least 1.
  94. inline Align assumeAligned(uint64_t Value) {
  95. return Value ? Align(Value) : Align();
  96. }
  97. /// This struct is a compact representation of a valid (power of two) or
  98. /// undefined (0) alignment.
  99. struct MaybeAlign : public llvm::Optional<Align> {
  100. private:
  101. using UP = llvm::Optional<Align>;
  102. public:
  103. /// Default is undefined.
  104. MaybeAlign() = default;
  105. /// Do not perform checks in case of copy/move construct/assign, because the
  106. /// checks have been performed when building `Other`.
  107. MaybeAlign(const MaybeAlign &Other) = default;
  108. MaybeAlign &operator=(const MaybeAlign &Other) = default;
  109. MaybeAlign(MaybeAlign &&Other) = default;
  110. MaybeAlign &operator=(MaybeAlign &&Other) = default;
  111. /// Use llvm::Optional<Align> constructor.
  112. using UP::UP;
  113. explicit MaybeAlign(uint64_t Value) {
  114. assert((Value == 0 || llvm::isPowerOf2_64(Value)) &&
  115. "Alignment is neither 0 nor a power of 2");
  116. if (Value)
  117. emplace(Value);
  118. }
  119. /// For convenience, returns a valid alignment or 1 if undefined.
  120. Align valueOrOne() const { return hasValue() ? getValue() : Align(); }
  121. };
  122. /// Checks that SizeInBytes is a multiple of the alignment.
  123. inline bool isAligned(Align Lhs, uint64_t SizeInBytes) {
  124. return SizeInBytes % Lhs.value() == 0;
  125. }
  126. /// Checks that Addr is a multiple of the alignment.
  127. inline bool isAddrAligned(Align Lhs, const void *Addr) {
  128. return isAligned(Lhs, reinterpret_cast<uintptr_t>(Addr));
  129. }
  130. /// Returns a multiple of A needed to store `Size` bytes.
  131. inline uint64_t alignTo(uint64_t Size, Align A) {
  132. const uint64_t Value = A.value();
  133. // The following line is equivalent to `(Size + Value - 1) / Value * Value`.
  134. // The division followed by a multiplication can be thought of as a right
  135. // shift followed by a left shift which zeros out the extra bits produced in
  136. // the bump; `~(Value - 1)` is a mask where all those bits being zeroed out
  137. // are just zero.
  138. // Most compilers can generate this code but the pattern may be missed when
  139. // multiple functions gets inlined.
  140. return (Size + Value - 1) & ~(Value - 1U);
  141. }
  142. /// If non-zero \p Skew is specified, the return value will be a minimal integer
  143. /// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
  144. /// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
  145. /// Skew mod \p A'.
  146. ///
  147. /// Examples:
  148. /// \code
  149. /// alignTo(5, Align(8), 7) = 7
  150. /// alignTo(17, Align(8), 1) = 17
  151. /// alignTo(~0LL, Align(8), 3) = 3
  152. /// \endcode
  153. inline uint64_t alignTo(uint64_t Size, Align A, uint64_t Skew) {
  154. const uint64_t Value = A.value();
  155. Skew %= Value;
  156. return ((Size + Value - 1 - Skew) & ~(Value - 1U)) + Skew;
  157. }
  158. /// Returns a multiple of A needed to store `Size` bytes.
  159. /// Returns `Size` if current alignment is undefined.
  160. inline uint64_t alignTo(uint64_t Size, MaybeAlign A) {
  161. return A ? alignTo(Size, A.getValue()) : Size;
  162. }
  163. /// Aligns `Addr` to `Alignment` bytes, rounding up.
  164. inline uintptr_t alignAddr(const void *Addr, Align Alignment) {
  165. uintptr_t ArithAddr = reinterpret_cast<uintptr_t>(Addr);
  166. assert(static_cast<uintptr_t>(ArithAddr + Alignment.value() - 1) >=
  167. ArithAddr &&
  168. "Overflow");
  169. return alignTo(ArithAddr, Alignment);
  170. }
  171. /// Returns the offset to the next integer (mod 2**64) that is greater than
  172. /// or equal to \p Value and is a multiple of \p Align.
  173. inline uint64_t offsetToAlignment(uint64_t Value, Align Alignment) {
  174. return alignTo(Value, Alignment) - Value;
  175. }
  176. /// Returns the necessary adjustment for aligning `Addr` to `Alignment`
  177. /// bytes, rounding up.
  178. inline uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment) {
  179. return offsetToAlignment(reinterpret_cast<uintptr_t>(Addr), Alignment);
  180. }
  181. /// Returns the log2 of the alignment.
  182. inline unsigned Log2(Align A) { return A.ShiftValue; }
  183. /// Returns the alignment that satisfies both alignments.
  184. /// Same semantic as MinAlign.
  185. inline Align commonAlignment(Align A, Align B) { return std::min(A, B); }
  186. /// Returns the alignment that satisfies both alignments.
  187. /// Same semantic as MinAlign.
  188. inline Align commonAlignment(Align A, uint64_t Offset) {
  189. return Align(MinAlign(A.value(), Offset));
  190. }
  191. /// Returns the alignment that satisfies both alignments.
  192. /// Same semantic as MinAlign.
  193. inline MaybeAlign commonAlignment(MaybeAlign A, MaybeAlign B) {
  194. return A && B ? commonAlignment(*A, *B) : A ? A : B;
  195. }
  196. /// Returns the alignment that satisfies both alignments.
  197. /// Same semantic as MinAlign.
  198. inline MaybeAlign commonAlignment(MaybeAlign A, uint64_t Offset) {
  199. return MaybeAlign(MinAlign((*A).value(), Offset));
  200. }
  201. /// Returns a representation of the alignment that encodes undefined as 0.
  202. inline unsigned encode(MaybeAlign A) { return A ? A->ShiftValue + 1 : 0; }
  203. /// Dual operation of the encode function above.
  204. inline MaybeAlign decodeMaybeAlign(unsigned Value) {
  205. if (Value == 0)
  206. return MaybeAlign();
  207. Align Out;
  208. Out.ShiftValue = Value - 1;
  209. return Out;
  210. }
  211. /// Returns a representation of the alignment, the encoded value is positive by
  212. /// definition.
  213. inline unsigned encode(Align A) { return encode(MaybeAlign(A)); }
  214. /// Comparisons between Align and scalars. Rhs must be positive.
  215. inline bool operator==(Align Lhs, uint64_t Rhs) {
  216. ALIGN_CHECK_ISPOSITIVE(Rhs);
  217. return Lhs.value() == Rhs;
  218. }
  219. inline bool operator!=(Align Lhs, uint64_t Rhs) {
  220. ALIGN_CHECK_ISPOSITIVE(Rhs);
  221. return Lhs.value() != Rhs;
  222. }
  223. inline bool operator<=(Align Lhs, uint64_t Rhs) {
  224. ALIGN_CHECK_ISPOSITIVE(Rhs);
  225. return Lhs.value() <= Rhs;
  226. }
  227. inline bool operator>=(Align Lhs, uint64_t Rhs) {
  228. ALIGN_CHECK_ISPOSITIVE(Rhs);
  229. return Lhs.value() >= Rhs;
  230. }
  231. inline bool operator<(Align Lhs, uint64_t Rhs) {
  232. ALIGN_CHECK_ISPOSITIVE(Rhs);
  233. return Lhs.value() < Rhs;
  234. }
  235. inline bool operator>(Align Lhs, uint64_t Rhs) {
  236. ALIGN_CHECK_ISPOSITIVE(Rhs);
  237. return Lhs.value() > Rhs;
  238. }
  239. /// Comparisons between MaybeAlign and scalars.
  240. inline bool operator==(MaybeAlign Lhs, uint64_t Rhs) {
  241. return Lhs ? (*Lhs).value() == Rhs : Rhs == 0;
  242. }
  243. inline bool operator!=(MaybeAlign Lhs, uint64_t Rhs) {
  244. return Lhs ? (*Lhs).value() != Rhs : Rhs != 0;
  245. }
  246. /// Comparisons operators between Align.
  247. inline bool operator==(Align Lhs, Align Rhs) {
  248. return Lhs.ShiftValue == Rhs.ShiftValue;
  249. }
  250. inline bool operator!=(Align Lhs, Align Rhs) {
  251. return Lhs.ShiftValue != Rhs.ShiftValue;
  252. }
  253. inline bool operator<=(Align Lhs, Align Rhs) {
  254. return Lhs.ShiftValue <= Rhs.ShiftValue;
  255. }
  256. inline bool operator>=(Align Lhs, Align Rhs) {
  257. return Lhs.ShiftValue >= Rhs.ShiftValue;
  258. }
  259. inline bool operator<(Align Lhs, Align Rhs) {
  260. return Lhs.ShiftValue < Rhs.ShiftValue;
  261. }
  262. inline bool operator>(Align Lhs, Align Rhs) {
  263. return Lhs.ShiftValue > Rhs.ShiftValue;
  264. }
  265. // Don't allow relational comparisons with MaybeAlign.
  266. bool operator<=(Align Lhs, MaybeAlign Rhs) = delete;
  267. bool operator>=(Align Lhs, MaybeAlign Rhs) = delete;
  268. bool operator<(Align Lhs, MaybeAlign Rhs) = delete;
  269. bool operator>(Align Lhs, MaybeAlign Rhs) = delete;
  270. bool operator<=(MaybeAlign Lhs, Align Rhs) = delete;
  271. bool operator>=(MaybeAlign Lhs, Align Rhs) = delete;
  272. bool operator<(MaybeAlign Lhs, Align Rhs) = delete;
  273. bool operator>(MaybeAlign Lhs, Align Rhs) = delete;
  274. bool operator<=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
  275. bool operator>=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
  276. bool operator<(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
  277. bool operator>(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
  278. inline Align operator*(Align Lhs, uint64_t Rhs) {
  279. assert(Rhs > 0 && "Rhs must be positive");
  280. return Align(Lhs.value() * Rhs);
  281. }
  282. inline MaybeAlign operator*(MaybeAlign Lhs, uint64_t Rhs) {
  283. assert(Rhs > 0 && "Rhs must be positive");
  284. return Lhs ? Lhs.getValue() * Rhs : MaybeAlign();
  285. }
  286. inline Align operator/(Align Lhs, uint64_t Divisor) {
  287. assert(llvm::isPowerOf2_64(Divisor) &&
  288. "Divisor must be positive and a power of 2");
  289. assert(Lhs != 1 && "Can't halve byte alignment");
  290. return Align(Lhs.value() / Divisor);
  291. }
  292. inline MaybeAlign operator/(MaybeAlign Lhs, uint64_t Divisor) {
  293. assert(llvm::isPowerOf2_64(Divisor) &&
  294. "Divisor must be positive and a power of 2");
  295. return Lhs ? Lhs.getValue() / Divisor : MaybeAlign();
  296. }
  297. inline Align max(MaybeAlign Lhs, Align Rhs) {
  298. return Lhs && *Lhs > Rhs ? *Lhs : Rhs;
  299. }
  300. inline Align max(Align Lhs, MaybeAlign Rhs) {
  301. return Rhs && *Rhs > Lhs ? *Rhs : Lhs;
  302. }
  303. #ifndef NDEBUG
  304. // For usage in LLVM_DEBUG macros.
  305. inline std::string DebugStr(const Align &A) {
  306. return std::to_string(A.value());
  307. }
  308. // For usage in LLVM_DEBUG macros.
  309. inline std::string DebugStr(const MaybeAlign &MA) {
  310. if (MA)
  311. return std::to_string(MA->value());
  312. return "None";
  313. }
  314. #endif // NDEBUG
  315. #undef ALIGN_CHECK_ISPOSITIVE
  316. } // namespace llvm
  317. #endif // LLVM_SUPPORT_ALIGNMENT_H_
  318. #ifdef __GNUC__
  319. #pragma GCC diagnostic pop
  320. #endif