Monado OpenXR Runtime
xrt_compiler.h
Go to the documentation of this file.
1// Copyright 2019, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Header holding common defines.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @ingroup xrt_iface
8 */
9
10#pragma once
11
12
13/*
14 * C99 is not a high bar to reach.
15 */
16#include <stddef.h>
17#include <stdint.h>
18#include <stdbool.h>
19#include <inttypes.h>
20
21#ifdef _MSC_VER
22#include <intrin.h>
23// for atomic intrinsics
24#include "xrt_windows.h"
25// Older MSVC versions do not have stdalign.h, define it manually using __declspec(align).
26#define XRT_ALIGNAS(n) __declspec(align(n))
27#elif defined(XRT_DOXYGEN)
28#define XRT_ALIGNAS(align)
29#else // _MSC_VER
30#include <stdalign.h>
31#define XRT_ALIGNAS(align) alignas(align)
32#endif
33
34#if (defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) || \
35 (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
36 (defined(__STDC_ENDIAN_NATIVE__) && __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__) || defined(__BIG_ENDIAN__) || \
37 defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || \
38 defined(__MIBSEB__)
39
40#define XRT_BIG_ENDIAN
41
42#elif (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
43 (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
44 (defined(__STDC_ENDIAN_NATIVE__) && __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__) || \
45 defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
46 defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || defined(__x86_64__) || defined(_M_X64) || \
47 defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
48
49#undef XRT_BIG_ENDIAN
50
51#else
52#error "@todo: Unable to determine current architecture."
53#endif
54
55/*!
56 * Array size helper.
57 */
58#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
59
60#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_ARCH_PPC64) || defined(__s390x__) || \
61 (defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8)
62#define XRT_64_BIT
63#else
64#define XRT_32_BIT
65#endif
66
67/*
68 * Printf helper attribute.
69 */
70#if defined(__GNUC__)
71#define XRT_PRINTF_FORMAT(fmt, list) __attribute__((format(printf, fmt, list)))
72#else
73#define XRT_PRINTF_FORMAT(fmt, list)
74#endif
75
76
77/*
78 * To silence unused warnings.
79 */
80#if defined(__GNUC__)
81#define XRT_MAYBE_UNUSED __attribute__((unused))
82#elif defined(_MSC_VER) && defined(__cplusplus)
83#define XRT_MAYBE_UNUSED [[maybe_unused]]
84#else
85#define XRT_MAYBE_UNUSED
86#endif
87
88
89/*
90 * To make sure return values are checked.
91 */
92#if defined(__GNUC__) && (__GNUC__ >= 4)
93#define XRT_CHECK_RESULT __attribute__((warn_unused_result))
94#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
95#define XRT_CHECK_RESULT _Check_return_
96#else
97#define XRT_CHECK_RESULT
98#endif
99
100
101/*
102 * To stop inlining.
103 */
104#if defined(__GNUC__)
105#define XRT_NO_INLINE __attribute__((noinline))
106#elif defined(_MSC_VER)
107#define XRT_NO_INLINE __declspec(noinline)
108#else
109#define XRT_NO_INLINE
110#endif
111
112
113#ifdef XRT_DOXYGEN
114/*!
115 * To trigger a trap/break in the debugger.
116 *
117 * @ingroup xrt_iface
118 */
119#define XRT_DEBUGBREAK()
120#elif defined(__clang__) || defined(__GNUC__)
121#define XRT_DEBUGBREAK() __builtin_trap()
122#elif defined(_MSC_VER)
123#define XRT_DEBUGBREAK() __debugbreak()
124#else
125#error "compiler not supported"
126#endif
127
128
129
130typedef volatile int32_t xrt_atomic_s32_t;
131
132static inline int32_t
133xrt_atomic_s32_inc_return(xrt_atomic_s32_t *p)
134{
135#if defined(__GNUC__)
136 return __sync_add_and_fetch(p, 1);
137#elif defined(_MSC_VER)
138 return InterlockedIncrement((volatile LONG *)p);
139#else
140#error "compiler not supported"
141#endif
142}
143static inline int32_t
144xrt_atomic_s32_dec_return(xrt_atomic_s32_t *p)
145{
146#if defined(__GNUC__)
147 return __sync_sub_and_fetch(p, 1);
148#elif defined(_MSC_VER)
149 return InterlockedDecrement((volatile LONG *)p);
150#else
151#error "compiler not supported"
152#endif
153}
154static inline int32_t
155xrt_atomic_s32_cmpxchg(xrt_atomic_s32_t *p, int32_t old_, int32_t new_)
156{
157#if defined(__GNUC__)
158 return __sync_val_compare_and_swap(p, old_, new_);
159#elif defined(_MSC_VER)
160 return InterlockedCompareExchange((volatile LONG *)p, old_, new_);
161#else
162#error "compiler not supported"
163#endif
164}
165
166#ifdef _MSC_VER
167typedef intptr_t ssize_t;
168#define _SSIZE_T_
169#define _SSIZE_T_DEFINED
170#endif
171
172/*!
173 * Get the holder from a pointer to a field.
174 *
175 * @ingroup xrt_iface
176 */
177#define container_of(ptr, type, field) (type *)((char *)ptr - offsetof(type, field))
178
179
180#ifdef XRT_DOXYGEN
181
182/*!
183 * Very small default init for structs that works in both C and C++. Helps with
184 * code that needs to be compiled with both C and C++.
185 *
186 * @ingroup xrt_iface
187 */
188
189// clang-format off
190#define XRT_STRUCT_INIT {}
191// clang-format on
192
193#elif defined(__cplusplus)
194
195// clang-format off
196#define XRT_STRUCT_INIT {}
197// clang-format on
198
199#else
200
201// clang-format off
202#define XRT_STRUCT_INIT {0}
203// clang-format on
204
205#endif
206
207/*
208 * C11 style designated initializers (as compound literals) causes warning messages
209 * in C++ (even in C++20), usage:
210 *
211 * @code{.c}
212 * static inline struct xrt_foo_bar
213 * xrt_foo_bar_make()
214 * {
215 * return XRT_C11_COMPOUND(struct xrt_foo_bar){
216 * .x = y,
217 * // ...
218 * };
219 * }
220 * @endcode
221 */
222#ifdef __cplusplus
223#define XRT_C11_COMPOUND(X)
224#else
225#define XRT_C11_COMPOUND(X) (X)
226#endif
A minimal way to include Windows.h.