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 146