Severe 2.084 regression when using staticArray on array of struct with class and bool member
Basile B.
b2.temp at gmx.com
Tue Feb 12 20:26:55 UTC 2019
On Tuesday, 12 February 2019 at 14:44:10 UTC, ag0aep6g wrote:
> On 12.02.19 15:06, Per Nordlöw wrote:
>> class C
>> {
>> this(int i) { this.i = i; }
>> int i;
>> }
>>
>> struct S
>> {
>> C c;
>> bool b; // removing this prevents bug
>> }
>>
>> void main()
>> {
>> import std.stdio : writeln;
>> import std.array : staticArray;
>>
>> auto c = new C(42);
>>
>> const S[1] s1 = [S(c)].staticArray;
>> const S[1] s2 = [S(c)];
>>
>> writeln(cast(void*)s1[0].c);
>> writeln(cast(void*)s2[0].c);
>>
>> assert(s1[0].c is
>> s2[0].c);
>> }
>
> Ouch. That looks bad. A reduction:
>
> ----
> struct S
> {
> ulong c;
> bool b; // removing this prevents bug
> }
>
> void main()
> {
> S[1] a = [S(42)];
> assert(a[0].c == 42); /* Passes. */
> f(a);
> }
>
> void f(S[1] a)
> {
> assert(a[0].c == 42); /* Fails. */
> }
> ----
>
> Fails since 2.070. https://run.dlang.io/is/LBhn4l
It's a bad codegen, or what i would call trivially "an ABI
disagreement", explaining why LDC doesn't exhibits the bug.
As far as I can see the problem is that the static array is
passed by the registers, so under linux, `c` in RDI, and `b` in
RSI but then in `f()` the backend thinks that it's passed using
the stack.
The bug goes away when S size is over or equal to 33 bytes
because in this case the parameter is well copied.
material leading to this conclusion:
```
struct S
{
ulong c;
bool b; // removing this prevents bug
}
import disassembler, std.stdio; // godbolt is too noisy with dmd
so i use mine
void main()
{
S[1] a = [S(42, true)];
showThatRegsAreUsed(a);
showDmdBadCodegen(a);
writeln(prettyDisasm(&showThatRegsAreUsed));
writeln(prettyDisasm(&showDmdBadCodegen));
}
void showDmdBadCodegen(S[1] a)
{
writeln(a[0].c);
}
void showThatRegsAreUsed(S[1] a)
{
alias writeul = writeln!ulong;
asm
{
naked;
push RSI;
call writeul; // 1st param, so 42
pop RSI;
mov RDI, RSI;
call writeul; // 2nd so RSI
ret;
}
}
```
output:
compiling /tmp/temp_7F711D03FA50.d
using /usr/bin/dmd (dmd)
/tmp/temp_7F711D03FA50.d successfully compiled
Runnable build duration: 0 minutes, 0 seconds and 399 msecs
42
1
0
;------- SUB 00000000004511ACh -------; showThatRegsAreUsed
00000000004511ACh push rsi
00000000004511ADh call 00000000004516FCh
00000000004511B2h pop rsi
00000000004511B3h mov rdi, rsi
00000000004511B6h call 00000000004516FCh
00000000004511BBh ret
;-------------------------------------
;------- SUB 000000000045119Ch -------; showDmdBadCodegen
000000000045119Ch push rbp
000000000045119Dh mov rbp, rsp
00000000004511A0h mov rdi, qword ptr [rbp+10h] ; ouch 42 is
erased here !
00000000004511A4h call 00000000004516FCh
00000000004511A9h pop rbp
00000000004511AAh ret
;-------------------------------------
More information about the Digitalmars-d
mailing list