forked from OSchip/llvm-project
Lift the 10-type limit for AlignedCharArrayUnion
This patch uses C++11 parameter packs and constexpr functions to allow AlignedCharArrayUnion to hold an arbitrary number of types. Differential Revision: https://reviews.llvm.org/D28429 llvm-svn: 291503
This commit is contained in:
parent
47132e5cab
commit
4d9c5c2280
|
@ -102,45 +102,38 @@ LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
|
|||
|
||||
#endif // _MSC_VER
|
||||
|
||||
namespace detail {
|
||||
template <typename T1,
|
||||
typename T2 = char, typename T3 = char, typename T4 = char,
|
||||
typename T5 = char, typename T6 = char, typename T7 = char,
|
||||
typename T8 = char, typename T9 = char, typename T10 = char>
|
||||
class AlignerImpl {
|
||||
T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
|
||||
// This code implements the equivalent of std::aligned_union from C++11.
|
||||
// That is supported by Visual Studio 2015 and GCC 5.1.
|
||||
// Once these are the baselines for LLVM, we can use std::aligned_union instead.
|
||||
|
||||
namespace detail {
|
||||
template <typename... Ts> class AlignerImpl;
|
||||
|
||||
template <typename T1, typename... Ts>
|
||||
class AlignerImpl<T1, Ts...> : AlignerImpl<Ts...> {
|
||||
T1 t;
|
||||
AlignerImpl() = delete;
|
||||
};
|
||||
|
||||
template <typename T1,
|
||||
typename T2 = char, typename T3 = char, typename T4 = char,
|
||||
typename T5 = char, typename T6 = char, typename T7 = char,
|
||||
typename T8 = char, typename T9 = char, typename T10 = char>
|
||||
union SizerImpl {
|
||||
char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)],
|
||||
arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)],
|
||||
arr9[sizeof(T9)], arr10[sizeof(T10)];
|
||||
};
|
||||
template <> class AlignerImpl<> { AlignerImpl() = delete; };
|
||||
|
||||
template <typename T1> constexpr size_t sizer() { return sizeof(T1); }
|
||||
|
||||
template <typename T1, typename T2, typename... Ts> constexpr size_t sizer() {
|
||||
return (sizeof(T1) > sizer<T2, Ts...>()) ? sizeof(T1) : sizer<T2, Ts...>();
|
||||
}
|
||||
} // end namespace detail
|
||||
|
||||
/// \brief This union template exposes a suitably aligned and sized character
|
||||
/// array member which can hold elements of any of up to ten types.
|
||||
/// array member which can hold elements of any of a number of types.
|
||||
///
|
||||
/// These types may be arrays, structs, or any other types. The goal is to
|
||||
/// expose a char array buffer member which can be used as suitable storage for
|
||||
/// a placement new of any of these types. Support for more than ten types can
|
||||
/// be added at the cost of more boilerplate.
|
||||
template <typename T1,
|
||||
typename T2 = char, typename T3 = char, typename T4 = char,
|
||||
typename T5 = char, typename T6 = char, typename T7 = char,
|
||||
typename T8 = char, typename T9 = char, typename T10 = char>
|
||||
struct AlignedCharArrayUnion : llvm::AlignedCharArray<
|
||||
alignof(llvm::detail::AlignerImpl<T1, T2, T3, T4, T5,
|
||||
T6, T7, T8, T9, T10>),
|
||||
sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5,
|
||||
T6, T7, T8, T9, T10>)> {
|
||||
};
|
||||
/// a placement new of any of these types.
|
||||
template <typename... Ts>
|
||||
struct AlignedCharArrayUnion
|
||||
: llvm::AlignedCharArray<alignof(llvm::detail::AlignerImpl<Ts...>),
|
||||
detail::sizer<Ts...>()> {};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_SUPPORT_ALIGNOF_H
|
||||
|
|
|
@ -91,6 +91,24 @@ V8::~V8() {}
|
|||
|
||||
template <typename M> struct T { M m; };
|
||||
|
||||
typedef uint8_t t1;
|
||||
typedef uint16_t t2;
|
||||
typedef uint32_t t3;
|
||||
typedef uint64_t t4;
|
||||
typedef int8_t t5;
|
||||
typedef int16_t t6;
|
||||
typedef int32_t t7;
|
||||
typedef int64_t t8;
|
||||
typedef struct { uint8_t bytes[16]; } t9;
|
||||
typedef struct { uint16_t words[16]; } t10;
|
||||
typedef struct { uint32_t words[16]; } t11;
|
||||
typedef struct { uint64_t words[16]; } t12;
|
||||
|
||||
typedef AlignedCharArrayUnion<t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12> U;
|
||||
|
||||
static_assert(sizeof(U) == sizeof(uint64_t[16]), "Statically-computed size must be right");
|
||||
static_assert(alignof(U) == alignof(uint64_t), "Statically-computed alignment must be right");
|
||||
|
||||
TEST(AlignOfTest, BasicAlignedArray) {
|
||||
EXPECT_LE(1u, alignof(AlignedCharArrayUnion<A1>));
|
||||
EXPECT_LE(2u, alignof(AlignedCharArrayUnion<A2>));
|
||||
|
|
Loading…
Reference in New Issue