Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ocamlopt generates broken object files #7427

Closed
vicuna opened this issue Dec 6, 2016 · 9 comments

Comments

Projects
None yet
1 participant
@vicuna
Copy link

commented Dec 6, 2016

Original bug ID: 7427
Reporter: @sliquister
Status: closed (set by @mshinwell on 2016-12-09T09:02:19Z)
Resolution: duplicate
Priority: high
Severity: minor
Version: 4.03.0
Category: back end (clambda to assembly)

Bug description

Given the file [1], the linking usually fails this way:

$ ocamlopt -version
4.03.0
$ rm -f main.o; ocamlopt main.ml
main.o: In function camlMain__ccc_1208': /path/to/main.ml:8: undefined reference to camlMain__bbb_1207'
collect2: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking

Although I see sometimes:
$ ocamlopt main.ml
/usr/bin/ld: error in main.o(.eh_frame); no .eh_frame_hdr table will be created.
/usr/bin/ld: main.o: invalid string offset 1126 >= 564 for section `.strtab'
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking
$ ocamlopt main.ml
main.o: file not recognized: File truncated
collect2: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking

and sometimes the link even succeeds.

[1]
$ cat main.ml
module F() = struct
let ( *>>| ) t f = f t
let ddd _ = assert false
module M = struct
let aaa = ddd (() *>>| fun _ -> assert false)
let bbb () = () *>>| (fun _ -> assert false)
end
let ccc () = M.bbb ()
end

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 6, 2016

Comment author: @xavierleroy

I couldn't reproduce the problem on my machine (x86-64, Ubuntu 16.04), neither with 4.03.0 nor with 4.03.0+flambda, both coming from OPAM.

Could you give us more details on your OCaml configuration and how to reproduce the issue?

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 6, 2016

Comment author: @sliquister

I can't reproduce the problem either with my instructions :/. I think I was confused when I was narrowing down the use case by the build system rebuilding things while I was running commands. That would explain the random errors.

In any case, I narrowed my issue again more carefully, and ended up at the same file, BUT the command to build is: ocamlopt -inline 20 main.ml. And this time, the only possible error is the first one.

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 6, 2016

Comment author: @sliquister

The machine is x86-64 as well, running linux. I just tested with 4.04.0 and I see the same problem.

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 7, 2016

Comment author: @xavierleroy

Reproduced with 4.03.0, no flambda, -inline 20.

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 7, 2016

Comment author: bvaugon

To simplify, the following example is broken with inlining <= 1 and works well with inlining > 1:

module F() = struct
module M = struct
let aaa = assert false
let bbb () = assert false
end
let ccc () = M.bbb ()
end

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 7, 2016

Comment author: @sliquister

Looking at the simpler example, I imagine something is deducing that bbb is dead code because of aaa, and deletes it. But that thing doesn't deduce that ccc is dead code and so ccc ends up calling a non-existent bbb.

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 8, 2016

Comment author: @mshinwell

I will look at this

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 8, 2016

Comment author: @mshinwell

The problem (with this specific example anyway) only occurs with Closure, not Flambda, as far as I can tell. This is probably because Flambda does both the lifting of the constant closure for "bbb" together with the rewriting of the variable "M.bbb" to the corresponding symbol where it is applied on the penultimate line. When using Closure, the lifting is left to Cmmgen.

In the function Cmmgen.transl_let there is a case that says "if the defining expression of a let doesn't have a result, then ignore the body". In this example, the defining expression of M.aaa is non-terminating and will hit this case. This causes the "bbb" closure not to be lifted.

The fix would appear to be to still examine the body of such lets to lift constant closures out of them. I will attempt to write a fix tomorrow.

@vicuna

This comment has been minimized.

Copy link
Author

commented Dec 9, 2016

Comment author: @mshinwell

Superceded by #959

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.