I have the following code:
static _Atomic float testf;
void func() {
testf=1.0f;
float f=testf;
printf("%f\n", f);
}
Running it causes the program to hit a Debug Assert, Invalid memory order, at vcruntime_c11_atomic_support.h:417. (MSVC version 19.37.32822.0).
I'm not that familiar with x64 calling conventions, but it looks like the generated assembly isn't calling either one of _Atomic_store32 or _Atomic_load32 correctly:
inline void _Atomic_store32(volatile int* _Ptr, int _Desired, int _Order);
inline int _Atomic_load32(const volatile int* _Ptr, int _Order);
; 41 : testf=1.0f;
mov r8d, 5 ; !!This seems to be _Order, corresponding to _Atomic_memory_order_seq_cst
movss xmm1, DWORD PTR __real@3f800000
lea rcx, OFFSET FLAT:testf
call _Atomic_store32 ; !!Where is EDX? That should contain _Desired.
; 42 : float f=testf;
movss xmm1, DWORD PTR __real@40a00000
lea rcx, OFFSET FLAT:testf
call _Atomic_load32 ; !!EDX should have _Order.
movss DWORD PTR f$[rsp], xmm0
Is MSVC atomic support bugged, or am I doing something wrong?
Looks like a compiler bug from that asm output.
It's like the compiler wants to call _Atomic_store32(void*, float)
since it's passing the second arg in XMM1. But that's the same function it uses for integers, I assume, so yeah the actual arg needs to be in EDX. Treating it like a variadic function would work for the Win x64 calling convention, since those functions need XMM args to be copied to the corresponding integer reg.
For the load, movss xmm1, DWORD PTR __real@40a00000
is loading a float constant with bit-pattern 0x40a00000
into the second arg-passing register (for FP args). That bit-pattern represents 5.0f
, so MSVC has got itself very confused about something, doing _Atomic_load32(&testf, (float)memory_order_seq_cst)
with those arg types.
Emitting code like that is definitely a sign of a compiler bug. (And nice job constructing a minimal test-case and showing the relevant asm. You could submit this exact example to MS's compiler team and they'd very quickly see the symptoms of something being wrong.)