Line data Source code
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 :
7 : /* Functionality related to memory alignment. */
8 :
9 : #ifndef mozilla_Alignment_h
10 : #define mozilla_Alignment_h
11 :
12 : #include "mozilla/Attributes.h"
13 : #include <stddef.h>
14 : #include <stdint.h>
15 :
16 : namespace mozilla {
17 :
18 : /*
19 : * This class, and the corresponding macro MOZ_ALIGNOF, figures out how many
20 : * bytes of alignment a given type needs.
21 : */
22 : template<typename T>
23 : class AlignmentFinder
24 : {
25 : struct Aligner
26 : {
27 : char mChar;
28 : T mT;
29 : };
30 :
31 : public:
32 : static const size_t alignment = sizeof(Aligner) - sizeof(T);
33 : };
34 :
35 : #define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
36 :
37 : /*
38 : * Declare the MOZ_ALIGNED_DECL macro for declaring aligned types.
39 : *
40 : * For instance,
41 : *
42 : * MOZ_ALIGNED_DECL(char arr[2], 8);
43 : *
44 : * will declare a two-character array |arr| aligned to 8 bytes.
45 : */
46 :
47 : #if defined(__GNUC__)
48 : # define MOZ_ALIGNED_DECL(_type, _align) \
49 : _type __attribute__((aligned(_align)))
50 : #elif defined(_MSC_VER)
51 : # define MOZ_ALIGNED_DECL(_type, _align) \
52 : __declspec(align(_align)) _type
53 : #else
54 : # warning "We don't know how to align variables on this compiler."
55 : # define MOZ_ALIGNED_DECL(_type, _align) _type
56 : #endif
57 :
58 : /*
59 : * AlignedElem<N> is a structure whose alignment is guaranteed to be at least N
60 : * bytes.
61 : *
62 : * We support 1, 2, 4, 8, and 16-bit alignment.
63 : */
64 : template<size_t Align>
65 : struct AlignedElem;
66 :
67 : /*
68 : * We have to specialize this template because GCC doesn't like
69 : * __attribute__((aligned(foo))) where foo is a template parameter.
70 : */
71 :
72 : template<>
73 : struct AlignedElem<1>
74 : {
75 : MOZ_ALIGNED_DECL(uint8_t elem, 1);
76 : };
77 :
78 : template<>
79 : struct AlignedElem<2>
80 : {
81 : MOZ_ALIGNED_DECL(uint8_t elem, 2);
82 : };
83 :
84 : template<>
85 : struct AlignedElem<4>
86 : {
87 : MOZ_ALIGNED_DECL(uint8_t elem, 4);
88 : };
89 :
90 : template<>
91 : struct AlignedElem<8>
92 : {
93 : MOZ_ALIGNED_DECL(uint8_t elem, 8);
94 : };
95 :
96 : template<>
97 : struct AlignedElem<16>
98 : {
99 : MOZ_ALIGNED_DECL(uint8_t elem, 16);
100 : };
101 :
102 : template<typename T>
103 : struct MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS AlignedStorage2
104 : {
105 : union U
106 : {
107 : char mBytes[sizeof(T)];
108 : uint64_t mDummy;
109 : } u;
110 :
111 126954 : const T* addr() const { return reinterpret_cast<const T*>(u.mBytes); }
112 7863325 : T* addr() { return static_cast<T*>(static_cast<void*>(u.mBytes)); }
113 :
114 141 : AlignedStorage2() = default;
115 :
116 : // AlignedStorage2 is non-copyable: the default copy constructor violates
117 : // strict aliasing rules, per bug 1269319.
118 : AlignedStorage2(const AlignedStorage2&) = delete;
119 : void operator=(const AlignedStorage2&) = delete;
120 : };
121 :
122 : } /* namespace mozilla */
123 :
124 : #endif /* mozilla_Alignment_h */
|