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