Division by zero

via Digitalmars-d digitalmars-d at puremagic.com
Fri Oct 3 05:31:52 PDT 2014


http://dlang.org/expression#MulExpression says:

"For integral operands of the / and % operators, [...]. If the 
divisor is zero, an Exception is thrown."

However, DMD behaves differently. Consider this simple test 
program:

     int test_int() {
         int x;
         return x/x;
     }

     long test_long() {
         long x;
         return x/x;
     }

     int test_runtime(int x) {
         return x/x;
     }

     int main() {
         return test_runtime(0);
     }

When compiled without optimization, the program receives SIGFPE 
at runtime (i.e. not an exception, but a signal).

The generated code for `test_int` and `test_long` looks like 
this, with the constants returned changing on each compilation:

Disassembly of section .text._D2xx8test_intFZi:

0000000000000000 <_D2xx8test_intFZi>:
    0:   55                      push   %rbp
    1:   48 8b ec                mov    %rsp,%rbp
    4:   b8 80 63 54 02          mov    $0x2546380,%eax
    9:   5d                      pop    %rbp
    a:   c3                      retq
    b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .text._D2xx9test_longFZl:

0000000000000000 <_D2xx9test_longFZl>:
    0:   55                      push   %rbp
    1:   48 8b ec                mov    %rsp,%rbp
    4:   48 b8 e0 63 54 02 00    movabs $0x25463e0,%rax
    b:   00 00 00
    e:   5d                      pop    %rbp
    f:   c3                      retq

When compiled with "-O -inline", it doesn't receive the signal, 
but returns a nonsense value. This is to be expected, because 
inlining just propagates the wrong value to the main function.

The same exercise for LDC 0.14.0: When run, the program behaves 
the similarly as with DMD (SIGFPE without optimization, always 
return value "1" with -O3). The disassembly without optimization:

Disassembly of section .text._D2xx8test_intFZi:

0000000000000000 <_D2xx8test_intFZi>:
    0:   c7 44 24 fc 00 00 00    movl   $0x0,-0x4(%rsp)
    7:   00
    8:   8b 44 24 fc             mov    -0x4(%rsp),%eax
    c:   99                      cltd
    d:   f7 7c 24 fc             idivl  -0x4(%rsp)
   11:   c3                      retq

Disassembly of section .text._D2xx9test_longFZl:

0000000000000000 <_D2xx9test_longFZl>:
    0:   48 c7 44 24 f8 00 00    movq   $0x0,-0x8(%rsp)
    7:   00 00
    9:   48 8b 44 24 f8          mov    -0x8(%rsp),%rax
    e:   48 99                   cqto
   10:   48 f7 7c 24 f8          idivq  -0x8(%rsp)
   15:   c3                      retq

However, with -O3, it gets interesting:

Disassembly of section .text._D2xx8test_intFZi:

0000000000000000 <_D2xx8test_intFZi>:
    0:   c3                      retq

Disassembly of section .text._D2xx9test_longFZl:

0000000000000000 <_D2xx9test_longFZl>:
    0:   c3                      retq

Disassembly of section .text._D2xx12test_runtimeFiZi:

0000000000000000 <_D2xx12test_runtimeFiZi>:
    0:   b8 01 00 00 00          mov    $0x1,%eax
    5:   c3                      retq

test_int() and test_long() return ...nothing! And test_runtime() 
always returns 1.

Now the big question: How many bugs are there, and where are 
they? Candidates: The specification, DMD's frontend (in two 
versions: DMD master, and 2.065 used by LDC), DMD's backend and 
LDC's backend.


More information about the Digitalmars-d mailing list