Skip to content

Wrong code generation of e / e' and e mod e' with effectful e #7533

@vicuna

Description

@vicuna

Original bug ID: 7533
Reporter: jmi
Assigned to: @mshinwell
Status: resolved (set by @mshinwell on 2017-05-15T08:34:58Z)
Resolution: duplicate
Priority: normal
Severity: minor
Version: 4.04.1
Category: back end (clambda to assembly)
Related to: #7531
Monitored by: @yallop

Bug description

Consider the examples

(int_of_string "") / (let e = let w = false in () in 0)
(int_of_string "") / (List.hd [0])

At runtime the dividend throws an exception and the divisor evaluates to 0.
Under call-by-value, I expect the dividend to be evaluated before attempting a division. This agrees with the bytecode backend's output:

Fatal error: exception Failure("int_of_string")

However with the native code backend I get:

Fatal error: exception Division_by_zero

thereby removing the effect of the dividend.

I believe the problem is in asmcomp/cmmgen.ml, line 410-414,
when the divisor is sufficiently complex to not hit (or get constant folded to hit) the earlier cases:

| (c1, c2) ->
bind "divisor" c2 (fun c2 ->
Cifthenelse(c2,
Cop(Cdivi, [c1; c2], dbg),
raise_symbol dbg "caml_exn_Division_by_zero"))

Note how c1 never gets evaluated when we branch on the result of c2 and it is 0.

There is a similar problem with 'mod' (replacing '/' with 'mod' in the examples):

(int_of_string "") mod (let e = let w = false in () in 0)
(int_of_string "") mod (List.hd [0])

and the code generation case for mod in asmcomp/cmmgen.ml, line 446-450.

This is confirmed and reproducable on version 4.04.1 under Debian and 4.04.0 under OSX.

Note, these two issues are different from #7201 (fixed in #954) which concerned how the native code backend removed a Division_by_zero in the 0 / e and 0 mod e cases.

Steps to reproduce

$ echo '(int_of_string "") / (let e = let w = false in () in 0)' > div.ml
$ ocamlopt -o div.native div.ml
$ ocamlc -o div.byte div.ml
$ ./div.native
Fatal error: exception Division_by_zero
$ ./div.byte
Fatal error: exception Failure("int_of_string")

$ echo '(int_of_string "") mod (let e = let w = false in () in 0)' > mod.ml
$ ocamlopt -o mod.native mod.ml
$ ocamlc -o mod.byte mod.ml
$ ./mod.native
Fatal error: exception Division_by_zero
$ ./mod.byte
Fatal error: exception Failure("int_of_string")

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions