codegen: use gen_frame_decompress_slot in gen_option_ord
[ajla.git] / compiler.h
blob23759578bfb58b67cbfea3ec1479cd423d306b80
1 /*
2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version.
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #ifdef HAVE_STDINT_H
21 #include <stdint.h>
22 #ifdef HAVE_INTTYPES_H
23 #include <inttypes.h>
24 #endif
26 #else
28 #ifdef HAVE_INT_T_U_INT_T
30 typedef u_int8_t uint8_t;
31 typedef u_int16_t uint16_t;
32 typedef u_int32_t uint32_t;
34 #else
36 typedef signed char int8_t;
37 typedef unsigned char uint8_t;
39 #if SIZEOF_UNSIGNED_SHORT == 2
40 typedef signed short int16_t;
41 typedef unsigned short uint16_t;
42 #else
43 no type for int16_t
44 #endif
46 #if SIZEOF_UNSIGNED == 4
47 typedef signed int32_t;
48 typedef unsigned uint32_t;
49 #elif SIZEOF_UNSIGNED_LONG == 4
50 typedef signed long int32_t;
51 typedef unsigned long uint32_t;
52 #else
53 no type for int32_t
54 #endif
56 #endif
58 #if defined(SIZEOF_UNSIGNED) && defined(SIZEOF_VOID_P) && SIZEOF_UNSIGNED && SIZEOF_UNSIGNED == SIZEOF_VOID_P
59 typedef int intptr_t;
60 typedef unsigned uintptr_t;
61 #elif defined(SIZEOF_UNSIGNED_LONG) && defined(SIZEOF_VOID_P) && SIZEOF_UNSIGNED_LONG && SIZEOF_UNSIGNED_LONG == SIZEOF_VOID_P
62 typedef long intptr_t;
63 typedef unsigned long uintptr_t;
64 #elif defined(SIZEOF_UNSIGNED_LONG_LONG) && defined(SIZEOF_VOID_P) && SIZEOF_UNSIGNED_LONG_LONG && SIZEOF_UNSIGNED_LONG_LONG == SIZEOF_VOID_P
65 typedef long long intptr_t;
66 typedef unsigned long long uintptr_t;
67 #else
68 typedef long intptr_t;
69 typedef unsigned long uintptr_t;
70 #endif
73 #ifndef HAVE_INT64_T_UINT64_T
74 #ifdef HAVE_INT64_T_U_INT64_T
75 typedef u_int64_t uint64_t;
76 #define HAVE_INT64_T_UINT64_T 1
77 #elif defined(SIZEOF_UNSIGNED_LONG) && SIZEOF_UNSIGNED_LONG == 8
78 typedef signed long int64_t;
79 typedef unsigned long uint64_t;
80 #define HAVE_INT64_T_UINT64_T 1
81 #elif defined(SIZEOF_UNSIGNED_LONG_LONG) && SIZEOF_UNSIGNED_LONG_LONG == 8
82 typedef signed long long int64_t;
83 typedef unsigned long long uint64_t;
84 #define HAVE_INT64_T_UINT64_T 1
85 #elif defined(_MSC_VER) || defined(__BORLANDC__)
86 typedef signed __int64 int64_t;
87 typedef unsigned __int64 uint64_t;
88 #define HAVE_INT64_T_UINT64_T 1
89 #endif
90 #endif
92 #ifdef HAVE_INT64_T_UINT64_T
93 typedef int64_t intmax_t;
94 typedef uint64_t uintmax_t;
95 #else
96 typedef long intmax_t;
97 typedef unsigned long uintmax_t;
98 #endif
100 #endif
103 #if defined(SIZEOF_UNSIGNED___INT128) && SIZEOF_UNSIGNED___INT128 > 8
104 typedef __int128 intbig_t;
105 typedef unsigned __int128 uintbig_t;
106 #else
107 typedef intmax_t intbig_t;
108 typedef uintmax_t uintbig_t;
109 #endif
112 #ifdef int8_t
113 #undef int8_t
114 #endif
115 #ifdef int16_t
116 #undef int16_t
117 #endif
118 #ifdef int32_t
119 #undef int32_t
120 #endif
121 #ifdef int64_t
122 #undef int64_t
123 #endif
124 #ifdef int128_t
125 #undef int128_t
126 #endif
127 #ifdef uint8_t
128 #undef uint8_t
129 #endif
130 #ifdef uint16_t
131 #undef uint16_t
132 #endif
133 #ifdef uint32_t
134 #undef uint32_t
135 #endif
136 #ifdef uint64_t
137 #undef uint64_t
138 #endif
139 #ifdef uint128_t
140 #undef uint128_t
141 #endif
144 #ifndef PRIdMAX
145 #ifdef HAVE_LONG_LONG
146 #define PRIdMAX "lld"
147 #else
148 #define PRIdMAX "ld"
149 #endif
150 #endif
152 #ifndef PRIuMAX
153 #ifdef HAVE_LONG_LONG
154 #define PRIuMAX "llu"
155 #else
156 #define PRIuMAX "lu"
157 #endif
158 #endif
160 #ifndef PRIxMAX
161 #ifdef HAVE_LONG_LONG
162 #define PRIxMAX "llx"
163 #else
164 #define PRIxMAX "lx"
165 #endif
166 #endif
168 #ifndef PRIXMAX
169 #ifdef HAVE_LONG_LONG
170 #define PRIXMAX "llX"
171 #else
172 #define PRIXMAX "lX"
173 #endif
174 #endif
177 #ifdef HAVE_STDBOOL_H
178 #include <stdbool.h>
179 #endif
180 #ifndef __bool_true_false_are_defined
181 #define bool char
182 #define false 0
183 #define true 1
184 #endif
186 #ifndef HAVE_SOCKLEN_T
187 #define socklen_t int
188 #endif
190 #ifndef HAVE_SIG_ATOMIC_T
191 #define sig_atomic_t int
192 #endif
194 #ifdef HAVE_C11_ATOMICS
195 #ifndef __cplusplus
196 #include <stdatomic.h>
197 #endif
198 #define atomic_type _Atomic
199 #define load_relaxed(p) atomic_load_explicit(p, memory_order_relaxed)
200 #define store_relaxed(p, v) atomic_store_explicit(p, v, memory_order_relaxed)
201 #else
202 #define atomic_type volatile
203 #define load_relaxed(p) (*(p))
204 #define store_relaxed(p, v) (*(p) = (v))
205 #endif
208 #if defined(SIZEOF_VOID_P) && SIZEOF_VOID_P > 0
209 #if SIZEOF_VOID_P >= 8
210 #define BIT64
211 #endif
212 #elif defined(__INITIAL_POINTER_SIZE)
213 #if __INITIAL_POINTER_SIZE >= 64
214 #define BIT64
215 #endif
216 #elif defined(_LP64) || defined(__LP64__) || defined(_WIN64)
217 #define BIT64
218 #endif
221 #ifndef UNUSUAL_UNKNOWN_ENDIAN
222 #if defined(CONFIG_LITTLE_ENDIAN)
223 #define C_LITTLE_ENDIAN
224 #elif defined(CONFIG_BIG_ENDIAN)
225 #define C_BIG_ENDIAN
226 #elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
227 #define C_LITTLE_ENDIAN
228 #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
229 #define C_BIG_ENDIAN
230 #endif
231 #endif
234 #define extern_const const
237 #define stringify_internal(arg) #arg
238 #define stringify(arg) stringify_internal(arg)
239 #define file_line __FILE__ ":" stringify(__LINE__)
243 * The defined() operator in macro expansion is not portable.
245 #if defined(__GNUC__) && defined(__GNUC_MINOR__)
246 #define DEFINED___GNUC____GNUC_MINOR__ 1
247 #else
248 #define DEFINED___GNUC____GNUC_MINOR__ 0
249 #endif
251 #if defined(__GNUC_PATCHLEVEL__)
252 #define DEFINED___GNUC_PATCHLEVEL__ 1
253 #else
254 #define DEFINED___GNUC_PATCHLEVEL__ 0
255 #endif
257 #define GNUC_ATLEAST(x, y, z) \
258 (DEFINED___GNUC____GNUC_MINOR__ && \
259 (__GNUC__ > (x) || \
260 (__GNUC__ == (x) && \
261 (__GNUC_MINOR__ > (y) || \
262 (__GNUC_MINOR__ == (y) && \
263 (!DEFINED___GNUC_PATCHLEVEL__ || \
264 __GNUC_PATCHLEVEL__ >= (z) \
272 #if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
273 #define DEFINED___CLANG____CLANG_MAJOR____CLANG_MINOR__ 1
274 #else
275 #define DEFINED___CLANG____CLANG_MAJOR____CLANG_MINOR__ 0
276 #endif
278 #if defined(__clang_patchlevel__)
279 #define DEFINED___CLANG_PATCHLEVEL__ 1
280 #else
281 #define DEFINED___CLANG_PATCHLEVEL__ 0
282 #endif
284 #define CLANG_ATLEAST(x, y, z) \
285 (DEFINED___CLANG____CLANG_MAJOR____CLANG_MINOR__ && \
286 (__clang_major__ > (x) || \
287 (__clang_major__ == (x) && \
288 (__clang_minor__ > (y) || \
289 (__clang_minor__ == (y) && \
290 (!DEFINED___CLANG_PATCHLEVEL__ || \
291 __clang_patchlevel__ >= (z) \
299 #if defined(__GNUC__) && !(defined(__clang__) || defined(__llvm__) || defined(__ICC) || defined(__OPEN64__) || defined(__PATHSCALE__) || defined(__PGI) || defined(__PGIC__))
300 #define HAVE_REAL_GNUC
301 #endif
303 #if GNUC_ATLEAST(2,0,0)
304 #define return_address __builtin_return_address(0)
305 #endif
307 #if GNUC_ATLEAST(2,0,0)
308 #define is_constant(expression) __builtin_constant_p(expression)
309 #else
310 #define is_constant(expression) (false)
311 #endif
313 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && __GNUC__ == 2 && __GNUC_MINOR__ <= 7
315 * Verify that the __attribute__ directive is properly placed. GCC 2 has more
316 * strict attribute placing rules than gcc 3 and following versions.
318 * egcs crashes on empty __attribute__ directive
320 #define attr_nothing __attribute__(())
321 #else
322 #define attr_nothing
323 #endif
325 #if GNUC_ATLEAST(2,0,0)
326 #define attr_unaligned __attribute__((packed))
327 #endif
329 #if GNUC_ATLEAST(2,0,0) && !defined(__MINGW32__)
330 #define attr_printf(x, y) __attribute__((format(printf, x, y)))
331 #else
332 #define attr_printf(x, y)
333 #endif
335 #if defined(HAVE_STDNORETURN_H) && !defined(__cplusplus) && !defined(__ICC)
336 #include <stdnoreturn.h>
337 #define attr_noreturn noreturn void
338 #elif GNUC_ATLEAST(2,5,0)
339 #define attr_noreturn void __attribute__((noreturn))
340 #elif defined(_MSC_VER) && _MSC_VER >= 1600 /* not sure */
341 #define attr_noreturn void __declspec(noreturn)
342 #else
343 #define attr_noreturn void
344 #endif
346 #if GNUC_ATLEAST(2,7,0)
347 #define attr_unused __attribute__((__unused__))
348 #else
349 #define attr_unused attr_nothing
350 #endif
352 #if GNUC_ATLEAST(2,96,0)
353 #define likely(x) (__builtin_expect((int)(x), 1))
354 #define unlikely(x) (__builtin_expect((int)(x), 0))
355 #else
356 #define likely(x) ((int)(x))
357 #define unlikely(x) ((int)(x))
358 #endif
360 #if GNUC_ATLEAST(3,0,0) && !defined(__DJGPP__) /* not sure */
361 #define attr_aligned(x) __attribute__((__aligned__(x)))
362 #elif defined(_MSC_VER) && _MSC_VER >= 1600 /* not sure */
363 #define attr_aligned(x) __declspec(align(x))
364 #else
365 #define attr_aligned(x) attr_nothing
366 #endif
368 #if GNUC_ATLEAST(3,1,0)
369 #define attr_noinline __attribute__((__noinline__))
370 #elif defined(_MSC_VER) && _MSC_VER >= 1600 /* not sure */
371 #define attr_noinline __declspec(noinline)
372 #else
373 #define attr_noinline
374 #endif
376 #if GNUC_ATLEAST(3,1,0)
377 #define attr_always_inline inline __attribute__((__always_inline__))
378 #elif defined(_MSC_VER) && _MSC_VER >= 1600 /* not sure */
379 #define attr_always_inline __forceinline
380 #else
381 #define attr_always_inline inline
382 #endif
384 #if defined(HAVE_REAL_GNUC) && !defined(UNUSUAL)
385 #define INLINE_WORKS
386 #endif
388 #if GNUC_ATLEAST(3,4,0)
389 #define attr_w __attribute__((__warn_unused_result__))
390 #else
391 #define attr_w attr_nothing
392 #endif
394 #if GNUC_ATLEAST(4,3,0)
395 #define attr_cold __attribute__((__noinline__,__cold__))
396 #define attr_hot __attribute__((/*__hot__*/))
397 #elif GNUC_ATLEAST(3,1,0)
398 #define attr_cold __attribute__((__noinline__))
399 #define attr_hot attr_nothing
400 #else
401 #define attr_cold attr_nothing
402 #define attr_hot attr_nothing
403 #endif
405 #if GNUC_ATLEAST(4,5,0)
406 #define attr_noclone __attribute__((__noclone__))
407 #else
408 #define attr_noclone attr_nothing
409 #endif
411 #if GNUC_ATLEAST(3,0,0) && !defined(__PCC__) && defined(__i386__)
412 #if GNUC_ATLEAST(4,1,0) && defined(HAVE_REAL_GNUC) && defined(__SSE__) && defined(__SSE_MATH__)
413 #define attr_fastcall __attribute__((__regparm__(3),__sseregparm__))
414 #else
415 #define attr_fastcall __attribute__((__regparm__(3)))
416 #endif
417 #elif GNUC_ATLEAST(4,4,0) && defined(__x86_64__) && (defined(__CYGWIN__) || defined(__WIN32))
418 /*#define attr_fastcall __attribute__((__sysv_abi__))*/
419 #define attr_fastcall attr_nothing
420 #elif defined(_MSC_VER)
421 #define attr_fastcall __fastcall
422 #elif defined(__TURBOC__) || defined(__BORLANDC__)
423 #define attr_fastcall __fastcall
424 #else
425 #define attr_fastcall attr_nothing
426 #endif
428 #define attr_hot_fastcall attr_hot attr_fastcall
430 #if defined(__GNUC__) && defined(__OPTIMIZE__) && !defined(__OPEN64__)
431 attr_noreturn not_reached(void);
432 #else
433 #define not_reached() internal(file_line, "this location should not be reached")
434 #endif
436 /* Borland C has preprocessor expansion size limits */
437 #if (defined(__TURBOC__) || defined(__BORLANDC__)) && !defined(__BIGGEST_ALIGNMENT__)
438 #define __BIGGEST_ALIGNMENT__ 8
439 #endif
441 #define HEAP_ALIGN (is_power_of_2(sizeof(void *)) ? sizeof(void *) * 2 : 16)
443 #if GNUC_ATLEAST(1,36,0)
444 #define align_of(type) __alignof__(type)
445 #elif defined(HAVE_STDALIGN_H)
446 #include <stdalign.h>
447 #define align_of(type) alignof(type)
448 #else
449 #define align_of(type) minimum(HEAP_ALIGN, \
450 !sizeof(type) ? 1 : \
451 sizeof(type) & -sizeof(type))
452 #endif
454 #if defined(__STDC__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901
455 #define FLEXIBLE_ARRAY
456 #elif defined(__GNUC__) && !defined(GNUC_PEDANTIC)
457 #define FLEXIBLE_ARRAY 0
458 #else
459 #define FLEXIBLE_ARRAY 1
460 #endif
462 #if defined(__GNUC__) && !defined(GNUC_PEDANTIC)
463 #define FLEXIBLE_ARRAY_GCC 0
464 #define EMPTY_TYPE struct { }
465 #else
466 #define FLEXIBLE_ARRAY_GCC 1
467 #define EMPTY_TYPE char
468 #endif
470 static attr_always_inline void *return_ptr(const void *ptr)
472 return (void *)ptr;
475 #if defined(HAVE_REAL_GNUC)
476 #define cast_ptr(type, ptr) ((type)return_ptr(ptr))
477 #else
478 #define cast_ptr(type, ptr) ((type)(void *)(ptr))
479 #endif
481 #if 1
482 #define cast_cpp cast_ptr
483 #else
484 #define cast_cpp(type, ptr) (ptr)
485 #endif
487 #ifndef HAVE___BUILTIN_ASSUME_ALIGNED
488 #define __builtin_assume_aligned(p, align) (p)
489 #endif
493 * We allocate partial structures with union as the last member.
494 * If this causes problems with any compiler, enable this.
496 #if 0
497 #define partial_sizeof_lower_bound(full) sizeof(full)
498 #define partial_sizeof(full, part) sizeof(full)
499 #define partial_sizeof_array(full, part, extra) maximum_maybe0(sizeof(full), (offsetof(full, part) + (extra) * sizeof(((full *)NULL)->part[0])))
500 #else
501 #define partial_sizeof_lower_bound(full) ((size_t)0)
502 #define partial_sizeof(full, part) (offsetof(full, part) + sizeof(((full *)NULL)->part))
503 #define partial_sizeof_array(full, part, extra) (offsetof(full, part) + (extra) * sizeof(((full *)NULL)->part[0]))
504 #endif
506 #if defined(_MSC_VER)
507 #define barrier_aliasing() do { } while (0)
508 #elif defined(HAVE_GCC_ASSEMBLER)
509 #define barrier_aliasing() __asm__ volatile ("":::"memory")
510 #else
511 #define NEED_EXPLICIT_ALIASING_BARRIER
512 extern volatile char * volatile alias_ptr;
513 #define barrier_aliasing() \
514 do { \
515 *alias_ptr = 0; \
516 } while (0)
517 #endif
519 #if defined(HAVE_GCC_ASSEMBLER)
520 #define ASM_PREVENT_CSE __asm__ volatile ("":::"memory")
521 #else
522 #define ASM_PREVENT_CSE do { } while (0)
523 #endif
525 #if defined(HAVE_GCC_ASSEMBLER) && 0
526 #define ASM_PREVENT_JOIN(i) __asm__ (""::"i"(i))
527 #else
528 #define ASM_PREVENT_JOIN(i) do { } while (0)
529 #endif
531 #if defined(HAVE_GCC_ASSEMBLER)
532 #define asm_copy(dest, src) __asm__ volatile (".if 0 \n .endif" : "=r"(dest) : "0"(src))
533 #endif
535 #if !defined(HAVE_INT64_T_UINT64_T)
536 #define EFFICIENT_WORD_SIZE 32
537 #elif defined(BIT64) || defined(__x86_64__) || defined(__aarch64__) || (defined(_PA_RISC2_0) && defined(__HP_cc)) || (defined(__VMS) && !defined(__VAX))
538 #define EFFICIENT_WORD_SIZE 64
539 #else
540 #define EFFICIENT_WORD_SIZE 32
541 #endif
543 #define int_efficient_t cat4(int,EFFICIENT_WORD_SIZE,_,t)
544 #define uint_efficient_t cat4(uint,EFFICIENT_WORD_SIZE,_,t)
546 #if defined(__alpha__) && (!defined(__alpha_bwx__) || defined(DEBUG_ENV))
547 typedef int32_t char_efficient_t;
548 typedef uint32_t uchar_efficient_t;
549 typedef int32_t short_efficient_t;
550 typedef uint32_t ushort_efficient_t;
551 #else
552 typedef int8_t char_efficient_t;
553 typedef uint8_t uchar_efficient_t;
554 typedef int16_t short_efficient_t;
555 typedef uint16_t ushort_efficient_t;
556 #endif
559 #if defined(HAVE_COMPUTED_GOTO) && defined(__clang__) && 0
560 /* Clang supports computed goto but it increases compilation time extremely. */
561 #undef HAVE_COMPUTED_GOTO
562 #endif
564 #if defined(HAVE_COMPUTED_GOTO) && defined(GNUC_PEDANTIC)
565 #undef HAVE_COMPUTED_GOTO
566 #endif
569 #if !defined(UNUSUAL_NO_ASSEMBLER)
571 #if defined(HAVE_GCC_ASSEMBLER) && (defined(__i386__) || defined(__x86_64__))
573 #define ARCH_X86
574 #ifdef HAVE_GCC_ASSEMBLER
575 #define INLINE_ASM_GCC_X86
576 #endif
578 #if defined(__i386__)
579 #define ARCH_X86_32
580 #define ARCH_NAME "i386"
581 #ifdef HAVE_GCC_ASSEMBLER
582 #define INLINE_ASM_GCC_I386
583 #endif
584 #elif defined(__x86_64__) && !defined(__ILP32__)
585 #define ARCH_X86_64
586 #define ARCH_NAME "x86_64"
587 #ifdef HAVE_GCC_ASSEMBLER
588 #define INLINE_ASM_GCC_X86_64
589 #endif
590 #else
591 #define ARCH_X86_X32
592 #define ARCH_NAME "x86_x32"
593 #ifdef HAVE_GCC_ASSEMBLER
594 #define INLINE_ASM_GCC_X32
595 #endif
596 #endif
598 #ifdef HAVE_GCC_ASSEMBLER
600 #if defined(__clang__) || defined(__llvm__) || !GNUC_ATLEAST(4,0,0) /* !!! TODO: check GCC version exactly */
602 * LLVM has inefficient "rm" implementation - it always references memory
603 * on the stack - https://bugs.llvm.org/show_bug.cgi?id=9723
605 * gcc 2.7 and 3.0 can't concatenate strings in asm constraint
607 #define X86_ASM_M
608 #else
609 #define X86_ASM_M "m"
610 #endif
612 #ifndef __SSE__
613 #define X86_ASM_XMM0_CLOB
614 #define X86_ASM_XMM0_CLOBC
615 #define X86_ASM_XMM1_CLOBC
616 #else
617 #define X86_ASM_XMM0_CLOB : "xmm0"
618 #define X86_ASM_XMM0_CLOBC , "xmm0"
619 #define X86_ASM_XMM1_CLOBC , "xmm1"
620 #endif
622 #ifndef __AVX__
623 #define X86_ASM_V
624 #define X86_ASM_AVX_PARAM(x) #x
625 #else
626 #define X86_ASM_V "v"
627 #define X86_ASM_AVX_PARAM(x) #x ", " #x
628 #endif
630 #endif
632 #elif defined(_M_IX86)
634 #define ARCH_X86
635 #define ARCH_X86_32
636 #define ARCH_NAME "i386"
638 #elif defined(_M_X64)
640 #define ARCH_X86
641 #define ARCH_X86_64
642 #define ARCH_NAME "x86_64"
644 #elif defined(__alpha__)
646 #define ARCH_ALPHA
647 #define ARCH_NAME "alpha"
649 #elif (defined(__arm__) && defined(__ARM_EABI__) && (!defined(__thumb__) || defined(__thumb2__))) || defined(__aarch64__)
651 #define ARCH_ARM
652 #ifdef __aarch64__
653 #define ARCH_ARM64
654 #define ARCH_NAME "aarchc64"
655 #else
656 #define ARCH_ARM32
657 #define ARCH_NAME "arm"
658 #endif
660 #ifdef __ARM_ARCH
661 #define ARM_VERSION __ARM_ARCH
662 #elif defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8A)
663 #define ARM_VERSION 8
664 #elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
665 #define ARM_VERSION 7
666 #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6M__)
667 #define ARM_VERSION 6
668 #elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
669 #define ARM_VERSION 5
670 #elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_3M__)
671 #define ARM_VERSION 4
672 #elif defined(__ARM_ARCH_3__)
673 #define ARM_VERSION 3
674 #elif defined(__ARM_ARCH_2__)
675 #define ARM_VERSION 2
676 #else
677 #define ARM_VERSION 1
678 #define ARM_VERSION_UNKNOWN
679 #endif
681 #if defined(HAVE_GCC_ASSEMBLER) && defined(HAVE_ARM_ASSEMBLER) && !defined(ARCH_ARM64)
682 #define INLINE_ASM_GCC_ARM
683 #if ARM_VERSION < 8
684 #define ARM_ASM_PREFIX ".cpu cortex-a15\n .fpu neon-vfpv4\n;;;;;;;;;;;;;;;;\n"
685 #else
686 #define ARM_ASM_PREFIX ".fpu neon-vfpv4\n;;;;;;;;;;;;;;;;\n"
687 #endif
688 #define ARM_ASM_APSR "apsr"
689 #define ARM_ASM_LO "Q"
690 #define ARM_ASM_HI "R"
691 #if !defined(__thumb2__)
692 #define ARM_ASM_S ""
693 #define ARM_ASM_S_CLOB
694 #define ARM_ASM_IF_T12(x,y) y
695 #else
696 #define INLINE_ASM_GCC_ARM_THUMB2
697 #define ARM_ASM_STRD "strd"
698 #define ARM_ASM_S "s"
699 #define ARM_ASM_S_CLOB : "cc"
700 #define ARM_ASM_IF_T12(x,y) x
701 #endif
702 #endif
704 #if defined(HAVE_GCC_ASSEMBLER) && defined(ARCH_ARM64)
705 #define INLINE_ASM_GCC_ARM64
706 #define ARM_ASM_PREFIX
707 #define ARM_ASM_APSR "nzcv"
708 #define ARM_ASM_LO "x"
709 #define ARM_ASM_HI "H"
710 #define ARM_ASM_STRD "stp"
711 #define ARM_ASM_S ""
712 #define ARM_ASM_S_CLOB
713 #define ARM_ASM_IF_T12(x,y) y
714 #endif
716 #if defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8A) || (defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'A')
717 #define ARM_ASM_DIV_NO_TRAP 1
718 #else
719 #define ARM_ASM_DIV_NO_TRAP 0
720 #endif
722 #elif defined(__ia64) && defined(__linux__)
724 #define ARCH_IA64
725 #define ARCH_NAME "ia64"
727 #elif defined(__loongarch64)
729 #define ARCH_LOONGARCH64
730 #define ARCH_NAME "loongarch64"
732 #elif defined(__mips) && defined(_MIPS_SIM) && (_MIPS_SIM == 1 || _MIPS_SIM == 2 || _MIPS_SIM == 3)
734 #define ARCH_MIPS
735 #if defined(__LP64__)
736 #define ARCH_MIPS64
737 #define ARCH_NAME "mips64"
738 #else
739 #define ARCH_MIPS32
740 #define ARCH_NAME "mips"
741 #if _MIPS_SIM == 1
742 #define ARCH_MIPS_O32
743 #else
744 #define ARCH_MIPS_N32
745 #endif
746 #endif
748 #elif defined(__hppa)
750 #define ARCH_PARISC
751 #if defined(__LP64__)
752 #define ARCH_PARISC64
753 #define ARCH_NAME "parisc64"
754 #define PA_SPACES 0
755 #else
756 #define ARCH_PARISC32
757 #define ARCH_NAME "parisc"
758 #ifdef __hpux
759 #define PA_SPACES 1
760 #else
761 #define PA_SPACES 0
762 #endif
763 #endif
765 #elif defined(__PPC__)
767 #define ARCH_POWER
768 #if defined(__LP64__)
769 #define ARCH_POWER64
770 #define ARCH_NAME "power64"
771 #else
772 #define ARCH_POWER32
773 #define ARCH_NAME "power"
774 #endif
776 #elif defined(__s390__)
778 #define ARCH_S390
779 #if defined(__LP64__)
780 #define ARCH_S390_64
781 #define ARCH_NAME "s390x"
782 #else
783 #define ARCH_S390_32
784 #define ARCH_NAME "s390"
785 #endif
787 #elif defined(__sparc__)
789 #define ARCH_SPARC
790 #if defined(__LP64__)
791 #define ARCH_SPARC64
792 #define ARCH_NAME "sparc64"
793 #else
794 #define ARCH_SPARC32
795 #define ARCH_NAME "sparc"
796 #endif
798 #elif defined(__riscv) && defined(_LP64)
800 #define ARCH_RISCV64
801 #define ARCH_NAME "riscv64"
803 #endif
806 #ifdef ARCH_X86
807 #if defined(OS_CYGWIN) || defined(OS_WIN32)
808 #define ARCH_X86_WIN_ABI
809 #endif
810 #endif
813 #if defined(HAVE_ASM_GOTO) && !defined(UNUSUAL_NO_ASSEMBLER_GOTO)
814 #define INLINE_ASM_GCC_LABELS
815 #endif
817 #endif
820 #if !defined(UNUSUAL_NO_TAGGED_POINTERS)
821 #if defined(HAVE_MMAP) || defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32)
822 #if defined(ARCH_ALPHA)
823 #define HAVE_CODEGEN
824 #define HAVE_CODEGEN_TRAPS
825 #endif
826 #if defined(ARCH_ARM32) && defined(__ARMEL__)
827 #define HAVE_CODEGEN
828 #endif
829 #if defined(ARCH_ARM64) && !defined(__ILP32__) && defined(HAVE___BUILTIN___CLEAR_CACHE)
830 #define HAVE_CODEGEN
831 #endif
832 #if defined(ARCH_IA64)
833 #define HAVE_CODEGEN
834 #endif
835 #if defined(ARCH_LOONGARCH64)
836 #define HAVE_CODEGEN
837 #endif
838 #if defined(ARCH_MIPS)
839 #define HAVE_CODEGEN
840 #define HAVE_CODEGEN_TRAPS
841 #endif
842 #if defined(ARCH_PARISC)
843 #define HAVE_CODEGEN
844 #endif
845 #if defined(ARCH_POWER)
846 #define HAVE_CODEGEN
847 #endif
848 #if defined(ARCH_S390)
849 #define HAVE_CODEGEN
850 #endif
851 #if defined(ARCH_SPARC)
852 #define HAVE_CODEGEN
853 #endif
854 #if defined(ARCH_RISCV64)
855 #define HAVE_CODEGEN
856 #endif
857 #if defined(ARCH_X86)
858 #define HAVE_CODEGEN
859 #endif
860 #endif
861 #endif
863 #if defined(HAVE_CODEGEN) && (defined(HAVE_MPROTECT) || defined(OS_DOS) || defined(OS_OS2) || defined(OS_WIN32))
864 #if defined(ARCH_ARM) && defined(HAVE___BUILTIN___CLEAR_CACHE)
865 #define CODEGEN_USE_HEAP
866 #endif
867 #if defined(ARCH_PARISC) && defined(HAVE_GCC_ASSEMBLER)
868 #define CODEGEN_USE_HEAP
869 #endif
870 #if defined(ARCH_RISCV64) && defined(HAVE___BUILTIN___CLEAR_CACHE)
871 #define CODEGEN_USE_HEAP
872 #endif
873 #if defined(ARCH_S390)
874 #define CODEGEN_USE_HEAP
875 #endif
876 #if defined(ARCH_SPARC64) && defined(HAVE_GCC_ASSEMBLER)
877 #define CODEGEN_USE_HEAP
878 #endif
879 #if defined(ARCH_X86)
880 #define CODEGEN_USE_HEAP
881 #endif
882 #endif
884 #if defined(CODEGEN_USE_HEAP) && defined(DISABLE_RWX_MAPPINGS)
885 #undef CODEGEN_USE_HEAP
886 #endif
888 #define CODE_ALIGNMENT 16
891 #ifdef attr_unaligned
892 #if defined(__i386__) || defined(__x86_64__) || defined(__ARM_FEATURE_UNALIGNED) || defined(__alpha__) || defined(__m68k__) || defined(__mips) || defined(__powerpc__) || defined(__s390__)
893 /* define if unaligned access to code array is faster then assembling the value from 16-bit code_t entries */
894 #define UNALIGNED_ACCESS
895 #endif
896 #endif
897 #if defined(__i386__) || defined(__x86_64__) || defined(__ARM_FEATURE_UNALIGNED) || defined(__m68k__) || defined(__powerpc__) || defined(__s390__)
898 /* define if unaligned access results in the same instructions as aligned access */
899 #define UNALIGNED_ACCESS_EFFICIENT
900 #endif
903 #ifdef THREAD_NONE
904 #define SMP_ALIAS_ALIGNMENT 1
905 #else
906 #define SMP_ALIAS_ALIGNMENT 128
907 #ifdef __SANITIZE_THREAD__
908 #define THREAD_SANITIZER
909 #endif
910 #endif
913 #ifdef UNUSUAL_ARITHMETICS
914 #define DIVIDE_ROUNDS_TO_ZERO 0
915 #define RIGHT_SHIFT_KEEPS_SIGN 0
916 #else
917 #define DIVIDE_ROUNDS_TO_ZERO ((intmax_t)9 / -4 == -2 && \
918 (intmax_t)-9 / 4 == -2 && \
919 (intmax_t)-9 / -4 == 2 && \
920 (intmax_t)9 % -4 == 1 && \
921 (intmax_t)-9 % 4 == -1 && \
922 (intmax_t)-9 % -4 == -1)
923 #define RIGHT_SHIFT_KEEPS_SIGN ((~(intmax_t)0x1234U >> 1) == ~(intmax_t)0x91aU)
924 #endif
927 /* Define if volatile access to pointer, uintptr_t and uint32_t is atomic */
928 #if (SIZEOF_UNSIGNED >= 4 || defined(THREAD_NONE)) && !defined(THREAD_SANITIZER)
929 #define POINTERS_ARE_ATOMIC
930 #endif
933 #define BAD_POINTER_1 ((void *)(uintptr_t)1)
934 #define BAD_POINTER_2 ((void *)(uintptr_t)2)
935 #define BAD_POINTER_3 ((void *)(uintptr_t)3)
936 #define SPECIAL_POINTER_1 BAD_POINTER_1
937 #define SPECIAL_POINTER_2 BAD_POINTER_2
938 #define SPECIAL_POINTER_3 BAD_POINTER_3
939 #if !defined(UNUSUAL_NO_TAGGED_POINTERS) && !defined(UNUSUAL_NO_ARCH_TAGGED_POINTERS)
940 #if defined(HAVE_POINTER_TAGS) && defined(__aarch64__) && !defined(__ILP32__)
941 #define POINTER_IGNORE_START 56
942 #define POINTER_IGNORE_BITS 8
943 #elif defined(HAVE_POINTER_TAGS) && defined(__s390__) && !defined(__LP64__)
944 #define POINTER_IGNORE_START 31
945 #define POINTER_IGNORE_BITS 1
946 #else
947 #define POINTER_TAG_BIT 0
948 #define POINTER_TAG ((uintptr_t)1 << POINTER_TAG_BIT)
949 #endif
950 #endif
952 #ifdef POINTER_TAG
953 static inline void *POINTER_TAG_ADD(void *ptr)
955 return (void *)((uintptr_t)ptr + POINTER_TAG);
957 static inline void *POINTER_TAG_CLEAR(void *ptr)
959 return (void *)((uintptr_t)ptr & ~(uintptr_t)POINTER_TAG);
961 static inline void *POINTER_TAG_SUB(void *ptr)
963 return (void *)((uintptr_t)ptr - POINTER_TAG);
965 static inline uintptr_t POINTER_TAG_GET(const void *ptr)
967 return (uintptr_t)ptr & POINTER_TAG;
969 #endif
970 #ifdef POINTER_IGNORE_START
971 #define POINTER_IGNORE_TOP_BIT (POINTER_IGNORE_START + POINTER_IGNORE_BITS - 1)
972 #define POINTER_IGNORE_MASK ((((uintptr_t)1 << POINTER_IGNORE_BITS) - 1) << POINTER_IGNORE_START)
973 #define POINTER_IGNORE_TOP ((uintptr_t)1 << POINTER_IGNORE_TOP_BIT)
974 #endif
977 #ifdef __ICC
978 #define CLZ_BSR_OP -
979 #else
980 #define CLZ_BSR_OP ^
981 #endif
983 #if defined(HAVE_REAL_GNUC) && defined(__mips_isa_rev) && __mips_isa_rev >= 6
984 #define broken_128bit_multiply volatile
985 #else
986 #define broken_128bit_multiply
987 #endif