2
0

AlignOf.h 8.1 KB

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