1/* @title: Type-Generic Compiler Wrappers */
2#pragma once
3#include <compiler/core.h>
4#include <compiler/intrinsic.h>
5
6#define cw_alloc_0() cc_malloc_like cc_warn_unused_result
7#define cw_alloc_1(sz) cw_alloc_0() cc_alloc_size(sz)
8#define cw_alloc_2(sz, align) cw_alloc_1(sz) cc_alloc_align(align)
9
10#define cw_alloc(...) PP_CALL2(cw_alloc, __VA_ARGS__)
11
12#define cw_popcount(x) \
13 cc_generic((x), unsigned char : ci_popcount((unsigned int) (x)), \
14 signed char : ci_popcount((unsigned int) (unsigned char) (x)), \
15 char : ci_popcount((unsigned int) (unsigned char) (x)), \
16 unsigned short : ci_popcount((unsigned int) (x)), \
17 short : ci_popcount((unsigned int) (unsigned short) (x)), \
18 unsigned int : ci_popcount(x), \
19 int : ci_popcount((unsigned int) (x)), \
20 unsigned long : ci_popcountl(x), \
21 long : ci_popcountl((unsigned long) (x)), \
22 unsigned long long : ci_popcountll(x), \
23 long long : ci_popcountll((unsigned long long) (x)), \
24 default : ci_popcountll((unsigned long long) (x)))
25
26#define cw_bswap16(x) ci_bswap16(x)
27#define cw_bswap32(x) ci_bswap32(x)
28#define cw_bswap64(x) ci_bswap64(x)
29
30#define cw_bswap(x) \
31 cc_generic((x), uint16_t : ci_bswap16(x), \
32 int16_t : (int16_t) ci_bswap16((uint16_t) (x)), \
33 uint32_t : ci_bswap32(x), \
34 int32_t : (int32_t) ci_bswap32((uint32_t) (x)), \
35 uint64_t : ci_bswap64(x), \
36 int64_t : (int64_t) ci_bswap64((uint64_t) (x)), \
37 default : (sizeof(x) == 2 ? ci_bswap16((uint16_t) (x)) \
38 : sizeof(x) == 4 ? ci_bswap32((uint32_t) (x)) \
39 : sizeof(x) == 8 ? ci_bswap64((uint64_t) (x)) \
40 : (x)))
41
42/*
43 * Count Leading Zeros
44 */
45#define cw_clz(x) \
46 ({ \
47 __auto_type __cw_clz_x = (x); \
48 ct_typecheck_unsigned_as(__cw_clz_x, x); \
49 __cw_clz_x == 0 ? (unsigned int) ct_bitsizeof(__cw_clz_x) \
50 : sizeof(__cw_clz_x) <= sizeof(unsigned int) \
51 ? (unsigned int) (ci_clz((unsigned int) __cw_clz_x) - \
52 (ct_bitsizeof(unsigned int) - \
53 ct_bitsizeof(__cw_clz_x))) \
54 : sizeof(__cw_clz_x) <= sizeof(unsigned long) \
55 ? (unsigned int) (ci_clzl((unsigned long) __cw_clz_x) - \
56 (ct_bitsizeof(unsigned long) - \
57 ct_bitsizeof(__cw_clz_x))) \
58 : (unsigned int) ci_clzll((unsigned long long) __cw_clz_x); \
59 })
60
61/*
62 * Count Leading Zeros
63 */
64#define cw_clz_nonzero(x) \
65 ({ \
66 __auto_type __cw_clzn_x = (x); \
67 ct_typecheck_unsigned_as(__cw_clzn_x, x); \
68 sizeof(__cw_clzn_x) <= sizeof(unsigned int) \
69 ? (unsigned int) (ci_clz((unsigned int) __cw_clzn_x) - \
70 (ct_bitsizeof(unsigned int) - \
71 ct_bitsizeof(__cw_clzn_x))) \
72 : sizeof(__cw_clzn_x) <= sizeof(unsigned long) \
73 ? (unsigned int) (ci_clzl((unsigned long) __cw_clzn_x) - \
74 (ct_bitsizeof(unsigned long) - \
75 ct_bitsizeof(__cw_clzn_x))) \
76 : (unsigned int) ci_clzll((unsigned long long) __cw_clzn_x); \
77 })
78
79/*
80 * Count Trailing Zeros
81 */
82#define cw_ctz(x) \
83 ({ \
84 __auto_type __cw_ctz_x = (x); \
85 ct_typecheck_unsigned_as(__cw_ctz_x, x); \
86 __cw_ctz_x == 0 \
87 ? (unsigned int) ct_bitsizeof(__cw_ctz_x) \
88 : (sizeof(__cw_ctz_x) <= sizeof(unsigned int) \
89 ? (unsigned int) ci_ctz((unsigned int) __cw_ctz_x) \
90 : sizeof(__cw_ctz_x) <= sizeof(unsigned long) \
91 ? (unsigned int) ci_ctzl((unsigned long) __cw_ctz_x) \
92 : (unsigned int) ci_ctzll( \
93 (unsigned long long) __cw_ctz_x)); \
94 })
95
96/* Fast Count Trailing Zeros: requires x != 0 */
97#define cw_ctz_nonzero(x) \
98 ({ \
99 __auto_type __cw_ctzn_x = (x); \
100 ct_typecheck_unsigned_as(__cw_ctzn_x, x); \
101 sizeof(__cw_ctzn_x) <= sizeof(unsigned int) \
102 ? (unsigned int) ci_ctz((unsigned int) __cw_ctzn_x) \
103 : sizeof(__cw_ctzn_x) <= sizeof(unsigned long) \
104 ? (unsigned int) ci_ctzl((unsigned long) __cw_ctzn_x) \
105 : (unsigned int) ci_ctzll((unsigned long long) __cw_ctzn_x); \
106 })
107
108/* Find First Set (1-based index, 0 if none) */
109#define cw_ffs(x) \
110 ({ \
111 __auto_type __cw_ffs_x = (x); \
112 ct_typecheck_integer_as(__cw_ffs_x, x); \
113 sizeof(__cw_ffs_x) <= sizeof(unsigned int) \
114 ? (unsigned int) ci_ffs((int) __cw_ffs_x) \
115 : sizeof(__cw_ffs_x) <= sizeof(unsigned long) \
116 ? (unsigned int) ci_ffsl((long) __cw_ffs_x) \
117 : (unsigned int) ci_ffsll((long long) __cw_ffs_x); \
118 })
119
120/* Find Last Set (1-based index, 0 if none) */
121#define cw_fls(x) \
122 ({ \
123 __auto_type __cw_fls_x = (x); \
124 ct_typecheck_unsigned_as(__cw_fls_x, x); \
125 __cw_fls_x == 0 ? 0u \
126 : (unsigned int) (ct_bitsizeof(__cw_fls_x) - \
127 cw_clz_nonzero(__cw_fls_x)); \
128 })
129
130#define cw_parity(x) \
131 cc_generic( \
132 (x), unsigned char : ci_parity((unsigned int) (x)), \
133 signed char : ci_parity((unsigned int) (unsigned char) (x)), \
134 char : ci_parity((unsigned int) (unsigned char) (x)), \
135 unsigned short : ci_parity((unsigned int) (x)), \
136 short : ci_parity((unsigned int) (unsigned short) (x)), \
137 unsigned int : ci_parity(x), int : ci_parity((unsigned int) (x)), \
138 unsigned long : ci_parityl(x), long : ci_parityl((unsigned long) (x)), \
139 unsigned long long : ci_parityll(x), \
140 long long : ci_parityll((unsigned long long) (x)), \
141 default : ci_parityll((unsigned long long) (x)))
142
143#define cw_rol(x, n) \
144 ({ \
145 __auto_type __cw_rol_x = (x); \
146 __auto_type __cw_rol_n = (n); \
147 ct_typecheck_unsigned_as(__cw_rol_x, x); \
148 ct_typecheck_integer_as(__cw_rol_n, n); \
149 unsigned int __cw_rol_shift = (unsigned int) __cw_rol_n; \
150 unsigned int __cw_rol_w = (unsigned int) ct_bitsizeof(__cw_rol_x); \
151 __cw_rol_shift &= (__cw_rol_w - 1u); \
152 (typeof(__cw_rol_x)) ((__cw_rol_x << __cw_rol_shift) | \
153 (__cw_rol_x >> ((__cw_rol_w - __cw_rol_shift) & \
154 (__cw_rol_w - 1u)))); \
155 })
156
157#define cw_ror(x, n) \
158 ({ \
159 __auto_type __cw_ror_x = (x); \
160 __auto_type __cw_ror_n = (n); \
161 ct_typecheck_unsigned_as(__cw_ror_x, x); \
162 ct_typecheck_integer_as(__cw_ror_n, n); \
163 unsigned int __cw_ror_shift = (unsigned int) __cw_ror_n; \
164 unsigned int __cw_ror_w = (unsigned int) ct_bitsizeof(__cw_ror_x); \
165 __cw_ror_shift &= (__cw_ror_w - 1u); \
166 (typeof(__cw_ror_x)) ((__cw_ror_x >> __cw_ror_shift) | \
167 (__cw_ror_x << ((__cw_ror_w - __cw_ror_shift) & \
168 (__cw_ror_w - 1u)))); \
169 })
170
171#define cw_sat_add(a, b) \
172 ({ \
173 __auto_type __cw_sa_a = (a); \
174 __auto_type __cw_sa_b = (b); \
175 typeof(__cw_sa_a) __cw_sa_res; \
176 if (ci_add_overflow(__cw_sa_a, __cw_sa_b, &__cw_sa_res)) { \
177 __cw_sa_res = (__cw_sa_b > 0) ? ct_max_val(typeof(__cw_sa_a)) \
178 : ct_min_val(typeof(__cw_sa_a)); \
179 } \
180 __cw_sa_res; \
181 })
182
183#define cw_sat_sub(a, b) \
184 ({ \
185 __auto_type __cw_ss_a = (a); \
186 __auto_type __cw_ss_b = (b); \
187 typeof(__cw_ss_a) __cw_ss_res; \
188 if (ci_sub_overflow(__cw_ss_a, __cw_ss_b, &__cw_ss_res)) { \
189 __cw_ss_res = (__cw_ss_b > 0) ? ct_min_val(typeof(__cw_ss_a)) \
190 : ct_max_val(typeof(__cw_ss_a)); \
191 } \
192 __cw_ss_res; \
193 })
194