1//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the AlignOf function that computes alignments for 11// arbitrary types. 12// 13//===----------------------------------------------------------------------===// 14 15#ifndef LLVM_SUPPORT_ALIGNOF_H 16#define LLVM_SUPPORT_ALIGNOF_H 17 18#include "llvm/Support/Compiler.h" 19#include <cstddef> 20 21namespace llvm { 22template <typename T> 23struct AlignmentCalcImpl { 24 char x; 25 T t; 26private: 27 AlignmentCalcImpl() {} // Never instantiate. 28}; 29 30/// AlignOf - A templated class that contains an enum value representing 31/// the alignment of the template argument. For example, 32/// AlignOf<int>::Alignment represents the alignment of type "int". The 33/// alignment calculated is the minimum alignment, and not necessarily 34/// the "desired" alignment returned by GCC's __alignof__ (for example). Note 35/// that because the alignment is an enum value, it can be used as a 36/// compile-time constant (e.g., for template instantiation). 37template <typename T> 38struct AlignOf { 39 enum { Alignment = 40 static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)) }; 41 42 enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; 43 enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; 44 enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; 45 enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; 46 47 enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; 48 enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; 49 enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; 50 enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; 51}; 52 53/// alignOf - A templated function that returns the minimum alignment of 54/// of a type. This provides no extra functionality beyond the AlignOf 55/// class besides some cosmetic cleanliness. Example usage: 56/// alignOf<int>() returns the alignment of an int. 57template <typename T> 58inline unsigned alignOf() { return AlignOf<T>::Alignment; } 59 60/// \struct AlignedCharArray 61/// \brief Helper for building an aligned character array type. 62/// 63/// This template is used to explicitly build up a collection of aligned 64/// character array types. We have to build these up using a macro and explicit 65/// specialization to cope with old versions of MSVC and GCC where only an 66/// integer literal can be used to specify an alignment constraint. Once built 67/// up here, we can then begin to indirect between these using normal C++ 68/// template parameters. 69 70// MSVC requires special handling here. 71#ifndef _MSC_VER 72 73#if __has_feature(cxx_alignas) 74template<std::size_t Alignment, std::size_t Size> 75struct AlignedCharArray { 76 alignas(Alignment) char buffer[Size]; 77}; 78 79#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES) 80/// \brief Create a type with an aligned char buffer. 81template<std::size_t Alignment, std::size_t Size> 82struct AlignedCharArray; 83 84#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 85 template<std::size_t Size> \ 86 struct AlignedCharArray<x, Size> { \ 87 __attribute__((aligned(x))) char buffer[Size]; \ 88 }; 89 90LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1) 91LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2) 92LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4) 93LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8) 94LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) 95LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) 96LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) 97LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) 98 99#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 100 101#else 102# error No supported align as directive. 103#endif 104 105#else // _MSC_VER 106 107/// \brief Create a type with an aligned char buffer. 108template<std::size_t Alignment, std::size_t Size> 109struct AlignedCharArray; 110 111// We provide special variations of this template for the most common 112// alignments because __declspec(align(...)) doesn't actually work when it is 113// a member of a by-value function argument in MSVC, even if the alignment 114// request is something reasonably like 8-byte or 16-byte. Note that we can't 115// even include the declspec with the union that forces the alignment because 116// MSVC warns on the existence of the declspec despite the union member forcing 117// proper alignment. 118 119template<std::size_t Size> 120struct AlignedCharArray<1, Size> { 121 union { 122 char aligned; 123 char buffer[Size]; 124 }; 125}; 126 127template<std::size_t Size> 128struct AlignedCharArray<2, Size> { 129 union { 130 short aligned; 131 char buffer[Size]; 132 }; 133}; 134 135template<std::size_t Size> 136struct AlignedCharArray<4, Size> { 137 union { 138 int aligned; 139 char buffer[Size]; 140 }; 141}; 142 143template<std::size_t Size> 144struct AlignedCharArray<8, Size> { 145 union { 146 double aligned; 147 char buffer[Size]; 148 }; 149}; 150 151 152// The rest of these are provided with a __declspec(align(...)) and we simply 153// can't pass them by-value as function arguments on MSVC. 154 155#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 156 template<std::size_t Size> \ 157 struct AlignedCharArray<x, Size> { \ 158 __declspec(align(x)) char buffer[Size]; \ 159 }; 160 161LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) 162LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) 163LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) 164LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) 165 166#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 167 168#endif // _MSC_VER 169 170namespace detail { 171template <typename T1, 172 typename T2 = char, typename T3 = char, typename T4 = char, 173 typename T5 = char, typename T6 = char, typename T7 = char, 174 typename T8 = char, typename T9 = char, typename T10 = char> 175class AlignerImpl { 176 T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10; 177 178 AlignerImpl(); // Never defined or instantiated. 179}; 180 181template <typename T1, 182 typename T2 = char, typename T3 = char, typename T4 = char, 183 typename T5 = char, typename T6 = char, typename T7 = char, 184 typename T8 = char, typename T9 = char, typename T10 = char> 185union SizerImpl { 186 char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], 187 arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)], 188 arr9[sizeof(T9)], arr10[sizeof(T10)]; 189}; 190} // end namespace detail 191 192/// \brief This union template exposes a suitably aligned and sized character 193/// array member which can hold elements of any of up to four types. 194/// 195/// These types may be arrays, structs, or any other types. The goal is to 196/// expose a char array buffer member which can be used as suitable storage for 197/// a placement new of any of these types. Support for more than seven types can 198/// be added at the cost of more boiler plate. 199template <typename T1, 200 typename T2 = char, typename T3 = char, typename T4 = char, 201 typename T5 = char, typename T6 = char, typename T7 = char, 202 typename T8 = char, typename T9 = char, typename T10 = char> 203struct AlignedCharArrayUnion : llvm::AlignedCharArray< 204 AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5, 205 T6, T7, T8, T9, T10> >::Alignment, 206 sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, 207 T6, T7, T8, T9, T10>)> { 208}; 209} // end namespace llvm 210#endif 211