Bug 22583 – Corrupted function parameters

Status
NEW
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2021-12-11T02:38:02Z
Last change time
2024-12-13T19:19:46Z
Keywords
backend, wrong-code
Assigned to
No Owner
Creator
ryuukk_
See also
https://issues.dlang.org/show_bug.cgi?id=22484, https://issues.dlang.org/show_bug.cgi?id=21301, https://issues.dlang.org/show_bug.cgi?id=23450
Moved to GitHub: dmd#20020 →

Comments

Comment #0 by ryuukk.dev — 2021-12-11T02:38:02Z
I encountered a weird bug Parameter gets corrupted, the following code works fine with LDC, but with dmd v2.098.0 it doesn't! https://run.dlang.io/is/T1uuT5 ``` import std; void main() { draw(null, Rectf(0, 0, 256,256), 64,64, 0,0, 128,128, 1, 1, 0 ); } void draw (void* texture, Rectf region, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation) { assert(texture == null); assert(region.x == 0); assert(region.y == 0); assert(region.width == 256); assert(region.height == 256); } struct Rectf { float x = 0; float y = 0; float width = 0; float height = 0; } ```
Comment #1 by dkorpel — 2021-12-12T13:15:29Z
This is probably because Rectf is passed by registers, triggering the same bug ashttps://issues.dlang.org/show_bug.cgi?id=22163
Comment #2 by dkorpel — 2021-12-13T13:14:12Z
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
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/20020 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB