www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 18749] New: bt instruction using 64-bit register for 32-bit

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: nobody puremagic.com
          Reporter: ag0aep6g 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.

--
Apr 09 2018