Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_BASE_MACROS_H_
6 : #define V8_BASE_MACROS_H_
7 :
8 : #include "src/base/compiler-specific.h"
9 : #include "src/base/format-macros.h"
10 : #include "src/base/logging.h"
11 :
12 :
13 : // TODO(all) Replace all uses of this macro with C++'s offsetof. To do that, we
14 : // have to make sure that only standard-layout types and simple field
15 : // designators are used.
16 : #define OFFSET_OF(type, field) \
17 : (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(16)->field)) - 16)
18 :
19 :
20 : // The arraysize(arr) macro returns the # of elements in an array arr.
21 : // The expression is a compile-time constant, and therefore can be
22 : // used in defining new arrays, for example. If you use arraysize on
23 : // a pointer by mistake, you will get a compile-time error.
24 : #define arraysize(array) (sizeof(ArraySizeHelper(array)))
25 :
26 :
27 : // This template function declaration is used in defining arraysize.
28 : // Note that the function doesn't need an implementation, as we only
29 : // use its type.
30 : template <typename T, size_t N>
31 : char (&ArraySizeHelper(T (&array)[N]))[N];
32 :
33 :
34 : #if !V8_CC_MSVC
35 : // That gcc wants both of these prototypes seems mysterious. VC, for
36 : // its part, can't decide which to use (another mystery). Matching of
37 : // template overloads: the final frontier.
38 : template <typename T, size_t N>
39 : char (&ArraySizeHelper(const T (&array)[N]))[N];
40 : #endif
41 :
42 :
43 : // bit_cast<Dest,Source> is a template function that implements the
44 : // equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in
45 : // very low-level functions like the protobuf library and fast math
46 : // support.
47 : //
48 : // float f = 3.14159265358979;
49 : // int i = bit_cast<int32>(f);
50 : // // i = 0x40490fdb
51 : //
52 : // The classical address-casting method is:
53 : //
54 : // // WRONG
55 : // float f = 3.14159265358979; // WRONG
56 : // int i = * reinterpret_cast<int*>(&f); // WRONG
57 : //
58 : // The address-casting method actually produces undefined behavior
59 : // according to ISO C++ specification section 3.10 -15 -. Roughly, this
60 : // section says: if an object in memory has one type, and a program
61 : // accesses it with a different type, then the result is undefined
62 : // behavior for most values of "different type".
63 : //
64 : // This is true for any cast syntax, either *(int*)&f or
65 : // *reinterpret_cast<int*>(&f). And it is particularly true for
66 : // conversions between integral lvalues and floating-point lvalues.
67 : //
68 : // The purpose of 3.10 -15- is to allow optimizing compilers to assume
69 : // that expressions with different types refer to different memory. gcc
70 : // 4.0.1 has an optimizer that takes advantage of this. So a
71 : // non-conforming program quietly produces wildly incorrect output.
72 : //
73 : // The problem is not the use of reinterpret_cast. The problem is type
74 : // punning: holding an object in memory of one type and reading its bits
75 : // back using a different type.
76 : //
77 : // The C++ standard is more subtle and complex than this, but that
78 : // is the basic idea.
79 : //
80 : // Anyways ...
81 : //
82 : // bit_cast<> calls memcpy() which is blessed by the standard,
83 : // especially by the example in section 3.9 . Also, of course,
84 : // bit_cast<> wraps up the nasty logic in one place.
85 : //
86 : // Fortunately memcpy() is very fast. In optimized mode, with a
87 : // constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
88 : // code with the minimal amount of data movement. On a 32-bit system,
89 : // memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
90 : // compiles to two loads and two stores.
91 : //
92 : // I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
93 : //
94 : // WARNING: if Dest or Source is a non-POD type, the result of the memcpy
95 : // is likely to surprise you.
96 : template <class Dest, class Source>
97 : V8_INLINE Dest bit_cast(Source const& source) {
98 : static_assert(sizeof(Dest) == sizeof(Source),
99 : "source and dest must be same size");
100 1187749 : Dest dest;
101 : memcpy(&dest, &source, sizeof(dest));
102 33952205 : return dest;
103 : }
104 :
105 :
106 : // Put this in the private: declarations for a class to be unassignable.
107 : #define DISALLOW_ASSIGN(TypeName) void operator=(const TypeName&)
108 :
109 :
110 : // A macro to disallow the evil copy constructor and operator= functions
111 : // This should be used in the private: declarations for a class
112 : #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
113 : TypeName(const TypeName&) = delete; \
114 : void operator=(const TypeName&) = delete
115 :
116 :
117 : // A macro to disallow all the implicit constructors, namely the
118 : // default constructor, copy constructor and operator= functions.
119 : //
120 : // This should be used in the private: declarations for a class
121 : // that wants to prevent anyone from instantiating it. This is
122 : // especially useful for classes containing only static methods.
123 : #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
124 : TypeName() = delete; \
125 : DISALLOW_COPY_AND_ASSIGN(TypeName)
126 :
127 :
128 : // Newly written code should use V8_INLINE and V8_NOINLINE directly.
129 : #define INLINE(declarator) V8_INLINE declarator
130 : #define NO_INLINE(declarator) V8_NOINLINE declarator
131 :
132 :
133 : // Newly written code should use WARN_UNUSED_RESULT.
134 : #define MUST_USE_RESULT WARN_UNUSED_RESULT
135 :
136 :
137 : // Define V8_USE_ADDRESS_SANITIZER macros.
138 : #if defined(__has_feature)
139 : #if __has_feature(address_sanitizer)
140 : #define V8_USE_ADDRESS_SANITIZER 1
141 : #endif
142 : #endif
143 :
144 : // Define DISABLE_ASAN macros.
145 : #ifdef V8_USE_ADDRESS_SANITIZER
146 : #define DISABLE_ASAN __attribute__((no_sanitize_address))
147 : #else
148 : #define DISABLE_ASAN
149 : #endif
150 :
151 : // DISABLE_CFI_PERF -- Disable Control Flow Integrity checks for Perf reasons.
152 : #if !defined(DISABLE_CFI_PERF)
153 : #if defined(__clang__) && defined(__has_attribute)
154 : #if __has_attribute(no_sanitize)
155 : #define DISABLE_CFI_PERF __attribute__((no_sanitize("cfi")))
156 : #endif
157 : #endif
158 : #endif
159 : #if !defined(DISABLE_CFI_PERF)
160 : #define DISABLE_CFI_PERF
161 : #endif
162 :
163 : #if V8_CC_GNU
164 : #define V8_IMMEDIATE_CRASH() __builtin_trap()
165 : #else
166 : #define V8_IMMEDIATE_CRASH() ((void(*)())0)()
167 : #endif
168 :
169 :
170 : // TODO(all) Replace all uses of this macro with static_assert, remove macro.
171 : #define STATIC_ASSERT(test) static_assert(test, #test)
172 :
173 :
174 : // The USE(x) template is used to silence C++ compiler warnings
175 : // issued for (yet) unused variables (typically parameters).
176 : template <typename T>
177 414066460 : inline void USE(T) { }
178 :
179 :
180 : #define IS_POWER_OF_TWO(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
181 :
182 :
183 : // Define our own macros for writing 64-bit constants. This is less fragile
184 : // than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
185 : // works on compilers that don't have it (like MSVC).
186 : #if V8_CC_MSVC
187 : # define V8_UINT64_C(x) (x ## UI64)
188 : # define V8_INT64_C(x) (x ## I64)
189 : # if V8_HOST_ARCH_64_BIT
190 : # define V8_INTPTR_C(x) (x ## I64)
191 : # define V8_PTR_PREFIX "ll"
192 : # else
193 : # define V8_INTPTR_C(x) (x)
194 : # define V8_PTR_PREFIX ""
195 : # endif // V8_HOST_ARCH_64_BIT
196 : #elif V8_CC_MINGW64
197 : # define V8_UINT64_C(x) (x ## ULL)
198 : # define V8_INT64_C(x) (x ## LL)
199 : # define V8_INTPTR_C(x) (x ## LL)
200 : # define V8_PTR_PREFIX "I64"
201 : #elif V8_HOST_ARCH_64_BIT
202 : # if V8_OS_MACOSX || V8_OS_OPENBSD
203 : # define V8_UINT64_C(x) (x ## ULL)
204 : # define V8_INT64_C(x) (x ## LL)
205 : # else
206 : # define V8_UINT64_C(x) (x ## UL)
207 : # define V8_INT64_C(x) (x ## L)
208 : # endif
209 : # define V8_INTPTR_C(x) (x ## L)
210 : # define V8_PTR_PREFIX "l"
211 : #else
212 : # define V8_UINT64_C(x) (x ## ULL)
213 : # define V8_INT64_C(x) (x ## LL)
214 : # define V8_INTPTR_C(x) (x)
215 : #if V8_OS_AIX
216 : #define V8_PTR_PREFIX "l"
217 : #else
218 : # define V8_PTR_PREFIX ""
219 : #endif
220 : #endif
221 :
222 : #define V8PRIxPTR V8_PTR_PREFIX "x"
223 : #define V8PRIdPTR V8_PTR_PREFIX "d"
224 : #define V8PRIuPTR V8_PTR_PREFIX "u"
225 :
226 : // ptrdiff_t is 't' according to the standard, but MSVC uses 'I'.
227 : #if V8_CC_MSVC
228 : #define V8PRIxPTRDIFF "Ix"
229 : #define V8PRIdPTRDIFF "Id"
230 : #define V8PRIuPTRDIFF "Iu"
231 : #else
232 : #define V8PRIxPTRDIFF "tx"
233 : #define V8PRIdPTRDIFF "td"
234 : #define V8PRIuPTRDIFF "tu"
235 : #endif
236 :
237 : // Fix for Mac OS X defining uintptr_t as "unsigned long":
238 : #if V8_OS_MACOSX
239 : #undef V8PRIxPTR
240 : #define V8PRIxPTR "lx"
241 : #undef V8PRIdPTR
242 : #define V8PRIdPTR "ld"
243 : #undef V8PRIuPTR
244 : #define V8PRIuPTR "lxu"
245 : #endif
246 :
247 : // The following macro works on both 32 and 64-bit platforms.
248 : // Usage: instead of writing 0x1234567890123456
249 : // write V8_2PART_UINT64_C(0x12345678,90123456);
250 : #define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
251 :
252 :
253 : // Compute the 0-relative offset of some absolute value x of type T.
254 : // This allows conversion of Addresses and integral types into
255 : // 0-relative int offsets.
256 : template <typename T>
257 : inline intptr_t OffsetFrom(T x) {
258 44700675136 : return x - static_cast<T>(0);
259 : }
260 :
261 :
262 : // Compute the absolute value of type T for some 0-relative offset x.
263 : // This allows conversion of 0-relative int offsets into Addresses and
264 : // integral types.
265 : template <typename T>
266 : inline T AddressFrom(intptr_t x) {
267 3259501134 : return static_cast<T>(static_cast<T>(0) + x);
268 : }
269 :
270 :
271 : // Return the largest multiple of m which is <= x.
272 : template <typename T>
273 : inline T RoundDown(T x, intptr_t m) {
274 : DCHECK(IS_POWER_OF_TWO(m));
275 3943233281 : return AddressFrom<T>(OffsetFrom(x) & -m);
276 : }
277 :
278 :
279 : // Return the smallest multiple of m which is >= x.
280 : template <typename T>
281 : inline T RoundUp(T x, intptr_t m) {
282 3942802144 : return RoundDown<T>(static_cast<T>(x + m - 1), m);
283 : }
284 :
285 : #endif // V8_BASE_MACROS_H_
|