[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