LLVM API Documentation
00001 //===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the AlignOf function that computes alignments for 00011 // arbitrary types. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_SUPPORT_ALIGNOF_H 00016 #define LLVM_SUPPORT_ALIGNOF_H 00017 00018 #include "llvm/Support/Compiler.h" 00019 #include <cstddef> 00020 00021 namespace llvm { 00022 template <typename T> 00023 struct AlignmentCalcImpl { 00024 char x; 00025 T t; 00026 private: 00027 AlignmentCalcImpl() {} // Never instantiate. 00028 }; 00029 00030 /// AlignOf - A templated class that contains an enum value representing 00031 /// the alignment of the template argument. For example, 00032 /// AlignOf<int>::Alignment represents the alignment of type "int". The 00033 /// alignment calculated is the minimum alignment, and not necessarily 00034 /// the "desired" alignment returned by GCC's __alignof__ (for example). Note 00035 /// that because the alignment is an enum value, it can be used as a 00036 /// compile-time constant (e.g., for template instantiation). 00037 template <typename T> 00038 struct AlignOf { 00039 enum { Alignment = 00040 static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)) }; 00041 00042 enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; 00043 enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; 00044 enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; 00045 enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; 00046 00047 enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; 00048 enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; 00049 enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; 00050 enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; 00051 }; 00052 00053 /// alignOf - A templated function that returns the minimum alignment of 00054 /// of a type. This provides no extra functionality beyond the AlignOf 00055 /// class besides some cosmetic cleanliness. Example usage: 00056 /// alignOf<int>() returns the alignment of an int. 00057 template <typename T> 00058 inline unsigned alignOf() { return AlignOf<T>::Alignment; } 00059 00060 /// \struct AlignedCharArray 00061 /// \brief Helper for building an aligned character array type. 00062 /// 00063 /// This template is used to explicitly build up a collection of aligned 00064 /// character array types. We have to build these up using a macro and explicit 00065 /// specialization to cope with old versions of MSVC and GCC where only an 00066 /// integer literal can be used to specify an alignment constraint. Once built 00067 /// up here, we can then begin to indirect between these using normal C++ 00068 /// template parameters. 00069 00070 // MSVC requires special handling here. 00071 #ifndef _MSC_VER 00072 00073 #if __has_feature(cxx_alignas) 00074 template<std::size_t Alignment, std::size_t Size> 00075 struct AlignedCharArray { 00076 alignas(Alignment) char buffer[Size]; 00077 }; 00078 00079 #elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES) 00080 /// \brief Create a type with an aligned char buffer. 00081 template<std::size_t Alignment, std::size_t Size> 00082 struct AlignedCharArray; 00083 00084 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 00085 template<std::size_t Size> \ 00086 struct AlignedCharArray<x, Size> { \ 00087 __attribute__((aligned(x))) char buffer[Size]; \ 00088 }; 00089 00090 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1) 00091 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2) 00092 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4) 00093 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8) 00094 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) 00095 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) 00096 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) 00097 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) 00098 00099 #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 00100 00101 #else 00102 # error No supported align as directive. 00103 #endif 00104 00105 #else // _MSC_VER 00106 00107 /// \brief Create a type with an aligned char buffer. 00108 template<std::size_t Alignment, std::size_t Size> 00109 struct AlignedCharArray; 00110 00111 // We provide special variations of this template for the most common 00112 // alignments because __declspec(align(...)) doesn't actually work when it is 00113 // a member of a by-value function argument in MSVC, even if the alignment 00114 // request is something reasonably like 8-byte or 16-byte. Note that we can't 00115 // even include the declspec with the union that forces the alignment because 00116 // MSVC warns on the existence of the declspec despite the union member forcing 00117 // proper alignment. 00118 00119 template<std::size_t Size> 00120 struct AlignedCharArray<1, Size> { 00121 union { 00122 char aligned; 00123 char buffer[Size]; 00124 }; 00125 }; 00126 00127 template<std::size_t Size> 00128 struct AlignedCharArray<2, Size> { 00129 union { 00130 short aligned; 00131 char buffer[Size]; 00132 }; 00133 }; 00134 00135 template<std::size_t Size> 00136 struct AlignedCharArray<4, Size> { 00137 union { 00138 int aligned; 00139 char buffer[Size]; 00140 }; 00141 }; 00142 00143 template<std::size_t Size> 00144 struct AlignedCharArray<8, Size> { 00145 union { 00146 double aligned; 00147 char buffer[Size]; 00148 }; 00149 }; 00150 00151 00152 // The rest of these are provided with a __declspec(align(...)) and we simply 00153 // can't pass them by-value as function arguments on MSVC. 00154 00155 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ 00156 template<std::size_t Size> \ 00157 struct AlignedCharArray<x, Size> { \ 00158 __declspec(align(x)) char buffer[Size]; \ 00159 }; 00160 00161 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) 00162 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) 00163 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) 00164 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) 00165 00166 #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT 00167 00168 #endif // _MSC_VER 00169 00170 namespace detail { 00171 template <typename T1, 00172 typename T2 = char, typename T3 = char, typename T4 = char, 00173 typename T5 = char, typename T6 = char, typename T7 = char, 00174 typename T8 = char, typename T9 = char, typename T10 = char> 00175 class AlignerImpl { 00176 T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10; 00177 00178 AlignerImpl(); // Never defined or instantiated. 00179 }; 00180 00181 template <typename T1, 00182 typename T2 = char, typename T3 = char, typename T4 = char, 00183 typename T5 = char, typename T6 = char, typename T7 = char, 00184 typename T8 = char, typename T9 = char, typename T10 = char> 00185 union SizerImpl { 00186 char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], 00187 arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)], 00188 arr9[sizeof(T9)], arr10[sizeof(T10)]; 00189 }; 00190 } // end namespace detail 00191 00192 /// \brief This union template exposes a suitably aligned and sized character 00193 /// array member which can hold elements of any of up to four types. 00194 /// 00195 /// These types may be arrays, structs, or any other types. The goal is to 00196 /// expose a char array buffer member which can be used as suitable storage for 00197 /// a placement new of any of these types. Support for more than seven types can 00198 /// be added at the cost of more boiler plate. 00199 template <typename T1, 00200 typename T2 = char, typename T3 = char, typename T4 = char, 00201 typename T5 = char, typename T6 = char, typename T7 = char, 00202 typename T8 = char, typename T9 = char, typename T10 = char> 00203 struct AlignedCharArrayUnion : llvm::AlignedCharArray< 00204 AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5, 00205 T6, T7, T8, T9, T10> >::Alignment, 00206 sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, 00207 T6, T7, T8, T9, T10>)> { 00208 }; 00209 } // end namespace llvm 00210 #endif