1 //===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the AlignOf function that computes alignments for
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_SUPPORT_ALIGNOF_H
16 #define LLVM_SUPPORT_ALIGNOF_H
18 #include "llvm/Support/Compiler.h"
24 struct AlignmentCalcImpl {
28 AlignmentCalcImpl() {} // Never instantiate.
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).
41 static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T)) };
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 };
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 };
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.
60 inline unsigned alignOf() { return AlignOf<T>::Alignment; }
63 /// \brief Helper for building an aligned character array type.
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> {
75 #if __has_feature(cxx_alignas)
76 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
77 template <> struct AlignedCharArrayImpl<x> { \
78 typedef char alignas(x) type; \
80 #elif defined(__clang__) || defined(__GNUC__)
81 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
82 template <> struct AlignedCharArrayImpl<x> { \
83 typedef char type __attribute__((aligned(x))); \
85 #elif defined(_MSC_VER)
86 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
87 template <> struct AlignedCharArrayImpl<x> { \
88 typedef __declspec(align(x)) char type; \
91 # error No supported align as directive.
94 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1);
95 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2);
96 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4);
97 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8);
98 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16);
99 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32);
100 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64);
101 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128);
102 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512);
103 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024);
104 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048);
105 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096);
106 LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192);
107 // Any larger and MSVC complains.
108 #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
110 /// \brief This class template exposes a typedef for type containing a suitable
111 /// aligned character array to hold elements of any of up to four types.
113 /// These types may be arrays, structs, or any other types. The goal is to
114 /// produce a union type containing a character array which, when used, forms
115 /// storage suitable to placement new any of these types over. Support for more
116 /// than four types can be added at the cost of more boiler plate.
117 template <typename T1,
118 typename T2 = char, typename T3 = char, typename T4 = char>
119 class AlignedCharArray {
121 T1 t1; T2 t2; T3 t3; T4 t4;
123 AlignerImpl(); // Never defined or instantiated.
126 char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)];
130 // Sadly, Clang and GCC both fail to align a character array properly even
131 // with an explicit alignment attribute. To work around this, we union
132 // the character array that will actually be used with a struct that contains
133 // a single aligned character member. Tests seem to indicate that both Clang
134 // and GCC will properly register the alignment of a struct containing an
135 // aligned member, and this alignment should carry over to the character
136 // array in the union.
138 // This is the only member of the union which should be used by clients:
139 char buffer[sizeof(SizerImpl)];
141 // This member of the union only exists to force the alignment.
143 typename llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment>::type
149 } // end namespace llvm