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