www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Division by zero

reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
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.
Oct 03 2014
next sibling parent "David Nadlinger" <code klickverbot.at> writes:
On Friday, 3 October 2014 at 12:31:54 UTC, Marc Schütz wrote:
 test_int() and test_long() return ...nothing!
Note that they just return whatever is in eax/rax at that time, just like DMD returns a garbage value. The fact that integer division by zero is undefined behavior on the LLVM side but defined in the D spec may well be an LDC bug, though. David
Oct 03 2014
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 3 October 2014 at 12:31:54 UTC, Marc Schütz wrote:
 "For integral operands of the / and % operators, [...]. If the 
 divisor is zero, an Exception is thrown."
It should probably just say that is implementation defined. I'm pretty sure it does throw an exception on Windows (at least 32 bit), but doing that on linux is a pain in the butt since the operating system sends a signal and transformaing that into an exception is hacky.
Oct 03 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 3 October 2014 at 12:55:35 UTC, Adam D. Ruppe wrote:
 On Friday, 3 October 2014 at 12:31:54 UTC, Marc Schütz wrote:
 "For integral operands of the / and % operators, [...]. If the 
 divisor is zero, an Exception is thrown."
It should probably just say that is implementation defined. I'm pretty sure it does throw an exception on Windows (at least 32 bit)...
Technically, the doc is also wrong for windows, since it's an *Error* that is thrown: object.Error (0): Integer Division by 0
Oct 03 2014
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/3/2014 6:11 AM, monarch_dodra wrote:
 On Friday, 3 October 2014 at 12:55:35 UTC, Adam D. Ruppe wrote:
 On Friday, 3 October 2014 at 12:31:54 UTC, Marc Schütz wrote:
 "For integral operands of the / and % operators, [...]. If the
 divisor is zero, an Exception is thrown."
It should probably just say that is implementation defined. I'm pretty sure it does throw an exception on Windows (at least 32 bit)...
Technically, the doc is also wrong for windows, since it's an *Error* that is thrown: object.Error (0): Integer Division by 0
In any case, a bugzilla issue should be filed for this.
Oct 03 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 3 October 2014 at 13:29:18 UTC, Walter Bright wrote:
 In any case, a bugzilla issue should be filed for this.
https://issues.dlang.org/show_bug.cgi?id=13569
Oct 03 2014
parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/3/2014 7:22 AM, monarch_dodra wrote:
 On Friday, 3 October 2014 at 13:29:18 UTC, Walter Bright wrote:
 In any case, a bugzilla issue should be filed for this.
https://issues.dlang.org/show_bug.cgi?id=13569
Thanks!
Oct 04 2014
prev sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Marc Schütz" " wrote in message 
news:pcvahdmzurxleawafjqs forum.dlang.org...

 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.
https://issues.dlang.org/show_bug.cgi?id=5908
Oct 03 2014
parent reply "David Nadlinger" <code klickverbot.at> writes:
On Friday, 3 October 2014 at 14:54:17 UTC, Daniel Murphy wrote:
 https://issues.dlang.org/show_bug.cgi?id=5908
By the way, this (just emitting an x86 idiv even if it the operands are known to trap) will likely be a pain to implement for LDC. There has been an (overly aggressive, on the side of two LLVM devs) discussion about this a year ago or so: http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/060930.html. Personally, I find their stance highly troublesome, as they have introduced undefined behavior that is hard to circumvent for practically no potential performance gain. I just hope we can somehow avoid emitting a branch on every integer division… Cheers, David
Oct 03 2014
parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"David Nadlinger"  wrote in message 
news:tqzutmhsvqtjskwvtixq forum.dlang.org...

 By the way, this (just emitting an x86 idiv even if it the operands are 
 known to trap) will likely be a pain to implement for LDC. There has been 
 an (overly aggressive, on the side of two LLVM devs) discussion about this 
 a year ago or so: 
 http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/060930.html.

 Personally, I find their stance highly troublesome, as they have 
 introduced undefined behavior that is hard to circumvent for practically 
 no potential performance gain. I just hope we can somehow avoid emitting a 
 branch on every integer division…
That's annoying, but I guess it makes sense given how much division varies across platforms.
Oct 03 2014