On Monday, 22 August 2016 at 04:52:40 UTC, Cauterite wrote:
On Monday, 22 August 2016 at 04:37:50 UTC, stunaep wrote:
I made a union to convert between int bits and floats, but the values are coming out wrong sometimes.

I can already tell what this is going to be...
The problem is almost certainly nothing to do with your union, it's this line:
float t2 = t.f;
This will load 0x7fb00000 into ST(0), which instantly converts it to 7FF00000 because it's a signalling NaN, then store ST(0) in your float `t2`.

Signalling NaNs are an ongoing problem in D's codegen. See Don's remarks at this page: https://issues.dlang.org/show_bug.cgi?id=16105#c2

The reason it works in other languages is because they don't place floats in the floating point registers for non-arithmetic operations. I've been trying to patch DMD's backend to behave this way too, but it's much harder than I expected (difficult codebase to understand/navigate).

That's a 32 bit codegen issue then because DMD64 's disasm shows that SSE regs are used:

====
void foo()
{
    union test { int i; float f; }
    test t = { i : 0x7fb00000};
    float t2 = t.f;
    test t3 = { f : t2 };
}
===

yields to

===
00000000004586D0h  push rbp
00000000004586D1h  mov rbp, rsp
00000000004586D4h  sub rsp, 10h
00000000004586D8h  mov dword ptr [rbp-10h], 7FB00000h
00000000004586DFh  movss xmm0, dword ptr [rbp-10h]
00000000004586E4h  movss dword ptr [rbp-0Ch], xmm0
00000000004586E9h  movss xmm1, dword ptr [rbp-0Ch]
00000000004586EEh  movss dword ptr [rbp-08h], xmm1
00000000004586F3h  leave
00000000004586F4h  ret
===

Reply via email to