Bug 21364 – Improperly aligned struct when one member is a GPR and the other is an XMM
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2020-11-05T13:40:54Z
Last change time
2020-11-10T04:33:56Z
Keywords
backend, pull, wrong-code
Assigned to
No Owner
Creator
aneas
Comments
Comment #0 by alexander.breckel — 2020-11-05T13:40:54Z
test.d
---------------------
struct X {
float x0;
long x1;
}
void foo(int bar, X x, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9) {
import std.stdio;
writeln(bar); // prints 0 instead of 1
}
void main() {
X x = X();
foo(1, x, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
---------------------
$ dmd -ofapp test.d && ./app
The writeln prints 0 instead of 1.
$ dmd --version
DMD64 D Compiler v2.094.0
The call to foo is compiled to:
9c9ec: 48 83 ec 08 sub $0x8,%rsp
9c9f0: 6a 01 pushq $0x1
9c9f2: ff 75 f8 pushq -0x8(%rbp)
9c9f5: ff 75 f0 pushq -0x10(%rbp)
9c9f8: 48 83 ec 08 sub $0x8,%rsp <----- wrong !!!
9c9fc: 6a 02 pushq $0x2
9c9fe: 6a 03 pushq $0x3
9ca00: 6a 04 pushq $0x4
9ca02: 41 b9 05 00 00 00 mov $0x5,%r9d
9ca08: 41 b8 06 00 00 00 mov $0x6,%r8d
9ca0e: b9 07 00 00 00 mov $0x7,%ecx
9ca13: ba 08 00 00 00 mov $0x8,%edx
9ca18: be 09 00 00 00 mov $0x9,%esi
9ca1d: bf 0a 00 00 00 mov $0xa,%edi
9ca22: e8 91 ff ff ff callq 9c9b8 <_D4test3fooFiSQm1XiiiiiiiiiZv>
After pushing the contents of the struct value x onto the stack, rsp is additionally decreased by 8. However, when accessing the function argument later on this additional space of 8 bytes is not taken into account. Smells like an unnecessary alignment padding for struct by-value function call arguments. Either the padding itself is wrong, or the offset in the symbol table does not include the padding.
Any small deviation from the code above "fixes" the issue, e.g. removing function arguments from the back, or changing the "float" to "long", or adding extern (C).
Comment #1 by alexander.breckel — 2020-11-05T15:41:45Z
Because of alignment, X.sizeof is 16. So the call is correct, but foo() gets it wrong and treats the size as 12.
Comment #4 by bugzilla — 2020-11-09T09:42:26Z
Correction: both functions get the size of X right at 16.
But, the alignment of X should be 8. Function foo() gets it right, while main() sees the alignment as 16.
Comment #5 by dlang-bot — 2020-11-09T10:34:38Z
@WalterBright created dlang/dmd pull request #11941 "fix Issue 21364 - Improperly aligned struct when one member is a GPR …" fixing this issue:
- fix Issue 21364 - Improperly aligned struct when one member is a GPR and the other is an XMM
https://github.com/dlang/dmd/pull/11941
Comment #6 by dlang-bot — 2020-11-10T04:33:56Z
dlang/dmd pull request #11941 "fix Issue 21364 - Improperly aligned struct when one member is a GPR …" was merged into master:
- 34bd6a00411e6119629f2cd273f46bdd7182e894 by Walter Bright:
fix Issue 21364 - Improperly aligned struct when one member is a GPR and the other is an XMM
https://github.com/dlang/dmd/pull/11941