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
===