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#endif // _MSC_VER
26
27#if (defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) || \
28 (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
29 (defined(__STDC_ENDIAN_NATIVE__) && __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__) || defined(__BIG_ENDIAN__) || \
30 defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || \
31 defined(__MIBSEB__)
32
33#define XRT_BIG_ENDIAN
34
35#elif (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
36 (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
37 (defined(__STDC_ENDIAN_NATIVE__) && __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__) || \
38 defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
39 defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || defined(__x86_64__) || defined(_M_X64) || \
40 defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
41
42#undef XRT_BIG_ENDIAN
43
44#else
45#error "@todo: Unable to determine current architecture."
46#endif
47
48/*!
49 * Array size helper.
50 */
51#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
52
53#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_ARCH_PPC64) || defined(__s390x__) || \
54 (defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8)
55#define XRT_64_BIT
56#else
57#define XRT_32_BIT
58#endif
59
60/*
61 * Printf helper attribute.
62 */
63#if defined(__GNUC__)
64#define XRT_PRINTF_FORMAT(fmt, list) __attribute__((format(printf, fmt, list)))
65#else
66#define XRT_PRINTF_FORMAT(fmt, list)
67#endif
68
69
70/*
71 * To silence unused warnings.
72 */
73#if defined(__GNUC__)
74#define XRT_MAYBE_UNUSED __attribute__((unused))
75#elif defined(_MSC_VER) && defined(__cplusplus)
76#define XRT_MAYBE_UNUSED [[maybe_unused]]
77#else
78#define XRT_MAYBE_UNUSED
79#endif
80
81
82/*
83 * To make sure return values are checked.
84 */
85#if defined(__GNUC__) && (__GNUC__ >= 4)
86#define XRT_CHECK_RESULT __attribute__((warn_unused_result))
87#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
88#define XRT_CHECK_RESULT _Check_return_
89#else
90#define XRT_CHECK_RESULT
91#endif
92
93
94/*
95 * To stop inlining.
96 */
97#if defined(__GNUC__)
98#define XRT_NO_INLINE __attribute__((noinline))
99#elif defined(_MSC_VER)
100#define XRT_NO_INLINE __declspec(noinline)
101#else
102#define XRT_NO_INLINE
103#endif
104
105
106#ifdef XRT_DOXYGEN
107/*!
108 * To trigger a trap/break in the debugger.
109 *
110 * @ingroup xrt_iface
111 */
112#define XRT_DEBUGBREAK()
113#elif defined(__clang__) || defined(__GNUC__)
114#define XRT_DEBUGBREAK() __builtin_trap()
115#elif defined(_MSC_VER)
116#define XRT_DEBUGBREAK() __debugbreak()
117#else
118#error "compiler not supported"
119#endif
120
121
122
123typedef volatile int32_t xrt_atomic_s32_t;
124
125static inline int32_t
126xrt_atomic_s32_inc_return(xrt_atomic_s32_t *p)
127{
128#if defined(__GNUC__)
129 return __sync_add_and_fetch(p, 1);
130#elif defined(_MSC_VER)
131 return InterlockedIncrement((volatile LONG *)p);
132#else
133#error "compiler not supported"
134#endif
135}
136static inline int32_t
137xrt_atomic_s32_dec_return(xrt_atomic_s32_t *p)
138{
139#if defined(__GNUC__)
140 return __sync_sub_and_fetch(p, 1);
141#elif defined(_MSC_VER)
142 return InterlockedDecrement((volatile LONG *)p);
143#else
144#error "compiler not supported"
145#endif
146}
147static inline int32_t
148xrt_atomic_s32_cmpxchg(xrt_atomic_s32_t *p, int32_t old_, int32_t new_)
149{
150#if defined(__GNUC__)
151 return __sync_val_compare_and_swap(p, old_, new_);
152#elif defined(_MSC_VER)
153 return InterlockedCompareExchange((volatile LONG *)p, old_, new_);
154#else
155#error "compiler not supported"
156#endif
157}
158
159#ifdef _MSC_VER
160typedef intptr_t ssize_t;
161#define _SSIZE_T_
162#define _SSIZE_T_DEFINED
163#endif
164
165/*!
166 * Get the holder from a pointer to a field.
167 *
168 * @ingroup xrt_iface
169 */
170#define container_of(ptr, type, field) (type *)((char *)ptr - offsetof(type, field))
171
172
173#ifdef XRT_DOXYGEN
174
175/*!
176 * Very small default init for structs that works in both C and C++. Helps with
177 * code that needs to be compiled with both C and C++.
178 *
179 * @ingroup xrt_iface
180 */
181
182// clang-format off
183#define XRT_STRUCT_INIT {}
184// clang-format on
185
186#elif defined(__cplusplus)
187
188// clang-format off
189#define XRT_STRUCT_INIT {}
190// clang-format on
191
192#else
193
194// clang-format off
195#define XRT_STRUCT_INIT {0}
196// clang-format on
197
198#endif
A minimal way to include Windows.h.