zend_portability.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@php.net> |
  16. | Zeev Suraski <zeev@php.net> |
  17. | Dmitry Stogov <dmitry@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #ifndef ZEND_PORTABILITY_H
  21. #define ZEND_PORTABILITY_H
  22. #ifdef __cplusplus
  23. #define BEGIN_EXTERN_C() extern "C" {
  24. #define END_EXTERN_C() }
  25. #else
  26. #define BEGIN_EXTERN_C()
  27. #define END_EXTERN_C()
  28. #endif
  29. /*
  30. * general definitions
  31. */
  32. #ifdef ZEND_WIN32
  33. # include "zend_config.w32.h"
  34. # define ZEND_PATHS_SEPARATOR ';'
  35. #elif defined(__riscos__)
  36. # include <zend_config.h>
  37. # define ZEND_PATHS_SEPARATOR ';'
  38. #else
  39. # include <zend_config.h>
  40. # define ZEND_PATHS_SEPARATOR ':'
  41. #endif
  42. #include "../TSRM/TSRM.h"
  43. #include <stdio.h>
  44. #include <assert.h>
  45. #include <math.h>
  46. #ifdef HAVE_UNIX_H
  47. # include <unix.h>
  48. #endif
  49. #include <stdarg.h>
  50. #include <stddef.h>
  51. #ifdef HAVE_DLFCN_H
  52. # include <dlfcn.h>
  53. #endif
  54. #include <limits.h>
  55. #if HAVE_ALLOCA_H && !defined(_ALLOCA_H)
  56. # include <alloca.h>
  57. #endif
  58. #if defined(ZEND_WIN32) && !defined(__clang__)
  59. #include <intrin.h>
  60. #endif
  61. #include "zend_range_check.h"
  62. /* GCC x.y.z supplies __GNUC__ = x and __GNUC_MINOR__ = y */
  63. #ifdef __GNUC__
  64. # define ZEND_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
  65. #else
  66. # define ZEND_GCC_VERSION 0
  67. #endif
  68. /* Compatibility with non-clang compilers */
  69. #ifndef __has_attribute
  70. # define __has_attribute(x) 0
  71. #endif
  72. #ifndef __has_builtin
  73. # define __has_builtin(x) 0
  74. #endif
  75. #ifndef __has_feature
  76. # define __has_feature(x) 0
  77. #endif
  78. #if defined(ZEND_WIN32) && !defined(__clang__)
  79. # define ZEND_ASSUME(c) __assume(c)
  80. #elif ((defined(__GNUC__) && ZEND_GCC_VERSION >= 4005) || __has_builtin(__builtin_unreachable)) && PHP_HAVE_BUILTIN_EXPECT
  81. # define ZEND_ASSUME(c) do { \
  82. if (__builtin_expect(!(c), 0)) __builtin_unreachable(); \
  83. } while (0)
  84. #else
  85. # define ZEND_ASSUME(c)
  86. #endif
  87. #if ZEND_DEBUG
  88. # define ZEND_ASSERT(c) assert(c)
  89. #else
  90. # define ZEND_ASSERT(c) ZEND_ASSUME(c)
  91. #endif
  92. #if ZEND_DEBUG
  93. # define ZEND_UNREACHABLE() do {ZEND_ASSERT(0); ZEND_ASSUME(0);} while (0)
  94. #else
  95. # define ZEND_UNREACHABLE() ZEND_ASSUME(0)
  96. #endif
  97. /* pseudo fallthrough keyword; */
  98. #if defined(__GNUC__) && __GNUC__ >= 7
  99. # define ZEND_FALLTHROUGH __attribute__((__fallthrough__))
  100. #else
  101. # define ZEND_FALLTHROUGH ((void)0)
  102. #endif
  103. /* Only use this macro if you know for sure that all of the switches values
  104. are covered by its case statements */
  105. #define EMPTY_SWITCH_DEFAULT_CASE() default: ZEND_UNREACHABLE(); break;
  106. #if defined(__GNUC__) && __GNUC__ >= 4
  107. # define ZEND_IGNORE_VALUE(x) (({ __typeof__ (x) __x = (x); (void) __x; }))
  108. #else
  109. # define ZEND_IGNORE_VALUE(x) ((void) (x))
  110. #endif
  111. #define zend_quiet_write(...) ZEND_IGNORE_VALUE(write(__VA_ARGS__))
  112. /* all HAVE_XXX test have to be after the include of zend_config above */
  113. #if defined(HAVE_LIBDL) && !defined(ZEND_WIN32)
  114. # if __has_feature(address_sanitizer)
  115. # define __SANITIZE_ADDRESS__
  116. # endif
  117. # ifndef RTLD_LAZY
  118. # define RTLD_LAZY 1 /* Solaris 1, FreeBSD's (2.1.7.1 and older) */
  119. # endif
  120. # ifndef RTLD_GLOBAL
  121. # define RTLD_GLOBAL 0
  122. # endif
  123. # ifdef PHP_USE_RTLD_NOW
  124. # define PHP_RTLD_MODE RTLD_NOW
  125. # else
  126. # define PHP_RTLD_MODE RTLD_LAZY
  127. # endif
  128. # if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT)
  129. # define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
  130. # elif defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(memory_sanitizer)
  131. # define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
  132. # else
  133. # define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL)
  134. # endif
  135. # define DL_UNLOAD dlclose
  136. # if defined(DLSYM_NEEDS_UNDERSCORE)
  137. # define DL_FETCH_SYMBOL(h,s) dlsym((h), "_" s)
  138. # else
  139. # define DL_FETCH_SYMBOL dlsym
  140. # endif
  141. # define DL_ERROR dlerror
  142. # define DL_HANDLE void *
  143. # define ZEND_EXTENSIONS_SUPPORT 1
  144. #elif defined(ZEND_WIN32)
  145. # define DL_LOAD(libname) LoadLibrary(libname)
  146. # define DL_FETCH_SYMBOL GetProcAddress
  147. # define DL_UNLOAD FreeLibrary
  148. # define DL_HANDLE HMODULE
  149. # define ZEND_EXTENSIONS_SUPPORT 1
  150. #else
  151. # define DL_HANDLE void *
  152. # define ZEND_EXTENSIONS_SUPPORT 0
  153. #endif
  154. /* AIX requires this to be the first thing in the file. */
  155. #ifndef __GNUC__
  156. # ifndef HAVE_ALLOCA_H
  157. # ifdef _AIX
  158. # pragma alloca
  159. # else
  160. # ifndef alloca /* predefined by HP cc +Olibcalls */
  161. char *alloca();
  162. # endif
  163. # endif
  164. # endif
  165. #endif
  166. #if ZEND_GCC_VERSION >= 2096 || __has_attribute(__malloc__)
  167. # define ZEND_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
  168. #else
  169. # define ZEND_ATTRIBUTE_MALLOC
  170. #endif
  171. #if ZEND_GCC_VERSION >= 4003 || __has_attribute(alloc_size)
  172. # define ZEND_ATTRIBUTE_ALLOC_SIZE(X) __attribute__ ((alloc_size(X)))
  173. # define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y) __attribute__ ((alloc_size(X,Y)))
  174. #else
  175. # define ZEND_ATTRIBUTE_ALLOC_SIZE(X)
  176. # define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y)
  177. #endif
  178. #if ZEND_GCC_VERSION >= 2007 || __has_attribute(format)
  179. # define ZEND_ATTRIBUTE_FORMAT(type, idx, first) __attribute__ ((format(type, idx, first)))
  180. #else
  181. # define ZEND_ATTRIBUTE_FORMAT(type, idx, first)
  182. #endif
  183. #if (ZEND_GCC_VERSION >= 3001 && !defined(__INTEL_COMPILER)) || __has_attribute(format)
  184. # define ZEND_ATTRIBUTE_PTR_FORMAT(type, idx, first) __attribute__ ((format(type, idx, first)))
  185. #else
  186. # define ZEND_ATTRIBUTE_PTR_FORMAT(type, idx, first)
  187. #endif
  188. #if ZEND_GCC_VERSION >= 3001 || __has_attribute(deprecated)
  189. # define ZEND_ATTRIBUTE_DEPRECATED __attribute__((deprecated))
  190. #elif defined(ZEND_WIN32)
  191. # define ZEND_ATTRIBUTE_DEPRECATED __declspec(deprecated)
  192. #else
  193. # define ZEND_ATTRIBUTE_DEPRECATED
  194. #endif
  195. #if ZEND_GCC_VERSION >= 4003 || __has_attribute(unused)
  196. # define ZEND_ATTRIBUTE_UNUSED __attribute__((unused))
  197. #else
  198. # define ZEND_ATTRIBUTE_UNUSED
  199. #endif
  200. #if defined(__GNUC__) && ZEND_GCC_VERSION >= 4003
  201. # define ZEND_COLD __attribute__((cold))
  202. # define ZEND_HOT __attribute__((hot))
  203. # ifdef __OPTIMIZE__
  204. # define ZEND_OPT_SIZE __attribute__((optimize("Os")))
  205. # define ZEND_OPT_SPEED __attribute__((optimize("Ofast")))
  206. # else
  207. # define ZEND_OPT_SIZE
  208. # define ZEND_OPT_SPEED
  209. # endif
  210. #else
  211. # define ZEND_COLD
  212. # define ZEND_HOT
  213. # define ZEND_OPT_SIZE
  214. # define ZEND_OPT_SPEED
  215. #endif
  216. #if defined(__GNUC__) && ZEND_GCC_VERSION >= 5000
  217. # define ZEND_ATTRIBUTE_UNUSED_LABEL __attribute__((unused));
  218. # define ZEND_ATTRIBUTE_COLD_LABEL __attribute__((cold));
  219. # define ZEND_ATTRIBUTE_HOT_LABEL __attribute__((hot));
  220. #else
  221. # define ZEND_ATTRIBUTE_UNUSED_LABEL
  222. # define ZEND_ATTRIBUTE_COLD_LABEL
  223. # define ZEND_ATTRIBUTE_HOT_LABEL
  224. #endif
  225. #if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
  226. # define ZEND_FASTCALL __attribute__((fastcall))
  227. #elif defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER == 1700
  228. # define ZEND_FASTCALL __fastcall
  229. #elif defined(_MSC_VER) && _MSC_VER >= 1800 && !defined(__clang__)
  230. # define ZEND_FASTCALL __vectorcall
  231. #else
  232. # define ZEND_FASTCALL
  233. #endif
  234. #if (defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__)) || __has_attribute(noreturn)
  235. # define HAVE_NORETURN
  236. # define ZEND_NORETURN __attribute__((noreturn))
  237. #elif defined(ZEND_WIN32)
  238. # define HAVE_NORETURN
  239. # define ZEND_NORETURN __declspec(noreturn)
  240. #else
  241. # define ZEND_NORETURN
  242. #endif
  243. #if __has_attribute(force_align_arg_pointer)
  244. # define ZEND_STACK_ALIGNED __attribute__((force_align_arg_pointer))
  245. #else
  246. # define ZEND_STACK_ALIGNED
  247. #endif
  248. #if (defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__))
  249. # define HAVE_NORETURN_ALIAS
  250. # define HAVE_ATTRIBUTE_WEAK
  251. #endif
  252. #if ZEND_GCC_VERSION >= 3001 || __has_builtin(__builtin_constant_p)
  253. # define HAVE_BUILTIN_CONSTANT_P
  254. #endif
  255. #ifdef HAVE_BUILTIN_CONSTANT_P
  256. # define ZEND_CONST_COND(_condition, _default) \
  257. (__builtin_constant_p(_condition) ? (_condition) : (_default))
  258. #else
  259. # define ZEND_CONST_COND(_condition, _default) \
  260. (_default)
  261. #endif
  262. #if ZEND_DEBUG || defined(ZEND_WIN32_NEVER_INLINE)
  263. # define zend_always_inline inline
  264. # define zend_never_inline
  265. #else
  266. # if defined(__GNUC__)
  267. # if __GNUC__ >= 3
  268. # define zend_always_inline inline __attribute__((always_inline))
  269. # define zend_never_inline __attribute__((noinline))
  270. # else
  271. # define zend_always_inline inline
  272. # define zend_never_inline
  273. # endif
  274. # elif defined(_MSC_VER)
  275. # define zend_always_inline __forceinline
  276. # define zend_never_inline __declspec(noinline)
  277. # else
  278. # if __has_attribute(always_inline)
  279. # define zend_always_inline inline __attribute__((always_inline))
  280. # else
  281. # define zend_always_inline inline
  282. # endif
  283. # if __has_attribute(noinline)
  284. # define zend_never_inline __attribute__((noinline))
  285. # else
  286. # define zend_never_inline
  287. # endif
  288. # endif
  289. #endif /* ZEND_DEBUG */
  290. #ifdef PHP_HAVE_BUILTIN_EXPECT
  291. # define EXPECTED(condition) __builtin_expect(!!(condition), 1)
  292. # define UNEXPECTED(condition) __builtin_expect(!!(condition), 0)
  293. #else
  294. # define EXPECTED(condition) (condition)
  295. # define UNEXPECTED(condition) (condition)
  296. #endif
  297. #ifndef XtOffsetOf
  298. # define XtOffsetOf(s_type, field) offsetof(s_type, field)
  299. #endif
  300. #if (defined(HAVE_ALLOCA) || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN)
  301. # define ZEND_ALLOCA_MAX_SIZE (32 * 1024)
  302. # define ALLOCA_FLAG(name) \
  303. bool name;
  304. # define SET_ALLOCA_FLAG(name) \
  305. name = 1
  306. # define do_alloca_ex(size, limit, use_heap) \
  307. ((use_heap = (UNEXPECTED((size) > (limit)))) ? emalloc(size) : alloca(size))
  308. # define do_alloca(size, use_heap) \
  309. do_alloca_ex(size, ZEND_ALLOCA_MAX_SIZE, use_heap)
  310. # define free_alloca(p, use_heap) \
  311. do { if (UNEXPECTED(use_heap)) efree(p); } while (0)
  312. #else
  313. # define ALLOCA_FLAG(name)
  314. # define SET_ALLOCA_FLAG(name)
  315. # define do_alloca(p, use_heap) emalloc(p)
  316. # define free_alloca(p, use_heap) efree(p)
  317. #endif
  318. #ifdef HAVE_SIGSETJMP
  319. # define SETJMP(a) sigsetjmp(a, 0)
  320. # define LONGJMP(a,b) siglongjmp(a, b)
  321. # define JMP_BUF sigjmp_buf
  322. #else
  323. # define SETJMP(a) setjmp(a)
  324. # define LONGJMP(a,b) longjmp(a, b)
  325. # define JMP_BUF jmp_buf
  326. #endif
  327. #if ZEND_DEBUG
  328. # define ZEND_FILE_LINE_D const char *__zend_filename, const uint32_t __zend_lineno
  329. # define ZEND_FILE_LINE_DC , ZEND_FILE_LINE_D
  330. # define ZEND_FILE_LINE_ORIG_D const char *__zend_orig_filename, const uint32_t __zend_orig_lineno
  331. # define ZEND_FILE_LINE_ORIG_DC , ZEND_FILE_LINE_ORIG_D
  332. # define ZEND_FILE_LINE_RELAY_C __zend_filename, __zend_lineno
  333. # define ZEND_FILE_LINE_RELAY_CC , ZEND_FILE_LINE_RELAY_C
  334. # define ZEND_FILE_LINE_C __FILE__, __LINE__
  335. # define ZEND_FILE_LINE_CC , ZEND_FILE_LINE_C
  336. # define ZEND_FILE_LINE_EMPTY_C NULL, 0
  337. # define ZEND_FILE_LINE_EMPTY_CC , ZEND_FILE_LINE_EMPTY_C
  338. # define ZEND_FILE_LINE_ORIG_RELAY_C __zend_orig_filename, __zend_orig_lineno
  339. # define ZEND_FILE_LINE_ORIG_RELAY_CC , ZEND_FILE_LINE_ORIG_RELAY_C
  340. #else
  341. # define ZEND_FILE_LINE_D void
  342. # define ZEND_FILE_LINE_DC
  343. # define ZEND_FILE_LINE_ORIG_D void
  344. # define ZEND_FILE_LINE_ORIG_DC
  345. # define ZEND_FILE_LINE_RELAY_C
  346. # define ZEND_FILE_LINE_RELAY_CC
  347. # define ZEND_FILE_LINE_C
  348. # define ZEND_FILE_LINE_CC
  349. # define ZEND_FILE_LINE_EMPTY_C
  350. # define ZEND_FILE_LINE_EMPTY_CC
  351. # define ZEND_FILE_LINE_ORIG_RELAY_C
  352. # define ZEND_FILE_LINE_ORIG_RELAY_CC
  353. #endif /* ZEND_DEBUG */
  354. #if ZEND_DEBUG
  355. # define Z_DBG(expr) (expr)
  356. #else
  357. # define Z_DBG(expr)
  358. #endif
  359. #ifdef ZTS
  360. # define ZTS_V 1
  361. #else
  362. # define ZTS_V 0
  363. #endif
  364. #ifndef LONG_MAX
  365. # define LONG_MAX 2147483647L
  366. #endif
  367. #ifndef LONG_MIN
  368. # define LONG_MIN (- LONG_MAX - 1)
  369. #endif
  370. #define MAX_LENGTH_OF_DOUBLE 32
  371. #undef MIN
  372. #undef MAX
  373. #define MAX(a, b) (((a)>(b))?(a):(b))
  374. #define MIN(a, b) (((a)<(b))?(a):(b))
  375. #define ZEND_BIT_TEST(bits, bit) \
  376. (((bits)[(bit) / (sizeof((bits)[0])*8)] >> ((bit) & (sizeof((bits)[0])*8-1))) & 1)
  377. #define ZEND_INFINITY INFINITY
  378. #define ZEND_NAN NAN
  379. #if defined(__cplusplus) && __cplusplus >= 201103L
  380. extern "C++" {
  381. # include <cmath>
  382. }
  383. # define zend_isnan std::isnan
  384. # define zend_isinf std::isinf
  385. # define zend_finite std::isfinite
  386. #else
  387. # include <math.h>
  388. # define zend_isnan(a) isnan(a)
  389. # define zend_isinf(a) isinf(a)
  390. # define zend_finite(a) isfinite(a)
  391. #endif
  392. #define ZEND_STRL(str) (str), (sizeof(str)-1)
  393. #define ZEND_STRS(str) (str), (sizeof(str))
  394. #define ZEND_NORMALIZE_BOOL(n) \
  395. ((n) ? (((n)<0) ? -1 : 1) : 0)
  396. #define ZEND_TRUTH(x) ((x) ? 1 : 0)
  397. #define ZEND_LOG_XOR(a, b) (ZEND_TRUTH(a) ^ ZEND_TRUTH(b))
  398. #define ZEND_MAX_RESERVED_RESOURCES 6
  399. /* excpt.h on Digital Unix 4.0 defines function_table */
  400. #undef function_table
  401. #ifdef ZEND_WIN32
  402. #define ZEND_SECURE_ZERO(var, size) RtlSecureZeroMemory((var), (size))
  403. #else
  404. #define ZEND_SECURE_ZERO(var, size) explicit_bzero((var), (size))
  405. #endif
  406. /* This check should only be used on network socket, not file descriptors */
  407. #ifdef ZEND_WIN32
  408. #define ZEND_VALID_SOCKET(sock) (INVALID_SOCKET != (sock))
  409. #else
  410. #define ZEND_VALID_SOCKET(sock) ((sock) >= 0)
  411. #endif
  412. /* Intrinsics macros start. */
  413. /* Memory sanitizer is incompatible with ifunc resolvers. Even if the resolver
  414. * is marked as no_sanitize("memory") it will still be instrumented and crash. */
  415. #if __has_feature(memory_sanitizer) || __has_feature(thread_sanitizer) || \
  416. __has_feature(dataflow_sanitizer)
  417. # undef HAVE_FUNC_ATTRIBUTE_IFUNC
  418. #endif
  419. /* Only use ifunc resolvers if we have __builtin_cpu_supports() and __builtin_cpu_init(),
  420. * otherwise the use of zend_cpu_supports() may not be safe inside ifunc resolvers. */
  421. #if defined(HAVE_FUNC_ATTRIBUTE_IFUNC) && defined(HAVE_FUNC_ATTRIBUTE_TARGET) && \
  422. defined(PHP_HAVE_BUILTIN_CPU_SUPPORTS) && defined(PHP_HAVE_BUILTIN_CPU_INIT)
  423. # define ZEND_INTRIN_HAVE_IFUNC_TARGET 1
  424. #endif
  425. #if (defined(__i386__) || defined(__x86_64__))
  426. # if defined(HAVE_TMMINTRIN_H)
  427. # define PHP_HAVE_SSSE3
  428. # endif
  429. # if defined(HAVE_NMMINTRIN_H)
  430. # define PHP_HAVE_SSE4_2
  431. # endif
  432. # if defined(HAVE_WMMINTRIN_H)
  433. # define PHP_HAVE_PCLMUL
  434. # endif
  435. /*
  436. * AVX2 support was added in gcc 4.7, but AVX2 intrinsics don't work in
  437. * __attribute__((target("avx2"))) functions until gcc 4.9.
  438. */
  439. # if defined(HAVE_IMMINTRIN_H) && \
  440. (defined(__llvm__) || defined(__clang__) || (defined(__GNUC__) && ZEND_GCC_VERSION >= 4009))
  441. # define PHP_HAVE_AVX2
  442. # endif
  443. #endif
  444. #ifdef __SSSE3__
  445. /* Instructions compiled directly. */
  446. # define ZEND_INTRIN_SSSE3_NATIVE 1
  447. #elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSSE3)) || defined(ZEND_WIN32)
  448. /* Function resolved by ifunc or MINIT. */
  449. # define ZEND_INTRIN_SSSE3_RESOLVER 1
  450. #endif
  451. /* Do not use for conditional declaration of API functions! */
  452. #if defined(ZEND_INTRIN_SSSE3_RESOLVER) && defined(ZEND_INTRIN_HAVE_IFUNC_TARGET)
  453. # define ZEND_INTRIN_SSSE3_FUNC_PROTO 1
  454. #elif defined(ZEND_INTRIN_SSSE3_RESOLVER)
  455. # define ZEND_INTRIN_SSSE3_FUNC_PTR 1
  456. #endif
  457. #ifdef ZEND_INTRIN_SSSE3_RESOLVER
  458. # ifdef HAVE_FUNC_ATTRIBUTE_TARGET
  459. # define ZEND_INTRIN_SSSE3_FUNC_DECL(func) ZEND_API func __attribute__((target("ssse3")))
  460. # else
  461. # define ZEND_INTRIN_SSSE3_FUNC_DECL(func) func
  462. # endif
  463. #else
  464. # define ZEND_INTRIN_SSSE3_FUNC_DECL(func)
  465. #endif
  466. #ifdef __SSE4_2__
  467. /* Instructions compiled directly. */
  468. # define ZEND_INTRIN_SSE4_2_NATIVE 1
  469. #elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSE4_2)) || defined(ZEND_WIN32)
  470. /* Function resolved by ifunc or MINIT. */
  471. # define ZEND_INTRIN_SSE4_2_RESOLVER 1
  472. #endif
  473. /* Do not use for conditional declaration of API functions! */
  474. #if defined(ZEND_INTRIN_SSE4_2_RESOLVER) && defined(ZEND_INTRIN_HAVE_IFUNC_TARGET)
  475. # define ZEND_INTRIN_SSE4_2_FUNC_PROTO 1
  476. #elif defined(ZEND_INTRIN_SSE4_2_RESOLVER)
  477. # define ZEND_INTRIN_SSE4_2_FUNC_PTR 1
  478. #endif
  479. #ifdef ZEND_INTRIN_SSE4_2_RESOLVER
  480. # ifdef HAVE_FUNC_ATTRIBUTE_TARGET
  481. # define ZEND_INTRIN_SSE4_2_FUNC_DECL(func) ZEND_API func __attribute__((target("sse4.2")))
  482. # else
  483. # define ZEND_INTRIN_SSE4_2_FUNC_DECL(func) func
  484. # endif
  485. #else
  486. # define ZEND_INTRIN_SSE4_2_FUNC_DECL(func)
  487. #endif
  488. #ifdef __PCLMUL__
  489. /* Instructions compiled directly. */
  490. # define ZEND_INTRIN_PCLMUL_NATIVE 1
  491. #elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_PCLMUL)) || defined(ZEND_WIN32)
  492. /* Function resolved by ifunc or MINIT. */
  493. # define ZEND_INTRIN_PCLMUL_RESOLVER 1
  494. #endif
  495. /* Do not use for conditional declaration of API functions! */
  496. #if defined(ZEND_INTRIN_PCLMUL_RESOLVER) && defined(ZEND_INTRIN_HAVE_IFUNC_TARGET) && (!defined(__GNUC__) || (ZEND_GCC_VERSION >= 9000))
  497. /* __builtin_cpu_supports has pclmul from gcc9 */
  498. # define ZEND_INTRIN_PCLMUL_FUNC_PROTO 1
  499. #elif defined(ZEND_INTRIN_PCLMUL_RESOLVER)
  500. # define ZEND_INTRIN_PCLMUL_FUNC_PTR 1
  501. #endif
  502. #ifdef ZEND_INTRIN_PCLMUL_RESOLVER
  503. # ifdef HAVE_FUNC_ATTRIBUTE_TARGET
  504. # define ZEND_INTRIN_PCLMUL_FUNC_DECL(func) ZEND_API func __attribute__((target("pclmul")))
  505. # else
  506. # define ZEND_INTRIN_PCLMUL_FUNC_DECL(func) func
  507. # endif
  508. #else
  509. # define ZEND_INTRIN_PCLMUL_FUNC_DECL(func)
  510. #endif
  511. #if defined(ZEND_INTRIN_SSE4_2_NATIVE) && defined(ZEND_INTRIN_PCLMUL_NATIVE)
  512. /* Instructions compiled directly. */
  513. # define ZEND_INTRIN_SSE4_2_PCLMUL_NATIVE 1
  514. #elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_SSE4_2) && defined(PHP_HAVE_PCLMUL)) || defined(ZEND_WIN32)
  515. /* Function resolved by ifunc or MINIT. */
  516. # define ZEND_INTRIN_SSE4_2_PCLMUL_RESOLVER 1
  517. #endif
  518. /* Do not use for conditional declaration of API functions! */
  519. #if defined(ZEND_INTRIN_SSE4_2_PCLMUL_RESOLVER) && defined(ZEND_INTRIN_HAVE_IFUNC_TARGET) && (!defined(__GNUC__) || (ZEND_GCC_VERSION >= 9000))
  520. /* __builtin_cpu_supports has pclmul from gcc9 */
  521. # define ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_PROTO 1
  522. #elif defined(ZEND_INTRIN_SSE4_2_PCLMUL_RESOLVER)
  523. # define ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_PTR 1
  524. #endif
  525. #ifdef ZEND_INTRIN_SSE4_2_PCLMUL_RESOLVER
  526. # ifdef HAVE_FUNC_ATTRIBUTE_TARGET
  527. # define ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_DECL(func) ZEND_API func __attribute__((target("sse4.2,pclmul")))
  528. # else
  529. # define ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_DECL(func) func
  530. # endif
  531. #else
  532. # define ZEND_INTRIN_SSE4_2_PCLMUL_FUNC_DECL(func)
  533. #endif
  534. #ifdef __AVX2__
  535. # define ZEND_INTRIN_AVX2_NATIVE 1
  536. #elif (defined(HAVE_FUNC_ATTRIBUTE_TARGET) && defined(PHP_HAVE_AVX2)) || defined(ZEND_WIN32)
  537. # define ZEND_INTRIN_AVX2_RESOLVER 1
  538. #endif
  539. /* Do not use for conditional declaration of API functions! */
  540. #if defined(ZEND_INTRIN_AVX2_RESOLVER) && defined(ZEND_INTRIN_HAVE_IFUNC_TARGET)
  541. # define ZEND_INTRIN_AVX2_FUNC_PROTO 1
  542. #elif defined(ZEND_INTRIN_AVX2_RESOLVER)
  543. # define ZEND_INTRIN_AVX2_FUNC_PTR 1
  544. #endif
  545. #ifdef ZEND_INTRIN_AVX2_RESOLVER
  546. # ifdef HAVE_FUNC_ATTRIBUTE_TARGET
  547. # define ZEND_INTRIN_AVX2_FUNC_DECL(func) ZEND_API func __attribute__((target("avx2")))
  548. # else
  549. # define ZEND_INTRIN_AVX2_FUNC_DECL(func) func
  550. # endif
  551. #else
  552. # define ZEND_INTRIN_AVX2_FUNC_DECL(func)
  553. #endif
  554. /* Intrinsics macros end. */
  555. #ifdef ZEND_WIN32
  556. # define ZEND_SET_ALIGNED(alignment, decl) __declspec(align(alignment)) decl
  557. #elif defined(HAVE_ATTRIBUTE_ALIGNED)
  558. # define ZEND_SET_ALIGNED(alignment, decl) decl __attribute__ ((__aligned__ (alignment)))
  559. #else
  560. # define ZEND_SET_ALIGNED(alignment, decl) decl
  561. #endif
  562. #define ZEND_SLIDE_TO_ALIGNED(alignment, ptr) (((zend_uintptr_t)(ptr) + ((alignment)-1)) & ~((alignment)-1))
  563. #define ZEND_SLIDE_TO_ALIGNED16(ptr) ZEND_SLIDE_TO_ALIGNED(Z_UL(16), ptr)
  564. #ifdef ZEND_WIN32
  565. # define _ZEND_EXPAND_VA(a) a
  566. # define ZEND_EXPAND_VA(code) _ZEND_EXPAND_VA(code)
  567. #else
  568. # define ZEND_EXPAND_VA(code) code
  569. #endif
  570. /* On CPU with few registers, it's cheaper to reload value then use spill slot */
  571. #if defined(__i386__) || (defined(_WIN32) && !defined(_WIN64))
  572. # define ZEND_PREFER_RELOAD
  573. #endif
  574. #if defined(ZEND_WIN32) && defined(_DEBUG)
  575. # define ZEND_IGNORE_LEAKS_BEGIN() _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & ~_CRTDBG_ALLOC_MEM_DF)
  576. # define ZEND_IGNORE_LEAKS_END() _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_ALLOC_MEM_DF)
  577. #else
  578. # define ZEND_IGNORE_LEAKS_BEGIN()
  579. # define ZEND_IGNORE_LEAKS_END()
  580. #endif
  581. /* MSVC yields C4090 when a (const T **) is passed to a (void *); ZEND_VOIDP works around that */
  582. #ifdef _MSC_VER
  583. # define ZEND_VOIDP(ptr) ((void *) ptr)
  584. #else
  585. # define ZEND_VOIDP(ptr) (ptr)
  586. #endif
  587. #if defined(__GNUC__) && ZEND_GCC_VERSION >= 9000
  588. # define ZEND_INDIRECT_RETURN __attribute__((__indirect_return__))
  589. #else
  590. # define ZEND_INDIRECT_RETURN
  591. #endif
  592. #endif /* ZEND_PORTABILITY_H */