https://issues.dlang.org/show_bug.cgi?id=18749
Issue ID: 18749 Summary: bt instruction using 64-bit register for 32-bit offset Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Keywords: wrong-code Severity: normal Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: ag0ae...@gmail.com ---- 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. --