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 21 namespace llvm { 22 23 template <typename T> 24 struct AlignmentCalcImpl { 25 char x; 26 T t; 27 private: 28 AlignmentCalcImpl() {} // Never instantiate. 29 }; 30 31 /// AlignOf - A templated class that contains an enum value representing 32 /// the alignment of the template argument. For example, 33 /// AlignOf<int>::Alignment represents the alignment of type "int". The 34 /// alignment calculated is the minimum alignment, and not necessarily 35 /// the "desired" alignment returned by GCC's __alignof__ (for example). Note 36 /// that because the alignment is an enum value, it can be used as a 37 /// compile-time constant (e.g., for template instantiation). 38 template <typename T> 39 struct AlignOf { 40 enum { Alignment = 41 static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)) }; 42 43 enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; 44 enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; 45 enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; 46 enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; 47 48 enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; 49 enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; 50 enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; 51 enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; 52 53 }; 54 55 /// alignOf - A templated function that returns the minimum alignment of 56 /// of a type. This provides no extra functionality beyond the AlignOf 57 /// class besides some cosmetic cleanliness. Example usage: 58 /// alignOf<int>() returns the alignment of an int. 59 template <typename T> 60 inline unsigned alignOf() { return AlignOf<T>::Alignment; } 61 62 63 /// \brief Helper for building an aligned character array type. 64 /// 65 /// This template is used to explicitly build up a collection of aligned 66 /// character types. We have to build these up using a macro and explicit 67 /// specialization to cope with old versions of MSVC and GCC where only an 68 /// integer literal can be used to specify an alignment constraint. Once built 69 /// up here, we can then begin to indirect between these using normal C++ 70 /// template parameters. 71 template <size_t Alignment> struct AlignedCharArrayImpl {}; 72 template <> struct AlignedCharArrayImpl<0> { 73 typedef char type; 74 }; 75 76 // MSVC requires special handling here. 77 #ifndef _MSC_VER 78 79 #if __has_feature(cxx_alignas) 80 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 81 template <> struct AlignedCharArrayImpl<x> { \ 82 typedef char alignas(x) type; \ 83 } 84 #elif defined(__clang__) || defined(__GNUC__) 85 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 86 template <> struct AlignedCharArrayImpl<x> { \ 87 typedef char type __attribute__((aligned(x))); \ 88 } 89 #else 90 # error No supported align as directive. 91 #endif 92 93 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1); 94 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2); 95 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4); 96 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8); 97 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16); 98 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32); 99 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64); 100 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128); 101 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512); 102 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024); 103 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048); 104 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096); 105 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); 106 107 #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 108 109 #else // _MSC_VER 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. 115 template <> struct AlignedCharArrayImpl<1> { typedef char type; }; 116 template <> struct AlignedCharArrayImpl<2> { typedef short type; }; 117 template <> struct AlignedCharArrayImpl<4> { typedef int type; }; 118 template <> struct AlignedCharArrayImpl<8> { typedef double type; }; 119 120 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 121 template <> struct AlignedCharArrayImpl<x> { \ 122 typedef __declspec(align(x)) char type; \ 123 } 124 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16); 125 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32); 126 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64); 127 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128); 128 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512); 129 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024); 130 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048); 131 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096); 132 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); 133 // Any larger and MSVC complains. 134 #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 135 136 #endif // _MSC_VER 137 138 /// \brief This union template exposes a suitably aligned and sized character 139 /// array member which can hold elements of any of up to four types. 140 /// 141 /// These types may be arrays, structs, or any other types. The goal is to 142 /// produce a union type containing a character array which, when used, forms 143 /// storage suitable to placement new any of these types over. Support for more 144 /// than four types can be added at the cost of more boiler plate. 145 template <typename T1, 146 typename T2 = char, typename T3 = char, typename T4 = char> 147 union AlignedCharArrayUnion { 148 private: 149 class AlignerImpl { 150 T1 t1; T2 t2; T3 t3; T4 t4; 151 152 AlignerImpl(); // Never defined or instantiated. 153 }; 154 union SizerImpl { 155 char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)]; 156 }; 157 158 public: 159 /// \brief The character array buffer for use by clients. 160 /// 161 /// No other member of this union should be referenced. The exist purely to 162 /// constrain the layout of this character array. 163 char buffer[sizeof(SizerImpl)]; 164 165 // Sadly, Clang and GCC both fail to align a character array properly even 166 // with an explicit alignment attribute. To work around this, we union 167 // the character array that will actually be used with a struct that contains 168 // a single aligned character member. Tests seem to indicate that both Clang 169 // and GCC will properly register the alignment of a struct containing an 170 // aligned member, and this alignment should carry over to the character 171 // array in the union. 172 struct { 173 typename llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment>::type 174 nonce_inner_member; 175 } nonce_member; 176 }; 177 178 } // end namespace llvm 179 #endif 180