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