Alignment.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim: set ts=8 sts=2 et sw=2 tw=80: */
  3. /* This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. /* Functionality related to memory alignment. */
  7. #ifndef mozilla_Alignment_h
  8. #define mozilla_Alignment_h
  9. #include "mozilla/Attributes.h"
  10. #include <stddef.h>
  11. #include <stdint.h>
  12. namespace mozilla {
  13. /*
  14. * This class, and the corresponding macro MOZ_ALIGNOF, figures out how many
  15. * bytes of alignment a given type needs.
  16. */
  17. template<typename T>
  18. class AlignmentFinder
  19. {
  20. struct Aligner
  21. {
  22. char mChar;
  23. T mT;
  24. };
  25. public:
  26. static const size_t alignment = sizeof(Aligner) - sizeof(T);
  27. };
  28. #define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
  29. /*
  30. * Declare the MOZ_ALIGNED_DECL macro for declaring aligned types.
  31. *
  32. * For instance,
  33. *
  34. * MOZ_ALIGNED_DECL(char arr[2], 8);
  35. *
  36. * will declare a two-character array |arr| aligned to 8 bytes.
  37. */
  38. #if defined(__GNUC__)
  39. # define MOZ_ALIGNED_DECL(_type, _align) \
  40. _type __attribute__((aligned(_align)))
  41. #elif defined(_MSC_VER)
  42. # define MOZ_ALIGNED_DECL(_type, _align) \
  43. __declspec(align(_align)) _type
  44. #else
  45. # warning "We don't know how to align variables on this compiler."
  46. # define MOZ_ALIGNED_DECL(_type, _align) _type
  47. #endif
  48. /*
  49. * AlignedElem<N> is a structure whose alignment is guaranteed to be at least N
  50. * bytes.
  51. *
  52. * We support 1, 2, 4, 8, and 16-bit alignment.
  53. */
  54. template<size_t Align>
  55. struct AlignedElem;
  56. /*
  57. * We have to specialize this template because GCC doesn't like
  58. * __attribute__((aligned(foo))) where foo is a template parameter.
  59. */
  60. template<>
  61. struct AlignedElem<1>
  62. {
  63. MOZ_ALIGNED_DECL(uint8_t elem, 1);
  64. };
  65. template<>
  66. struct AlignedElem<2>
  67. {
  68. MOZ_ALIGNED_DECL(uint8_t elem, 2);
  69. };
  70. template<>
  71. struct AlignedElem<4>
  72. {
  73. MOZ_ALIGNED_DECL(uint8_t elem, 4);
  74. };
  75. template<>
  76. struct AlignedElem<8>
  77. {
  78. MOZ_ALIGNED_DECL(uint8_t elem, 8);
  79. };
  80. template<>
  81. struct AlignedElem<16>
  82. {
  83. MOZ_ALIGNED_DECL(uint8_t elem, 16);
  84. };
  85. /*
  86. * This utility pales in comparison to Boost's aligned_storage. The utility
  87. * simply assumes that uint64_t is enough alignment for anyone. This may need
  88. * to be extended one day...
  89. *
  90. * As an important side effect, pulling the storage into this template is
  91. * enough obfuscation to confuse gcc's strict-aliasing analysis into not giving
  92. * false negatives when we cast from the char buffer to whatever type we've
  93. * constructed using the bytes.
  94. */
  95. template<size_t Nbytes>
  96. struct AlignedStorage
  97. {
  98. union U
  99. {
  100. char mBytes[Nbytes];
  101. uint64_t mDummy;
  102. } u;
  103. const void* addr() const { return u.mBytes; }
  104. void* addr() { return u.mBytes; }
  105. AlignedStorage() = default;
  106. // AlignedStorage is non-copyable: the default copy constructor violates
  107. // strict aliasing rules, per bug 1269319.
  108. AlignedStorage(const AlignedStorage&) = delete;
  109. void operator=(const AlignedStorage&) = delete;
  110. };
  111. template<typename T>
  112. struct MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS AlignedStorage2
  113. {
  114. union U
  115. {
  116. char mBytes[sizeof(T)];
  117. uint64_t mDummy;
  118. } u;
  119. const T* addr() const { return reinterpret_cast<const T*>(u.mBytes); }
  120. T* addr() { return static_cast<T*>(static_cast<void*>(u.mBytes)); }
  121. AlignedStorage2() = default;
  122. // AlignedStorage2 is non-copyable: the default copy constructor violates
  123. // strict aliasing rules, per bug 1269319.
  124. AlignedStorage2(const AlignedStorage2&) = delete;
  125. void operator=(const AlignedStorage2&) = delete;
  126. };
  127. } /* namespace mozilla */
  128. #endif /* mozilla_Alignment_h */