----
ulong f(ulong* p, uint shift)
{
return (*p >> shift) & 1;
}
ulong g(ulong* p, ulong shift)
{
return f(p, cast(uint) shift);
}
void main()
{
enum shift = uint.max + 1L;
assert(cast(uint) shift == 0);
ulong s = 1;
assert(g(&s, shift));
}
----
Compile with `-O`. Resulting program segfaults.
Generated code for f and g:
----
0000000000000000 <_D4test1fFPmkZm>:
0: 55 push rbp
1: 48 8b ec mov rbp,rsp
4: 48 0f a3 3e bt QWORD PTR [rsi],rdi
8: 19 c0 sbb eax,eax
a: f7 d8 neg eax
c: 5d pop rbp
d: c3 ret
0000000000000000 <_D4test1gFPmmZm>:
0: 55 push rbp
1: 48 8b ec mov rbp,rsp
4: e8 00 00 00 00 call 9 <_D4test1gFPmmZm+0x9>
5: R_X86_64_PLT32 _D4test1fFPmkZm-0x4
9: 5d pop rbp
a: c3 ret
----
The bt instruction in f should use edi instead of rdi. The high bits of rdi are garbage left over from the call to g.
The code for g is correct. It's only included to show what's going on: g immediately calls f, without zeroing the high bits of rdi.
Comment #1 by dlang-bot — 2020-06-21T06:10:15Z
@WalterBright created dlang/dmd pull request #11304 "fix Issue 18749 - bt instruction using 64-bit register for 32-bit offset" fixing this issue:
- fix Issue 18749 - bt instruction using 64-bit register for 32-bit offset
https://github.com/dlang/dmd/pull/11304
Comment #2 by dlang-bot — 2020-06-25T02:36:01Z
dlang/dmd pull request #11304 "fix Issue 18749 - bt instruction using 64-bit register for 32-bit offset" was merged into master:
- 94fe8606b02f7065d85393ed9d2685a55012378a by Walter Bright:
fix Issue 18749 - bt instruction using 64-bit register for 32-bit offset
https://github.com/dlang/dmd/pull/11304