17ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===//
27ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
37ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//                     The LLVM Compiler Infrastructure
47ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
57ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// This file is distributed under the University of Illinois Open Source
67ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// License. See LICENSE.TXT for details.
77ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
87ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//===----------------------------------------------------------------------===//
97ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
102df178997d17474042e8c3704cc93ab2db6619bfNicolas Capens// This file defines the AlignedCharArray and AlignedCharArrayUnion classes.
117ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//
127ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens//===----------------------------------------------------------------------===//
137ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
147ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#ifndef LLVM_SUPPORT_ALIGNOF_H
157ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#define LLVM_SUPPORT_ALIGNOF_H
167ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
177ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#include "llvm/Support/Compiler.h"
187ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#include <cstddef>
197ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
207ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensnamespace llvm {
217ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
227ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// \struct AlignedCharArray
237ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// \brief Helper for building an aligned character array type.
247ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens///
257ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// This template is used to explicitly build up a collection of aligned
267ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// character array types. We have to build these up using a macro and explicit
272df178997d17474042e8c3704cc93ab2db6619bfNicolas Capens/// specialization to cope with MSVC (at least till 2015) where only an
287ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// integer literal can be used to specify an alignment constraint. Once built
297ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// up here, we can then begin to indirect between these using normal C++
307ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// template parameters.
317ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
327ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// MSVC requires special handling here.
337ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#ifndef _MSC_VER
347ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
357ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate<std::size_t Alignment, std::size_t Size>
367ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensstruct AlignedCharArray {
372df178997d17474042e8c3704cc93ab2db6619bfNicolas Capens  LLVM_ALIGNAS(Alignment) char buffer[Size];
387ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
397ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
407ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#else // _MSC_VER
417ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
427ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// \brief Create a type with an aligned char buffer.
437ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate<std::size_t Alignment, std::size_t Size>
447ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensstruct AlignedCharArray;
457ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
467ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// We provide special variations of this template for the most common
477ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// alignments because __declspec(align(...)) doesn't actually work when it is
487ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// a member of a by-value function argument in MSVC, even if the alignment
497ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// request is something reasonably like 8-byte or 16-byte. Note that we can't
507ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// even include the declspec with the union that forces the alignment because
517ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// MSVC warns on the existence of the declspec despite the union member forcing
527ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// proper alignment.
537ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
547ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate<std::size_t Size>
557ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensstruct AlignedCharArray<1, Size> {
567ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  union {
577ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    char aligned;
587ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    char buffer[Size];
597ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  };
607ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
617ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
627ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate<std::size_t Size>
637ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensstruct AlignedCharArray<2, Size> {
647ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  union {
657ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    short aligned;
667ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    char buffer[Size];
677ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  };
687ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
697ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
707ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate<std::size_t Size>
717ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensstruct AlignedCharArray<4, Size> {
727ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  union {
737ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    int aligned;
747ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    char buffer[Size];
757ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  };
767ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
777ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
787ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate<std::size_t Size>
797ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensstruct AlignedCharArray<8, Size> {
807ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  union {
817ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    double aligned;
827ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    char buffer[Size];
837ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  };
847ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
857ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
867ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
877ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// The rest of these are provided with a __declspec(align(...)) and we simply
887ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens// can't pass them by-value as function arguments on MSVC.
897ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
907ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
917ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  template<std::size_t Size> \
927ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  struct AlignedCharArray<x, Size> { \
937ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    __declspec(align(x)) char buffer[Size]; \
947ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  };
957ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
967ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas CapensLLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
977ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas CapensLLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
987ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas CapensLLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
997ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas CapensLLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
1007ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1017ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
1027ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1037ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#endif // _MSC_VER
1047ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1057ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensnamespace detail {
1067ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate <typename T1,
1077ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T2 = char, typename T3 = char, typename T4 = char,
1087ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T5 = char, typename T6 = char, typename T7 = char,
1097ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T8 = char, typename T9 = char, typename T10 = char>
1107ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensclass AlignerImpl {
1117ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
1127ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1137ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  AlignerImpl() = delete;
1147ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
1157ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1167ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate <typename T1,
1177ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T2 = char, typename T3 = char, typename T4 = char,
1187ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T5 = char, typename T6 = char, typename T7 = char,
1197ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T8 = char, typename T9 = char, typename T10 = char>
1207ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensunion SizerImpl {
1217ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens  char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)],
1227ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens       arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)],
1237ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens       arr9[sizeof(T9)], arr10[sizeof(T10)];
1247ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
1257ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens} // end namespace detail
1267ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1277ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// \brief This union template exposes a suitably aligned and sized character
1287ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// array member which can hold elements of any of up to ten types.
1297ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens///
1307ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// These types may be arrays, structs, or any other types. The goal is to
1317ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// expose a char array buffer member which can be used as suitable storage for
1327ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// a placement new of any of these types. Support for more than ten types can
1337ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens/// be added at the cost of more boilerplate.
1347ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capenstemplate <typename T1,
1357ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T2 = char, typename T3 = char, typename T4 = char,
1367ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T5 = char, typename T6 = char, typename T7 = char,
1377ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens          typename T8 = char, typename T9 = char, typename T10 = char>
1387ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capensstruct AlignedCharArrayUnion : llvm::AlignedCharArray<
1392df178997d17474042e8c3704cc93ab2db6619bfNicolas Capens    alignof(llvm::detail::AlignerImpl<T1, T2, T3, T4, T5,
1402df178997d17474042e8c3704cc93ab2db6619bfNicolas Capens                                      T6, T7, T8, T9, T10>),
1417ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens    sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5,
1427ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens                                     T6, T7, T8, T9, T10>)> {
1437ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens};
1447ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens} // end namespace llvm
1457ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens
1467ad046f5968d4709c3c68d165387d13f1da7bab6Nicolas Capens#endif // LLVM_SUPPORT_ALIGNOF_H
147