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 AlignedCharArray and AlignedCharArrayUnion classes.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_ALIGNOF_H
15#define LLVM_SUPPORT_ALIGNOF_H
16
17#include "llvm/Support/Compiler.h"
18#include <cstddef>
19
20namespace llvm {
21
22/// \struct AlignedCharArray
23/// \brief Helper for building an aligned character array type.
24///
25/// This template is used to explicitly build up a collection of aligned
26/// character array types. We have to build these up using a macro and explicit
27/// specialization to cope with MSVC (at least till 2015) where only an
28/// integer literal can be used to specify an alignment constraint. Once built
29/// up here, we can then begin to indirect between these using normal C++
30/// template parameters.
31
32// MSVC requires special handling here.
33#ifndef _MSC_VER
34
35template<std::size_t Alignment, std::size_t Size>
36struct AlignedCharArray {
37  LLVM_ALIGNAS(Alignment) char buffer[Size];
38};
39
40#else // _MSC_VER
41
42/// \brief Create a type with an aligned char buffer.
43template<std::size_t Alignment, std::size_t Size>
44struct AlignedCharArray;
45
46// We provide special variations of this template for the most common
47// alignments because __declspec(align(...)) doesn't actually work when it is
48// a member of a by-value function argument in MSVC, even if the alignment
49// request is something reasonably like 8-byte or 16-byte. Note that we can't
50// even include the declspec with the union that forces the alignment because
51// MSVC warns on the existence of the declspec despite the union member forcing
52// proper alignment.
53
54template<std::size_t Size>
55struct AlignedCharArray<1, Size> {
56  union {
57    char aligned;
58    char buffer[Size];
59  };
60};
61
62template<std::size_t Size>
63struct AlignedCharArray<2, Size> {
64  union {
65    short aligned;
66    char buffer[Size];
67  };
68};
69
70template<std::size_t Size>
71struct AlignedCharArray<4, Size> {
72  union {
73    int aligned;
74    char buffer[Size];
75  };
76};
77
78template<std::size_t Size>
79struct AlignedCharArray<8, Size> {
80  union {
81    double aligned;
82    char buffer[Size];
83  };
84};
85
86
87// The rest of these are provided with a __declspec(align(...)) and we simply
88// can't pass them by-value as function arguments on MSVC.
89
90#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
91  template<std::size_t Size> \
92  struct AlignedCharArray<x, Size> { \
93    __declspec(align(x)) char buffer[Size]; \
94  };
95
96LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
97LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
98LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
99LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
100
101#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
102
103#endif // _MSC_VER
104
105namespace detail {
106template <typename T1,
107          typename T2 = char, typename T3 = char, typename T4 = char,
108          typename T5 = char, typename T6 = char, typename T7 = char,
109          typename T8 = char, typename T9 = char, typename T10 = char>
110class AlignerImpl {
111  T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
112
113  AlignerImpl() = delete;
114};
115
116template <typename T1,
117          typename T2 = char, typename T3 = char, typename T4 = char,
118          typename T5 = char, typename T6 = char, typename T7 = char,
119          typename T8 = char, typename T9 = char, typename T10 = char>
120union SizerImpl {
121  char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)],
122       arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)],
123       arr9[sizeof(T9)], arr10[sizeof(T10)];
124};
125} // end namespace detail
126
127/// \brief This union template exposes a suitably aligned and sized character
128/// array member which can hold elements of any of up to ten types.
129///
130/// These types may be arrays, structs, or any other types. The goal is to
131/// expose a char array buffer member which can be used as suitable storage for
132/// a placement new of any of these types. Support for more than ten types can
133/// be added at the cost of more boilerplate.
134template <typename T1,
135          typename T2 = char, typename T3 = char, typename T4 = char,
136          typename T5 = char, typename T6 = char, typename T7 = char,
137          typename T8 = char, typename T9 = char, typename T10 = char>
138struct AlignedCharArrayUnion : llvm::AlignedCharArray<
139    alignof(llvm::detail::AlignerImpl<T1, T2, T3, T4, T5,
140                                      T6, T7, T8, T9, T10>),
141    sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5,
142                                     T6, T7, T8, T9, T10>)> {
143};
144} // end namespace llvm
145
146#endif // LLVM_SUPPORT_ALIGNOF_H
147