[Issue 15573] mystery crashes in @safe code

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Tue Jan 19 18:42:03 PST 2016


https://issues.dlang.org/show_bug.cgi?id=15573

--- Comment #23 from hsteoh at quickfur.ath.cx ---
There appears to be a codegen bug in dmd. Prior to the idiv instruction
(integer division, at n/m), it needs to load EDX:EAX with the (extended) value
of n. EAX is loaded correctly but EDX is not correctly zeroed (since we are
dividing byte values, EDX should be zeroed). As a result, the idiv instruction
will produce a garbage value.

In the code compiled without -O -inline, there is an "xor %edx,%edx"
instruction prior to the idiv. Apparently, -O and -inline interacts together
badly and this instruction somehow gets elided.

Here's the disassembly of main(), compiled with dmd -O -inline (with some
embedded comments mapping sections to various source code snippets):

------
0000000000438bc8 <_Dmain>:
  438bc8:       55                      push   %rbp
  438bc9:       48 8b ec                mov    %rsp,%rbp
  438bcc:       48 81 ec 80 00 00 00    sub    $0x80,%rsp
  438bd3:       48 89 5d 88             mov    %rbx,-0x78(%rbp)
  438bd7:       4c 89 65 90             mov    %r12,-0x70(%rbp)
  438bdb:       4c 89 6d 98             mov    %r13,-0x68(%rbp)
  438bdf:       4c 89 75 a0             mov    %r14,-0x60(%rbp)
  438be3:       4c 89 7d a8             mov    %r15,-0x58(%rbp)
  438be7:       be 01 00 00 00          mov    $0x1,%esi
  438bec:       bf 30 27 68 00          mov    $0x682730,%edi
        // testValues = [-2]
  438bf1:       e8 b2 21 00 00          callq  43ada8 <_d_arrayliteralTX>
  438bf6:       49 89 c4                mov    %rax,%r12
  438bf9:       41 c6 04 24 fe          movb   $0xfe,(%r12)
  438bfe:       4c 89 65 c8             mov    %r12,-0x38(%rbp)
  438c02:       48 c7 45 c0 01 00 00    movq   $0x1,-0x40(%rbp)
  438c09:       00 
  438c0a:       31 db                   xor    %ebx,%ebx
        // foreach(m; testValues)
  438c0c:       48 83 fb 01             cmp    $0x1,%rbx
  438c10:       72 0a                   jb     438c1c <_Dmain+0x54>
  438c12:       bf 16 00 00 00          mov    $0x16,%edi
        // array bounds check
  438c17:       e8 94 07 00 00          callq  4393b0 <_D4test7__arrayZ>
  438c1c:       48 8b 45 c8             mov    -0x38(%rbp),%rax
        // ecx := testValues[i]
  438c20:       0f be 0c 03             movsbl (%rbx,%rax,1),%ecx
        // -0x8(%rbp) := (byte) m
  438c24:       88 4d f8                mov    %cl,-0x8(%rbp)
  438c27:       45 31 e4                xor    %r12d,%r12d
  438c2a:       48 89 5d f0             mov    %rbx,-0x10(%rbp)
        // foreach (n; testValues)
  438c2e:       49 83 fc 01             cmp    $0x1,%r12
  438c32:       72 0a                   jb     438c3e <_Dmain+0x76>
  438c34:       bf 17 00 00 00          mov    $0x17,%edi
        // array bounds check
  438c39:       e8 72 07 00 00          callq  4393b0 <_D4test7__arrayZ>
  438c3e:       48 8b 55 c8             mov    -0x38(%rbp),%rdx
        // ebx := testValues[i]
  438c42:       41 0f be 1c 14          movsbl (%r12,%rdx,1),%ebx
        // -0x7(%rbp) := (byte) n
  438c47:       88 5d f9                mov    %bl,-0x7(%rbp)
        // extend to 32 bits
  438c4a:       0f be db                movsbl %bl,%ebx
  438c4d:       89 5d b0                mov    %ebx,-0x50(%rbp)
  438c50:       db 45 b0                fildl  -0x50(%rbp)
  438c53:       0f be 45 f8             movsbl -0x8(%rbp),%eax
  438c57:       89 45 b0                mov    %eax,-0x50(%rbp)
  438c5a:       db 45 b0                fildl  -0x50(%rbp)
        // theory = cast(real)n / m;
  438c5d:       de f9                   fdivrp %st,%st(1)
  438c5f:       db 7d d0                fstpt  -0x30(%rbp)
  438c62:       66 c7 45 da 00 00       movw   $0x0,-0x26(%rbp)
  438c68:       c7 45 dc 00 00 00 00    movl   $0x0,-0x24(%rbp)
  438c6f:       f2 48 0f 10 45 d0       rex.W movsd -0x30(%rbp),%xmm0
  438c75:       f2 48 0f 11 45 e0       rex.W movsd %xmm0,-0x20(%rbp)
  438c7b:       f2 48 0f 10 4d d8       rex.W movsd -0x28(%rbp),%xmm1
  438c81:       f2 48 0f 11 4d e8       rex.W movsd %xmm1,-0x18(%rbp)
  438c87:       0f b7 4d d8             movzwl -0x28(%rbp),%ecx
        // (inlined isNan): EXPMASK & (cast(ushort*)&x)[EXPPOS_SHORT]
  438c8b:       66 81 e1 ff 7f          and    $0x7fff,%cx
  438c90:       ba ff 7f 00 00          mov    $0x7fff,%edx
        // e == EXPMASK
  438c95:       66 3b ca                cmp    %dx,%cx
  438c98:       75 13                   jne    438cad <_Dmain+0xe5>
        // rax := -0x20(%rbp) == ps
  438c9a:       48 8b 45 e0             mov    -0x20(%rbp),%rax
        // isNaN: ps & 0x7fff_ffff_ffff_ffff
  438c9e:       48 bb ff ff ff ff ff    movabs $0x7fffffffffffffff,%rbx
  438ca5:       ff ff 7f 
  438ca8:       48 85 c3                test   %rax,%rbx
  438cab:       75 05                   jne    438cb2 <_Dmain+0xea>
        // isNaN == false
  438cad:       45 31 ed                xor    %r13d,%r13d
        // r13d := return value of isNaN
  438cb0:       eb 06                   jmp    438cb8 <_Dmain+0xf0>
        // isNaN == true
  438cb2:       41 bd 01 00 00 00       mov    $0x1,%r13d
        // r13d := return value of isNaN
        // NOTE: r13d == thrInval  (enregistered)

        // esi := IntFlag.NULL
  438cb8:       31 f6                   xor    %esi,%esi
  438cba:       64 48 8b 0c 25 00 00    mov    %fs:0x0,%rcx
  438cc1:       00 00 
  438cc3:       48 8b 15 66 91 24 00    mov    0x249166(%rip),%rdx        #
681e30 <_DYNAMIC+0x258>
  438cca:       89 34 11                mov    %esi,(%rcx,%rdx,1)
        // (inlined safeDiv): right == 0
  438ccd:       38 75 f8                cmp    %dh,-0x8(%rbp)
        // r14b := div0 = (right == 0)
  438cd0:       41 0f 94 c6             sete   %r14b
        // eax := left == n
  438cd4:       0f be 45 f9             movsbl -0x7(%rbp),%eax
        // left == int.min
  438cd8:       3d 00 00 00 80          cmp    $0x80000000,%eax
  438cdd:       75 06                   jne    438ce5 <_Dmain+0x11d>
        // cast(bool)right
  438cdf:       40 38 75 f8             cmp    %sil,-0x8(%rbp)
  438ce3:       75 05                   jne    438cea <_Dmain+0x122>
        // r15d := posOver := false
  438ce5:       45 31 ff                xor    %r15d,%r15d
  438ce8:       eb 06                   jmp    438cf0 <_Dmain+0x128>
        // r15d := posOver := true
  438cea:       41 bf 01 00 00 00       mov    $0x1,%r15d
        // if (div0)
  438cf0:       45 84 f6                test   %r14b,%r14b
************* PROBLEM: EDX not zeroed here *********************
  438cf3:       74 1e                   je     438d13 <_Dmain+0x14b>

  438cf5:       41 80 ff 01             cmp    $0x1,%r15b
  438cf9:       bb 01 00 00 00          mov    $0x1,%ebx
  438cfe:       64 48 8b 0c 25 00 00    mov    %fs:0x0,%rcx
  438d05:       00 00 
  438d07:       48 8b 15 22 91 24 00    mov    0x249122(%rip),%rdx        #
681e30 <_DYNAMIC+0x258>
  438d0e:       89 1c 11                mov    %ebx,(%rcx,%rdx,1)
        // return 0;
  438d11:       eb 0b                   jmp    438d1e <_Dmain+0x156>

        // >>from: 438cf3 (if (!div0))
        // return left / right
        // edi := m
  438d13:       40 0f be 7d f8          rex movsbl -0x8(%rbp),%edi
  438d18:       99                      cltd   
        // left / right
        // (edi == right == m)
        // idiv: EDX:EAX / edi  <--- *** PROBLEM: EDX not loaded with correct
value
        // eax := quotient
        // edx := remainder
  438d19:       f7 ff                   idiv   %edi
  438d1b:       48 89 c6                mov    %rax,%rsi

        // >>from: safeDiv: if (div0)
  438d1e:       89 75 b0                mov    %esi,-0x50(%rbp)
  438d21:       db 45 b0                fildl  -0x50(%rbp)
  438d24:       db 6d d0                fldt   -0x30(%rbp)
  438d27:       df e9                   fucomip %st(1),%st
  438d29:       dd d8                   fstp   %st(0)
  438d2b:       bf 01 00 00 00          mov    $0x1,%edi
  438d30:       7a 02                   jp     438d34 <_Dmain+0x16c>
  438d32:       74 02                   je     438d36 <_Dmain+0x16e>
  438d34:       31 ff                   xor    %edi,%edi
  438d36:       e8 b5 00 00 00          callq  438df0
<_D3std5stdio14__T7writelnTbZ7writelnFNfbZv>
  438d3b:       45 84 ed                test   %r13b,%r13b
  438d3e:       74 17                   je     438d57 <_Dmain+0x18f>
  438d40:       0f be 45 f8             movsbl -0x8(%rbp),%eax
  438d44:       64 48 8b 0c 25 00 00    mov    %fs:0x0,%rcx
  438d4b:       00 00 
  438d4d:       48 8b 15 ec 90 24 00    mov    0x2490ec(%rip),%rdx        #
681e40 <_DYNAMIC+0x268>
  438d54:       89 04 11                mov    %eax,(%rcx,%rdx,1)
  438d57:       49 ff c4                inc    %r12
  438d5a:       49 83 fc 01             cmp    $0x1,%r12
        // end inner loop
  438d5e:       0f 82 ca fe ff ff       jb     438c2e <_Dmain+0x66>
  438d64:       48 8b 5d f0             mov    -0x10(%rbp),%rbx
  438d68:       48 ff c3                inc    %rbx
  438d6b:       48 83 fb 01             cmp    $0x1,%rbx
        // end outer loop
  438d6f:       0f 82 97 fe ff ff       jb     438c0c <_Dmain+0x44>
  438d75:       31 c0                   xor    %eax,%eax
  438d77:       48 8b 5d 88             mov    -0x78(%rbp),%rbx
  438d7b:       4c 8b 65 90             mov    -0x70(%rbp),%r12
  438d7f:       4c 8b 6d 98             mov    -0x68(%rbp),%r13
  438d83:       4c 8b 75 a0             mov    -0x60(%rbp),%r14
  438d87:       4c 8b 7d a8             mov    -0x58(%rbp),%r15
  438d8b:       48 8b e5                mov    %rbp,%rsp
  438d8e:       5d                      pop    %rbp
  438d8f:       c3                      retq   
------

--


More information about the Digitalmars-d-bugs mailing list