This code, compiled with -release -O, breaks on win32 and linux32 (and presumably other32).
The for loop comparison (table[i].a != 0) gets implemented as a load+or+bne, but the increment for the loop index gets inserted between the or and the loop, which trashes the flags register. This results in an infinite loop and eventually a segfault.
extern(C) int printf(const(char)*,...);
struct Struct
{
ulong a;
uint b;
};
__gshared Struct[] table =
[
Struct(1, 1),
Struct(0, 2)
];
void main()
{
for (int i = 0; table[i].a; i++)
{
ulong tbl = table[i].a;
printf("i:%d stc:%lld\n", i, tbl);
if (1 + tbl)
{
if (tbl == 0x80000)
return;
}
}
}
condition asm: _003 == array base, ebx = current offset, esi = loop index
?_016: add ebx, 16 ; 005E _ 83. C3, 10
mov ecx, dword ptr [?_003] ; 0061 _ 8B. 0D, 00000034(segrel)
mov edx, dword ptr [ebx+ecx+4H] ; 0067 _ 8B. 54 0B, 04
or edx, dword ptr [ebx+ecx] ; 006B _ 0B. 14 0B
inc esi ; 006E _ 46
jnz ?_014 ; 006F _ 75, A4
Comment #1 by yebblies — 2014-07-23T11:17:21Z
Quick fix is to disable the block in cgsched.c that has comment "make sure CFpsw is reliably set". Turns out CFpsw is _not_ reliably set.