Properly test the LLVM_USE_RVALUE_REFERENCES macro.
[oota-llvm.git] / include / llvm / Support / AlignOf.h
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 #if __has_feature(cxx_alignas)
76 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
77   template <> struct AlignedCharArrayImpl<x> { \
78     typedef char alignas(x) type; \
79   }
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))); \
84   }
85 #elif defined(_MSC_VER)
86 #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
87   template <> struct AlignedCharArrayImpl<x> { \
88     typedef __declspec(align(x)) char type; \
89   }
90 #else
91 # error No supported align as directive.
92 #endif
93
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
109
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.
112 ///
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 {
120   class AlignerImpl {
121     T1 t1; T2 t2; T3 t3; T4 t4;
122
123     AlignerImpl(); // Never defined or instantiated.
124   };
125   union SizerImpl {
126     char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)];
127   };
128
129 public:
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.
137   union union_type {
138     // This is the only member of the union which should be used by clients:
139     char buffer[sizeof(SizerImpl)];
140
141     // This member of the union only exists to force the alignment.
142     struct {
143       typename llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment>::type
144         nonce_inner_member;
145     } nonce_member;
146   };
147 };
148
149 } // end namespace llvm
150 #endif