#ifndef _MACROS_H #define _MACROS_H #ifdef __cplusplus #include #include #define $CXX 1 #define $C 0 #else #include #define $CXX 0 #define $C 1 #endif // Empty token #define $NULL #if $CXX // C++ #define LINK_START(C) extern #C { #define LINK_END } #define restrict __restrict__ #define $auto __auto_type #define typeof(...) decltype(__VA_ARGS__) #define $typeof(...) __typeof__(__VA_ARGS__) #define $LIKELY(expr) __builtin_expect(bool(expr), true) #define $UNLIKELY(expr) __builtin_expect(bool(expr), false) #else // C #define $LIKELY(expr) __builtin_expect((bool)(expr), true) #define $UNLIKELY(expr) __builtin_expect((bool)(expr), false) #define auto __auto_type #define $auto __auto_type #define LINK_START(_) #define LINK_END #define nullptr ((void*)0) #define $typeof __typeof__ #define alignof _Alignof #define static_assert _Static_assert #define alignas(...) __attribute__((aligned(__VA_ARGS__))) #endif #define unrestrict __attribute__((__may_alias__)) #define ASSUME(X) ({ if(!(X)) __builtin_unreachable(); (void)0; }) #if $CXX #define $READ_ONCE_FROM(...) [&] () noexcept -> auto { using cvx_t = ::std::add_pointer_t<::std::add_const_t<::std::add_volatile_t>>; \ return *static_cast(::std::addressof(__VA_ARGS__)); \ }() #define $WRITE_ONCE_TO(X, value) [&] () noexcept -> decltype(auto) { using vx_t = ::std::add_pointer_t<::std::add_volatile_t>; \ static_assert(::std::is_convertible_v())>, "Cannot convert " #value " to assign to " #X); \ return *static_cast(::std::addressof(X)) = ::std::forward(value); \ }() #else #define $READ_ONCE_FROM(X) ({ $auto $__read_once_from = (X); *((const volatile $typeof($__read_once_from)*)(&$__read_once_from)); }) #define $WRITE_ONCE_TO(X, value) ({ $auto $__write_once_to = (X); *((volatile $typeof($__write_once_to)*)(&$__write_once_to)) = (value); }) #endif #define $identity_type(...) $typeof(__VA_ARGS__) #define $TRANSMUTE(T, expr) \ ({ $auto $__expr_from = (expr); \ static_assert(sizeof(typeof($__expr_from)) == sizeof(T) \ && alignof(typeof($__expr_from)) == alignof(typeof($__expr_from)), "Transmute source type does not have identical layout to dest type " #T); \ union { typeof($__expr_from) from; $typeof(T) to; } $__rec = { .from = $__expr_from; }; \ $__rec.to; }) #if $CXX #define TRANSMUTE(T, ...) ::std::bit_cast<$typeof(T)>(__VA_ARGS__) #else #define TRANSMUTE(T, ...) $TRANSMUTE(T, __VA_ARGS__) #endif #define $__int_width_ #define $int(N) $identity_type(_BitInt(N)) #define $sint(N) $identity_type(signed _BitInt(N)) #define $uint(N) $identity_type(unsigned _BitInt(N)) #if !defined(_MACROS_HH) && defined(__cplusplus) #include "macros.hh" #endif #endif /* _MACROS_H */