Toplevel entrypoints for classes/traits/interfaces
[hiphop-php.git] / hphp / util / portability.h
blob9fab54fd0302f06b18bbc5b1f6a2eea81e5ac867
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #pragma once
18 #include <folly/Likely.h> // defining LIKELY/UNLIKELY is part of this header
19 #include <folly/Portability.h>
20 #include <folly/CPortability.h> // FOLLY_DISABLE_ADDRESS_SANITIZER, FOLLY_EXPORT
22 //////////////////////////////////////////////////////////////////////
25 * Various macros to make certain things conditional on either
26 * compiler or architecture.
28 * Currently we don't *really* compile on anything other than gcc or
29 * sometimes clang, and there are some parts of the code using
30 * __attribute__ stuff directly, but some things go through these
31 * macros to make it maybe easier to change later.
34 //////////////////////////////////////////////////////////////////////
36 // TODO: does clang define __GNUC__ ?
37 #ifndef __GNUC__
38 # define __attribute__(x)
39 #endif
41 //////////////////////////////////////////////////////////////////////
43 #ifdef ATTRIBUTE_UNUSED
44 # undef ATTRIBUTE_UNUSED
45 #endif
46 #ifdef ATTRIBUTE_PRINTF
47 # undef ATTRIBUTE_PRINTF
48 #endif
49 #ifdef ATTRIBUTE_PRINTF_STRING
50 # undef ATTRIBUTE_PRINTF_STRING
51 #endif
53 #define ATTRIBUTE_PRINTF_STRING FOLLY_PRINTF_FORMAT
55 #ifdef _MSC_VER
56 #define ATTRIBUTE_PRINTF(a1, a2)
57 #ifndef __thread
58 # define __thread __declspec(thread)
59 #endif
60 #define ATTRIBUTE_UNUSED
61 #define ATTRIBUTE_USED
63 #define ALWAYS_INLINE __forceinline
64 #define EXTERNALLY_VISIBLE
65 #define FLATTEN
66 #define NEVER_INLINE __declspec(noinline)
67 #define UNUSED
69 #else
70 #define ATTRIBUTE_PRINTF(a1, a2) \
71 __attribute__((__format__ (__printf__, a1, a2)))
72 #define ATTRIBUTE_UNUSED __attribute__((__unused__))
73 #define ATTRIBUTE_USED __attribute__((__used__))
74 #ifndef NDEBUG
75 # define FLATTEN /*nop*/
76 # define ALWAYS_INLINE inline
77 # define INLINE_FLATTEN inline
78 #else
79 # define FLATTEN __attribute__((__flatten__))
80 # define ALWAYS_INLINE inline __attribute__((__always_inline__))
81 # define INLINE_FLATTEN inline __attribute__((__always_inline__,__flatten__))
82 #endif
83 #define NEVER_INLINE __attribute__((__noinline__))
84 #define UNUSED __attribute__((__unused__))
86 #endif
88 #ifdef __clang__
89 #define NO_OPT [[clang::optnone]]
90 #define EXTERNALLY_VISIBLE ATTRIBUTE_USED FOLLY_EXPORT
91 #else
92 #define NO_OPT __attribute__((__optimize__("O0")))
93 #define EXTERNALLY_VISIBLE __attribute__((__externally_visible__))
94 #endif
96 #if defined(__GNUC__)
97 # define HHVM_ATTRIBUTE_WEAK __attribute__((__weak__))
98 #elif defined(__clang__)
99 # define HHVM_ATTRIBUTE_WEAK __attribute__((__weak_import__))
100 #else
101 # define HHVM_ATTRIBUTE_WEAK
102 #endif
104 #ifdef __clang__
105 #define NO_PROFILING
106 #elif defined(__GNUC__)
107 #define NO_PROFILING __attribute__((no_profile_instrument_function))
108 #else
109 #define NO_PROFILING
110 #endif
112 #ifndef NDEBUG
113 # define DEBUG_ONLY /* nop */
114 #else
115 # define DEBUG_ONLY UNUSED
116 #endif
118 #ifndef NDEBUG
119 #define DEBUG_NOEXCEPT
120 #else
121 #define DEBUG_NOEXCEPT noexcept
122 #endif
126 * AARCH64 needs to create a walkable stack frame for
127 * getFrameRegs() when a FixupEntry isIndirect()
129 #ifdef __aarch64__
130 #define AARCH64_WALKABLE_FRAME() asm("" ::: "memory");
131 #else
132 #define AARCH64_WALKABLE_FRAME()
133 #endif
137 * We need to keep some unreferenced functions from being removed by
138 * the linker. There is no compile time mechanism for doing this, but
139 * by putting them in the same section as some other, referenced function
140 * in the same file, we can keep them around.
142 * So this macro should be used to mark at least one function that is
143 * referenced, and other functions that are not referenced in the same
144 * file.
146 * Note: this may not work properly with LTO. We'll revisit when/if we
147 * move to it.
149 #ifndef __APPLE__
150 # define KEEP_SECTION \
151 __attribute__((__section__(".text.keep")))
152 #else
153 # define KEEP_SECTION \
154 __attribute__((__section__(".text,.text.keep")))
155 #endif
157 #if defined(__APPLE__)
158 // OS X has a macro "isset" defined in this header. Force the include so we can
159 // make sure the macro gets undef'd. (I think this also applies to BSD, but we
160 // can cross that road when we come to it.)
161 # include <sys/param.h>
162 # ifdef isset
163 # undef isset
164 # endif
165 #endif
167 //////////////////////////////////////////////////////////////////////
168 // DECLARE_FRAME_POINTER
170 #if defined(__x86_64__)
172 # define DECLARE_FRAME_POINTER(fp) \
173 auto const fp = (ActRec*) __builtin_frame_address(0)
174 # define FRAME_POINTER_IS_ACCURATE
176 #elif defined(_M_X64)
178 // TODO: FIXME! Without this implemented properly, the JIT
179 // will fail "pretty spectacularly".
180 # define DECLARE_FRAME_POINTER(fp) \
181 always_assert(false); \
182 register ActRec* fp = nullptr;
184 #elif defined(__AARCH64EL__)
186 # if defined(__clang__)
187 # define DECLARE_FRAME_POINTER(fp) register ActRec* fp = (ActRec*) \
188 __builtin_frame_address(0)
189 #else
190 # define DECLARE_FRAME_POINTER(fp) register ActRec* fp asm("x29")
191 #endif
193 #elif defined(__powerpc64__)
195 # if defined(__clang__)
196 # error Clang implementation not done for PPC64
197 # endif
198 # define DECLARE_FRAME_POINTER(fp) \
199 auto const fp = (ActRec*) __builtin_frame_address(0)
200 # define FRAME_POINTER_IS_ACCURATE
202 #else
204 # error What are the stack and frame pointers called on your architecture?
206 #endif
208 //////////////////////////////////////////////////////////////////////
209 // CALLEE_SAVED_BARRIER
211 #ifdef _MSC_VER
212 // Unfortunately, we have no way to tell MSVC to do this, so we'll
213 // probably have to use a pair of assembly stubs to manage this.
214 #define CALLEE_SAVED_BARRIER() always_assert(false);
215 #elif defined (__powerpc64__)
216 // After gcc 5.4.1 we can't clobber r30 on PPC64 anymore because it's used as
217 // PIC register.
218 #if __GNUC__ > 5 || (__GNUC__ == 5 && (__GNUC_MINOR__ >= 4) && \
219 (__GNUC_PATCHLEVEL__ >= 1))
220 #define CALLEE_SAVED_BARRIER()\
221 asm volatile("" : : : "r2", "r14", "r15", "r16", "r17", "r18", "r19",\
222 "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \
223 "r28", "r29", "cr2", "cr3", "cr4", "v20", "v21", "v22", \
224 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", \
225 "v31");
226 #else
227 // On gcc versions < 5.4.1 we need to include r30 on barrier as it's not
228 // saved by gcc.
229 #define CALLEE_SAVED_BARRIER()\
230 asm volatile("" : : : "r2", "r14", "r15", "r16", "r17", "r18", "r19",\
231 "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \
232 "r28", "r29", "r30", "cr2", "cr3", "cr4", "v20", "v21", \
233 "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
234 "v30", "v31");
235 #endif
236 #elif defined (__AARCH64EL__)
237 #define CALLEE_SAVED_BARRIER()\
238 asm volatile("" : : : "x19", "x20", "x21", "x22", "x23", "x24", "x25",\
239 "x26", "x27", "x28", \
240 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15")
241 #else
242 #define CALLEE_SAVED_BARRIER()\
243 asm volatile("" : : : "rbx", "r12", "r13", "r14", "r15");
244 #endif
246 //////////////////////////////////////////////////////////////////////
248 // We reserve the exit status 127 to signal a failure in the
249 // interpreter. 127 is a valid exit code on all reasonable
250 // architectures: POSIX requires at least 8 unsigned bits and
251 // Windows 32 signed bits.
252 #define HPHP_EXIT_FAILURE 127
254 //////////////////////////////////////////////////////////////////////
256 #if FACEBOOK
257 #define USE_FOLLY_SYMBOLIZER 1
258 // Linking in libbfd is a gigantic PITA, but if folly symbolizer doesn't
259 // work on your platform, you'll need to figure it out.
260 #define HAVE_LIBBFD 1
261 #endif
263 #ifndef PACKAGE
264 // The value doesn't matter, but it must be defined before you include
265 // bfd.h
266 #define PACKAGE "hhvm"
267 #endif
269 //////////////////////////////////////////////////////////////////////
271 #ifdef _MSC_VER
272 # include "hphp/util/portability/fnmatch.h"
273 # include "hphp/util/portability/glob.h"
274 # include "hphp/util/portability/rand_r.h"
275 # include "hphp/util/portability/strfmon.h"
276 #endif
278 #if defined(_MSC_VER) && _MSC_FULL_VER <= 190023506 // 2015 Update 1 or below
279 // MSVC2015 has an issue with getting function pointers to templated functions
280 // if the expected result type isn't auto. Unfortunately, when I made the
281 // initial bug report, I oversimplified the use-case, and, while the case I
282 // reported was indeed fixed in Update 1 RC, none of our actual uses of it were
283 // fixed.
284 // This is being tracked at MS as #163251.
285 # define MSVC_REQUIRE_AUTO_TEMPLATED_OVERLOAD 1
286 // 2015 RTM doesn't like it when you try to add via a double duration.
287 // Bug Report: https://connect.microsoft.com/VisualStudio/feedback/details/1839243
288 # define MSVC_NO_STD_CHRONO_DURATION_DOUBLE_ADD 1
289 #endif
291 #ifdef __APPLE__
292 #define ASM_LOCAL_LABEL(x) "L" x
293 #else
294 #define ASM_LOCAL_LABEL(x) ".L" x
295 #endif