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.

Reply via email to