MMgr
v1.0.0
Zero-heap memory manager in C11. One borrowed buffer, carved by asserted offset.
Loading...
Searching...
No Matches
mmgr_compiler_directives.h
1
/**
2
* @brief Preprocessor definitions; declares no type and defines no function.
3
*/
4
#ifndef MMGR_COMPILER_DIRECTIVES_H
5
#define MMGR_COMPILER_DIRECTIVES_H
6
7
#include <stddef.h>
8
9
/**
10
* @brief Set to 1 when __clang__ is defined, 0 otherwise.
11
*
12
* @note Defined on both branches, and so #ifdef MMGR_CC_CLANG is always true.
13
*/
14
#if defined(__clang__)
15
#define MMGR_CC_CLANG 1
16
#else
17
18
#define MMGR_CC_CLANG 0
19
#endif
20
21
/**
22
* @brief Set to 1 when __GNUC__ is defined and __clang__ is not, 0 otherwise.
23
*/
24
#if defined(__GNUC__) && !defined(__clang__)
25
#define MMGR_CC_GNU 1
26
#else
27
28
#define MMGR_CC_GNU 0
29
#endif
30
31
/**
32
* @brief Set to 1 when __GNUC__ or __clang__ is defined, 0 otherwise.
33
*
34
* @note Used as the fallback value of MMGR_HAS_ATTRIBUTE.
35
*/
36
#if defined(__GNUC__) || defined(__clang__)
37
#define MMGR_CC_GNU_ATTRS 1
38
#else
39
40
#define MMGR_CC_GNU_ATTRS 0
41
#endif
42
43
/**
44
* @brief Expands to __has_attribute(x) where __has_attribute is defined.
45
*
46
* @param[in] x Attribute name, as passed to __has_attribute.
47
* @return The value __has_attribute gives for x.
48
* @warning Expands to MMGR_CC_GNU_ATTRS where __has_attribute is undefined, ignoring x.
49
*/
50
#if defined(__has_attribute)
51
#define MMGR_HAS_ATTRIBUTE(x) __has_attribute(x)
52
#else
53
54
#define MMGR_HAS_ATTRIBUTE(x) MMGR_CC_GNU_ATTRS
55
#endif
56
57
/**
58
* @brief Expands to __has_builtin(x) where __has_builtin is defined.
59
*
60
* @param[in] x Builtin name, as passed to __has_builtin.
61
* @return The value __has_builtin gives for x.
62
* @warning Expands to 0 where __has_builtin is undefined, ignoring x.
63
*/
64
#if defined(__has_builtin)
65
#define MMGR_HAS_BUILTIN(x) __has_builtin(x)
66
#else
67
68
#define MMGR_HAS_BUILTIN(x) 0
69
#endif
70
71
/**
72
* @brief Expands to a two-operand static assertion.
73
*
74
* @param[in] cond Constant expression passed through unchanged.
75
* @param[in] msg Message operand passed through unchanged.
76
* @note static_assert where __cplusplus is defined or __STDC_VERSION__ >= 202311L.
77
* @note _Static_assert otherwise.
78
*/
79
#if defined(__cplusplus)
80
#define MMGR_STATIC_ASSERT(cond, msg) static_assert(cond, msg)
81
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
82
#define MMGR_STATIC_ASSERT(cond, msg) static_assert(cond, msg)
83
#else
84
85
#define MMGR_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
86
#endif
87
88
/**
89
* @brief Expands to extern "C" { where __cplusplus is defined.
90
*
91
* @warning The expansion contains an open {; MMGR_FINIS_DECLS supplies the }.
92
* @note Expands to nothing where __cplusplus is undefined.
93
*/
94
#ifdef __cplusplus
95
#define MMGR_INCIPE_DECLS \
96
extern "C" \
97
{
98
99
/** @brief Expands to } where __cplusplus is defined, closing MMGR_INCIPE_DECLS. */
100
#define MMGR_FINIS_DECLS }
101
#else
102
103
#define MMGR_INCIPE_DECLS
104
105
/** @brief Expands to nothing where __cplusplus is undefined. */
106
#define MMGR_FINIS_DECLS
107
#endif
108
109
/**
110
* @brief Expands to a##b.
111
*
112
* @param[in] a Left operand of ##.
113
* @param[in] b Right operand of ##.
114
* @return The single token formed by joining a and b.
115
* @note Called by MMGR_CAT.
116
*/
117
#define MMGR_CAT_(a, b) a##b
118
119
/**
120
* @brief Expands to MMGR_CAT_(a, b).
121
*
122
* @param[in] a Left operand, forwarded to MMGR_CAT_.
123
* @param[in] b Right operand, forwarded to MMGR_CAT_.
124
* @return The single token formed by joining a and b.
125
* @note Builds a macro name from a count, as in MMGR_NS_LAYOUT and mmgr_carcer_init.
126
*/
127
#define MMGR_CAT(a, b) MMGR_CAT_(a, b)
128
129
/**
130
* @brief Expands to MMGR_NARG_ with __VA_ARGS__ followed by the constants 24 down to 0.
131
*
132
* @param[in] ... The list to count.
133
* @return The number of arguments, for one to twenty-four arguments.
134
* @warning An empty list gives 1.
135
* @warning Twenty-five or more arguments make MMGR_ARG_N select an argument instead of a constant.
136
*/
137
#define MMGR_NARG(...) \
138
MMGR_NARG_(__VA_ARGS__, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
139
/**
140
* @brief Expands to MMGR_ARG_N(__VA_ARGS__).
141
*
142
* @param[in] ... The list from MMGR_NARG, followed by the constants 24 down to 0.
143
* @return The value MMGR_ARG_N selects.
144
* @note Called by MMGR_NARG.
145
*/
146
#define MMGR_NARG_(...) MMGR_ARG_N(__VA_ARGS__)
147
148
/**
149
* @brief Expands to its twenty-fifth argument.
150
*
151
* @param[in] _1 Arguments one through twenty-four, discarded.
152
* @param[in] N The twenty-fifth argument.
153
* @param[in] ... Arguments beyond the twenty-fifth, discarded.
154
* @return N.
155
*/
156
#define MMGR_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, \
157
_22, _23, _24, N, ...) \
158
N
159
160
/**
161
* @brief Expands to backend(&(ArgsType){__VA_ARGS__}).
162
*
163
* @param[in] backend Function called with the address of the literal.
164
* @param[in] ArgsType Type of the compound literal.
165
* @param[in] ... Initializers for the compound literal.
166
* @return The value backend returns.
167
* @warning backend receives the address of the literal [BORROWS].
168
*/
169
#define MMGR_CALL(backend, ArgsType, ...) backend(&(ArgsType){__VA_ARGS__})
170
171
/**
172
* @brief Expands to sizeof(void (*)(void)).
173
*
174
* @note Multiplied by a loculus index in MMGR_NS_LOCULUS, and by the member count in the two layout macros.
175
*/
176
#define MMGR_FP_SIZE (sizeof(void (*)(void)))
177
178
/**
179
* @brief Expands to MMGR_STATIC_ASSERT that offsetof(T, member) equals loculus * MMGR_FP_SIZE.
180
*
181
* @param[in] T Struct type passed to offsetof.
182
* @param[in] member Member name passed to offsetof.
183
* @param[in] loculus Index, cast to size_t and multiplied by MMGR_FP_SIZE.
184
* @note T, member and loculus are stringized into the assertion message.
185
*/
186
#define MMGR_NS_LOCULUS(T, member, loculus) \
187
MMGR_STATIC_ASSERT(offsetof(T, member) == (size_t)(loculus) * MMGR_FP_SIZE, \
188
#T "." #member " is not at dispatch loculus " #loculus)
189
190
/**
191
* @brief MMGR_NS_L1 to MMGR_NS_L24 expand to one MMGR_NS_LOCULUS per member, at indices 0 upward.
192
*
193
* @param[in] T Struct type forwarded to MMGR_NS_LOCULUS.
194
* @param[in] a Member names in order; a takes index 0, b takes index 1.
195
* @note MMGR_NS_L<n> expands MMGR_NS_L<n-1> before its own MMGR_NS_LOCULUS.
196
* @warning Selected by MMGR_NS_LAYOUT through MMGR_CAT on the argument count.
197
*/
198
#define MMGR_NS_L1(T, a) MMGR_NS_LOCULUS(T, a, 0);
199
#define MMGR_NS_L2(T, a, b) MMGR_NS_L1(T, a) MMGR_NS_LOCULUS(T, b, 1);
200
#define MMGR_NS_L3(T, a, b, c) MMGR_NS_L2(T, a, b) MMGR_NS_LOCULUS(T, c, 2);
201
#define MMGR_NS_L4(T, a, b, c, d) MMGR_NS_L3(T, a, b, c) MMGR_NS_LOCULUS(T, d, 3);
202
#define MMGR_NS_L5(T, a, b, c, d, e) MMGR_NS_L4(T, a, b, c, d) MMGR_NS_LOCULUS(T, e, 4);
203
#define MMGR_NS_L6(T, a, b, c, d, e, f) MMGR_NS_L5(T, a, b, c, d, e) MMGR_NS_LOCULUS(T, f, 5);
204
#define MMGR_NS_L7(T, a, b, c, d, e, f, g) MMGR_NS_L6(T, a, b, c, d, e, f) MMGR_NS_LOCULUS(T, g, 6);
205
#define MMGR_NS_L8(T, a, b, c, d, e, f, g, h) MMGR_NS_L7(T, a, b, c, d, e, f, g) MMGR_NS_LOCULUS(T, h, 7);
206
#define MMGR_NS_L9(T, a, b, c, d, e, f, g, h, i) MMGR_NS_L8(T, a, b, c, d, e, f, g, h) MMGR_NS_LOCULUS(T, i, 8);
207
#define MMGR_NS_L10(T, a, b, c, d, e, f, g, h, i, j) MMGR_NS_L9(T, a, b, c, d, e, f, g, h, i) MMGR_NS_LOCULUS(T, j, 9);
208
#define MMGR_NS_L11(T, a, b, c, d, e, f, g, h, i, j, k) \
209
MMGR_NS_L10(T, a, b, c, d, e, f, g, h, i, j) MMGR_NS_LOCULUS(T, k, 10);
210
#define MMGR_NS_L12(T, a, b, c, d, e, f, g, h, i, j, k, l) \
211
MMGR_NS_L11(T, a, b, c, d, e, f, g, h, i, j, k) MMGR_NS_LOCULUS(T, l, 11);
212
#define MMGR_NS_L13(T, a, b, c, d, e, f, g, h, i, j, k, l, m) \
213
MMGR_NS_L12(T, a, b, c, d, e, f, g, h, i, j, k, l) MMGR_NS_LOCULUS(T, m, 12);
214
#define MMGR_NS_L14(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
215
MMGR_NS_L13(T, a, b, c, d, e, f, g, h, i, j, k, l, m) MMGR_NS_LOCULUS(T, n, 13);
216
#define MMGR_NS_L15(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
217
MMGR_NS_L14(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n) MMGR_NS_LOCULUS(T, o, 14);
218
#define MMGR_NS_L16(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
219
MMGR_NS_L15(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) MMGR_NS_LOCULUS(T, p, 15);
220
#define MMGR_NS_L17(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
221
MMGR_NS_L16(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) MMGR_NS_LOCULUS(T, q, 16);
222
#define MMGR_NS_L18(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) \
223
MMGR_NS_L17(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) MMGR_NS_LOCULUS(T, r, 17);
224
#define MMGR_NS_L19(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) \
225
MMGR_NS_L18(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) MMGR_NS_LOCULUS(T, s, 18);
226
#define MMGR_NS_L20(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) \
227
MMGR_NS_L19(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) MMGR_NS_LOCULUS(T, t, 19);
228
#define MMGR_NS_L21(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) \
229
MMGR_NS_L20(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) MMGR_NS_LOCULUS(T, u, 20);
230
#define MMGR_NS_L22(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) \
231
MMGR_NS_L21(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) MMGR_NS_LOCULUS(T, v, 21);
232
#define MMGR_NS_L23(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) \
233
MMGR_NS_L22(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) MMGR_NS_LOCULUS(T, w, 22);
234
#define MMGR_NS_L24(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) \
235
MMGR_NS_L23(T, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) MMGR_NS_LOCULUS(T, x, 23);
236
237
/**
238
* @brief Expands the matching MMGR_NS_L, then asserts sizeof(T) equals the member count times MMGR_FP_SIZE.
239
*
240
* @param[in] T Struct type forwarded to MMGR_NS_L and to sizeof.
241
* @param[in] ... Member names in loculus order, one to twenty-four.
242
* @note MMGR_NARG(__VA_ARGS__) is cast to size_t before the multiply.
243
* @warning Any size other than the member count times MMGR_FP_SIZE fails the assertion.
244
*/
245
#define MMGR_NS_LAYOUT(T, ...) \
246
MMGR_CAT(MMGR_NS_L, MMGR_NARG(__VA_ARGS__))(T, __VA_ARGS__) \
247
MMGR_STATIC_ASSERT(sizeof(T) == (size_t)MMGR_NARG(__VA_ARGS__) * MMGR_FP_SIZE, \
248
#T " has a member that is not in its dispatch list, or is padded")
249
250
/**
251
* @brief Expands to static const.
252
*
253
* @note Used to declare the dispatch tables, such as ascii, spat and clz.
254
*/
255
#define MMGR_NS static const
256
257
/**
258
* @brief Expands to __attribute__((flatten)) where MMGR_HAS_ATTRIBUTE(flatten) is non-zero.
259
*
260
* @note For a caller and not for the library. It asks the compiler to inline everything the function it
261
* marks calls, which reaches an entry body that the inliner would otherwise leave out of line
262
* on size. The entries are large enough that it does leave them: measured on an ESP32-S3, a
263
* cellul.len over eight bytes costs 112 cycles called and 80 inlined, and so the call is 32 of
264
* them - a third of the work at that length, and it is paid on every entry.
265
* @note Worth it where an extent is short and settled before the build, as this library
266
* is for. A long scan amortizes the call and will not notice: the same measurement at 64 bytes
267
* is 253 against 240.
268
* @note Costs the walk's code at every site that takes it, and so it belongs on the one hot function a
269
* caller cares about and not on a translation unit.
270
* @warning Needs the entry body visible. A build without link-time optimization gets nothing from
271
* it. See MMGR_LTO.
272
* @warning Expands to nothing where MMGR_HAS_ATTRIBUTE(flatten) is 0, which costs speed and never
273
* correctness.
274
*/
275
#if MMGR_HAS_ATTRIBUTE(flatten)
276
#define MMGR_FLATTEN __attribute__((flatten))
277
#else
278
279
#define MMGR_FLATTEN
280
#endif
281
282
/**
283
* @brief Expands to __attribute__((packed)) where MMGR_HAS_ATTRIBUTE(packed) is non-zero, and to the
284
* fixed underlying type `: unsigned char` for a C++ compiler without it.
285
*
286
* @note The C++ arm is nvcc over MSVC, which a .cu reaching MMgr on Windows compiles under. C++11 made
287
* the fixed underlying type standard.
288
* @warning On the C++ arm the width is one byte whatever the range, and therefore an enumerator past 255 or below
289
* 0 fails the build there.
290
* @warning Expands to nothing where MMGR_HAS_ATTRIBUTE(packed) is 0 in C.
291
* @note mmgr_types.h asserts sizeof(MmgrEnumProbe) == 1 to catch that case.
292
*/
293
#if MMGR_HAS_ATTRIBUTE(packed)
294
#define MMGR_ENUM_PACKED __attribute__((packed))
295
#elif defined(__cplusplus)
296
#define MMGR_ENUM_PACKED : unsigned char
297
#else
298
299
#define MMGR_ENUM_PACKED
300
#endif
301
302
/**
303
* @brief Expands to __attribute__((aligned(n))) where MMGR_HAS_ATTRIBUTE(aligned) is non-zero.
304
*
305
* @param[in] n Alignment operand passed to the attribute.
306
* @warning Expands to nothing where MMGR_HAS_ATTRIBUTE(aligned) is 0, ignoring n.
307
*/
308
#if MMGR_HAS_ATTRIBUTE(aligned)
309
#define MMGR_ALIGN(n) __attribute__((aligned(n)))
310
#else
311
312
#define MMGR_ALIGN(n)
313
#endif
314
315
/**
316
* @brief Expands to __attribute__((may_alias)) where MMGR_HAS_ATTRIBUTE(may_alias) is non-zero.
317
*
318
* @warning Expands to nothing where MMGR_HAS_ATTRIBUTE(may_alias) is 0.
319
*/
320
#if MMGR_HAS_ATTRIBUTE(may_alias)
321
#define MMGR_ALIAS __attribute__((may_alias))
322
#else
323
324
#define MMGR_ALIAS
325
#endif
326
327
/**
328
* @brief Expands to __attribute__((unused)) where MMGR_HAS_ATTRIBUTE(unused) is non-zero.
329
*
330
* @warning Expands to nothing where MMGR_HAS_ATTRIBUTE(unused) is 0.
331
*/
332
#if MMGR_HAS_ATTRIBUTE(unused)
333
#define MMGR_UNUSED __attribute__((unused))
334
#else
335
336
#define MMGR_UNUSED
337
#endif
338
339
/**
340
* @brief Expands to __attribute__((weak)) where MMGR_HAS_ATTRIBUTE(weak) is non-zero.
341
*
342
* @warning Expands to nothing where MMGR_HAS_ATTRIBUTE(weak) is 0.
343
*/
344
#if MMGR_HAS_ATTRIBUTE(weak)
345
#define MMGR_WEAK __attribute__((weak))
346
#else
347
348
#define MMGR_WEAK
349
#endif
350
351
/**
352
* @brief Expands to static inline __attribute__((always_inline)).
353
*
354
* @note Expands to static inline where MMGR_HAS_ATTRIBUTE(always_inline) is 0.
355
* @warning Neither definition is made when MMGR_INLINE is already defined.
356
*/
357
#ifndef MMGR_INLINE
358
#if MMGR_HAS_ATTRIBUTE(always_inline)
359
#define MMGR_INLINE static inline __attribute__((always_inline))
360
#else
361
#define MMGR_INLINE static inline
362
#endif
363
#endif
364
365
/**
366
* @brief Expands to _Pragma(#directive) where MMGR_CC_GNU is non-zero.
367
*
368
* @param[in] directive Pragma text, stringized by #.
369
* @warning Expands to nothing where MMGR_CC_GNU is 0, ignoring directive.
370
*/
371
#if MMGR_CC_GNU
372
#define MMGR_TU_PRAGMA(directive) _Pragma(#directive)
373
#else
374
375
#define MMGR_TU_PRAGMA(directive)
376
#endif
377
378
/**
379
* @brief Expands to MMGR_TU_PRAGMA(GCC optimize("O2")).
380
*
381
* @warning Expands to nothing where MMGR_CC_GNU is 0, through MMGR_TU_PRAGMA.
382
*/
383
#define MMGR_OPTIMIZE_O2 MMGR_TU_PRAGMA(GCC optimize("O2"))
384
385
#if defined(__clang__)
386
/** @brief Expands to _Pragma("clang diagnostic push") where __clang__ is defined. */
387
#define MMGR_DIAG_PUSH _Pragma("clang diagnostic push")
388
389
/** @brief Expands to _Pragma("clang diagnostic pop") where __clang__ is defined. */
390
#define MMGR_DIAG_POP _Pragma("clang diagnostic pop")
391
392
/**
393
* @brief Expands to _Pragma(MMGR_DIAG_STR(clang diagnostic ignored w)) where __clang__ is defined.
394
*
395
* @param[in] w Warning name as a string literal, such as "-Wpadded".
396
* @note MMGR_DIAG_STR stringizes the whole pragma text, including w.
397
*/
398
#define MMGR_DIAG_IGNORE(w) _Pragma(MMGR_DIAG_STR(clang diagnostic ignored w))
399
400
/**
401
* @brief Expands to #x.
402
*
403
* @param[in] x Token sequence to stringize.
404
* @return x as a string literal.
405
* @note Called by MMGR_DIAG_IGNORE.
406
*/
407
#define MMGR_DIAG_STR(x) #x
408
#elif defined(__GNUC__)
409
/** @brief Expands to _Pragma("GCC diagnostic push") where __GNUC__ is defined and __clang__ is not. */
410
#define MMGR_DIAG_PUSH _Pragma("GCC diagnostic push")
411
412
/** @brief Expands to _Pragma("GCC diagnostic pop") where __GNUC__ is defined and __clang__ is not. */
413
#define MMGR_DIAG_POP _Pragma("GCC diagnostic pop")
414
415
/**
416
* @brief Expands to #x.
417
*
418
* @param[in] x Token sequence to stringize.
419
* @return x as a string literal.
420
* @note Called by MMGR_DIAG_IGNORE.
421
*/
422
#define MMGR_DIAG_STR(x) #x
423
424
/**
425
* @brief Expands to _Pragma(MMGR_DIAG_STR(GCC diagnostic ignored w)).
426
*
427
* @param[in] w Warning name as a string literal, such as "-Wpadded".
428
* @note Selected where __GNUC__ is defined and __clang__ is not.
429
* @note MMGR_DIAG_STR stringizes the whole pragma text, including w.
430
*/
431
#define MMGR_DIAG_IGNORE(w) _Pragma(MMGR_DIAG_STR(GCC diagnostic ignored w))
432
#else
433
434
/** @brief Expands to nothing when __clang__ and __GNUC__ are both undefined. */
435
#define MMGR_DIAG_PUSH
436
437
/** @brief Expands to nothing when __clang__ and __GNUC__ are both undefined. */
438
#define MMGR_DIAG_POP
439
440
/**
441
* @brief Expands to nothing when __clang__ and __GNUC__ are both undefined.
442
*
443
* @param[in] w Warning name as a string literal, discarded.
444
*/
445
#define MMGR_DIAG_IGNORE(w)
446
#endif
447
448
/**
449
* @brief Set to 1 when __BYTE_ORDER__ and __ORDER_BIG_ENDIAN__ are both defined and equal, 0 otherwise.
450
*
451
* @warning Neither definition is made when MMGR_HW_BIG_ENDIAN is already defined.
452
*/
453
#ifndef MMGR_HW_BIG_ENDIAN
454
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
455
#define MMGR_HW_BIG_ENDIAN 1
456
#else
457
458
#define MMGR_HW_BIG_ENDIAN 0
459
#endif
460
#endif
461
462
/**
463
* @brief Set to 1 when the target loads a word from any address in one instruction, 0 otherwise.
464
*
465
* @note Not whether an unaligned load compiles - every target here accepts one through
466
* mmgr_proxim_word_t, which carries MMGR_ALIGN(1). It is whether the hardware does it, or the
467
* compiler assembles it out of byte loads and shifts. Measured on one such load: ARMv7-M emits
468
* a single ldr, Xtensa twelve instructions and RISC-V eleven.
469
* @note The difference decides which of two shapes is faster in a scan that needs the word at an
470
* offset of one. Where a load is a single instruction, take it; where it is a dozen, derive
471
* the word from the one already in hand and a byte.
472
* @note __ARM_FEATURE_UNALIGNED is the compiler's own answer for ARM, and is switched off by
473
* -mno-unaligned-access. x86 is stated directly, having no equivalent macro.
474
* @warning Neither definition is made when MMGR_HW_FAST_UNALIGNED is already defined.
475
*/
476
#ifndef MMGR_HW_FAST_UNALIGNED
477
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__x86_64__) || defined(__i386__)
478
#define MMGR_HW_FAST_UNALIGNED 1
479
#else
480
481
#define MMGR_HW_FAST_UNALIGNED 0
482
#endif
483
#endif
484
485
#endif
src
config
mmgr_compiler_directives.h
MMgr v1.0.0
·
github.com/dstroy0/MMgr
·
AGPL-3.0-or-later
·
Generated by doxygen 1.18.0