Index: include/llvm/Support/AlignOf.h =================================================================== --- include/llvm/Support/AlignOf.h +++ include/llvm/Support/AlignOf.h @@ -103,7 +103,7 @@ /// class besides some cosmetic cleanliness. Example usage: /// alignOf() returns the alignment of an int. template -inline unsigned alignOf() { return AlignOf::Alignment; } +LLVM_CONSTEXPR inline unsigned alignOf() { return AlignOf::Alignment; } /// \struct AlignedCharArray /// \brief Helper for building an aligned character array type. Index: include/llvm/Support/MathExtras.h =================================================================== --- include/llvm/Support/MathExtras.h +++ include/llvm/Support/MathExtras.h @@ -671,6 +671,25 @@ return (Value + Align - 1 - Skew) / Align * Align + Skew; } +/// Returns the next integer (mod 2**64) that is greater than or equal to +/// \p Value and is a multiple of \c Align. \c Align must be non-zero. +template +LLVM_CONSTEXPR inline uint64_t alignTo(uint64_t Value) { + static_assert(Align != 0u, "Align must be non-zero"); + return (Value + Align - 1) / Align * Align; +} + +// alignTo for contexts where a constant expression is required. +// FIXME: remove when LLVM_CONSTEXPR becomes really constexpr +template +struct AlignTo { + static_assert(Align != 0u, "Align must be non-zero"); + template + struct from_value { + static const uint64_t value = (Value + Align - 1) / Align * Align; + }; +}; + /// Returns the largest uint64_t less than or equal to \p Value and is /// \p Skew mod \p Align. \p Align must be non-zero inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) { Index: include/llvm/Support/TrailingObjects.h =================================================================== --- include/llvm/Support/TrailingObjects.h +++ include/llvm/Support/TrailingObjects.h @@ -146,8 +146,13 @@ using ParentType::getTrailingObjectsImpl; using ParentType::additionalSizeToAllocImpl; + struct RequiresRealignment { + static const bool value = + llvm::AlignOf::Alignment < llvm::AlignOf::Alignment; + }; + static LLVM_CONSTEXPR bool requiresRealignment() { - return llvm::AlignOf::Alignment < llvm::AlignOf::Alignment; + return RequiresRealignment::value; } // These two functions are helper functions for @@ -197,11 +202,27 @@ typename ExtractSecondType::type... MoreCounts) { return additionalSizeToAllocImpl( (requiresRealignment() - ? llvm::alignTo(SizeSoFar, llvm::alignOf()) + ? llvm::alignTo()>(SizeSoFar) : SizeSoFar) + sizeof(NextTy) * Count1, MoreCounts...); } + + // additionalSizeToAllocImpl for contexts where a constant expression is + // required. + // FIXME: remove when LLVM_CONSTEXPR becomes really constexpr + template + struct AdditionalSizeToAllocImpl { + static_assert(sizeof...(MoreTys) == sizeof...(MoreCounts), + "Number of counts do not match number of types"); + static const size_t value = ParentType::template AdditionalSizeToAllocImpl< + (RequiresRealignment::value + ? llvm::AlignTo::Alignment>:: + template from_value::value + : SizeSoFar) + + sizeof(NextTy) * Count1, + MoreCounts...>::value; + }; }; // The base case of the TrailingObjectsImpl inheritance recursion, @@ -218,6 +239,13 @@ return SizeSoFar; } + // additionalSizeToAllocImpl for contexts where a constant expression is + // required. + // FIXME: remove when LLVM_CONSTEXPR becomes really constexpr + template struct AdditionalSizeToAllocImpl { + static const size_t value = SizeSoFar; + }; + template static void verifyTrailingObjectsAlignment() {} }; @@ -343,6 +371,21 @@ return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...); } + // totalSizeToAlloc for contexts where a constant expression is required. + // FIXME: remove when LLVM_CONSTEXPR becomes really constexpr + template struct TotalSizeToAlloc { + static_assert( + std::is_same, Foo>::value, + "Arguments to TotalSizeToAlloc do not match with TrailingObjects"); + template struct with_counts { + static_assert(sizeof...(TrailingTys) == sizeof...(Counts), + "Number of counts do not match number of types"); + static const size_t value = + sizeof(BaseTy) + + ParentType::template AdditionalSizeToAllocImpl<0, Counts...>::value; + }; + }; + /// A type where its ::with_counts template member has a ::type member /// suitable for use as uninitialized storage for an object with the given /// trailing object counts. The template arguments are similar to those @@ -360,7 +403,9 @@ /// \endcode template struct FixedSizeStorage { template struct with_counts { - enum { Size = totalSizeToAlloc(Counts...) }; + enum { + Size = TotalSizeToAlloc::template with_counts::value + }; typedef llvm::AlignedCharArray< llvm::AlignOf::Alignment, Size > type;