hubert.reinterpretcast created this revision.
hubert.reinterpretcast added reviewers: aaron.ballman, faisalv, rsmith.
hubert.reinterpretcast added a subscriber: cfe-commits.
This change fixes issues with `LLVM_CONSTEXPR` functions and
`TrailingObjects::FixedSizeStorage`. In particular, some of the functions
marked `LLVM_CONSTEXPR` used by `FixedSizeStorage` were not implemented such
that they evaluate successfully as part of a constant expression despite
constant arguments.
This change also implements a more traditional template-meta path to
accommodate MSVC.
https://reviews.llvm.org/D22668
Files:
include/llvm/Support/AlignOf.h
include/llvm/Support/MathExtras.h
include/llvm/Support/TrailingObjects.h
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<PrevTy>::Alignment < llvm::AlignOf<NextTy>::Alignment;
+ };
+
static LLVM_CONSTEXPR bool requiresRealignment() {
- return llvm::AlignOf<PrevTy>::Alignment < llvm::AlignOf<NextTy>::Alignment;
+ return RequiresRealignment::value;
}
// These two functions are helper functions for
@@ -197,11 +202,27 @@
typename ExtractSecondType<MoreTys, size_t>::type... MoreCounts) {
return additionalSizeToAllocImpl(
(requiresRealignment()
- ? llvm::alignTo(SizeSoFar, llvm::alignOf<NextTy>())
+ ? llvm::alignTo<llvm::alignOf<NextTy>()>(SizeSoFar)
: SizeSoFar) +
sizeof(NextTy) * Count1,
MoreCounts...);
}
+
+ // additionalSizeToAllocImpl for contexts where a constant expression is
+ // required.
+ // FIXME: remove when LLVM_CONSTEXPR becomes really constexpr
+ template <size_t SizeSoFar, size_t Count1, size_t... MoreCounts>
+ 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<llvm::AlignOf<NextTy>::Alignment>::
+ template from_value<SizeSoFar>::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 <size_t SizeSoFar> struct AdditionalSizeToAllocImpl {
+ static const size_t value = SizeSoFar;
+ };
+
template <bool CheckAlignment> 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 <typename... Tys> struct TotalSizeToAlloc {
+ static_assert(
+ std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value,
+ "Arguments to TotalSizeToAlloc do not match with TrailingObjects");
+ template <size_t... Counts> 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 <typename... Tys> struct FixedSizeStorage {
template <size_t... Counts> struct with_counts {
- enum { Size = totalSizeToAlloc<Tys...>(Counts...) };
+ enum {
+ Size = TotalSizeToAlloc<Tys...>::template with_counts<Counts...>::value
+ };
typedef llvm::AlignedCharArray<
llvm::AlignOf<BaseTy>::Alignment, Size
> 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 <uint64_t Align>
+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 <uint64_t Align>
+struct AlignTo {
+ static_assert(Align != 0u, "Align must be non-zero");
+ template <uint64_t Value>
+ 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/AlignOf.h
===================================================================
--- include/llvm/Support/AlignOf.h
+++ include/llvm/Support/AlignOf.h
@@ -103,7 +103,7 @@
/// class besides some cosmetic cleanliness. Example usage:
/// alignOf<int>() returns the alignment of an int.
template <typename T>
-inline unsigned alignOf() { return AlignOf<T>::Alignment; }
+LLVM_CONSTEXPR inline unsigned alignOf() { return AlignOf<T>::Alignment; }
/// \struct AlignedCharArray
/// \brief Helper for building an aligned character array type.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits