diff options
Diffstat (limited to 'llvm/include/llvm/Support/Alignment.h')
-rw-r--r-- | llvm/include/llvm/Support/Alignment.h | 166 |
1 files changed, 69 insertions, 97 deletions
diff --git a/llvm/include/llvm/Support/Alignment.h b/llvm/include/llvm/Support/Alignment.h index 72fad87dd0d4d..667434e8a407f 100644 --- a/llvm/include/llvm/Support/Alignment.h +++ b/llvm/include/llvm/Support/Alignment.h @@ -22,17 +22,16 @@ #define LLVM_SUPPORT_ALIGNMENT_H_ #include "llvm/ADT/Optional.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" #include <cassert> -#include <limits> +#ifndef NDEBUG +#include <string> +#endif // NDEBUG namespace llvm { #define ALIGN_CHECK_ISPOSITIVE(decl) \ assert(decl > 0 && (#decl " should be defined")) -#define ALIGN_CHECK_ISSET(decl) \ - assert(decl.hasValue() && (#decl " should be defined")) /// This struct is a compact representation of a valid (non-zero power of two) /// alignment. @@ -86,11 +85,14 @@ public: uint64_t value() const { return uint64_t(1) << ShiftValue; } /// Returns a default constructed Align which corresponds to no alignment. - /// This is useful to test for unalignment as it conveys clear semantic. - /// `if (A != Align::None())` - /// would be better than - /// `if (A > Align(1))` - constexpr static const Align None() { return Align(); } + /// It was decided to deprecate Align::None because it's too close to + /// llvm::None which can be used to initialize `MaybeAlign`. + /// MaybeAlign = llvm::None means unspecified alignment, + /// Align = Align::None() means alignment of one byte. + LLVM_ATTRIBUTE_DEPRECATED(constexpr static const Align None(), + "Use Align() or Align(1) instead") { + return Align(); + } /// Allow constructions of constexpr Align. template <size_t kValue> constexpr static LogValue Constant() { @@ -147,13 +149,6 @@ inline bool isAligned(Align Lhs, uint64_t SizeInBytes) { return SizeInBytes % Lhs.value() == 0; } -/// Checks that SizeInBytes is a multiple of the alignment. -/// Returns false if the alignment is undefined. -inline bool isAligned(MaybeAlign Lhs, uint64_t SizeInBytes) { - ALIGN_CHECK_ISSET(Lhs); - return SizeInBytes % (*Lhs).value() == 0; -} - /// Checks that Addr is a multiple of the alignment. inline bool isAddrAligned(Align Lhs, const void *Addr) { return isAligned(Lhs, reinterpret_cast<uintptr_t>(Addr)); @@ -161,17 +156,34 @@ inline bool isAddrAligned(Align Lhs, const void *Addr) { /// Returns a multiple of A needed to store `Size` bytes. inline uint64_t alignTo(uint64_t Size, Align A) { - const uint64_t value = A.value(); - // The following line is equivalent to `(Size + value - 1) / value * value`. + const uint64_t Value = A.value(); + // The following line is equivalent to `(Size + Value - 1) / Value * Value`. // The division followed by a multiplication can be thought of as a right // shift followed by a left shift which zeros out the extra bits produced in - // the bump; `~(value - 1)` is a mask where all those bits being zeroed out + // the bump; `~(Value - 1)` is a mask where all those bits being zeroed out // are just zero. // Most compilers can generate this code but the pattern may be missed when // multiple functions gets inlined. - return (Size + value - 1) & ~(value - 1); + return (Size + Value - 1) & ~(Value - 1U); +} + +/// If non-zero \p Skew is specified, the return value will be a minimal integer +/// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for +/// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p +/// Skew mod \p A'. +/// +/// Examples: +/// \code +/// alignTo(5, Align(8), 7) = 7 +/// alignTo(17, Align(8), 1) = 17 +/// alignTo(~0LL, Align(8), 3) = 3 +/// \endcode +inline uint64_t alignTo(uint64_t Size, Align A, uint64_t Skew) { + const uint64_t Value = A.value(); + Skew %= Value; + return ((Size + Value - 1 - Skew) & ~(Value - 1U)) + Skew; } /// Returns a multiple of A needed to store `Size` bytes. @@ -184,7 +196,8 @@ inline uint64_t alignTo(uint64_t Size, MaybeAlign A) { inline uintptr_t alignAddr(const void *Addr, Align Alignment) { uintptr_t ArithAddr = reinterpret_cast<uintptr_t>(Addr); assert(static_cast<uintptr_t>(ArithAddr + Alignment.value() - 1) >= - ArithAddr && "Overflow"); + ArithAddr && + "Overflow"); return alignTo(ArithAddr, Alignment); } @@ -203,13 +216,6 @@ inline uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment) { /// Returns the log2 of the alignment. inline unsigned Log2(Align A) { return A.ShiftValue; } -/// Returns the log2 of the alignment. -/// \pre A must be defined. -inline unsigned Log2(MaybeAlign A) { - ALIGN_CHECK_ISSET(A); - return Log2(A.getValue()); -} - /// Returns the alignment that satisfies both alignments. /// Same semantic as MinAlign. inline Align commonAlignment(Align A, Align B) { return std::min(A, B); } @@ -281,26 +287,6 @@ inline bool operator==(MaybeAlign Lhs, uint64_t Rhs) { inline bool operator!=(MaybeAlign Lhs, uint64_t Rhs) { return Lhs ? (*Lhs).value() != Rhs : Rhs != 0; } -inline bool operator<=(MaybeAlign Lhs, uint64_t Rhs) { - ALIGN_CHECK_ISSET(Lhs); - ALIGN_CHECK_ISPOSITIVE(Rhs); - return (*Lhs).value() <= Rhs; -} -inline bool operator>=(MaybeAlign Lhs, uint64_t Rhs) { - ALIGN_CHECK_ISSET(Lhs); - ALIGN_CHECK_ISPOSITIVE(Rhs); - return (*Lhs).value() >= Rhs; -} -inline bool operator<(MaybeAlign Lhs, uint64_t Rhs) { - ALIGN_CHECK_ISSET(Lhs); - ALIGN_CHECK_ISPOSITIVE(Rhs); - return (*Lhs).value() < Rhs; -} -inline bool operator>(MaybeAlign Lhs, uint64_t Rhs) { - ALIGN_CHECK_ISSET(Lhs); - ALIGN_CHECK_ISPOSITIVE(Rhs); - return (*Lhs).value() > Rhs; -} /// Comparisons operators between Align. inline bool operator==(Align Lhs, Align Rhs) { @@ -322,56 +308,30 @@ inline bool operator>(Align Lhs, Align Rhs) { return Lhs.ShiftValue > Rhs.ShiftValue; } -/// Comparisons operators between Align and MaybeAlign. -inline bool operator==(Align Lhs, MaybeAlign Rhs) { - ALIGN_CHECK_ISSET(Rhs); - return Lhs.value() == (*Rhs).value(); -} -inline bool operator!=(Align Lhs, MaybeAlign Rhs) { - ALIGN_CHECK_ISSET(Rhs); - return Lhs.value() != (*Rhs).value(); -} -inline bool operator<=(Align Lhs, MaybeAlign Rhs) { - ALIGN_CHECK_ISSET(Rhs); - return Lhs.value() <= (*Rhs).value(); -} -inline bool operator>=(Align Lhs, MaybeAlign Rhs) { - ALIGN_CHECK_ISSET(Rhs); - return Lhs.value() >= (*Rhs).value(); -} -inline bool operator<(Align Lhs, MaybeAlign Rhs) { - ALIGN_CHECK_ISSET(Rhs); - return Lhs.value() < (*Rhs).value(); -} -inline bool operator>(Align Lhs, MaybeAlign Rhs) { - ALIGN_CHECK_ISSET(Rhs); - return Lhs.value() > (*Rhs).value(); -} +// Don't allow relational comparisons with MaybeAlign. +bool operator<=(Align Lhs, MaybeAlign Rhs) = delete; +bool operator>=(Align Lhs, MaybeAlign Rhs) = delete; +bool operator<(Align Lhs, MaybeAlign Rhs) = delete; +bool operator>(Align Lhs, MaybeAlign Rhs) = delete; -/// Comparisons operators between MaybeAlign and Align. -inline bool operator==(MaybeAlign Lhs, Align Rhs) { - ALIGN_CHECK_ISSET(Lhs); - return Lhs && (*Lhs).value() == Rhs.value(); -} -inline bool operator!=(MaybeAlign Lhs, Align Rhs) { - ALIGN_CHECK_ISSET(Lhs); - return Lhs && (*Lhs).value() != Rhs.value(); -} -inline bool operator<=(MaybeAlign Lhs, Align Rhs) { - ALIGN_CHECK_ISSET(Lhs); - return Lhs && (*Lhs).value() <= Rhs.value(); -} -inline bool operator>=(MaybeAlign Lhs, Align Rhs) { - ALIGN_CHECK_ISSET(Lhs); - return Lhs && (*Lhs).value() >= Rhs.value(); -} -inline bool operator<(MaybeAlign Lhs, Align Rhs) { - ALIGN_CHECK_ISSET(Lhs); - return Lhs && (*Lhs).value() < Rhs.value(); +bool operator<=(MaybeAlign Lhs, Align Rhs) = delete; +bool operator>=(MaybeAlign Lhs, Align Rhs) = delete; +bool operator<(MaybeAlign Lhs, Align Rhs) = delete; +bool operator>(MaybeAlign Lhs, Align Rhs) = delete; + +bool operator<=(MaybeAlign Lhs, MaybeAlign Rhs) = delete; +bool operator>=(MaybeAlign Lhs, MaybeAlign Rhs) = delete; +bool operator<(MaybeAlign Lhs, MaybeAlign Rhs) = delete; +bool operator>(MaybeAlign Lhs, MaybeAlign Rhs) = delete; + +inline Align operator*(Align Lhs, uint64_t Rhs) { + assert(Rhs > 0 && "Rhs must be positive"); + return Align(Lhs.value() * Rhs); } -inline bool operator>(MaybeAlign Lhs, Align Rhs) { - ALIGN_CHECK_ISSET(Lhs); - return Lhs && (*Lhs).value() > Rhs.value(); + +inline MaybeAlign operator*(MaybeAlign Lhs, uint64_t Rhs) { + assert(Rhs > 0 && "Rhs must be positive"); + return Lhs ? Lhs.getValue() * Rhs : MaybeAlign(); } inline Align operator/(Align Lhs, uint64_t Divisor) { @@ -395,8 +355,20 @@ inline Align max(Align Lhs, MaybeAlign Rhs) { return Rhs && *Rhs > Lhs ? *Rhs : Lhs; } +#ifndef NDEBUG +// For usage in LLVM_DEBUG macros. +inline std::string DebugStr(const Align &A) { + return std::to_string(A.value()); +} +// For usage in LLVM_DEBUG macros. +inline std::string DebugStr(const MaybeAlign &MA) { + if (MA) + return std::to_string(MA->value()); + return "None"; +} +#endif // NDEBUG + #undef ALIGN_CHECK_ISPOSITIVE -#undef ALIGN_CHECK_ISSET } // namespace llvm |