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