michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* Functionality related to memory alignment. */ michael@0: michael@0: #ifndef mozilla_Alignment_h michael@0: #define mozilla_Alignment_h michael@0: michael@0: #include michael@0: #include michael@0: michael@0: namespace mozilla { michael@0: michael@0: /* michael@0: * This class, and the corresponding macro MOZ_ALIGNOF, figures out how many michael@0: * bytes of alignment a given type needs. michael@0: */ michael@0: template michael@0: class AlignmentFinder michael@0: { michael@0: struct Aligner michael@0: { michael@0: char c; michael@0: T t; michael@0: }; michael@0: michael@0: public: michael@0: static const size_t alignment = sizeof(Aligner) - sizeof(T); michael@0: }; michael@0: michael@0: #define MOZ_ALIGNOF(T) mozilla::AlignmentFinder::alignment michael@0: michael@0: /* michael@0: * Declare the MOZ_ALIGNED_DECL macro for declaring aligned types. michael@0: * michael@0: * For instance, michael@0: * michael@0: * MOZ_ALIGNED_DECL(char arr[2], 8); michael@0: * michael@0: * will declare a two-character array |arr| aligned to 8 bytes. michael@0: */ michael@0: michael@0: #if defined(__GNUC__) michael@0: # define MOZ_ALIGNED_DECL(_type, _align) \ michael@0: _type __attribute__((aligned(_align))) michael@0: #elif defined(_MSC_VER) michael@0: # define MOZ_ALIGNED_DECL(_type, _align) \ michael@0: __declspec(align(_align)) _type michael@0: #else michael@0: # warning "We don't know how to align variables on this compiler." michael@0: # define MOZ_ALIGNED_DECL(_type, _align) _type michael@0: #endif michael@0: michael@0: /* michael@0: * AlignedElem is a structure whose alignment is guaranteed to be at least N michael@0: * bytes. michael@0: * michael@0: * We support 1, 2, 4, 8, and 16-bit alignment. michael@0: */ michael@0: template michael@0: struct AlignedElem; michael@0: michael@0: /* michael@0: * We have to specialize this template because GCC doesn't like __attribute__((aligned(foo))) where michael@0: * foo is a template parameter. michael@0: */ michael@0: michael@0: template<> michael@0: struct AlignedElem<1> michael@0: { michael@0: MOZ_ALIGNED_DECL(uint8_t elem, 1); michael@0: }; michael@0: michael@0: template<> michael@0: struct AlignedElem<2> michael@0: { michael@0: MOZ_ALIGNED_DECL(uint8_t elem, 2); michael@0: }; michael@0: michael@0: template<> michael@0: struct AlignedElem<4> michael@0: { michael@0: MOZ_ALIGNED_DECL(uint8_t elem, 4); michael@0: }; michael@0: michael@0: template<> michael@0: struct AlignedElem<8> michael@0: { michael@0: MOZ_ALIGNED_DECL(uint8_t elem, 8); michael@0: }; michael@0: michael@0: template<> michael@0: struct AlignedElem<16> michael@0: { michael@0: MOZ_ALIGNED_DECL(uint8_t elem, 16); michael@0: }; michael@0: michael@0: /* michael@0: * This utility pales in comparison to Boost's aligned_storage. The utility michael@0: * simply assumes that uint64_t is enough alignment for anyone. This may need michael@0: * to be extended one day... michael@0: * michael@0: * As an important side effect, pulling the storage into this template is michael@0: * enough obfuscation to confuse gcc's strict-aliasing analysis into not giving michael@0: * false negatives when we cast from the char buffer to whatever type we've michael@0: * constructed using the bytes. michael@0: */ michael@0: template michael@0: struct AlignedStorage michael@0: { michael@0: union U { michael@0: char bytes[Nbytes]; michael@0: uint64_t _; michael@0: } u; michael@0: michael@0: const void* addr() const { return u.bytes; } michael@0: void* addr() { return u.bytes; } michael@0: }; michael@0: michael@0: template michael@0: struct AlignedStorage2 michael@0: { michael@0: union U { michael@0: char bytes[sizeof(T)]; michael@0: uint64_t _; michael@0: } u; michael@0: michael@0: const T* addr() const { return reinterpret_cast(u.bytes); } michael@0: T* addr() { return static_cast(static_cast(u.bytes)); } michael@0: }; michael@0: michael@0: } /* namespace mozilla */ michael@0: michael@0: #endif /* mozilla_Alignment_h */