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