HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
src
hikogui
macros.hpp
1
// Copyright Take Vos 2023.
2
// Distributed under the Boost Software License, Version 1.0.
3
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5
#ifndef HI_ASSERT_HPP
6
#define HI_ASSERT_HPP
7
8
#define HI_OS_WINDOWS 'W'
9
#define HI_OS_MACOS 'A'
10
#define HI_OS_MOBILE 'M'
11
#define HI_OS_OTHER 'O'
12
13
#if defined(_WIN32)
14
#define HI_OPERATING_SYSTEM HI_OS_WINDOWS
15
#elif defined(TARGET_OS_MAC) and not defined(TARGET_OS_IPHONE)
16
#define HI_OPERATING_SYSTEM HI_OS_MACOS
17
#elif defined(TARGET_OS_IPHONE) or defined(__ANDROID__)
18
#define HI_OPERATING_SYSTEM HI_OS_MOBILE
19
#else
20
#define HI_OPERATING_SYSTEM HI_OS_OTHER
21
#endif
22
23
#define HI_CC_MSVC 'm'
24
#define HI_CC_GCC 'g'
25
#define HI_CC_CLANG 'c'
26
27
#if defined(__clang__)
28
#define HI_COMPILER HI_CC_CLANG
29
#elif defined(_MSC_BUILD)
30
#define HI_COMPILER HI_CC_MSVC
31
#elif defined(__GNUC__)
32
#define HI_COMPILER HI_CC_GCC
33
#else
34
#error "Could not detect the compiler."
35
#endif
36
37
#define HI_CPU_X86 'i'
38
#define HI_CPU_X64 'I'
39
#define HI_CPU_ARM 'a'
40
#define HI_CPU_ARM64 'A'
41
#define HI_CPU_UNKNOWN '-'
42
43
#if defined(__amd64__) or defined(__amd64) or defined(__x86_64__) or defined(__x86_64) or defined(_M_AMD64) or defined(_M_X64)
44
#define HI_PROCESSOR HI_CPU_X64
45
#elif defined(__aarch64__) or defined(_M_ARM64)
46
#define HI_PROCESSOR HI_CPU_ARM64
47
#elif defined(__i386__) or defined(_M_IX86)
48
#define HI_PROCESSOR HI_CPU_X86
49
#elif defined(__arm__) or defined(__arm) or defeind(_ARM) or defined(_M_ARM)
50
#define HI_PROCESSOR HI_CPU_ARM
51
#else
52
#define HI_PROCESSOR HI_CPU_UNKNOWN
53
#endif
54
55
#if defined(__AVX512BW__) and defined(__AVX512CD__) and defined(__AVX512DQ__) and defined(__AVX512F__) and defined(__AVX512VL__)
56
#define HI_X86_64_LEVEL 4
57
#elif defined(__AVX2__)
58
#define HI_X86_64_LEVEL 3
59
#elif defined(__SSE4_2__) and defined(__SSSE3__)
60
#define HI_X86_64_LEVEL 2
61
#elif HI_PROCESSOR == HI_CPU_X64
62
#define HI_X86_64_LEVEL 1
63
#endif
64
65
#if defined(HI_X86_64_MAX_LEVEL) and defined(HI_X86_64_LEVEL) and HI_X86_64_MAX_LEVEL < HI_X86_64_LEVEL
66
#undef HI_X86_64_LEVEL
67
#define HI_X86_64_LEVEL HI_X86_64_MAX_LEVEL
68
#endif
69
70
#if defined(HI_X86_64_LEVEL) and HI_X86_64_LEVEL >= 4
71
#define HI_HAS_AVX512F 1
72
#define HI_HAS_AVX512BW 1
73
#define HI_HAS_AVX512CD 1
74
#define HI_HAS_AVX512DQ 1
75
#define HI_HAS_AVX512VL 1
76
#endif
77
78
#if defined(HI_X86_64_LEVEL) and HI_X86_64_LEVEL >= 3
79
#define HI_HAS_AVX 1
80
#define HI_HAS_AVX2 1
81
#define HI_HAS_BMI1 1
82
#define HI_HAS_BMI2 1
83
#define HI_HAS_F16C 1
84
#define HI_HAS_FMA 1
85
#define HI_HAS_LZCNT 1
86
#define HI_HAS_MOVBE 1
87
#define HI_HAS_OSXSAVE 1
88
#endif
89
90
#if defined(HI_X86_64_LEVEL) and HI_X86_64_LEVEL >= 2
91
#define HI_HAS_CMPXCHG16B 1
92
#define HI_HAS_LAHF_SAHF 1
93
#define HI_HAS_POPCNT 1
94
#define HI_HAS_SSE3 1
95
#define HI_HAS_SSE4_1 1
96
#define HI_HAS_SSE4_2 1
97
#define HI_HAS_SSSE3 1
98
#endif
99
100
#if defined(HI_X86_64_LEVEL) and HI_X86_64_LEVEL >= 1
101
#define HI_HAS_CMOV 1
102
#define HI_HAS_CX8 1
103
#define HI_HAS_FPU 1
104
#define HI_HAS_FXSR 1
105
#define HI_HAS_MMX 1
106
#define HI_HAS_OSFXSR 1
107
#define HI_HAS_SCE 1
108
#define HI_HAS_SSE 1
109
#define HI_HAS_SSE2 1
110
#endif
111
112
#if HI_COMPILER == HI_CC_CLANG
113
#define hi_assume(condition) __builtin_assume(to_bool(condition))
114
#define hi_force_inline inline __attribute__((always_inline))
115
#define hi_no_inline __attribute__((noinline))
116
#define hi_restrict __restrict__
117
#define hi_warning_push() _Pragma("warning(push)")
118
#define hi_warning_pop() _Pragma("warning(push)")
119
#define hi_warning_ignore_msvc(code)
120
#define hi_warning_ignore_clang(a) _Pragma(hi_stringify(clang diagnostic ignored a))
121
122
#elif HI_COMPILER == HI_CC_MSVC
123
#define hi_assume(condition) __assume(condition)
124
#define hi_force_inline __forceinline
125
#define hi_no_inline __declspec(noinline)
126
#define hi_restrict __restrict
127
#define hi_warning_push() _Pragma("warning( push )")
128
#define hi_warning_pop() _Pragma("warning( pop )")
129
#define hi_msvc_pragma(a) _Pragma(a)
130
#define hi_warning_ignore_msvc(code) _Pragma(hi_stringify(warning(disable : code)))
131
#define hi_warning_ignore_clang(a)
132
133
#elif HI_COMPILER == HI_CC_GCC
134
#define hi_assume(condition) \
135
do { \
136
if (!(condition)) \
137
std::unreachable(); \
138
} while (false)
139
#define hi_force_inline inline __attribute__((always_inline))
140
#define hi_no_inline __attribute__((noinline))
141
#define hi_restrict __restrict__
142
#define hi_warning_push() _Pragma("warning(push)")
143
#define hi_warning_pop() _Pragma("warning(pop)")
144
#define hi_msvc_pragma(a)
145
#define hi_warning_ignore_clang(a)
146
#define msvc_pragma(a)
147
148
#else
149
#define hi_assume(condition) static_assert(sizeof(condition) == 1)
150
#define hi_force_inline inline
151
#define hi_no_inline
152
#define hi_restrict
153
#define hi_warning_push()
154
#define hi_warning_pop()
155
#define hi_msvc_pragma(a)
156
#define hi_warning_ignore_clang(a)
157
#define msvc_pragma(a)
158
#endif
159
162
#ifndef hi_export_module
163
#define hi_export_module(x)
164
#endif
165
168
#ifndef hi_export
169
#define hi_export
170
#endif
171
178
#ifndef hilet
179
#define hilet auto const
180
#endif
181
184
#ifndef hi_forward
185
#define hi_forward(x) std::forward<decltype(x)>(x)
186
#endif
187
194
#define hi_return_if_valid(expression) \
195
do { \
196
if constexpr (requires { expression; }) { \
197
return expression; \
198
} \
199
} while (false)
200
201
// One clang-format off is not enough to stop clang-format to format.
202
// clang-format off
203
#define hi_num_va_args_impl( \
204
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
205
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
206
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
207
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
208
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
209
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
210
_61,_62,_63,N,...) N
211
#define hi_num_va_args_(...) hi_num_va_args_impl(__VA_ARGS__)
212
// clang-format on
213
219
// clang-format off
220
#define hi_num_va_args(...) hi_num_va_args_(__VA_ARGS__ __VA_OPT__(,) \
221
63,62,61,60, \
222
59,58,57,56,55,54,53,52,51,50, \
223
49,48,47,46,45,44,43,42,41,40, \
224
39,38,37,36,35,34,33,32,31,30, \
225
29,28,27,26,25,24,23,22,21,20, \
226
19,18,17,16,15,14,13,12,11,10, \
227
9,8,7,6,5,4,3,2,1,0)
228
// clang-format on
229
230
#define hi_parans ()
231
232
#define hi_expand1(...) __VA_ARGS__
233
#define hi_expand2(...) hi_expand1(hi_expand1(hi_expand1(hi_expand1(__VA_ARGS__))))
234
#define hi_expand3(...) hi_expand2(hi_expand2(hi_expand2(hi_expand2(__VA_ARGS__))))
235
#define hi_expand4(...) hi_expand3(hi_expand3(hi_expand3(hi_expand3(__VA_ARGS__))))
236
241
#define hi_expand(...) hi_expand4(hi_expand4(hi_expand4(hi_expand4(__VA_ARGS__))))
242
243
#define hi_for_each_again() hi_for_each_helper
244
#define hi_for_each_helper(macro, first_arg, ...) macro(first_arg) __VA_OPT__(hi_for_each_again hi_parans(macro, __VA_ARGS__))
245
251
#define hi_for_each(macro, ...) __VA_OPT__(hi_expand(hi_for_each_helper(macro, __VA_ARGS__)))
252
253
#define hi_stringify_(x) #x
254
#define hi_stringify(x) hi_stringify_(x)
255
256
#define hi_cat_(a, b) a##b
257
#define hi_cat(a, b) hi_cat_(a, b)
258
259
#define hi_return_on_self_assignment(other) \
260
if (&(other) == this) [[unlikely]] \
261
return *this;
262
272
#define hi_get_overloaded_macro2(_1, _2, name, ...) name
273
280
#if defined(_WIN32)
281
#define hi_debug_break() \
282
do { \
283
if (::hi::prepare_debug_break()) { \
284
__debugbreak(); \
285
} \
286
} while (false)
287
#else
288
#error Missing implementation of hi_debug_break().
289
#endif
290
301
#if defined(_WIN32)
302
#define hi_debug_abort(...) \
303
do { \
304
::hi::prepare_debug_break(__FILE__ ":" hi_stringify(__LINE__) ":" __VA_ARGS__); \
305
__debugbreak(); \
306
} while (false)
307
#else
308
#error Missing implementation of hi_debug_abort().
309
#endif
310
321
#define hi_check(expression, message, ...) \
322
do { \
323
if (not(expression)) { \
324
if constexpr (__VA_OPT__(not ) false) { \
325
throw parse_error(std::format(message __VA_OPT__(, ) __VA_ARGS__)); \
326
} else { \
327
throw parse_error(message); \
328
} \
329
} \
330
} while (false)
331
343
#define hi_check_bounds(x, ...) \
344
do { \
345
if (not ::hi::bound_check(x, __VA_ARGS__)) { \
346
throw parse_error("assert bounds: " hi_stringify(x) " between " hi_for_each(hi_stringify, (__VA_ARGS__))); \
347
} \
348
} while (false)
349
362
#define hi_check_subspan(span, offset, ...) \
363
[&](auto _hi_check_subspan_span, size_t _hi_check_subspan_offset, auto... _hi_check_subspan_count) { \
364
if constexpr (sizeof...(_hi_check_subspan_count) == 0) { \
365
if (_hi_check_subspan_offset < _hi_check_subspan_span.size()) { \
366
return _hi_check_subspan_span.subspan(_hi_check_subspan_offset); \
367
} \
368
} else if constexpr (sizeof...(_hi_check_subspan_count) == 1) { \
369
if (_hi_check_subspan_offset + wide_cast<size_t>(_hi_check_subspan_count...) <= _hi_check_subspan_span.size()) { \
370
return _hi_check_subspan_span.subspan(_hi_check_subspan_offset, _hi_check_subspan_count...); \
371
} \
372
} \
373
throw parse_error( \
374
"assert bounds on: " hi_stringify(span) ".subspan(" hi_stringify(offset __VA_OPT__(", ") __VA_ARGS__) ")"); \
375
}(span, offset __VA_OPT__(, ) __VA_ARGS__)
376
387
#define hi_check_at(span, index) \
388
[&](auto _hi_check_subspan_span, size_t _hi_check_subspan_index) { \
389
if (_hi_check_subspan_index < _hi_check_subspan_span.size()) { \
390
return _hi_check_subspan_span[_hi_check_subspan_index]; \
391
} else { \
392
throw parse_error("assert bounds on: " hi_stringify(span) "[" hi_stringify(index) "]"); \
393
} \
394
}(span, index)
395
396
#define hi_hresult_check(expression) \
397
([](HRESULT result) { \
398
if (FAILED(result)) { \
399
throw ::hi::io_error(std::format("Call to '{}' failed with {:08x}", #expression, result)); \
400
} \
401
return result; \
402
}(expression))
403
410
#define hi_assert(expression, ...) \
411
do { \
412
if (not(expression)) { \
413
hi_debug_abort("assert: " __VA_ARGS__ " not (" hi_stringify(expression) ")"); \
414
} \
415
} while (false)
416
423
#define hi_assert_or_return(x, y) \
424
if (!(x)) { \
425
[[unlikely]] return y; \
426
}
427
436
#define hi_assert_bounds(x, ...) \
437
do { \
438
if (not ::hi::bound_check(x, __VA_ARGS__)) { \
439
hi_debug_abort("assert bounds: " hi_stringify(x) " between " hi_for_each(hi_stringify, (__VA_ARGS__))); \
440
} \
441
} while (false)
442
449
#define hi_assert_not_null(x, ...) \
450
do { \
451
if (x == nullptr) { \
452
hi_debug_abort("assert not-null: " __VA_ARGS__ " (" hi_stringify(x) ")"); \
453
} \
454
} while (false)
455
463
#ifndef NDEBUG
464
#define hi_axiom(expression, ...) hi_assert(expression __VA_OPT__(, ) __VA_ARGS__)
465
#else
466
#define hi_axiom(expression, ...) hi_assume(expression)
467
#endif
468
478
#ifndef NDEBUG
479
#define hi_axiom_bounds(x, ...) hi_assert_bounds(x, __VA_ARGS__)
480
#else
481
#define hi_axiom_bounds(x, ...) hi_assume(not ::hi::bound_check(x, __VA_ARGS__))
482
#endif
483
490
#ifndef NDEBUG
491
#define hi_axiom_not_null(expression, ...) hi_assert_not_null(expression __VA_OPT__(, ) __VA_ARGS__)
492
#else
493
#define hi_axiom_not_null(expression, ...) hi_assume(expression != nullptr)
494
#endif
495
501
#ifndef NDEBUG
502
#define hi_no_default(...) \
503
[[unlikely]] hi_debug_abort("Reached no-default:" __VA_ARGS__); \
504
std::terminate()
505
#else
506
#define hi_no_default(...) std::unreachable()
507
#endif
508
514
#define hi_static_no_default(...) \
515
[]<bool Flag = false>() \
516
{ \
517
static_assert(Flag, "No default: " __VA_ARGS__); \
518
} \
519
()
520
526
#define hi_not_implemented(...) \
527
[[unlikely]] hi_debug_abort("Not implemented: " __VA_ARGS__); \
528
std::terminate()
529
535
#define hi_static_not_implemented(...) hi_static_no_default("Not implemented: " __VA_ARGS__)
536
543
#define hi_print(fmt, ...) console_output(std::format(fmt __VA_OPT__(, ) __VA_ARGS__))
544
545
#define hi_format_argument_check(arg) \
546
static_assert( \
547
::std::is_default_constructible_v<std::formatter<std::decay_t<decltype(arg)>>>, \
548
"std::format, argument '" #arg "' does not have a specialized std::formatter<>.");
549
562
#define hi_format_check(fmt, ...) \
563
static_assert(::hi::format_count(fmt) != -1, "std::format, Unexpected '{' inside argument-format."); \
564
static_assert(::hi::format_count(fmt) != -2, "std::format, Unexpected '}' without corresponding '{'."); \
565
static_assert(::hi::format_count(fmt) != -3, "std::format, Missing '}' at end of format string."); \
566
static_assert( \
567
::hi::format_count(fmt) == hi_num_va_args(__VA_ARGS__), "std::format, invalid number of arguments for format string."); \
568
hi_for_each(hi_format_argument_check, __VA_ARGS__)
569
570
#define hi_log(level, fmt, ...) \
571
hi_format_check(fmt __VA_OPT__(, ) __VA_ARGS__); \
572
::hi::log_global.add<level, __FILE__, __LINE__, fmt>(__VA_ARGS__)
573
574
#define hi_log_debug(fmt, ...) hi_log(::hi::global_state_type::log_debug, fmt __VA_OPT__(, ) __VA_ARGS__)
575
#define hi_log_info(fmt, ...) hi_log(::hi::global_state_type::log_info, fmt __VA_OPT__(, ) __VA_ARGS__)
576
#define hi_log_statistics(fmt, ...) hi_log(::hi::global_state_type::log_statistics, fmt __VA_OPT__(, ) __VA_ARGS__)
577
#define hi_log_trace(fmt, ...) hi_log(::hi::global_state_type::log_trace, fmt __VA_OPT__(, ) __VA_ARGS__)
578
#define hi_log_audit(fmt, ...) hi_log(::hi::global_state_type::log_audit, fmt __VA_OPT__(, ) __VA_ARGS__)
579
#define hi_log_warning(fmt, ...) hi_log(::hi::global_state_type::log_warning, fmt __VA_OPT__(, ) __VA_ARGS__)
580
#define hi_log_error(fmt, ...) hi_log(::hi::global_state_type::log_error, fmt __VA_OPT__(, ) __VA_ARGS__)
581
#define hi_log_fatal(fmt, ...) \
582
hi_log(::hi::global_state_type::log_fatal, fmt __VA_OPT__(, ) __VA_ARGS__); \
583
hi_debug_abort(); \
584
std::terminate()
585
586
#define hi_log_info_once(name, fmt, ...) \
587
do { \
588
if (++::hi::global_counter<name> == 1) { \
589
hi_log(::hi::global_state_type::log_info, fmt __VA_OPT__(, ) __VA_ARGS__); \
590
} \
591
} while (false)
592
593
#define hi_log_error_once(name, fmt, ...) \
594
do { \
595
if (++::hi::global_counter<name> == 1) { \
596
hi_log(::hi::global_state_type::log_error, fmt __VA_OPT__(, ) __VA_ARGS__); \
597
} \
598
} while (false)
599
600
#endif
Generated on Mon Apr 22 2024 12:53:16 for HikoGUI by
1.10.0