Zth (libzth)
Loading...
Searching...
No Matches
macros.h
Go to the documentation of this file.
1#ifndef ZTH_MACROS_H
2#define ZTH_MACROS_H
3/*
4 * SPDX-FileCopyrightText: 2019-2026 Jochem Rutgers
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 */
8
9
10
12// Preamble
13//
14
15#ifdef _DEBUG
16# undef NDEBUG
17#endif
18#if !defined(_DEBUG) && !defined(NDEBUG)
19# define _DEBUG
20#endif
21
22#ifndef ZTH_THREADS
23# define ZTH_THREADS 1
24#endif
25
26#if !ZTH_THREADS && defined(ZTH_HAVE_LIBZMQ)
27# undef ZTH_THREADS
28# define ZTH_THREADS 1
29#endif
30
31
32
34// Compiler
35//
36
37#ifdef __clang_analyzer__
38// We don't use clang for compiling, but we do use clang-tidy.
39# define CLANG_TIDY
40#endif
41
42#if defined(__GNUC__) || defined(CLANG_TIDY)
43// This is gcc
44# ifdef __cplusplus
45# if __cplusplus < 201103L && !defined(decltype)
46# define decltype(x) \
47 __typeof__(x) // Well, not really true when references are
48 // involved...
49# endif
50# endif
51# if ZTH_THREADS
52# define ZTH_TLS_DECLARE(type, var) extern __thread type var;
53# define ZTH_TLS_DEFINE(type, var, init) __thread type var = init;
54# define ZTH_TLS_STATIC(type, var, init) static __thread type var = init;
55# define ZTH_TLS_STATIC_DEFAULT(type, var) static __thread type var;
56# define ZTH_TLS_MEMBER(type, var) static __thread type var;
57# define ZTH_TLS_SET(var, value) var = value
58# define ZTH_TLS_GET(var) var
59# endif
60# ifndef _GNU_SOURCE
61# define _GNU_SOURCE
62# endif
63# ifndef CLANG_TIDY
64# define ZTH_ATTR_PRINTF gnu_printf
65# endif
66# ifndef GCC_VERSION
67# define GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)
68# endif
69# if GCC_VERSION < 50000
70# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
71# endif
72# if GCC_VERSION >= 70000 && defined(__cplusplus) && __cplusplus < 201703L
73# pragma GCC diagnostic ignored "-Wnoexcept-type"
74# endif
75# if GCC_VERSION >= 130000 && GCC_VERSION < 140000 && defined(__cplusplus)
76# pragma GCC diagnostic ignored "-Wmismatched-new-delete"
77# endif
78# ifndef UNUSED_PAR
79# define UNUSED_PAR(name) name __attribute__((unused))
80# endif
81#else
82# error Unsupported compiler. Please use gcc.
83#endif
84
85#ifdef CPPCHECK
86# define __attribute__(x)
87#endif
88
89#if defined(__cplusplus) && __cplusplus >= 201703L
90# define ZTH_FALLTHROUGH [[fallthrough]];
91#elif GCC_VERSION >= 70000L
92# define ZTH_FALLTHROUGH __attribute__((fallthrough));
93#else
94# define ZTH_FALLTHROUGH
95#endif
96
97#ifndef ZTH_TLS_DECLARE
98# undef ZTH_THREADS
99# define ZTH_THREADS 0
100# define ZTH_TLS_DECLARE(type, var) extern type var;
101# define ZTH_TLS_DEFINE(type, var, init) type var = init;
102# define ZTH_TLS_STATIC(type, var, init) static type var = init;
103# define ZTH_TLS_STATIC_DEFAULT(type, var) static type var;
104# define ZTH_TLS_MEMBER(type, var) static type var;
105# define ZTH_TLS_SET(var, value) var = value
106# define ZTH_TLS_GET(var) var
107#endif
108
109#ifndef ZTH_ATTR_PRINTF
110# define ZTH_ATTR_PRINTF printf
111#endif
112
113#define __STDC_FORMAT_MACROS
114
115#ifndef EXTERN_C
116# ifdef __cplusplus
117# define EXTERN_C extern "C"
118# else
119# define EXTERN_C
120# endif
121#endif
122
123#if defined(ZTH_OS_WINDOWS) && defined(ZTH_SHARED_LIB) && ZTH_SHARED_LIB
124# if defined(ZTH_BUILD_LIB)
125# define ZTH_EXPORT __declspec(dllexport)
126# else
127# define ZTH_EXPORT __declspec(dllimport)
128# endif
129#endif // Windows DLL
130
131#ifndef ZTH_EXPORT
132# define ZTH_EXPORT __attribute__((visibility("default")))
133#endif
134
135#ifdef __cplusplus
136# ifdef ZTH_INLINE_EMIT
137# define ZTH_INLINE
138# else
139# define ZTH_INLINE __attribute__((gnu_inline)) inline
140# endif
141#else
142# define ZTH_INLINE __attribute__((gnu_inline)) extern inline
143#endif
144
145/*
146HOWTO inline:
147
148// Inline private C++-only function:
149#ifdef __cplusplus
150inline void foo() { baz::bar(); }
151#endif
152
153// Inline public C++-only function:
154#ifdef __cplusplus
155ZTH_EXPORT inline void foo() { baz::bar(); }
156#endif
157
158// Inline public C/C++ function:
159EXTERN_C ZTH_EXPORT ZTH_INLINE void foo() { bar(); }
160
161// Inline public C/C++ function with C++-only implementation:
162#ifdef __cplusplus
163EXTERN_C ZTH_EXPORT ZTH_INLINE void foo() { baz::bar(); }
164#else
165ZTH_EXPORT void foo();
166#endif
167*/
168
169#ifndef __cplusplus
170# ifndef noexcept
171# define noexcept
172# endif
173#elif __cplusplus < 201103L
174# ifndef constexpr
175# define constexpr
176# endif
177# ifndef constexpr14
178# define constexpr14
179# endif
180# ifndef override
181# define override
182# endif
183# ifndef final
184# define final
185# endif
186# ifndef is_default
187# define is_default \
188 {}
189# endif
190# ifndef noexcept
191# define noexcept throw()
192# endif
193# ifndef nullptr
194# define nullptr NULL
195# endif
196# ifndef alignas
197# define alignas(...) __attribute__((aligned(sizeof(void*))))
198# endif
199# ifndef LREF_QUALIFIED
200# define LREF_QUALIFIED
201# endif
202# ifndef inline17
203# define inline17 static
204# endif
205# ifndef static_assert
206# pragma GCC diagnostic ignored "-Wunused-local-typedefs"
207# define ZTH_STATIC_ASSERT_FAILED_(line) zth_static_assert_failed_##line
208# define ZTH_STATIC_ASSERT_FAILED(line) ZTH_STATIC_ASSERT_FAILED_(line)
209# define static_assert(x, ...) \
210 typedef char ZTH_STATIC_ASSERT_FAILED( \
211 __LINE__)[(x) ? 1 : -1] /* NOLINT(clang-diagnostic-vla-cxx-extension) \
212 */
213# endif
214#else
215# ifndef constexpr14
216# if __cplusplus < 201402L
217# define constexpr14
218# else
219# define constexpr14 constexpr
220# endif
221# endif
222# ifndef is_default
223# define is_default = default;
224# endif
225# ifndef LREF_QUALIFIED
226# define LREF_QUALIFIED &
227# endif
228# ifndef inline17
229# if __cplusplus < 201703L
230# define inline17 static
231# else
232# define inline17 inline
233# endif
234# endif
235#endif
236
237#if defined(__SANITIZE_ADDRESS__) && !defined(ZTH_ENABLE_ASAN)
238# define ZTH_ENABLE_ASAN
239#endif
240
241#if defined(ZTH_ALLOW_DEPRECATED)
242# define ZTH_DEPRECATED(...)
243#elif defined(__cplusplus) && __cplusplus >= 201402L
244# define ZTH_DEPRECATED(...) [[deprecated(__VA_ARGS__)]]
245#elif !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
246# define ZTH_DEPRECATED(...) [[deprecated(__VA_ARGS__)]]
247#else
248# define ZTH_DEPRECATED(...) __attribute__((deprecated))
249#endif
250
251
252
254// Hardware
255//
256
257#if defined(__x86_64__)
258# define ZTH_ARCH_X86_64 1
259#elif defined(__i386__)
260# define ZTH_ARCH_X86 1
261#elif defined(__aarch64__) && defined(__APPLE__)
262# define ZTH_ARCH_ARM64 1
263#elif defined(__arm__)
264# define ZTH_ARCH_ARM 1
265# if defined(__ARM_ARCH) && __ARM_ARCH >= 6 && defined(__ARM_ARCH_PROFILE) \
266 && __ARM_ARCH_PROFILE == 'M'
267# define ZTH_ARM_HAVE_MPU
268# endif
269# define __isb() __asm__ volatile("isb" ::: "memory")
270# define __dsb() __asm__ volatile("dsb" ::: "memory")
271# define __dmb() __asm__ volatile("dmb" ::: "memory")
272# define barrier() __dsb()
273#else
274# error Unsupported hardware platform.
275#endif
276
277#ifndef barrier
278# if GCC_VERSION < 40802L
279# define barrier() __sync_synchronize()
280# else
281# define barrier() __atomic_thread_fence()
282# endif
283#endif
284
285
286
288// OS
289//
290
291#if defined(_WIN32) || defined(__CYGWIN__)
292# define ZTH_OS_WINDOWS 1
293# define _WANT_IO_C99_FORMATS 1
294# define __USE_MINGW_ANSI_STDIO 1
295# define WIN32_LEAN_AND_MEAN
296# define NOGDI
297# if defined(UNICODE) || defined(_UNICODE)
298# error Do not use UNICODE. Use ANSI with UTF-8 instead.
299# endif
300# ifdef __CYGWIN__
301# define ZTH_HAVE_PTHREAD
302# endif
303// # define ZTH_HAVE_WINSOCK
304# ifdef ZTH_CONFIG_WRAP_IO
305# error ZTH_CONFIG_WRAP_IO is not supported on Windows.
306# endif
307#elif defined(__linux__) && !defined(ZTH_OS_BAREMETAL)
308# define ZTH_OS_LINUX 1
309# define ZTH_OS_POSIX 1
310// # define ZTH_HAVE_VALGRIND
311# define ZTH_HAVE_PTHREAD
312// # define ZTH_HAVE_LIBUNWIND
313# define ZTH_HAVE_POLL
314# define ZTH_HAVE_MMAN
315#elif defined(__APPLE__)
316# include <TargetConditionals.h>
317# ifdef TARGET_OS_MAC
318# define ZTH_OS_MAC 1
319# define ZTH_OS_POSIX 1
320# else
321# error Unsupported Apple platform.
322# endif
323# define ZTH_HAVE_PTHREAD
324# define ZTH_HAVE_POLL
325# define ZTH_HAVE_MMAN
326# include <Availability.h>
327# if __MAC_OS_X_VERSION_MAX_ALLOWED < 1012
328// OSX 10.12 includes clock_gettime(). Otherwise, implement it by Zth.
329# define ZTH_CUSTOM_CLOCK_GETTIME
330# endif
331#elif defined(ZTH_ARCH_ARM)
332// Assume having newlib
333# define ZTH_OS_BAREMETAL 1
334# define ZTH_CUSTOM_CLOCK_GETTIME
335# include <newlib.h>
336# ifndef NEWLIB_VERSION
337# define NEWLIB_VERSION (__NEWLIB__ * 10000L + __NEWLIB_MINOR__ * 100L + __NEWLIB_PATCHLEVEL__)
338# endif
339# ifndef ZTH_FORMAT_LIMITED
340# define ZTH_FORMAT_LIMITED 1
341# endif
342# ifdef __NEWLIB_NANO__
343# undef ZTH_HAVE_EXCEPTIONS
344# define ZTH_HAVE_EXCEPTIONS 0
345# endif
346#else
347# error Unsupported OS.
348#endif
349
350#if defined(_DEBUG) && defined(ZTH_HAVE_VALGRIND)
351# define ZTH_USE_VALGRIND
352#endif
353
354#if !ZTH_THREADS
355# undef ZTH_HAVE_PTHREAD
356#endif
357
358
359
361// Exception support
362//
363
364#if defined(__cplusplus) && defined(__cpp_exceptions)
365# ifndef ZTH_HAVE_EXCEPTIONS
366# define ZTH_HAVE_EXCEPTIONS 1
367# endif
368#else
369# undef ZTH_HAVE_EXCEPTIONS
370# define ZTH_HAVE_EXCEPTIONS 0
371#endif
372
373#if !ZTH_HAVE_EXCEPTIONS
374# define try if(true)
375# define catch(...) if(false)
376# define zth_throw(...) zth_terminate()
377#else
378# define zth_throw(...) throw __VA_ARGS__
379#endif
380
381
382
384// Context-switch approach
385//
386
387// We have the following approaches. If one of them is already defined, it is
388// used as preferred one, if compatible.
389//
390// - ZTH_CONTEXT_SIGALTSTACK
391// - ZTH_CONTEXT_SJLJ
392// - ZTH_CONTEXT_UCONTEXT
393// - ZTH_CONTEXT_WINFIBER
394
395#ifdef ZTH_OS_WINDOWS
396# ifndef ZTH_CONTEXT_WINFIBER
397# define ZTH_CONTEXT_WINFIBER
398# endif
399# undef ZTH_CONTEXT_SIGALTSTACK
400# undef ZTH_CONTEXT_SJLJ
401# undef ZTH_CONTEXT_UCONTEXT
402#elif defined(ZTH_OS_BAREMETAL)
403// Assume having newlib with setjmp/longjmp fiddling.
404# ifndef ZTH_CONTEXT_SJLJ
405# define ZTH_CONTEXT_SJLJ
406# endif
407# if defined(ZTH_ARCH_ARM) && defined(__ARM_ARCH) && __ARM_ARCH >= 6 \
408 && defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M'
409# define ZTH_ARM_USE_PSP
410# define ZTH_STACK_SWITCH
411# endif
412# undef ZTH_CONTEXT_SIGALTSTACK
413# undef ZTH_CONTEXT_UCONTEXT
414# undef ZTH_CONTEXT_WINFIBER
415#elif defined(ZTH_HAVE_VALGRIND)
416// Valgrind does not handle sigaltstack very well.
417# ifndef ZTH_CONTEXT_UCONTEXT
418# define ZTH_CONTEXT_UCONTEXT
419# endif
420# undef ZTH_CONTEXT_SIGALTSTACK
421# undef ZTH_CONTEXT_SJLJ
422# undef ZTH_CONTEXT_WINFIBER
423#else
424// Default approach is ucontext.
425# undef ZTH_CONTEXT_SJLJ
426# undef ZTH_CONTEXT_WINFIBER
427# if defined(ZTH_CONTEXT_UCONTEXT)
428# undef ZTH_CONTEXT_SIGALTSTACK
429# elif !defined(ZTH_CONTEXT_SIGALTSTACK) || defined(ZTH_ENABLE_ASAN)
430# undef ZTH_CONTEXT_SIGALTSTACK
431# define ZTH_CONTEXT_UCONTEXT
432# endif
433#endif
434
435#ifdef ZTH_CONTEXT_WINFIBER
436# ifndef WINVER
437# define WINVER 0x0501
438# elif WINVER < 0x0400
439# error WINVER should be at least 0x0400
440# endif
441# ifndef _WIN32_WINNT
442# define _WIN32_WINNT WINVER
443# elif _WIN32_WINNT < 0x0400
444# error _WIN32_WINNT should be at least 0x0400
445# endif
446#endif
447
448#endif // ZTH_MACROS_H