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