codegen: move gen_imm from arch-specific files to codegen.c
[ajla.git] / common.h
blob48225fb630a0202a100dad11847d2a099eda7e3b
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 #define cat_(a, b) a##b
20 #define cat(a, b) cat_(a, b)
21 #define cat3(a, b, c) cat(a, cat(b, c))
22 #define cat4(a, b, c, d) cat(a, cat(b, cat(c, d)))
23 #define cat5(a, b, c, d, e) cat(a, cat(b, cat(c, cat(d, e))))
24 #define cat6(a, b, c, d, e, f) cat(a, cat(b, cat(c, cat(d, cat(e, f)))))
25 #define cat7(a, b, c, d, e, f, g) cat(a, cat(b, cat(c, cat(d, cat(e, cat(f, g))))))
27 #define n_array_elements(a) (sizeof(a) / sizeof(a[0]))
29 #ifndef __GNUC__
30 static const int zero = 0;
31 #else
32 static inline int zero_(void)
34 return 0;
36 #define zero (zero_())
37 #endif
38 #define uzero ((unsigned)zero)
40 #define round_down(x, y) ((x) & ~((y) - 1 + 0 * (x)))
41 #define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1 + 0 * (x)))
43 #define minimum(x, y) ((x) < (y) ? (x) : (y))
44 #define maximum(x, y) ((x) >= (y) ? (x) : (y))
45 #define maximum_maybe0(x, y) ((x) >= (y) + zero ? (x) : (y))
47 #define sign_bit(type) ((type)(-((type)1 << (8 * sizeof(type) - 2)) * 2))
48 #define signed_maximum(type) (~sign_bit(type))
49 #define is_unsigned(type) ((type)-1 >= 1)
51 #define is_power_of_2(x) ((x) && !((x) & ((x) - 1)))
53 static const size_t attr_unused size_t_limit = (size_t)-1; /* use const to avoid warning */
55 #ifndef DEBUG
56 #define ajla_assert(x, msg) ((void)zero)
57 #else
58 #define ajla_assert(x, msg) (likely(x) ? (void)0 : internal msg)
59 #endif
61 #ifndef DEBUG_LOW_OVERHEAD
62 #define ajla_assert_lo(x, msg) ((void)zero)
63 #else
64 #define ajla_assert_lo(x, msg) (likely(x) ? (void)0 : internal msg)
65 #endif
67 #define for_all_fixed0x_(macro)
68 #define for_all_fixed1x_(macro) for_all_fixed0x_(macro) macro(0, int8_t, uint8_t, 1, 8)
69 #define for_all_fixed2x_(macro) for_all_fixed1x_(macro) macro(1, int16_t, uint16_t, 2, 16)
70 #define for_all_fixed3x_(macro) for_all_fixed2x_(macro) macro(2, int32_t, uint32_t, 4, 32)
71 #define for_all_fixed4x_(macro) for_all_fixed3x_(macro) macro(3, int64_t, uint64_t, 8, 64)
72 #define for_all_fixed5x_(macro) for_all_fixed4x_(macro) macro(4, int128_t, uint128_t, 16, 128)
73 #define for_all_fixed(macro) cat3(for_all_fixed,TYPE_FIXED_N,x_)(macro)
75 #define for_all_empty(n, t)
77 #if INT_MASK & 0x1
78 #define for_all_int1x_(m, mn) m(0, int8_t, uint8_t, 1, 8)
79 #else
80 #define for_all_int1x_(m, mn) mn(0, int8_t)
81 #endif
82 #if INT_MASK & 0x2
83 #define for_all_int2x_(m, mn) for_all_int1x_(m, mn) m(1, int16_t, uint16_t, 2, 16)
84 #else
85 #define for_all_int2x_(m, mn) for_all_int1x_(m, mn) mn(1, int16_t)
86 #endif
87 #if INT_MASK & 0x4
88 #define for_all_int3x_(m, mn) for_all_int2x_(m, mn) m(2, int32_t, uint32_t, 4, 32)
89 #else
90 #define for_all_int3x_(m, mn) for_all_int2x_(m, mn) mn(2, int32_t)
91 #endif
92 #if INT_MASK & 0x8
93 #define for_all_int4x_(m, mn) for_all_int3x_(m, mn) m(3, int64_t, uint64_t, 8, 64)
94 #else
95 #define for_all_int4x_(m, mn) for_all_int3x_(m, mn) mn(3, int64_t)
96 #endif
97 #if INT_MASK & 0x10
98 #define for_all_int5x_(m, mn) for_all_int4x_(m, mn) m(4, int128_t, uint128_t, 16, 128)
99 #else
100 #define for_all_int5x_(m, mn) for_all_int4x_(m, mn) mn(4, int128_t)
101 #endif
102 #define for_all_int(m, mn) cat3(for_all_int,TYPE_INT_N,x_)(m, mn)
104 #define for_all_real0x_(m, mn)
105 #if REAL_MASK & 0x1
106 #define for_all_real1x_(m, mn) for_all_real0x_(m, mn) m(0, real16_t, native_real16_t, pack_real16_t, unpack_real16_t)
107 #else
108 #define for_all_real1x_(m, mn) for_all_real0x_(m, mn) mn(0, real16_t)
109 #endif
110 #if REAL_MASK & 0x2
111 #define for_all_real2x_(m, mn) for_all_real1x_(m, mn) m(1, real32_t, native_real32_t, pack_real32_t, unpack_real32_t)
112 #else
113 #define for_all_real2x_(m, mn) for_all_real1x_(m, mn) mn(1, real32_t)
114 #endif
115 #if REAL_MASK & 0x4
116 #define for_all_real3x_(m, mn) for_all_real2x_(m, mn) m(2, real64_t, native_real64_t, pack_real64_t, unpack_real64_t)
117 #else
118 #define for_all_real3x_(m, mn) for_all_real2x_(m, mn) mn(2, real64_t)
119 #endif
120 #if REAL_MASK & 0x8
121 #define for_all_real4x_(m, mn) for_all_real3x_(m, mn) m(3, real80_t, native_real80_t, pack_real80_t, unpack_real80_t)
122 #else
123 #define for_all_real4x_(m, mn) for_all_real3x_(m, mn) mn(3, real80_t)
124 #endif
125 #if REAL_MASK & 0x10
126 #define for_all_real5x_(m, mn) for_all_real4x_(m, mn) m(4, real128_t, native_real128_t, pack_real128_t, unpack_real128_t)
127 #else
128 #define for_all_real5x_(m, mn) for_all_real4x_(m, mn) mn(4, real128_t)
129 #endif
130 #define for_all_real(m, mn) cat3(for_all_real,TYPE_REAL_N,x_)(m, mn)
133 static inline unsigned low_bit(unsigned x)
135 #if defined(HAVE_BUILTIN_CTZ)
136 return __builtin_ctz(x);
137 #elif defined(HAVE_FFS)
138 return ffs(x) - 1;
139 #else
140 unsigned ret = 0;
141 while (1) {
142 if (x & 1)
143 break;
144 x >>= 1;
145 ret++;
147 return ret;
148 #endif
151 static inline unsigned high_bit(unsigned x)
153 #if defined(HAVE_BUILTIN_CLZ)
154 return sizeof(unsigned) * 8 - 1 - __builtin_clz(x);
155 #elif defined(HAVE_FLS)
156 return fls(x) - 1;
157 #else
158 unsigned ret = (unsigned)-1;
159 do {
160 ret++;
161 x >>= 1;
162 } while (x);
163 return ret;
164 #endif
167 static inline unsigned log_2(unsigned x)
169 ajla_assert(is_power_of_2(x), (file_line, "log_2: value %u is not a power of 2", x));
170 return low_bit(x);
173 static inline int pop_count(unsigned x)
175 #if defined(HAVE_BUILTIN_POPCOUNT)
176 return __builtin_popcount(x);
177 #else
178 int ret = 0;
179 while (x)
180 x &= x - 1, ret++;
181 return ret;
182 #endif
185 #if 1
186 #define assert_alignment(ptr, align) \
187 (ajla_assert(is_power_of_2(align), (file_line, "assert_alignment: value %" PRIuMAX " is not a power of 2", (uintmax_t)(align))),\
188 ajla_assert(!((uintptr_t)(ptr) & ((align) - 1)), (file_line, "assert_alignment: pointer %p is not aligned on %" PRIuMAX "", (void *)(ptr), (uintmax_t)(align))),\
189 __builtin_assume_aligned(ptr, align))
190 #else
191 #define assert_alignment(ptr, align) (__builtin_assume_aligned(ptr, align))
192 #endif
194 #define get_struct_(ptr, str, entry) (cast_ptr(str *, (cast_ptr(char *, (ptr)) - offsetof(str, entry))))
195 #define get_struct(ptr, str, entry) ((void)sizeof(&get_struct_(ptr, str, entry)->entry == (ptr)), get_struct_(ptr, str, entry))
197 static inline uintptr_t ptr_to_num(const void *ptr)
199 return (uintptr_t)ptr;
202 static inline void *num_to_ptr(uintptr_t num)
204 return (void *)num;
207 #define binary_search(t, n, result, equal, less, not_found) \
208 do { \
209 t start_ = 0; \
210 t end_ = (n); \
211 while (1) { \
212 t diff_ = end_ - start_; \
213 if (unlikely(!diff_)) { \
214 (result) = start_; \
215 not_found; \
216 not_reached(); \
218 (result) = start_ + (diff_ >> 1); \
219 if (unlikely(equal)) { \
220 break; \
222 if (less) { \
223 start_ = (result) + 1; \
224 } else { \
225 end_ = (result); \
228 } while (0)