Nevermind, it actually looks like it has to do with the amount of float parameters. This still triggers it:
```
void main()
{
draw([1, 2, 3], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
void draw(float[3] region, float, float, float, float, float, float, float, float, float)
{
assert(region[0] == 1);
assert(region[1] == 2);
assert(region[2] == 3);
}
```
But removing any `float` will make it work.
Comment #3 by hsteoh — 2022-11-01T22:15:40Z
Disassembly of _Dmain:
0000000000029a50 <_Dmain>:
29a50: 55 push %rbp
29a51: 48 89 e5 mov %rsp,%rbp
29a54: 48 83 ec 40 sub $0x40,%rsp
29a58: c7 45 f0 00 00 00 00 movl $0x0,-0x10(%rbp)
29a5f: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp)
29a66: c7 45 f8 00 00 80 43 movl $0x43800000,-0x8(%rbp)
29a6d: c7 45 fc 00 00 80 43 movl $0x43800000,-0x4(%rbp)
29a74: 0f 10 45 f0 movups -0x10(%rbp),%xmm0
29a78: 0f 29 45 e0 movaps %xmm0,-0x20(%rbp)
29a7c: f2 0f 10 45 e0 movsd -0x20(%rbp),%xmm0
29a81: f2 0f 10 4d e8 movsd -0x18(%rbp),%xmm1 ;<---- this looks wrong
29a86: 31 c0 xor %eax,%eax
29a88: 48 89 e0 mov %rsp,%rax
29a8b: c7 40 10 00 00 00 00 movl $0x0,0x10(%rax)
29a92: c7 40 08 00 00 80 3f movl $0x3f800000,0x8(%rax)
29a99: c7 00 00 00 80 3f movl $0x3f800000,(%rax)
29a9f: 31 c0 xor %eax,%eax
29aa1: 89 c7 mov %eax,%edi
29aa3: f3 0f 10 1d 55 a5 05 movss 0x5a555(%rip),%xmm3 # 84000 <_fini+0xc24>
29aaa: 00
29aab: 0f 57 ed xorps %xmm5,%xmm5
29aae: f3 0f 10 3d 4e a5 05 movss 0x5a54e(%rip),%xmm7 # 84004 <_fini+0xc28>
29ab5: 00
29ab6: 0f 28 d3 movaps %xmm3,%xmm2
29ab9: 0f 28 e5 movaps %xmm5,%xmm4
29abc: 0f 28 f7 movaps %xmm7,%xmm6
29abf: e8 0c 00 00 00 call 29ad0 <_D4test4drawFPvSQo5RectffffffffffZv>
29ac4: 31 c0 xor %eax,%eax
29ac6: 48 83 c4 40 add $0x40,%rsp
29aca: 5d pop %rbp
29acb: c3 ret
------
Something is fishy with the codegen here.
- The start of the function loads 4 float values (0, 0, 256f (==0x43800000), 256f) onto the stack locations (rbp-10), (rbp-0c), (rbp-8), (rbp-4): this is the initialization of the temporary Rectf.
- Immediately after that, it loads (rbp-10) into xmm0, copies xmm0 to (rbp-20), then (rbp-20) back to xmm0. Not sure what's the point of this, but it seems to have something to do with data alignment.
- Then it loads (rbp-18) into xmm1: this looks wrong, (rbp-18) has never been initialized up to this point, so this loads a garbage value into xmm1 (this line is marked "this looks wrong" in the listing above). This appears to be the reason assert(region.y == 0) fails.
Not sure what exactly is going on with the codegen here, but this appears to be the point where the bug happens.
Comment #4 by hsteoh — 2022-11-01T22:25:02Z
Actually nevermind, ignore what I just said. It's doing a float truncation there from xmm0, that's not the bug. Also, I mixed up the disassembly, the above listing is from LDC, not DMD.
Comment #5 by dfj1esp02 — 2022-11-02T16:42:25Z
Probably something to do with passing float arguments. 8 arguments are passed in registers xmm0 to xmm7, the rest are pushed on stack. So I suppose 8 is the threshold value.
Comment #6 by robert.schadek — 2024-12-13T19:19:46Z