For math functions as I'm not confident I would do a good job even for simple ones, I wanted to look how they are implemented in the CRT. I searched a little bit, and it seems that musl libc is well organized and easy to browse. So my idea was to make a header where I would copy the musl functions I needed.
But for some of those functions there seems to be intrinsics available. For example, floor, ceil, round, sqrt. Is there a reason to use the C functions instead of the intrinsics ? My only target is x64 with SSE 4.2. Will I encounter problem using the instrinsics, expecting them to behave like the CRT ?
A second issue I encountered is that my asserts don't work with stb libs.
My assert is simply:
1 | #define _assert( expression ) if ( !( expression ) ) { __debugbreak( ); }
|
But in the stb libs several "if"s don't use curly braces:
1 2 3 4 5 6 | if ( a ) stb_assert( expression_a ); else if ( b ) stb_assert( expression_b ); else stb_assert( expression_c ); |
Which, once expanded, produce:
1 2 3 4 5 6 7 8 9 10 | if ( a ) if ( expression_a ) { __debugbreak( ); }; else if ( b ) if ( expression_b ) { __debugbreak( ); }; else if ( expression_c ) { __debugbreak( ); }; |
There are 2 issues: the nesting of ifs are wrong; there is a semicolon between closing curly braces and "else". Is there some trick I can use to fix that ? The assert from MSVC assert.h looks like this:
1 2 3 4 5 6 7 8 9 10 11 | #ifdef __cplusplus extern "C" { #endif _CRTIMP void __cdecl _wassert(_In_z_ const wchar_t * _Message, _In_z_ const wchar_t *_File, _In_ unsigned _Line); #ifdef __cplusplus } #endif #define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) ) |
I tried to do
1 | #define _assert( expression ) ( ( expression ) || __debugbreak( ) )
|
and some variations with no success. I get the following error: error C2297: '||': illegal, right operand has type 'void' which I guess makes sense but why is it working in the MSVC code ? I don't understand what the MSVC macro is trying to do. It's casting something to void, it has "!!" which I guess just cancel itself, ... ?
musl has a similar macro. It also has the _Noreturn which is __attribute__((__noreturn__)), but I don't know the equivalent for MSVC or even if I can set that for __debugbreak( ) since it's an intrinsics to output int3 in the assembly.
1 2 3 4 5 6 7 8 9 10 11 | #define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__, __func__),0))) #ifdef __cplusplus extern "C" { #endif _Noreturn void __assert_fail (const char *, const char *, int, const char *); #ifdef __cplusplus } #endif |