From 21af1df8e3301cb54ba824b2e1f5619fb1269905 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Tue, 4 Jul 2017 18:20:52 +0200 Subject: [PATCH] New upstream version 4.05.0~rc1 --- .depend | 234 ++- .gitattributes | 37 + .gitignore | 5 + .mailmap | 12 +- .travis-ci.sh | 38 +- .travis.yml | 3 +- CONTRIBUTING.md | 17 +- Changes | 751 ++++++- HACKING.adoc | 260 +++ INSTALL.adoc | 5 +- Makefile | 1275 ++++++++---- Makefile.nt | 753 +------ Makefile.shared | 318 --- README.adoc | 50 +- README.win32.adoc | 48 +- VERSION | 2 +- appveyor.yml | 63 +- appveyor_build.sh | 70 +- asmcomp/CSEgen.ml | 8 +- asmcomp/afl_instrument.ml | 94 + asmcomp/afl_instrument.mli | 4 + asmcomp/amd64/CSE.ml | 2 +- asmcomp/amd64/arch.ml | 10 +- asmcomp/amd64/emit.mlp | 14 +- asmcomp/amd64/proc.ml | 5 +- asmcomp/amd64/reload.ml | 2 +- asmcomp/amd64/selection.ml | 57 +- asmcomp/arm/emit.mlp | 8 +- asmcomp/arm/selection.ml | 111 +- asmcomp/arm64/emit.mlp | 8 +- asmcomp/arm64/selection.ml | 78 +- asmcomp/asmlibrarian.ml | 2 +- asmcomp/asmpackager.ml | 7 +- asmcomp/clambda.ml | 3 +- asmcomp/clambda.mli | 1 + asmcomp/closure.ml | 62 +- asmcomp/cmm.ml | 23 +- asmcomp/cmm.mli | 26 +- asmcomp/cmmgen.ml | 1817 ++++++++++------- asmcomp/comballoc.ml | 8 +- asmcomp/compilenv.ml | 4 +- asmcomp/compilenv.mli | 2 +- asmcomp/deadcode.ml | 13 +- asmcomp/emitaux.ml | 27 +- asmcomp/emitaux.mli | 15 +- asmcomp/export_info.ml | 22 +- asmcomp/export_info.mli | 5 +- asmcomp/export_info_for_pack.ml | 93 +- asmcomp/flambda_to_clambda.ml | 4 +- asmcomp/i386/emit.mlp | 8 +- asmcomp/i386/selection.ml | 57 +- asmcomp/import_approx.ml | 57 +- asmcomp/interf.ml | 20 +- asmcomp/linearize.ml | 25 +- asmcomp/liveness.ml | 46 +- asmcomp/mach.ml | 8 +- asmcomp/mach.mli | 2 +- asmcomp/power/emit.mlp | 8 +- asmcomp/power/selection.ml | 38 +- asmcomp/printcmm.ml | 59 +- asmcomp/printcmm.mli | 3 +- asmcomp/printmach.ml | 18 +- asmcomp/reloadgen.ml | 7 +- asmcomp/s390x/emit.mlp | 94 +- asmcomp/s390x/selection.ml | 16 +- asmcomp/selectgen.ml | 479 +++-- asmcomp/selectgen.mli | 56 +- asmcomp/spacetime_profiling.ml | 70 +- asmcomp/sparc/emit.mlp | 1 + asmcomp/sparc/selection.ml | 13 +- asmcomp/spill.ml | 93 +- asmcomp/split.ml | 26 +- asmcomp/strmatch.ml | 25 +- asmcomp/strmatch.mli | 3 +- asmcomp/un_anf.ml | 58 +- asmrun/.depend | 128 +- asmrun/Makefile | 317 ++- asmrun/Makefile.nt | 75 +- asmrun/amd64.S | 5 +- asmrun/arm64.S | 4 +- asmrun/backtrace_prim.c | 17 +- asmrun/clambda_checks.c | 11 +- asmrun/fail.c | 10 + asmrun/natdynlink.c | 45 +- asmrun/signals_asm.c | 2 +- asmrun/spacetime.c | 7 +- asmrun/spacetime_offline.c | 2 +- asmrun/spacetime_snapshot.c | 2 +- asmrun/startup.c | 28 +- boot/ocamlc | Bin 2122123 -> 2152389 bytes boot/ocamldep | Bin 715495 -> 2077996 bytes boot/ocamllex | Bin 269414 -> 280321 bytes bytecomp/bytegen.ml | 2 + bytecomp/bytelibrarian.ml | 2 +- bytecomp/bytelink.ml | 7 + bytecomp/bytepackager.ml | 42 +- bytecomp/cmo_format.mli | 6 + bytecomp/emitcode.ml | 2 +- bytecomp/lambda.ml | 10 +- bytecomp/lambda.mli | 15 +- bytecomp/matching.ml | 54 +- bytecomp/printlambda.ml | 26 +- .../semantics_of_primitives.ml | 53 +- .../semantics_of_primitives.mli | 6 +- bytecomp/simplif.ml | 9 +- bytecomp/simplif.mli | 5 +- bytecomp/symtable.ml | 6 - bytecomp/symtable.mli | 1 + bytecomp/translattribute.ml | 8 +- bytecomp/translclass.ml | 12 +- bytecomp/translcore.ml | 92 +- bytecomp/translmod.ml | 78 +- bytecomp/translobj.ml | 2 +- byterun/.depend | 1504 +++++++------- byterun/Makefile | 278 ++- byterun/Makefile.common | 143 -- byterun/Makefile.nt | 57 +- byterun/afl.c | 162 ++ byterun/alloc.c | 3 + byterun/array.c | 3 +- byterun/backtrace.c | 43 +- byterun/backtrace_prim.c | 14 +- byterun/caml/backtrace_prim.h | 3 + byterun/caml/callback.h | 1 + byterun/caml/fail.h | 12 +- byterun/caml/gc.h | 14 +- byterun/caml/memory.h | 6 +- byterun/caml/misc.h | 5 +- byterun/caml/mlvalues.h | 15 +- byterun/caml/osdeps.h | 10 +- {asmrun => byterun/caml}/spacetime.h | 10 + byterun/caml/startup.h | 6 + byterun/compact.c | 7 +- byterun/debugger.c | 3 +- byterun/dynlink.c | 6 +- byterun/extern.c | 12 +- byterun/fail.c | 73 +- byterun/finalise.c | 2 +- byterun/fix_code.c | 2 + byterun/gc_ctrl.c | 6 +- byterun/ints.c | 7 - byterun/memory.c | 19 +- byterun/minor_gc.c | 4 +- byterun/misc.c | 9 +- byterun/obj.c | 2 +- byterun/printexc.c | 10 +- byterun/signals.c | 2 +- byterun/spacetime.h | 21 - byterun/startup.c | 47 +- byterun/startup_aux.c | 5 +- byterun/sys.c | 48 +- byterun/unix.c | 73 +- byterun/weak.c | 12 +- byterun/win32.c | 35 +- config/Makefile-templ | 7 +- config/Makefile.mingw | 36 +- config/Makefile.mingw64 | 36 +- config/Makefile.msvc | 39 +- config/Makefile.msvc64 | 38 +- config/auto-aux/hashbang3 | 2 + config/m-nt.h | 9 +- configure | 222 +- debugger/.depend | 12 +- debugger/Makefile | 115 +- debugger/Makefile.nt | 3 +- debugger/Makefile.shared | 128 -- debugger/command_line.ml | 5 +- debugger/loadprinter.ml | 5 + debugger/show_source.ml | 15 +- driver/compenv.ml | 5 +- driver/compile.ml | 38 +- driver/compmisc.ml | 21 +- driver/compmisc.mli | 2 + driver/main.ml | 32 +- driver/main_args.ml | 41 + driver/main_args.mli | 8 + driver/optcompile.ml | 38 +- driver/optmain.ml | 35 +- driver/pparse.ml | 23 +- emacs/caml-types.el | 2 +- lex/output.ml | 43 +- man/ocamlc.m | 22 + man/ocamldep.m | 17 + man/ocamlopt.m | 37 + middle_end/base_types/set_of_closures_id.ml | 1 + middle_end/base_types/set_of_closures_id.mli | 1 + .../base_types/set_of_closures_origin.ml | 1 + .../base_types/set_of_closures_origin.mli | 1 + middle_end/closure_conversion.ml | 34 +- middle_end/closure_conversion_aux.ml | 26 +- middle_end/closure_conversion_aux.mli | 12 +- middle_end/debuginfo.ml | 25 + middle_end/debuginfo.mli | 4 + middle_end/flambda.ml | 9 + middle_end/flambda.mli | 6 + middle_end/flambda_invariants.ml | 9 +- middle_end/inline_and_simplify.ml | 31 +- middle_end/inlining_cost.ml | 4 +- middle_end/inlining_decision.ml | 6 +- middle_end/inlining_stats_types.ml | 25 +- middle_end/inlining_stats_types.mli | 6 +- middle_end/lift_constants.ml | 12 +- middle_end/middle_end.ml | 8 +- middle_end/simple_value_approx.ml | 51 +- middle_end/simple_value_approx.mli | 19 +- ocamldoc/.depend | 12 +- ocamldoc/Makefile | 421 ++-- ocamldoc/Makefile.nt | 242 +-- ocamldoc/odoc_analyse.ml | 9 +- ocamldoc/odoc_args.ml | 2 + ocamldoc/odoc_ast.ml | 22 +- ocamldoc/odoc_cross.ml | 179 +- ocamldoc/odoc_global.ml | 1 + ocamldoc/odoc_global.mli | 3 + ocamldoc/odoc_html.ml | 21 +- ocamldoc/odoc_latex.ml | 66 +- ocamldoc/odoc_messages.ml | 11 +- ocamldoc/odoc_module.ml | 133 +- ocamldoc/odoc_sig.ml | 28 +- otherlibs/Makefile | 3 +- otherlibs/bigarray/.depend | 12 +- otherlibs/bigarray/Makefile | 19 +- otherlibs/bigarray/Makefile.nt | 8 - otherlibs/bigarray/bigarray.ml | 30 + otherlibs/bigarray/bigarray.mli | 87 +- otherlibs/bigarray/bigarray_stubs.c | 19 +- otherlibs/dynlink/Makefile | 5 +- otherlibs/dynlink/natdynlink.ml | 27 +- otherlibs/graph/dump_img.c | 6 +- otherlibs/graph/events.c | 6 +- otherlibs/graph/fill.c | 2 +- otherlibs/graph/graphics.mli | 7 +- otherlibs/graph/image.c | 2 +- otherlibs/graph/open.c | 8 +- otherlibs/graph/text.c | 6 +- otherlibs/num/Makefile | 30 +- otherlibs/num/Makefile.nt | 7 +- otherlibs/num/big_int.ml | 15 + otherlibs/num/big_int.mli | 38 +- otherlibs/num/nat_stubs.c | 26 +- otherlibs/num/num.ml | 15 + otherlibs/num/num.mli | 19 + otherlibs/raw_spacetime_lib/.depend | 9 + otherlibs/raw_spacetime_lib/Makefile | 66 +- otherlibs/raw_spacetime_lib/Makefile.nt | 7 - otherlibs/raw_spacetime_lib/Makefile.shared | 74 - otherlibs/str/.depend | 3 +- otherlibs/str/Makefile | 26 +- otherlibs/str/Makefile.nt | 7 +- otherlibs/str/str.ml | 14 +- otherlibs/str/strstubs.c | 1 - otherlibs/systhreads/Makefile | 143 +- otherlibs/systhreads/Makefile.nt | 104 +- otherlibs/systhreads/condition.mli | 2 +- otherlibs/systhreads/st_posix.h | 18 +- otherlibs/systhreads/st_stubs.c | 152 +- otherlibs/systhreads/st_win32.h | 11 +- otherlibs/systhreads/thread.mli | 2 +- otherlibs/systhreads/threadUnix.mli | 10 +- otherlibs/threads/.depend | 4 +- otherlibs/threads/Makefile | 6 +- otherlibs/threads/condition.mli | 2 +- otherlibs/threads/pervasives.ml | 18 + otherlibs/threads/scheduler.c | 114 +- otherlibs/threads/thread.mli | 4 +- otherlibs/threads/threadUnix.mli | 11 +- otherlibs/threads/unix.ml | 248 ++- otherlibs/unix/.depend | 2 +- otherlibs/unix/Makefile | 3 + otherlibs/unix/accept.c | 22 +- otherlibs/unix/access.c | 22 +- otherlibs/unix/addrofstr.c | 14 +- otherlibs/unix/bind.c | 2 +- otherlibs/unix/connect.c | 6 +- otherlibs/unix/dup.c | 13 +- otherlibs/unix/dup2.c | 49 +- otherlibs/unix/envir.c | 2 +- otherlibs/unix/errmsg.c | 2 +- otherlibs/unix/execv.c | 2 +- otherlibs/unix/execve.c | 4 +- otherlibs/unix/execvp.c | 25 +- otherlibs/unix/fchmod.c | 2 +- otherlibs/unix/fchown.c | 2 +- otherlibs/unix/fcntl.c | 24 +- otherlibs/unix/ftruncate.c | 4 +- otherlibs/unix/getaddrinfo.c | 16 +- otherlibs/unix/getcwd.c | 4 +- otherlibs/unix/getgr.c | 15 +- otherlibs/unix/getgroups.c | 4 +- otherlibs/unix/gethost.c | 46 +- otherlibs/unix/gethostname.c | 4 +- otherlibs/unix/getlogin.c | 2 +- otherlibs/unix/getnameinfo.c | 16 +- otherlibs/unix/getpeername.c | 2 +- otherlibs/unix/getproto.c | 16 +- otherlibs/unix/getpw.c | 20 +- otherlibs/unix/getserv.c | 20 +- otherlibs/unix/getsockname.c | 2 +- otherlibs/unix/gettimeofday.c | 4 +- otherlibs/unix/gmtime.c | 8 +- otherlibs/unix/initgroups.c | 2 +- otherlibs/unix/itimer.c | 6 +- otherlibs/unix/kill.c | 2 +- otherlibs/unix/listen.c | 2 +- otherlibs/unix/lockf.c | 10 +- otherlibs/unix/mkfifo.c | 2 +- otherlibs/unix/open.c | 46 +- otherlibs/unix/opendir.c | 2 +- otherlibs/unix/pipe.c | 15 +- otherlibs/unix/putenv.c | 6 +- otherlibs/unix/read.c | 4 +- otherlibs/unix/readdir.c | 4 +- otherlibs/unix/readlink.c | 4 +- otherlibs/unix/rewinddir.c | 2 +- otherlibs/unix/select.c | 10 +- otherlibs/unix/sendrecv.c | 36 +- otherlibs/unix/setgroups.c | 4 +- otherlibs/unix/setsid.c | 2 +- otherlibs/unix/shutdown.c | 2 +- otherlibs/unix/signals.c | 16 +- otherlibs/unix/sleep.c | 12 +- otherlibs/unix/socket.c | 21 +- otherlibs/unix/socketaddr.c | 30 +- otherlibs/unix/socketpair.c | 20 +- otherlibs/unix/sockopt.c | 10 +- otherlibs/unix/stat.c | 2 +- otherlibs/unix/strofaddr.c | 8 +- otherlibs/unix/symlink.c | 2 +- otherlibs/unix/termios.c | 16 +- otherlibs/unix/time.c | 2 +- otherlibs/unix/times.c | 4 +- otherlibs/unix/truncate.c | 4 +- otherlibs/unix/unix.ml | 202 +- otherlibs/unix/unix.mli | 158 +- otherlibs/unix/unixLabels.mli | 47 +- otherlibs/unix/unixsupport.c | 43 +- otherlibs/unix/unixsupport.h | 5 + otherlibs/unix/utimes.c | 2 +- otherlibs/unix/wait.c | 20 +- otherlibs/unix/write.c | 8 +- .../Makefile.shared => win32graph/Makefile} | 35 +- otherlibs/win32graph/Makefile.nt | 24 +- otherlibs/win32graph/dib.c | 499 ----- otherlibs/win32graph/draw.c | 31 +- otherlibs/win32graph/events.c | 2 +- otherlibs/win32graph/open.c | 6 +- otherlibs/win32unix/Makefile | 67 + otherlibs/win32unix/Makefile.nt | 49 +- otherlibs/win32unix/accept.c | 13 +- otherlibs/win32unix/channels.c | 4 +- otherlibs/win32unix/close.c | 2 - otherlibs/win32unix/connect.c | 4 +- otherlibs/win32unix/createprocess.c | 43 +- otherlibs/win32unix/dup.c | 6 +- otherlibs/win32unix/dup2.c | 8 +- otherlibs/win32unix/errmsg.c | 6 +- otherlibs/win32unix/gettimeofday.c | 2 +- otherlibs/win32unix/link.c | 2 +- otherlibs/win32unix/lockf.c | 12 +- otherlibs/win32unix/lseek.c | 2 +- otherlibs/win32unix/open.c | 31 +- otherlibs/win32unix/pipe.c | 6 +- otherlibs/win32unix/read.c | 19 +- otherlibs/win32unix/select.c | 24 +- otherlibs/win32unix/sendrecv.c | 26 +- otherlibs/win32unix/sleep.c | 4 +- otherlibs/win32unix/socket.c | 7 +- otherlibs/win32unix/sockopt.c | 6 +- otherlibs/win32unix/stat.c | 34 +- otherlibs/win32unix/symlink.c | 3 +- otherlibs/win32unix/system.c | 6 +- otherlibs/win32unix/times.c | 2 +- otherlibs/win32unix/unix.ml | 104 +- otherlibs/win32unix/unixsupport.c | 27 +- otherlibs/win32unix/unixsupport.h | 14 +- otherlibs/win32unix/windir.c | 10 +- otherlibs/win32unix/winwait.c | 10 +- otherlibs/win32unix/winworker.c | 8 +- otherlibs/win32unix/winworker.h | 1 + otherlibs/win32unix/write.c | 16 +- parsing/HACKING.adoc | 9 + parsing/ast_helper.ml | 51 + parsing/ast_helper.mli | 23 +- parsing/ast_mapper.ml | 22 +- parsing/ast_mapper.mli | 8 +- parsing/parser.mly | 95 +- parsing/parsetree.mli | 21 +- parsing/pprintast.ml | 88 +- parsing/printast.ml | 14 +- stdlib/.depend | 10 +- stdlib/Makefile | 266 ++- stdlib/Makefile.nt | 32 +- stdlib/Makefile.shared | 138 -- stdlib/StdlibModules | 1 + stdlib/arg.ml | 163 +- stdlib/arg.mli | 56 +- stdlib/array.mli | 4 +- stdlib/arrayLabels.mli | 127 +- stdlib/buffer.ml | 6 + stdlib/buffer.mli | 6 + stdlib/bytes.ml | 41 +- stdlib/bytes.mli | 31 +- stdlib/bytesLabels.mli | 108 +- stdlib/digest.ml | 3 +- stdlib/digest.mli | 4 +- stdlib/ephemeron.ml | 25 + stdlib/ephemeron.mli | 21 +- stdlib/format.mli | 21 +- stdlib/gc.ml | 4 +- stdlib/gc.mli | 4 +- stdlib/genlex.mli | 4 +- stdlib/hashtbl.ml | 42 + stdlib/hashtbl.mli | 22 +- stdlib/int32.ml | 5 + stdlib/int32.mli | 5 + stdlib/int64.ml | 7 + stdlib/int64.mli | 4 + stdlib/lazy.mli | 6 +- stdlib/list.ml | 36 + stdlib/list.mli | 46 +- stdlib/listLabels.mli | 107 +- stdlib/map.ml | 100 + stdlib/map.mli | 72 +- stdlib/marshal.mli | 2 +- stdlib/moreLabels.mli | 20 + stdlib/nativeint.ml | 5 + stdlib/nativeint.mli | 8 +- stdlib/obj.mli | 2 +- stdlib/pervasives.ml | 23 +- stdlib/pervasives.mli | 43 +- stdlib/printexc.ml | 6 +- stdlib/printexc.mli | 40 +- stdlib/printf.mli | 2 +- stdlib/queue.mli | 4 +- stdlib/random.mli | 2 +- stdlib/scanf.mli | 88 +- stdlib/set.ml | 115 +- stdlib/set.mli | 65 +- stdlib/spacetime.ml | 4 +- stdlib/spacetime.mli | 12 +- stdlib/stack.mli | 4 +- stdlib/stream.mli | 4 +- stdlib/string.ml | 31 +- stdlib/string.mli | 36 + stdlib/stringLabels.mli | 96 +- stdlib/sys.mli | 8 +- stdlib/sys.mlp | 6 + stdlib/uchar.ml | 8 +- stdlib/uchar.mli | 6 - stdlib/weak.ml | 21 + stdlib/weak.mli | 12 +- testsuite/HACKING.adoc | 11 + testsuite/makefiles/Makefile.common | 6 +- testsuite/makefiles/Makefile.several | 6 +- testsuite/tests/asmcomp/Makefile | 12 +- testsuite/tests/asmcomp/catch-rec.cmm | 5 + testsuite/tests/asmcomp/catch-try.cmm | 7 + testsuite/tests/asmcomp/even-odd-spill.cmm | 19 + testsuite/tests/asmcomp/even-odd.cmm | 8 + testsuite/tests/asmcomp/lexcmm.mll | 32 +- testsuite/tests/asmcomp/main.ml | 31 +- testsuite/tests/asmcomp/parsecmm.mly | 92 +- testsuite/tests/asmcomp/parsecmmaux.ml | 19 +- testsuite/tests/asmcomp/parsecmmaux.mli | 4 + testsuite/tests/asmcomp/pgcd.cmm | 9 + .../tests/backtrace/backtrace2.byte.reference | 71 +- testsuite/tests/backtrace/backtrace2.ml | 66 +- .../backtrace/backtrace2.native.reference | 71 +- .../backtrace/raw_backtrace.byte.reference | 38 +- testsuite/tests/backtrace/raw_backtrace.ml | 20 +- .../backtrace/raw_backtrace.native.reference | 38 +- .../basic-float/zero_sized_float_arrays.ml | 15 + .../zero_sized_float_arrays.reference | 0 testsuite/tests/basic-modules/Makefile | 2 +- testsuite/tests/basic-modules/main.ml | 8 + testsuite/tests/basic-modules/pr7427.ml | 7 + testsuite/tests/basic/divint.ml | 5 + testsuite/tests/basic/eval_order_1.ml | 4 + testsuite/tests/basic/eval_order_1.reference | 1 + testsuite/tests/basic/eval_order_2.ml | 24 + testsuite/tests/basic/eval_order_2.reference | 0 testsuite/tests/basic/eval_order_3.ml | 22 + testsuite/tests/basic/eval_order_3.reference | 1 + testsuite/tests/basic/eval_order_4.ml | 17 + testsuite/tests/basic/eval_order_4.reference | 4 + testsuite/tests/basic/includestruct.ml | 16 + testsuite/tests/basic/includestruct.reference | 2 + testsuite/tests/basic/opt_variants.ml | 114 ++ testsuite/tests/basic/opt_variants.reference | 0 testsuite/tests/basic/pr7533.ml | 19 + testsuite/tests/basic/pr7533.reference | 0 testsuite/tests/basic/switch_opts.ml | 63 + testsuite/tests/basic/switch_opts.reference | 1 + testsuite/tests/basic/zero_divided_by_n.ml | 17 + .../tests/basic/zero_divided_by_n.reference | 0 testsuite/tests/embedded/cmstub.c | 4 +- testsuite/tests/exotic-syntax/exotic.ml | 7 + .../tests/flambda/Makefile | 18 +- testsuite/tests/flambda/gpr998.ml | 39 + testsuite/tests/flambda/gpr998.reference | 0 .../float_subst_boxed_number.ml | 10 + .../ignored_scan_counters.ml | 3 + .../ignored_scan_counters.ml.reference | 3 +- testsuite/tests/lib-arg/Makefile | 3 +- testsuite/tests/lib-arg/testarg.ml | 74 +- testsuite/tests/lib-arg/testerror.ml | 41 + testsuite/tests/lib-arg/testerror.reference | 45 + testsuite/tests/lib-bigarray-file/Makefile | 23 + testsuite/tests/lib-bigarray-file/mapfile.ml | 109 + .../tests/lib-bigarray-file/mapfile.reference | 3 + testsuite/tests/lib-bigarray/bigarrays.ml | 122 ++ .../tests/lib-bigarray/bigarrays.reference | 8 + testsuite/tests/lib-bigarray/weak_bigarray.ml | 28 + .../lib-bigarray/weak_bigarray.reference | 3 + .../tests/lib-buffer/Makefile | 11 +- testsuite/tests/lib-buffer/test.ml | 86 + testsuite/tests/lib-buffer/test.reference | 6 + testsuite/tests/lib-bytes/Makefile | 19 + testsuite/tests/lib-bytes/test_bytes.ml | 122 ++ .../tests/lib-bytes/test_bytes.reference | 2 + testsuite/tests/lib-dynlink-csharp/Makefile | 7 +- testsuite/tests/lib-dynlink-native/Makefile | 2 +- testsuite/tests/lib-hashtbl/htbl.ml | 1 + testsuite/tests/lib-marshal/intextaux.c | 4 +- testsuite/tests/lib-set/testmap.ml | 52 + testsuite/tests/lib-set/testset.ml | 74 + testsuite/tests/lib-stdlabels/Makefile | 19 + .../tests/lib-stdlabels/test_stdlabels.ml | 40 + .../lib-stdlabels/test_stdlabels.reference | 0 .../tests/lib-threads/backtrace_threads.ml | 18 + .../lib-threads/backtrace_threads.reference | 0 testsuite/tests/lib-uchar/test.ml | 11 - testsuite/tests/lib-unix/Makefile | 36 + testsuite/tests/lib-unix/cloexec.ml | 51 + testsuite/tests/lib-unix/cloexec.reference | 21 + testsuite/tests/lib-unix/cmdline_prog.c | 10 + testsuite/tests/lib-unix/dup.ml | 5 + testsuite/tests/lib-unix/dup.reference | 1 + testsuite/tests/lib-unix/dup2.ml | 24 + testsuite/tests/lib-unix/dup2.reference | 2 + testsuite/tests/lib-unix/fdstatus.c | 73 + testsuite/tests/lib-unix/pipe_eof.ml | 34 + testsuite/tests/lib-unix/pipe_eof.reference | 1 + testsuite/tests/lib-unix/redirections.ml | 113 + .../tests/lib-unix/redirections.reference | 28 + testsuite/tests/lib-unix/reflector.c | 74 + testsuite/tests/lib-unix/test_unix_cmdline.ml | 28 + .../lib-unix/test_unix_cmdline.reference | 13 + testsuite/tests/link-test/Makefile | 8 +- testsuite/tests/messages/Makefile | 3 + testsuite/tests/messages/precise_locations.ml | 93 + testsuite/tests/misc/gcwords.ml | 24 + testsuite/tests/misc/gcwords.reference | 1 + testsuite/tests/parsetree/source.ml | 24 +- testsuite/tests/parsetree/test.ml | 8 +- .../missing_set_of_closures/Makefile | 45 + .../regression/missing_set_of_closures/a.ml | 9 + .../regression/missing_set_of_closures/b.ml | 4 + .../regression/missing_set_of_closures/b2.ml | 2 + .../missing_set_of_closures/dir/c.ml | 2 + .../tests/regression/pr7426/Makefile | 26 +- testsuite/tests/regression/pr7426/pr7426.ml | 1 + .../tests/regression/pr7426/pr7426.reference | 0 testsuite/tests/runtime-C-exceptions/Makefile | 7 + .../tests/runtime-C-exceptions/stub_test.c | 20 + testsuite/tests/runtime-C-exceptions/test.ml | 11 + .../tests/runtime-C-exceptions/test.reference | 2 + testsuite/tests/tool-command-line/Makefile | 54 + .../tests/tool-command-line/unknown-file | 0 .../unknown-file.byte.reference | 1 + .../unknown-file.opt.reference | 1 + .../tool-debugger/find-artifacts/Makefile | 2 +- testsuite/tests/tool-ocamlc-open/Makefile | 14 + testsuite/tests/tool-ocamlc-open/a.ml | 3 + testsuite/tests/tool-ocamlc-open/b.ml | 1 + testsuite/tests/tool-ocamldoc-2/Makefile | 5 +- .../tool-ocamldoc-2/inline_records.reference | 5 - .../inline_records_bis.reference | 5 - testsuite/tests/tool-ocamldoc-2/loop.ml | 3 + .../tests/tool-ocamldoc-2/loop.reference | 36 + .../short_description.reference | 21 + .../tool-ocamldoc-2/short_description.txt | 4 + testsuite/tests/tool-ocamldoc-2/variants.mli | 38 + .../tests/tool-ocamldoc-2/variants.reference | 190 ++ testsuite/tests/tool-ocamldoc-html/Loop.ml | 3 + .../tests/tool-ocamldoc-html/Loop.reference | 20 + testsuite/tests/tool-ocamldoc-html/Makefile | 8 +- .../tool-ocamldoc-html/Module_whitespace.ml | 4 + .../Module_whitespace.reference | 24 + .../tests/tool-ocamldoc-html/Variants.mli | 38 + .../tool-ocamldoc-html/Variants.reference | 232 +++ testsuite/tests/tool-ocamldoc-open/Makefile | 2 +- testsuite/tests/tool-ocamldoc-open/alias.ml | 4 +- .../tests/tool-ocamldoc-open/doc.reference | 15 +- testsuite/tests/tool-ocamldoc/t05.ml | 3 + testsuite/tests/tool-ocamldoc/t05.reference | 6 + .../tests/tool-toplevel-invocation/Makefile | 36 + .../first_arg_fail.txt | 3 + .../first_arg_fail.txt.reference | 1 + .../indirect_first_arg_fail.txt | 2 + .../indirect_first_arg_fail.txt.reference | 1 + .../indirect_last_arg_fail.txt | 2 + .../indirect_last_arg_fail.txt.reference | 1 + .../last_arg_fail.txt | 3 + .../last_arg_fail.txt.reference | 1 + .../tests/tool-toplevel-invocation/test.ml | 1 + .../tool-toplevel-invocation/working_arg.txt | 2 + .../working_arg.txt.reference | 4 + testsuite/tests/tool-toplevel/Makefile | 1 + testsuite/tests/tool-toplevel/pr7060.ml | 6 + .../tests/tool-toplevel/pr7060.ml.reference | 16 + .../tests/translprim/array_spec.ml.reference | 40 +- .../translprim/comparison_table.ml.reference | 141 +- .../translprim/module_coercion.ml.reference | 155 +- testsuite/tests/typing-extensions/cast.ml | 2 + .../tests/typing-extensions/cast.ml.reference | 1 + .../tests/typing-extensions/extensions.ml | 2 + .../typing-extensions/extensions.ml.reference | 5 +- testsuite/tests/typing-gadts/pr7421.ml | 26 + testsuite/tests/typing-gadts/pr7432.ml | 27 + .../implicit_unpack.ml.reference | 16 + testsuite/tests/typing-misc/records.ml | 22 +- .../tests/typing-modules-bugs/pr7414_bad.ml | 55 + testsuite/tests/typing-modules/aliases.ml | 32 + testsuite/tests/typing-modules/pr7348.ml | 37 + .../Tests.ml.principal.reference | 2 +- .../tests/typing-objects/Tests.ml.reference | 2 +- .../tests/typing-objects/pr6383.ml.reference | 4 +- testsuite/tests/typing-poly/poly.ml | 27 + testsuite/tests/typing-private/private.ml | 5 + .../private.ml.principal.reference | 4 +- .../tests/typing-private/private.ml.reference | 4 +- .../typing-short-paths/pr6836.ml.reference | 2 +- .../short-paths.ml.reference | 8 + testsuite/tests/typing-unboxed-types/test.ml | 35 + .../typing-unboxed-types/test.ml.reference | 43 +- testsuite/tests/typing-unboxed/test.ml | 3 + .../tests/typing-unboxed/test.ml.reference | 1 + .../ambiguous_guarded_disjunction.ml | 3 + ...ambiguous_guarded_disjunction.ml.reference | 5 +- .../tests/typing-warnings/application.ml | 3 + .../typing-warnings/application.ml.reference | 3 +- .../tests/typing-warnings/exhaustiveness.ml | 3 + .../exhaustiveness.ml.reference | 7 + testsuite/tests/typing-warnings/pr6872.ml | 3 + .../pr6872.ml.principal.reference | 3 +- .../tests/typing-warnings/pr6872.ml.reference | 3 +- testsuite/tests/typing-warnings/pr7297.ml | 3 + .../tests/typing-warnings/pr7297.ml.reference | 3 +- .../tests/typing-warnings/unused_types.ml | 6 + .../typing-warnings/unused_types.ml.reference | 1 + testsuite/tests/unwind/Makefile | 2 +- testsuite/tests/warnings/Makefile | 1 + testsuite/tests/warnings/w04.ml | 12 + testsuite/tests/warnings/w04.reference | 3 + testsuite/tests/warnings/w33.ml | 16 + testsuite/tests/warnings/w33.reference | 4 + testsuite/tests/warnings/w60.ml | 23 + testsuite/tests/warnings/w60.mli | 12 + testsuite/tests/warnings/w60.reference | 0 tools/.depend | 26 +- tools/Makefile | 383 +++- tools/Makefile.nt | 10 +- tools/Makefile.shared | 383 ---- tools/check-typo | 2 +- tools/ci-build | 145 +- tools/cmt2annot.ml | 2 +- tools/dumpobj.ml | 8 +- tools/lintapidiff.ml | 313 +++ tools/make-version-header.sh | 4 +- tools/make_opcodes.mll | 47 + tools/objinfo.ml | 60 +- tools/objinfo_helper.c | 2 - tools/ocamlcp.ml | 4 +- tools/ocamldep.ml | 15 +- tools/ocamlmklib.ml | 19 +- tools/ocamloptp.ml | 6 +- tools/ocamlprof.ml | 10 +- tools/primreq.ml | 10 +- tools/read_cmt.ml | 8 +- toplevel/genprintval.ml | 16 +- toplevel/opttoploop.ml | 4 +- toplevel/opttopmain.ml | 51 +- toplevel/topmain.ml | 50 +- typing/HACKING.adoc | 58 + typing/btype.ml | 27 +- typing/btype.mli | 4 +- typing/cmt_format.ml | 24 +- typing/cmt_format.mli | 5 +- typing/ctype.ml | 17 +- typing/env.ml | 12 +- typing/env.mli | 4 +- typing/mtype.ml | 17 + typing/mtype.mli | 1 + typing/oprint.ml | 4 +- typing/outcometree.mli | 2 +- typing/parmatch.ml | 51 +- typing/printtyp.ml | 18 +- typing/printtyped.ml | 4 +- typing/subst.ml | 27 +- typing/subst.mli | 1 - typing/tast_mapper.ml | 5 +- typing/typeclass.ml | 14 +- typing/typecore.ml | 47 +- typing/typecore.mli | 2 + typing/typedecl.ml | 93 +- typing/typedtree.ml | 3 +- typing/typedtree.mli | 6 +- typing/typedtreeIter.ml | 2 +- typing/typedtreeMap.ml | 4 +- typing/typemod.ml | 16 +- typing/typemod.mli | 2 +- typing/typetexp.ml | 11 +- typing/untypeast.ml | 36 +- utils/ccomp.ml | 33 +- utils/clflags.ml | 35 +- utils/clflags.mli | 21 +- utils/config.mli | 10 + utils/config.mlp | 28 +- utils/identifiable.ml | 13 +- utils/identifiable.mli | 2 +- utils/misc.ml | 8 +- utils/misc.mli | 10 +- utils/numbers.mli | 2 +- utils/targetint.ml | 98 + utils/targetint.mli | 188 ++ utils/timings.ml | 32 +- utils/timings.mli | 9 +- yacc/Makefile | 14 +- yacc/Makefile.nt | 3 - yacc/reader.c | 7 +- 731 files changed, 17768 insertions(+), 9569 deletions(-) create mode 100644 HACKING.adoc delete mode 100644 Makefile.shared create mode 100644 asmcomp/afl_instrument.ml create mode 100644 asmcomp/afl_instrument.mli rename {middle_end => bytecomp}/semantics_of_primitives.ml (75%) rename {middle_end => bytecomp}/semantics_of_primitives.mli (96%) delete mode 100644 byterun/Makefile.common create mode 100644 byterun/afl.c rename {asmrun => byterun/caml}/spacetime.h (98%) delete mode 100644 byterun/spacetime.h create mode 100755 config/auto-aux/hashbang3 delete mode 100644 debugger/Makefile.shared delete mode 100644 otherlibs/raw_spacetime_lib/Makefile.shared rename otherlibs/{num/Makefile.shared => win32graph/Makefile} (62%) delete mode 100644 otherlibs/win32graph/dib.c create mode 100644 otherlibs/win32unix/Makefile create mode 100644 parsing/HACKING.adoc delete mode 100755 stdlib/Makefile.shared create mode 100644 testsuite/HACKING.adoc create mode 100644 testsuite/tests/asmcomp/catch-rec.cmm create mode 100644 testsuite/tests/asmcomp/catch-try.cmm create mode 100644 testsuite/tests/asmcomp/even-odd-spill.cmm create mode 100644 testsuite/tests/asmcomp/even-odd.cmm create mode 100644 testsuite/tests/asmcomp/pgcd.cmm create mode 100644 testsuite/tests/basic-float/zero_sized_float_arrays.ml create mode 100644 testsuite/tests/basic-float/zero_sized_float_arrays.reference create mode 100644 testsuite/tests/basic-modules/pr7427.ml create mode 100644 testsuite/tests/basic/eval_order_1.ml create mode 100644 testsuite/tests/basic/eval_order_1.reference create mode 100644 testsuite/tests/basic/eval_order_2.ml create mode 100644 testsuite/tests/basic/eval_order_2.reference create mode 100644 testsuite/tests/basic/eval_order_3.ml create mode 100644 testsuite/tests/basic/eval_order_3.reference create mode 100644 testsuite/tests/basic/eval_order_4.ml create mode 100644 testsuite/tests/basic/eval_order_4.reference create mode 100755 testsuite/tests/basic/opt_variants.ml create mode 100644 testsuite/tests/basic/opt_variants.reference create mode 100644 testsuite/tests/basic/pr7533.ml create mode 100644 testsuite/tests/basic/pr7533.reference create mode 100644 testsuite/tests/basic/switch_opts.ml create mode 100644 testsuite/tests/basic/switch_opts.reference create mode 100644 testsuite/tests/basic/zero_divided_by_n.ml create mode 100644 testsuite/tests/basic/zero_divided_by_n.reference rename otherlibs/bigarray/Makefile.shared => testsuite/tests/flambda/Makefile (67%) create mode 100644 testsuite/tests/flambda/gpr998.ml create mode 100644 testsuite/tests/flambda/gpr998.reference create mode 100644 testsuite/tests/lib-arg/testerror.ml create mode 100644 testsuite/tests/lib-arg/testerror.reference create mode 100644 testsuite/tests/lib-bigarray-file/Makefile create mode 100644 testsuite/tests/lib-bigarray-file/mapfile.ml create mode 100644 testsuite/tests/lib-bigarray-file/mapfile.reference create mode 100644 testsuite/tests/lib-bigarray/weak_bigarray.ml create mode 100644 testsuite/tests/lib-bigarray/weak_bigarray.reference rename tools/make-opcodes => testsuite/tests/lib-buffer/Makefile (74%) create mode 100644 testsuite/tests/lib-buffer/test.ml create mode 100644 testsuite/tests/lib-buffer/test.reference create mode 100644 testsuite/tests/lib-bytes/Makefile create mode 100644 testsuite/tests/lib-bytes/test_bytes.ml create mode 100644 testsuite/tests/lib-bytes/test_bytes.reference create mode 100644 testsuite/tests/lib-stdlabels/Makefile create mode 100644 testsuite/tests/lib-stdlabels/test_stdlabels.ml create mode 100644 testsuite/tests/lib-stdlabels/test_stdlabels.reference create mode 100644 testsuite/tests/lib-threads/backtrace_threads.ml create mode 100644 testsuite/tests/lib-threads/backtrace_threads.reference create mode 100644 testsuite/tests/lib-unix/Makefile create mode 100644 testsuite/tests/lib-unix/cloexec.ml create mode 100644 testsuite/tests/lib-unix/cloexec.reference create mode 100644 testsuite/tests/lib-unix/cmdline_prog.c create mode 100644 testsuite/tests/lib-unix/dup.ml create mode 100644 testsuite/tests/lib-unix/dup.reference create mode 100644 testsuite/tests/lib-unix/dup2.ml create mode 100644 testsuite/tests/lib-unix/dup2.reference create mode 100644 testsuite/tests/lib-unix/fdstatus.c create mode 100644 testsuite/tests/lib-unix/pipe_eof.ml create mode 100644 testsuite/tests/lib-unix/pipe_eof.reference create mode 100644 testsuite/tests/lib-unix/redirections.ml create mode 100644 testsuite/tests/lib-unix/redirections.reference create mode 100644 testsuite/tests/lib-unix/reflector.c create mode 100644 testsuite/tests/lib-unix/test_unix_cmdline.ml create mode 100644 testsuite/tests/lib-unix/test_unix_cmdline.reference create mode 100644 testsuite/tests/messages/Makefile create mode 100644 testsuite/tests/messages/precise_locations.ml create mode 100644 testsuite/tests/misc/gcwords.ml create mode 100644 testsuite/tests/misc/gcwords.reference create mode 100644 testsuite/tests/regression/missing_set_of_closures/Makefile create mode 100644 testsuite/tests/regression/missing_set_of_closures/a.ml create mode 100644 testsuite/tests/regression/missing_set_of_closures/b.ml create mode 100644 testsuite/tests/regression/missing_set_of_closures/b2.ml create mode 100644 testsuite/tests/regression/missing_set_of_closures/dir/c.ml rename otherlibs/str/Makefile.shared => testsuite/tests/regression/pr7426/Makefile (65%) create mode 100644 testsuite/tests/regression/pr7426/pr7426.ml create mode 100644 testsuite/tests/regression/pr7426/pr7426.reference create mode 100644 testsuite/tests/runtime-C-exceptions/Makefile create mode 100644 testsuite/tests/runtime-C-exceptions/stub_test.c create mode 100644 testsuite/tests/runtime-C-exceptions/test.ml create mode 100644 testsuite/tests/runtime-C-exceptions/test.reference create mode 100644 testsuite/tests/tool-command-line/Makefile create mode 100644 testsuite/tests/tool-command-line/unknown-file create mode 100644 testsuite/tests/tool-command-line/unknown-file.byte.reference create mode 100644 testsuite/tests/tool-command-line/unknown-file.opt.reference create mode 100644 testsuite/tests/tool-ocamlc-open/Makefile create mode 100644 testsuite/tests/tool-ocamlc-open/a.ml create mode 100644 testsuite/tests/tool-ocamlc-open/b.ml create mode 100644 testsuite/tests/tool-ocamldoc-2/loop.ml create mode 100644 testsuite/tests/tool-ocamldoc-2/loop.reference create mode 100644 testsuite/tests/tool-ocamldoc-2/short_description.reference create mode 100644 testsuite/tests/tool-ocamldoc-2/short_description.txt create mode 100644 testsuite/tests/tool-ocamldoc-2/variants.mli create mode 100644 testsuite/tests/tool-ocamldoc-2/variants.reference create mode 100644 testsuite/tests/tool-ocamldoc-html/Loop.ml create mode 100644 testsuite/tests/tool-ocamldoc-html/Loop.reference create mode 100644 testsuite/tests/tool-ocamldoc-html/Module_whitespace.ml create mode 100644 testsuite/tests/tool-ocamldoc-html/Module_whitespace.reference create mode 100644 testsuite/tests/tool-ocamldoc-html/Variants.mli create mode 100644 testsuite/tests/tool-ocamldoc-html/Variants.reference create mode 100644 testsuite/tests/tool-ocamldoc/t05.ml create mode 100644 testsuite/tests/tool-ocamldoc/t05.reference create mode 100644 testsuite/tests/tool-toplevel-invocation/Makefile create mode 100644 testsuite/tests/tool-toplevel-invocation/first_arg_fail.txt create mode 100644 testsuite/tests/tool-toplevel-invocation/first_arg_fail.txt.reference create mode 100644 testsuite/tests/tool-toplevel-invocation/indirect_first_arg_fail.txt create mode 100644 testsuite/tests/tool-toplevel-invocation/indirect_first_arg_fail.txt.reference create mode 100644 testsuite/tests/tool-toplevel-invocation/indirect_last_arg_fail.txt create mode 100644 testsuite/tests/tool-toplevel-invocation/indirect_last_arg_fail.txt.reference create mode 100644 testsuite/tests/tool-toplevel-invocation/last_arg_fail.txt create mode 100644 testsuite/tests/tool-toplevel-invocation/last_arg_fail.txt.reference create mode 100644 testsuite/tests/tool-toplevel-invocation/test.ml create mode 100644 testsuite/tests/tool-toplevel-invocation/working_arg.txt create mode 100644 testsuite/tests/tool-toplevel-invocation/working_arg.txt.reference create mode 100644 testsuite/tests/tool-toplevel/pr7060.ml create mode 100644 testsuite/tests/tool-toplevel/pr7060.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr7421.ml create mode 100644 testsuite/tests/typing-gadts/pr7432.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr7414_bad.ml create mode 100644 testsuite/tests/typing-modules/pr7348.ml create mode 100644 testsuite/tests/warnings/w04.ml create mode 100644 testsuite/tests/warnings/w04.reference create mode 100644 testsuite/tests/warnings/w33.ml create mode 100644 testsuite/tests/warnings/w33.reference create mode 100755 testsuite/tests/warnings/w60.ml create mode 100755 testsuite/tests/warnings/w60.mli create mode 100644 testsuite/tests/warnings/w60.reference delete mode 100644 tools/Makefile.shared create mode 100644 tools/lintapidiff.ml create mode 100644 tools/make_opcodes.mll create mode 100644 typing/HACKING.adoc create mode 100644 utils/targetint.ml create mode 100644 utils/targetint.mli diff --git a/.depend b/.depend index 45132604..b46b8e42 100644 --- a/.depend +++ b/.depend @@ -31,6 +31,9 @@ utils/strongly_connected_components.cmo : utils/numbers.cmi utils/misc.cmi \ utils/strongly_connected_components.cmx : utils/numbers.cmx utils/misc.cmx \ utils/identifiable.cmx utils/strongly_connected_components.cmi utils/strongly_connected_components.cmi : utils/identifiable.cmi +utils/targetint.cmo : utils/misc.cmi utils/targetint.cmi +utils/targetint.cmx : utils/misc.cmx utils/targetint.cmi +utils/targetint.cmi : utils/tbl.cmo : utils/tbl.cmi utils/tbl.cmx : utils/tbl.cmi utils/tbl.cmi : @@ -43,12 +46,12 @@ utils/timings.cmi : utils/warnings.cmo : utils/misc.cmi utils/warnings.cmi utils/warnings.cmx : utils/misc.cmx utils/warnings.cmi utils/warnings.cmi : -parsing/ast_helper.cmo : parsing/parsetree.cmi parsing/longident.cmi \ - parsing/location.cmi parsing/docstrings.cmi parsing/asttypes.cmi \ - parsing/ast_helper.cmi -parsing/ast_helper.cmx : parsing/parsetree.cmi parsing/longident.cmx \ - parsing/location.cmx parsing/docstrings.cmx parsing/asttypes.cmi \ - parsing/ast_helper.cmi +parsing/ast_helper.cmo : parsing/syntaxerr.cmi parsing/parsetree.cmi \ + parsing/longident.cmi parsing/location.cmi parsing/docstrings.cmi \ + parsing/asttypes.cmi parsing/ast_helper.cmi +parsing/ast_helper.cmx : parsing/syntaxerr.cmx parsing/parsetree.cmi \ + parsing/longident.cmx parsing/location.cmx parsing/docstrings.cmx \ + parsing/asttypes.cmi parsing/ast_helper.cmi parsing/ast_helper.cmi : parsing/parsetree.cmi parsing/longident.cmi \ parsing/location.cmi parsing/docstrings.cmi parsing/asttypes.cmi parsing/ast_invariants.cmo : parsing/syntaxerr.cmi parsing/parsetree.cmi \ @@ -133,10 +136,10 @@ parsing/parsetree.cmi : parsing/longident.cmi parsing/location.cmi \ parsing/asttypes.cmi parsing/pprintast.cmo : parsing/parsetree.cmi utils/misc.cmi \ parsing/longident.cmi parsing/location.cmi parsing/asttypes.cmi \ - parsing/pprintast.cmi + parsing/ast_helper.cmi parsing/pprintast.cmi parsing/pprintast.cmx : parsing/parsetree.cmi utils/misc.cmx \ parsing/longident.cmx parsing/location.cmx parsing/asttypes.cmi \ - parsing/pprintast.cmi + parsing/ast_helper.cmx parsing/pprintast.cmi parsing/pprintast.cmi : parsing/parsetree.cmi parsing/printast.cmo : parsing/parsetree.cmi utils/misc.cmi \ parsing/longident.cmi parsing/location.cmi parsing/asttypes.cmi \ @@ -426,9 +429,9 @@ typing/typemod.cmo : utils/warnings.cmi typing/typetexp.cmi typing/types.cmi \ typing/mtype.cmi utils/misc.cmi parsing/longident.cmi \ parsing/location.cmi typing/includemod.cmi typing/ident.cmi \ typing/env.cmi typing/ctype.cmi utils/config.cmi typing/cmt_format.cmi \ - utils/clflags.cmi parsing/builtin_attributes.cmi typing/btype.cmi \ - parsing/asttypes.cmi parsing/ast_iterator.cmi typing/annot.cmi \ - typing/typemod.cmi + typing/cmi_format.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \ + typing/btype.cmi parsing/asttypes.cmi parsing/ast_iterator.cmi \ + typing/annot.cmi typing/typemod.cmi typing/typemod.cmx : utils/warnings.cmx typing/typetexp.cmx typing/types.cmx \ typing/typedtree.cmx typing/typedecl.cmx typing/typecore.cmx \ typing/typeclass.cmx typing/subst.cmx typing/stypes.cmx \ @@ -436,13 +439,13 @@ typing/typemod.cmx : utils/warnings.cmx typing/typetexp.cmx typing/types.cmx \ typing/mtype.cmx utils/misc.cmx parsing/longident.cmx \ parsing/location.cmx typing/includemod.cmx typing/ident.cmx \ typing/env.cmx typing/ctype.cmx utils/config.cmx typing/cmt_format.cmx \ - utils/clflags.cmx parsing/builtin_attributes.cmx typing/btype.cmx \ - parsing/asttypes.cmi parsing/ast_iterator.cmx typing/annot.cmi \ - typing/typemod.cmi + typing/cmi_format.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \ + typing/btype.cmx parsing/asttypes.cmi parsing/ast_iterator.cmx \ + typing/annot.cmi typing/typemod.cmi typing/typemod.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \ parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ parsing/location.cmi typing/includemod.cmi typing/ident.cmi \ - typing/env.cmi parsing/asttypes.cmi + typing/env.cmi typing/cmi_format.cmi parsing/asttypes.cmi typing/types.cmo : typing/primitive.cmi typing/path.cmi \ parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ typing/ident.cmi parsing/asttypes.cmi typing/types.cmi @@ -525,7 +528,7 @@ bytecomp/bytepackager.cmi : typing/ident.cmi typing/env.cmi bytecomp/bytesections.cmo : utils/config.cmi bytecomp/bytesections.cmi bytecomp/bytesections.cmx : utils/config.cmx bytecomp/bytesections.cmi bytecomp/bytesections.cmi : -bytecomp/cmo_format.cmi : bytecomp/lambda.cmi typing/ident.cmi +bytecomp/cmo_format.cmi : utils/tbl.cmi bytecomp/lambda.cmi typing/ident.cmi bytecomp/dll.cmo : utils/misc.cmi utils/config.cmi bytecomp/dll.cmi bytecomp/dll.cmx : utils/misc.cmx utils/config.cmx bytecomp/dll.cmi bytecomp/dll.cmi : @@ -597,6 +600,11 @@ bytecomp/printlambda.cmi : bytecomp/lambda.cmi bytecomp/runtimedef.cmo : bytecomp/runtimedef.cmi bytecomp/runtimedef.cmx : bytecomp/runtimedef.cmi bytecomp/runtimedef.cmi : +bytecomp/semantics_of_primitives.cmo : bytecomp/lambda.cmi \ + bytecomp/semantics_of_primitives.cmi +bytecomp/semantics_of_primitives.cmx : bytecomp/lambda.cmx \ + bytecomp/semantics_of_primitives.cmi +bytecomp/semantics_of_primitives.cmi : bytecomp/lambda.cmi bytecomp/simplif.cmo : utils/warnings.cmi utils/tbl.cmi typing/stypes.cmi \ utils/misc.cmi parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ utils/clflags.cmi parsing/asttypes.cmi typing/annot.cmi \ @@ -620,7 +628,7 @@ bytecomp/symtable.cmx : utils/tbl.cmx bytecomp/runtimedef.cmx \ bytecomp/lambda.cmx typing/ident.cmx bytecomp/dll.cmx utils/config.cmx \ bytecomp/cmo_format.cmi utils/clflags.cmx bytecomp/bytesections.cmx \ parsing/asttypes.cmi bytecomp/symtable.cmi -bytecomp/symtable.cmi : utils/misc.cmi typing/ident.cmi \ +bytecomp/symtable.cmi : utils/misc.cmi bytecomp/lambda.cmi typing/ident.cmi \ bytecomp/cmo_format.cmi bytecomp/translattribute.cmo : utils/warnings.cmi typing/typedtree.cmi \ parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ @@ -645,16 +653,16 @@ bytecomp/translclass.cmx : typing/types.cmx bytecomp/typeopt.cmx \ bytecomp/translclass.cmi : typing/typedtree.cmi parsing/location.cmi \ bytecomp/lambda.cmi typing/ident.cmi parsing/asttypes.cmi bytecomp/translcore.cmo : typing/types.cmi bytecomp/typeopt.cmi \ - typing/typedtree.cmi bytecomp/translobj.cmi bytecomp/translattribute.cmi \ - typing/primitive.cmi typing/predef.cmi typing/path.cmi \ - typing/parmatch.cmi utils/misc.cmi bytecomp/matching.cmi \ + typing/typedtree.cmi typing/typecore.cmi bytecomp/translobj.cmi \ + bytecomp/translattribute.cmi typing/primitive.cmi typing/predef.cmi \ + typing/path.cmi typing/parmatch.cmi utils/misc.cmi bytecomp/matching.cmi \ parsing/longident.cmi parsing/location.cmi bytecomp/lambda.cmi \ typing/ident.cmi typing/env.cmi utils/config.cmi utils/clflags.cmi \ typing/btype.cmi parsing/asttypes.cmi bytecomp/translcore.cmi bytecomp/translcore.cmx : typing/types.cmx bytecomp/typeopt.cmx \ - typing/typedtree.cmx bytecomp/translobj.cmx bytecomp/translattribute.cmx \ - typing/primitive.cmx typing/predef.cmx typing/path.cmx \ - typing/parmatch.cmx utils/misc.cmx bytecomp/matching.cmx \ + typing/typedtree.cmx typing/typecore.cmx bytecomp/translobj.cmx \ + bytecomp/translattribute.cmx typing/primitive.cmx typing/predef.cmx \ + typing/path.cmx typing/parmatch.cmx utils/misc.cmx bytecomp/matching.cmx \ parsing/longident.cmx parsing/location.cmx bytecomp/lambda.cmx \ typing/ident.cmx typing/env.cmx utils/config.cmx utils/clflags.cmx \ typing/btype.cmx parsing/asttypes.cmi bytecomp/translcore.cmi @@ -701,8 +709,15 @@ asmcomp/CSEgen.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ asmcomp/CSEgen.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ asmcomp/cmm.cmx asmcomp/CSEgen.cmi asmcomp/CSEgen.cmi : asmcomp/mach.cmi -asmcomp/arch.cmo : utils/clflags.cmi -asmcomp/arch.cmx : utils/clflags.cmx +asmcomp/afl_instrument.cmo : bytecomp/lambda.cmi typing/ident.cmi \ + middle_end/debuginfo.cmi asmcomp/cmm.cmi utils/clflags.cmi \ + parsing/asttypes.cmi asmcomp/afl_instrument.cmi +asmcomp/afl_instrument.cmx : bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/debuginfo.cmx asmcomp/cmm.cmx utils/clflags.cmx \ + parsing/asttypes.cmi asmcomp/afl_instrument.cmi +asmcomp/afl_instrument.cmi : asmcomp/cmm.cmi +asmcomp/arch.cmo : utils/config.cmi utils/clflags.cmi +asmcomp/arch.cmx : utils/config.cmx utils/clflags.cmx asmcomp/asmgen.cmo : asmcomp/un_anf.cmi bytecomp/translmod.cmi \ utils/timings.cmi middle_end/base_types/symbol.cmi asmcomp/split.cmi \ asmcomp/spill.cmi asmcomp/selection.cmi asmcomp/scheduling.cmi \ @@ -811,14 +826,16 @@ asmcomp/clambda.cmx : bytecomp/lambda.cmx typing/ident.cmx \ asmcomp/clambda.cmi : bytecomp/lambda.cmi typing/ident.cmi \ middle_end/debuginfo.cmi parsing/asttypes.cmi asmcomp/closure.cmo : utils/warnings.cmi utils/tbl.cmi bytecomp/switch.cmi \ - bytecomp/simplif.cmi typing/primitive.cmi utils/misc.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ + bytecomp/simplif.cmi bytecomp/semantics_of_primitives.cmi \ + typing/primitive.cmi utils/misc.cmi parsing/location.cmi \ + bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ middle_end/debuginfo.cmi utils/config.cmi asmcomp/compilenv.cmi \ utils/clflags.cmi asmcomp/clambda.cmi parsing/asttypes.cmi \ asmcomp/arch.cmo asmcomp/closure.cmi asmcomp/closure.cmx : utils/warnings.cmx utils/tbl.cmx bytecomp/switch.cmx \ - bytecomp/simplif.cmx typing/primitive.cmx utils/misc.cmx \ - parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ + bytecomp/simplif.cmx bytecomp/semantics_of_primitives.cmx \ + typing/primitive.cmx utils/misc.cmx parsing/location.cmx \ + bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ middle_end/debuginfo.cmx utils/config.cmx asmcomp/compilenv.cmx \ utils/clflags.cmx asmcomp/clambda.cmx parsing/asttypes.cmi \ asmcomp/arch.cmx asmcomp/closure.cmi @@ -836,25 +853,27 @@ asmcomp/closure_offsets.cmx : middle_end/base_types/variable.cmx \ asmcomp/closure_offsets.cmi : middle_end/base_types/var_within_closure.cmi \ middle_end/flambda.cmi middle_end/base_types/closure_id.cmi asmcomp/cmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/arch.cmo asmcomp/cmm.cmi + middle_end/debuginfo.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ + asmcomp/cmm.cmi asmcomp/cmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx asmcomp/arch.cmx asmcomp/cmm.cmi + middle_end/debuginfo.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ + asmcomp/cmm.cmi asmcomp/cmm.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi + middle_end/debuginfo.cmi parsing/asttypes.cmi asmcomp/cmmgen.cmo : asmcomp/un_anf.cmi typing/types.cmi bytecomp/switch.cmi \ asmcomp/strmatch.cmi asmcomp/proc.cmi bytecomp/printlambda.cmi \ typing/primitive.cmi utils/misc.cmi bytecomp/lambda.cmi typing/ident.cmi \ middle_end/debuginfo.cmi utils/config.cmi asmcomp/compilenv.cmi \ asmcomp/cmx_format.cmi asmcomp/cmm.cmi utils/clflags.cmi \ asmcomp/clambda.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ - asmcomp/cmmgen.cmi + asmcomp/afl_instrument.cmi asmcomp/cmmgen.cmi asmcomp/cmmgen.cmx : asmcomp/un_anf.cmx typing/types.cmx bytecomp/switch.cmx \ asmcomp/strmatch.cmx asmcomp/proc.cmx bytecomp/printlambda.cmx \ typing/primitive.cmx utils/misc.cmx bytecomp/lambda.cmx typing/ident.cmx \ middle_end/debuginfo.cmx utils/config.cmx asmcomp/compilenv.cmx \ asmcomp/cmx_format.cmi asmcomp/cmm.cmx utils/clflags.cmx \ asmcomp/clambda.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ - asmcomp/cmmgen.cmi + asmcomp/afl_instrument.cmx asmcomp/cmmgen.cmi asmcomp/cmmgen.cmi : asmcomp/cmx_format.cmi asmcomp/cmm.cmi \ asmcomp/clambda.cmi asmcomp/cmx_format.cmi : asmcomp/export_info.cmi asmcomp/clambda.cmi @@ -872,16 +891,16 @@ asmcomp/compilenv.cmo : utils/warnings.cmi middle_end/base_types/symbol.cmi \ typing/ident.cmi middle_end/flambda.cmi asmcomp/export_info.cmi \ typing/env.cmi utils/config.cmi \ middle_end/base_types/compilation_unit.cmi asmcomp/cmx_format.cmi \ - middle_end/base_types/closure_id.cmi asmcomp/clambda.cmi \ - asmcomp/compilenv.cmi + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + asmcomp/clambda.cmi asmcomp/compilenv.cmi asmcomp/compilenv.cmx : utils/warnings.cmx middle_end/base_types/symbol.cmx \ middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ parsing/location.cmx middle_end/base_types/linkage_name.cmx \ typing/ident.cmx middle_end/flambda.cmx asmcomp/export_info.cmx \ typing/env.cmx utils/config.cmx \ middle_end/base_types/compilation_unit.cmx asmcomp/cmx_format.cmi \ - middle_end/base_types/closure_id.cmx asmcomp/clambda.cmx \ - asmcomp/compilenv.cmi + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + asmcomp/clambda.cmx asmcomp/compilenv.cmi asmcomp/compilenv.cmi : utils/timings.cmi middle_end/base_types/symbol.cmi \ middle_end/base_types/set_of_closures_id.cmi \ middle_end/base_types/linkage_name.cmi typing/ident.cmi \ @@ -938,6 +957,7 @@ asmcomp/export_info.cmi : middle_end/base_types/variable.cmi \ asmcomp/export_info_for_pack.cmo : middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/symbol.cmi \ + middle_end/base_types/set_of_closures_origin.cmi \ middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ middle_end/flambda.cmi asmcomp/export_info.cmi \ @@ -947,6 +967,7 @@ asmcomp/export_info_for_pack.cmo : middle_end/base_types/variable.cmi \ asmcomp/export_info_for_pack.cmx : middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ middle_end/base_types/symbol.cmx \ + middle_end/base_types/set_of_closures_origin.cmx \ middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ middle_end/flambda.cmx asmcomp/export_info.cmx \ @@ -1000,9 +1021,9 @@ asmcomp/import_approx.cmx : middle_end/base_types/variable.cmx \ asmcomp/import_approx.cmi : middle_end/base_types/symbol.cmi \ middle_end/simple_value_approx.cmi asmcomp/interf.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ - asmcomp/interf.cmi + asmcomp/cmm.cmi asmcomp/interf.cmi asmcomp/interf.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ - asmcomp/interf.cmi + asmcomp/cmm.cmx asmcomp/interf.cmi asmcomp/interf.cmi : asmcomp/mach.cmi asmcomp/linearize.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \ asmcomp/mach.cmi middle_end/debuginfo.cmi utils/config.cmi \ @@ -1014,10 +1035,10 @@ asmcomp/linearize.cmi : asmcomp/reg.cmi asmcomp/mach.cmi \ middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/liveness.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \ asmcomp/printmach.cmi utils/misc.cmi asmcomp/mach.cmi utils/config.cmi \ - asmcomp/liveness.cmi + asmcomp/cmm.cmi asmcomp/liveness.cmi asmcomp/liveness.cmx : asmcomp/reg.cmx asmcomp/proc.cmx \ asmcomp/printmach.cmx utils/misc.cmx asmcomp/mach.cmx utils/config.cmx \ - asmcomp/liveness.cmi + asmcomp/cmm.cmx asmcomp/liveness.cmi asmcomp/liveness.cmi : asmcomp/mach.cmi asmcomp/mach.cmo : asmcomp/reg.cmi middle_end/debuginfo.cmi asmcomp/cmm.cmi \ asmcomp/arch.cmo asmcomp/mach.cmi @@ -1033,10 +1054,12 @@ asmcomp/printclambda.cmx : bytecomp/printlambda.cmx bytecomp/lambda.cmx \ asmcomp/printclambda.cmi asmcomp/printclambda.cmi : asmcomp/clambda.cmi asmcomp/printcmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/printcmm.cmi + middle_end/debuginfo.cmi asmcomp/cmm.cmi parsing/asttypes.cmi \ + asmcomp/printcmm.cmi asmcomp/printcmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx asmcomp/cmm.cmx asmcomp/printcmm.cmi -asmcomp/printcmm.cmi : asmcomp/cmm.cmi + middle_end/debuginfo.cmx asmcomp/cmm.cmx parsing/asttypes.cmi \ + asmcomp/printcmm.cmi +asmcomp/printcmm.cmi : middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/printlinear.cmo : asmcomp/printmach.cmi asmcomp/printcmm.cmi \ asmcomp/mach.cmi asmcomp/linearize.cmi middle_end/debuginfo.cmi \ asmcomp/printlinear.cmi @@ -1062,9 +1085,9 @@ asmcomp/reg.cmo : typing/ident.cmi asmcomp/cmm.cmi asmcomp/reg.cmi asmcomp/reg.cmx : typing/ident.cmx asmcomp/cmm.cmx asmcomp/reg.cmi asmcomp/reg.cmi : typing/ident.cmi asmcomp/cmm.cmi asmcomp/reload.cmo : asmcomp/reloadgen.cmi asmcomp/reg.cmi asmcomp/mach.cmi \ - asmcomp/cmm.cmi utils/clflags.cmi asmcomp/reload.cmi + asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/reload.cmi asmcomp/reload.cmx : asmcomp/reloadgen.cmx asmcomp/reg.cmx asmcomp/mach.cmx \ - asmcomp/cmm.cmx utils/clflags.cmx asmcomp/reload.cmi + asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/reload.cmi asmcomp/reload.cmi : asmcomp/mach.cmi asmcomp/reloadgen.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \ asmcomp/reloadgen.cmi @@ -1084,50 +1107,53 @@ asmcomp/scheduling.cmi : asmcomp/linearize.cmi asmcomp/selectgen.cmo : utils/tbl.cmi bytecomp/simplif.cmi asmcomp/reg.cmi \ asmcomp/proc.cmi utils/misc.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \ typing/ident.cmi middle_end/debuginfo.cmi utils/config.cmi \ - asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/selectgen.cmi + asmcomp/cmm.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ + asmcomp/selectgen.cmi asmcomp/selectgen.cmx : utils/tbl.cmx bytecomp/simplif.cmx asmcomp/reg.cmx \ asmcomp/proc.cmx utils/misc.cmx asmcomp/mach.cmx bytecomp/lambda.cmx \ typing/ident.cmx middle_end/debuginfo.cmx utils/config.cmx \ - asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/selectgen.cmi -asmcomp/selectgen.cmi : utils/tbl.cmi asmcomp/reg.cmi asmcomp/mach.cmi \ - typing/ident.cmi middle_end/debuginfo.cmi asmcomp/cmm.cmi \ - asmcomp/arch.cmo -asmcomp/selection.cmo : asmcomp/spacetime_profiling.cmi asmcomp/proc.cmi \ - asmcomp/mach.cmi utils/config.cmi asmcomp/cmm.cmi utils/clflags.cmi \ - asmcomp/arch.cmo asmcomp/selection.cmi -asmcomp/selection.cmx : asmcomp/spacetime_profiling.cmx asmcomp/proc.cmx \ - asmcomp/mach.cmx utils/config.cmx asmcomp/cmm.cmx utils/clflags.cmx \ - asmcomp/arch.cmx asmcomp/selection.cmi + asmcomp/cmm.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ + asmcomp/selectgen.cmi +asmcomp/selectgen.cmi : asmcomp/reg.cmi asmcomp/mach.cmi typing/ident.cmi \ + middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo +asmcomp/selection.cmo : asmcomp/spacetime_profiling.cmi \ + asmcomp/selectgen.cmi asmcomp/proc.cmi asmcomp/mach.cmi utils/config.cmi \ + asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/selection.cmi +asmcomp/selection.cmx : asmcomp/spacetime_profiling.cmx \ + asmcomp/selectgen.cmx asmcomp/proc.cmx asmcomp/mach.cmx utils/config.cmx \ + asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/selection.cmi asmcomp/selection.cmi : asmcomp/mach.cmi asmcomp/cmm.cmi -asmcomp/spacetime_profiling.cmo : utils/tbl.cmi asmcomp/selectgen.cmi \ - asmcomp/proc.cmi utils/misc.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \ - typing/ident.cmi middle_end/debuginfo.cmi utils/config.cmi \ - asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/spacetime_profiling.cmi -asmcomp/spacetime_profiling.cmx : utils/tbl.cmx asmcomp/selectgen.cmx \ - asmcomp/proc.cmx utils/misc.cmx asmcomp/mach.cmx bytecomp/lambda.cmx \ - typing/ident.cmx middle_end/debuginfo.cmx utils/config.cmx \ - asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/spacetime_profiling.cmi +asmcomp/spacetime_profiling.cmo : asmcomp/selectgen.cmi asmcomp/proc.cmi \ + utils/misc.cmi asmcomp/mach.cmi bytecomp/lambda.cmi typing/ident.cmi \ + middle_end/debuginfo.cmi utils/config.cmi asmcomp/cmm.cmi \ + parsing/asttypes.cmi asmcomp/arch.cmo asmcomp/spacetime_profiling.cmi +asmcomp/spacetime_profiling.cmx : asmcomp/selectgen.cmx asmcomp/proc.cmx \ + utils/misc.cmx asmcomp/mach.cmx bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/debuginfo.cmx utils/config.cmx asmcomp/cmm.cmx \ + parsing/asttypes.cmi asmcomp/arch.cmx asmcomp/spacetime_profiling.cmi asmcomp/spacetime_profiling.cmi : asmcomp/selectgen.cmi asmcomp/spill.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \ - asmcomp/mach.cmi asmcomp/spill.cmi + asmcomp/mach.cmi asmcomp/cmm.cmi asmcomp/spill.cmi asmcomp/spill.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \ - asmcomp/mach.cmx asmcomp/spill.cmi + asmcomp/mach.cmx asmcomp/cmm.cmx asmcomp/spill.cmi asmcomp/spill.cmi : asmcomp/mach.cmi asmcomp/split.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \ asmcomp/split.cmi asmcomp/split.cmx : asmcomp/reg.cmx utils/misc.cmx asmcomp/mach.cmx \ asmcomp/split.cmi asmcomp/split.cmi : asmcomp/mach.cmi -asmcomp/strmatch.cmo : bytecomp/lambda.cmi typing/ident.cmi asmcomp/cmm.cmi \ +asmcomp/strmatch.cmo : bytecomp/lambda.cmi typing/ident.cmi \ + middle_end/debuginfo.cmi asmcomp/cmm.cmi parsing/asttypes.cmi \ asmcomp/arch.cmo asmcomp/strmatch.cmi -asmcomp/strmatch.cmx : bytecomp/lambda.cmx typing/ident.cmx asmcomp/cmm.cmx \ +asmcomp/strmatch.cmx : bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/debuginfo.cmx asmcomp/cmm.cmx parsing/asttypes.cmi \ asmcomp/arch.cmx asmcomp/strmatch.cmi -asmcomp/strmatch.cmi : asmcomp/cmm.cmi -asmcomp/un_anf.cmo : middle_end/semantics_of_primitives.cmi \ +asmcomp/strmatch.cmi : middle_end/debuginfo.cmi asmcomp/cmm.cmi +asmcomp/un_anf.cmo : bytecomp/semantics_of_primitives.cmi \ asmcomp/printclambda.cmi utils/misc.cmi bytecomp/lambda.cmi \ typing/ident.cmi middle_end/debuginfo.cmi utils/clflags.cmi \ asmcomp/clambda.cmi parsing/asttypes.cmi asmcomp/un_anf.cmi -asmcomp/un_anf.cmx : middle_end/semantics_of_primitives.cmx \ +asmcomp/un_anf.cmx : bytecomp/semantics_of_primitives.cmx \ asmcomp/printclambda.cmx utils/misc.cmx bytecomp/lambda.cmx \ typing/ident.cmx middle_end/debuginfo.cmx utils/clflags.cmx \ asmcomp/clambda.cmx parsing/asttypes.cmi asmcomp/un_anf.cmi @@ -1195,12 +1221,12 @@ middle_end/backend_intf.cmi : middle_end/base_types/symbol.cmi \ middle_end/closure_conversion.cmo : middle_end/base_types/variable.cmi \ middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi bytecomp/simplif.cmi \ - bytecomp/printlambda.cmi typing/primitive.cmi typing/predef.cmi \ - utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \ - utils/misc.cmi parsing/location.cmi \ - middle_end/base_types/linkage_name.cmi middle_end/lift_code.cmi \ - bytecomp/lambda.cmi typing/ident.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda.cmi middle_end/debuginfo.cmi utils/config.cmi \ + bytecomp/printlambda.cmi typing/predef.cmi utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + parsing/location.cmi middle_end/base_types/linkage_name.cmi \ + middle_end/lift_code.cmi bytecomp/lambda.cmi typing/ident.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda.cmi \ + middle_end/debuginfo.cmi utils/config.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_id.cmi \ middle_end/closure_conversion_aux.cmi utils/clflags.cmi \ @@ -1208,12 +1234,12 @@ middle_end/closure_conversion.cmo : middle_end/base_types/variable.cmi \ middle_end/closure_conversion.cmx : middle_end/base_types/variable.cmx \ middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ middle_end/base_types/static_exception.cmx bytecomp/simplif.cmx \ - bytecomp/printlambda.cmx typing/primitive.cmx typing/predef.cmx \ - utils/numbers.cmx middle_end/base_types/mutable_variable.cmx \ - utils/misc.cmx parsing/location.cmx \ - middle_end/base_types/linkage_name.cmx middle_end/lift_code.cmx \ - bytecomp/lambda.cmx typing/ident.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda.cmx middle_end/debuginfo.cmx utils/config.cmx \ + bytecomp/printlambda.cmx typing/predef.cmx utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + parsing/location.cmx middle_end/base_types/linkage_name.cmx \ + middle_end/lift_code.cmx bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda.cmx \ + middle_end/debuginfo.cmx utils/config.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_id.cmx \ middle_end/closure_conversion_aux.cmx utils/clflags.cmx \ @@ -1222,15 +1248,15 @@ middle_end/closure_conversion.cmi : bytecomp/lambda.cmi typing/ident.cmi \ middle_end/flambda.cmi middle_end/backend_intf.cmi middle_end/closure_conversion_aux.cmo : middle_end/base_types/variable.cmi \ middle_end/base_types/symbol.cmi \ - middle_end/base_types/static_exception.cmi typing/primitive.cmi \ - utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \ - utils/misc.cmi parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ + middle_end/base_types/static_exception.cmi utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ middle_end/closure_conversion_aux.cmi middle_end/closure_conversion_aux.cmx : middle_end/base_types/variable.cmx \ middle_end/base_types/symbol.cmx \ - middle_end/base_types/static_exception.cmx typing/primitive.cmx \ - utils/numbers.cmx middle_end/base_types/mutable_variable.cmx \ - utils/misc.cmx parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/base_types/static_exception.cmx utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ middle_end/closure_conversion_aux.cmi middle_end/closure_conversion_aux.cmi : middle_end/base_types/variable.cmi \ middle_end/base_types/symbol.cmi \ @@ -1240,10 +1266,10 @@ middle_end/closure_conversion_aux.cmi : middle_end/base_types/variable.cmi \ middle_end/debuginfo.cmo : parsing/location.cmi middle_end/debuginfo.cmi middle_end/debuginfo.cmx : parsing/location.cmx middle_end/debuginfo.cmi middle_end/debuginfo.cmi : parsing/location.cmi -middle_end/effect_analysis.cmo : middle_end/semantics_of_primitives.cmi \ +middle_end/effect_analysis.cmo : bytecomp/semantics_of_primitives.cmi \ utils/misc.cmi bytecomp/lambda.cmi middle_end/flambda.cmi \ middle_end/effect_analysis.cmi -middle_end/effect_analysis.cmx : middle_end/semantics_of_primitives.cmx \ +middle_end/effect_analysis.cmx : bytecomp/semantics_of_primitives.cmx \ utils/misc.cmx bytecomp/lambda.cmx middle_end/flambda.cmx \ middle_end/effect_analysis.cmi middle_end/effect_analysis.cmi : middle_end/flambda.cmi @@ -1722,11 +1748,6 @@ middle_end/remove_unused_program_constructs.cmx : \ middle_end/effect_analysis.cmx \ middle_end/remove_unused_program_constructs.cmi middle_end/remove_unused_program_constructs.cmi : middle_end/flambda.cmi -middle_end/semantics_of_primitives.cmo : bytecomp/printlambda.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/semantics_of_primitives.cmi -middle_end/semantics_of_primitives.cmx : bytecomp/printlambda.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/semantics_of_primitives.cmi -middle_end/semantics_of_primitives.cmi : bytecomp/lambda.cmi middle_end/share_constants.cmo : middle_end/base_types/symbol.cmi \ middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ middle_end/share_constants.cmi @@ -1737,7 +1758,8 @@ middle_end/share_constants.cmi : middle_end/flambda.cmi middle_end/simple_value_approx.cmo : middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/inlining_cost.cmi \ + middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ + bytecomp/lambda.cmi middle_end/inlining_cost.cmi \ middle_end/freshening.cmi middle_end/flambda_utils.cmi \ middle_end/flambda.cmi middle_end/base_types/export_id.cmi \ middle_end/effect_analysis.cmi middle_end/base_types/closure_id.cmi \ @@ -1745,7 +1767,8 @@ middle_end/simple_value_approx.cmo : middle_end/base_types/variable.cmi \ middle_end/simple_value_approx.cmx : middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/inlining_cost.cmx \ + middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ + bytecomp/lambda.cmx middle_end/inlining_cost.cmx \ middle_end/freshening.cmx middle_end/flambda_utils.cmx \ middle_end/flambda.cmx middle_end/base_types/export_id.cmx \ middle_end/effect_analysis.cmx middle_end/base_types/closure_id.cmx \ @@ -1753,7 +1776,8 @@ middle_end/simple_value_approx.cmx : middle_end/base_types/variable.cmx \ middle_end/simple_value_approx.cmi : middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ - bytecomp/lambda.cmi middle_end/freshening.cmi middle_end/flambda.cmi \ + middle_end/base_types/set_of_closures_id.cmi bytecomp/lambda.cmi \ + middle_end/freshening.cmi middle_end/flambda.cmi \ middle_end/base_types/export_id.cmi middle_end/base_types/closure_id.cmi middle_end/simplify_boxed_integer_ops.cmo : middle_end/simplify_common.cmi \ middle_end/simplify_boxed_integer_ops_intf.cmi \ @@ -1779,14 +1803,14 @@ middle_end/simplify_common.cmi : middle_end/simple_value_approx.cmi \ middle_end/simplify_primitives.cmo : middle_end/base_types/tag.cmi \ middle_end/base_types/symbol.cmi middle_end/simplify_common.cmi \ middle_end/simplify_boxed_integer_ops.cmi \ - middle_end/simple_value_approx.cmi middle_end/semantics_of_primitives.cmi \ + middle_end/simple_value_approx.cmi bytecomp/semantics_of_primitives.cmi \ utils/misc.cmi bytecomp/lambda.cmi middle_end/inlining_cost.cmi \ middle_end/flambda.cmi utils/clflags.cmi parsing/asttypes.cmi \ middle_end/simplify_primitives.cmi middle_end/simplify_primitives.cmx : middle_end/base_types/tag.cmx \ middle_end/base_types/symbol.cmx middle_end/simplify_common.cmx \ middle_end/simplify_boxed_integer_ops.cmx \ - middle_end/simple_value_approx.cmx middle_end/semantics_of_primitives.cmx \ + middle_end/simple_value_approx.cmx bytecomp/semantics_of_primitives.cmx \ utils/misc.cmx bytecomp/lambda.cmx middle_end/inlining_cost.cmx \ middle_end/flambda.cmx utils/clflags.cmx parsing/asttypes.cmi \ middle_end/simplify_primitives.cmi @@ -1972,11 +1996,11 @@ driver/compile.cmx : utils/warnings.cmx typing/typemod.cmx \ driver/compmisc.cmx driver/compenv.cmx utils/clflags.cmx \ bytecomp/bytegen.cmx parsing/builtin_attributes.cmx driver/compile.cmi driver/compile.cmi : -driver/compmisc.cmo : typing/typemod.cmi utils/misc.cmi \ +driver/compmisc.cmo : utils/warnings.cmi typing/typemod.cmi utils/misc.cmi \ parsing/longident.cmi parsing/location.cmi typing/ident.cmi \ typing/env.cmi utils/config.cmi driver/compenv.cmi utils/clflags.cmi \ parsing/asttypes.cmi driver/compmisc.cmi -driver/compmisc.cmx : typing/typemod.cmx utils/misc.cmx \ +driver/compmisc.cmx : utils/warnings.cmx typing/typemod.cmx utils/misc.cmx \ parsing/longident.cmx parsing/location.cmx typing/ident.cmx \ typing/env.cmx utils/config.cmx driver/compenv.cmx utils/clflags.cmx \ parsing/asttypes.cmi driver/compmisc.cmi diff --git a/.gitattributes b/.gitattributes index be13cb1a..a816cdfe 100644 --- a/.gitattributes +++ b/.gitattributes @@ -24,6 +24,11 @@ *.png binary *.tfm binary +# 'union' merge driver just unions textual content in case of conflict +# http://krlmlr.github.io/using-gitattributes-to-avoid-merge-conflicts/ +/.mailmap merge=union +/Changes merge=union + # No header for text files (would be too obtrusive). *.md ocaml-typo=missing-header README* ocaml-typo=missing-header @@ -128,3 +133,35 @@ testsuite/tests/parsing/*.ml text eol=lf # Similarly, the docstring tests fail for the same reason on Windows testsuite/tests/docstrings/empty.ml text eol=lf + +# And w04.ml +testsuite/tests/warnings/w04.ml text eol=lf + +# These are forced to \n to allow the Cygwin testsuite to pass on a +# Windows-checkout +testsuite/tests/formatting/margins.ml text eol=lf +testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml text eol=lf +testsuite/tests/typing-extension-constructor/test.ml text eol=lf +testsuite/tests/typing-extensions/extensions.ml text eol=lf +testsuite/tests/typing-extensions/open_types.ml text eol=lf +testsuite/tests/typing-objects/Exemples.ml text eol=lf +testsuite/tests/typing-objects/pr5619_bad.ml text eol=lf +testsuite/tests/typing-objects/pr6123_bad.ml text eol=lf +testsuite/tests/typing-objects/pr6907_bad.ml text eol=lf +testsuite/tests/typing-objects/Tests.ml text eol=lf +testsuite/tests/typing-pattern_open/pattern_open.ml text eol=lf +testsuite/tests/typing-private/private.ml text eol=lf +testsuite/tests/typing-recordarg/recordarg.ml text eol=lf +testsuite/tests/typing-short-paths/pr5918.ml text eol=lf +testsuite/tests/typing-sigsubst/sigsubst.ml text eol=lf +testsuite/tests/typing-typeparam/newtype.ml text eol=lf +testsuite/tests/typing-unboxed/test.ml text eol=lf +testsuite/tests/typing-unboxed-types/test.ml text eol=lf +testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml text eol=lf +testsuite/tests/typing-warnings/coercions.ml text eol=lf +testsuite/tests/typing-warnings/exhaustiveness.ml text eol=lf +testsuite/tests/typing-warnings/pr6872.ml text eol=lf +testsuite/tests/typing-warnings/pr7085.ml text eol=lf +testsuite/tests/typing-warnings/pr7115.ml text eol=lf +testsuite/tests/typing-warnings/records.ml text eol=lf +testsuite/tests/typing-warnings/unused_types.ml text eol=lf diff --git a/.gitignore b/.gitignore index 332ecb86..04da75db 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ /asmrun/*.p.c /asmrun/*.d.c /asmrun/alloc.c +/asmrun/afl.c /asmrun/array.c /asmrun/backtrace.c /asmrun/callback.c @@ -94,6 +95,7 @@ /asmrun/terminfo.c /asmrun/unix.c /asmrun/weak.c +/asmrun/win32.c /boot/Saved /boot/ocamlrun @@ -121,6 +123,7 @@ /config/m.h /config/s.h /config/Makefile +/config/auto-aux/hashbang4 /debugger/lexer.ml /debugger/parser.ml @@ -360,6 +363,8 @@ /tools/cmpbyt.opt /tools/stripdebug /tools/stripdebug.opt +/tools/make_opcodes +/tools/make_opcodes.ml /utils/config.ml diff --git a/.mailmap b/.mailmap index 96b52348..b4483d02 100644 --- a/.mailmap +++ b/.mailmap @@ -32,8 +32,8 @@ Jérémie Dimino # # Preferred Name nickname # or -# Preferred Name -# Preferred Name @github.com +# Preferred Name +# Preferred Name # to indicate a preference associated to a Mantis account. Florian Angeletti octachron @@ -46,6 +46,7 @@ Simon Cruanes Frederic Bour David Sheets David Allsopp +David Allsopp Tim Cuthbertson Grégoire Henry Julien Moutinho @@ -68,6 +69,13 @@ Reed Wilson David Scott Martin Neuhäußer Goswin von Brederlow +Thomas Leonard +Thomas Leonard +Adrien Nader +Sébastien Hinderer +Gabriel Scherer +Immanuel Litzroth +Jacques Le Normand # These contributors prefer to be referred to pseudonymously diff --git a/.travis-ci.sh b/.travis-ci.sh index a0df8aa1..2722fef3 100755 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -18,7 +18,7 @@ PREFIX=~/local BuildAndTest () { case $XARCH in i386) - echo< /dev/null \ - && exit 1 || echo pass + && CheckNoChangesMessage || echo pass +} + +CheckNoChangesMessage () { + if test -n "$(git log --grep="[Nn]o [Cc]hange.* needed" --max-count=1 $TRAVIS_COMMIT_RANGE)" + then echo pass + elif test -n "$(curl https://api.github.com/repos/$TRAVIS_REPO_SLUG/issues/$TRAVIS_PULL_REQUEST/labels \ + | grep 'no-change-entry-needed')" + then echo pass + else exit 1 + fi } CheckTestsuiteModified () { - echo<" + and "0 mod " in the case when was a non-constant + evaluating to zero + (Mark Shinwell) + +- MPR#7357, GPR#832: Improve compilation time for toplevel + include(struct ... end : sig ... end) + (Alain Frisch, report by Hongbo Zhang, review by Jacques Garrigue) + +- GPR#504: Instrumentation support for fuzzing with afl-fuzz. + (Stephen Dolan, review by Alain Frisch, Pierre Chambart, Mark + Shinwell, Gabriel Scherer and Damien Doligez) + +- GPR#863, GPR#1068, GPR#1069: Optimise matches with constant + results to lookup tables. + (Stephen Dolan, review by Gabriel Scherer, Pierre Chambart, + Mark Shinwell, and bug report by Gabriel Scherer) + +- GPR#1150: Fix typo in arm64 assembler directives + (KC Sivaramakrishnan) + +- PR#7533, GPR#1173: Correctly perform side effects for certain + cases of "/" and "mod" + (Mark Shinwell, report by Jan Mitgaard) + +### Runtime system: + +- MPR#385, GPR#953: Add caml_startup_exn + (Mark Shinwell) + +- PR#7423, GPR#946: expose new exception-raising functions + `void caml_{failwith,invalid_argument}_value(value msg)` + in addition to + `void caml_{failwith,invalid_argument}(char const *msg)`. + The previous functions would not free their message argument, so + were inconvient for dynamically-allocated messages; the messages + passed to the new functions are handled by the garbage collector. + (Gabriel Scherer, review by Mark Shinwell, request by Immanuel Litzroth) + +- PR#7557, GPR#1213: More security for getenv + (Damien Doligez, reports by Seth Arnold and Eric Milliken, review by + Xavier Leroy, David Allsopp, Stephen Dolan, Hannes Mehnert) + +- GPR#795: remove 256-character limitation on Sys.executable_name + (Xavier Leroy) + +- GPR#891: Use -fno-builtin-memcmp when building runtime with gcc. + (Leo White) + +### Type system: + +- PR#6608, GPR#901: unify record types when overriding all fields + (Tadeu Zagallo and Gabriel Scherer, report by Jeremy Yallop, + review by David Allsopp, Jacques Garrigue) + +* PR#7414, GPR#929: Soundness bug with non-generalized type variables and + functors. + (Jacques Garrigue, report by Leo White) + +### Compiler user-interface and warnings: + +- PR#7050, GPR#748 GPR#843 GPR#864: new `-args/-args0 ` parameters to + provide extra command-line arguments in a file -- see documentation. + User programs may implement similar options using the new `Expand` + constructor of the `Arg` module. + (Bernhard Schommer, review by Jérémie Dimino, Gabriel Scherer + and Damien Doligez, discussion with Alain Frisch and Xavier Leroy, + feature request from the Coq team) + +- PR#7137, GPR#960: "-open" command line flag now accepts a module path + (not a module name) (Arseniy Alekseyev and Leo White) + +- PR#7172, GPR#970: add extra (ocamlc -config) options + int_size, word_size, ext_exe + (Gabriel Scherer, request by Daniel Bünzli) + +- PR#7315, GPR#736: refine some error locations + (Gabriel Scherer and Alain Frisch, report by Matej Košík) + +- PR#7473, GPR#1025: perform proper globbing for command-line arguments on + Windows + (Jonathan Protzenko) + +- PR#7479: make sure "ocamlc -pack" is only given .cmo and .cmi files, + and that "ocamlopt -pack" is only given .cmx and .cmi files. + (Xavier Leroy) + +- GPR#796: allow compiler plugins to declare their own arguments. + (Fabrice Le Fessant) + +- GPR#829: better error when opening a module aliased to a functor + (Alain Frisch) + +- GPR#911: ocamlc/ocamlopt do not pass warnings-related options to C + compiler when called to compile third-party C source files + (Sébastien Hinderer) + +- GPR#915: fix -dsource (pprintast.ml) bugs + (Runhang Li, review by Alain Frisch) + +* GPR#933: ocamlopt -p now reports an error on platforms that do not + support profiling with gprof; dummy profiling libraries are no longer + installed on such platforms. + This can be tested with ocamlopt -config + (Sébastien Hinderer) + +- GPR#1009: "ocamlc -c -linkall" and "ocamlopt -c -linkall" can now be used + to set the "always link" flag on individual compilation units. This + controls linking with finer granularity than "-a -linkall", which sets + the "always link" flag on all units of the given library. + (Xavier Leroy) + +- GPR#1015: add option "-plugin PLUGIN" to ocamldep too. Use compilerlibs + to build ocamldep. + (Fabrice Le Fessant) + +- GPR#1027: various improvements to -dtimings, mostly including time + spent in subprocesses like preprocessors + (Valentin Gatien-Baron, review by Gabriel Scherer) + +- GPR#1098: the compiler now takes the boolean "OCAML_COLOR" environment + variable into account if "-color" is not provided. This allows users + to override the default behaviour without modifying invocations of ocaml + manually. + (Hannes Mehnert, Guillaume Bury, + review by Daniel Bünzli, Gabriel Scherer, Damien Doligez) + +### Standard library: + +- PR#6975, GPR#902: Truncate function added to stdlib Buffer module + (Dhruv Makwana, review by Alain Frisch and Gabriel Scherer) + +- PR#7279 GPR#710: `Weak.get_copy` `Ephemeron.*_copy` doesn't copy + custom blocks anymore + (François Bobot, Alain Frisch, bug reported by Martin R. Neuhäußer, + review by Thomas Braibant and Damien Doligez) + +* PR#7500, GPR#1081: Remove Uchar.dump + (Daniel Bünzli) + +- GPR#760: Add a functions List.compare_lengths and + List.compare_length_with to avoid full list length computations + (Fabrice Le Fessant) + +- GPR#778: Arg: added option Expand that allows to expand a string + argument to a string array of new arguments + (Bernhard Schommer) + +- GPR#849: Exposed Spacetime.enabled value + (Leo White) + +- GPR#885: Option-returning variants of stdlib functions + (Alain Frisch, review by David Allsopp and Bart Jacobs) + +- GPR#869: Add find_first, find_first_opt, find_last, find_last_opt to + maps and sets. Find the first or last binding or element + satisfying a monotonic predicate. + (Gabriel de Perthuis, with contributions from Alain Frisch, review by + Hezekiah M. Carty and Simon Cruanes, initial report by Gerd Stolpmann) + +- GPR#875: Add missing functions to ArrayLabels, BytesLabels, + ListLabels, MoreLabels, StringLabels so they are compatible with + non-labeled counterparts. + (Roma Sokolov) + +- GPR#999: Arg, do not repeat thrice usage_msg when reporting an error + (Florian Angeletti, review by Gabriel Scherer) + +- GPR#1042: Fix escaping of command-line arguments in + Unix.create_process{,_env} under Windows. Arguments with tabs should now + be received verbatim by the child process. + (Nicolas Ojeda Bar, Andreas Hauptmann review by Xavier Leroy) + +### Debugging and profiling: + +- PR#7258: ocamldebug's "install_printer" command had problems with + module aliases + (Xavier Leroy) + +- GPR#378: Add [Printexc.raise_with_backtrace] to raise an exception using + an explicit backtrace + (François Bobot, review by Gabriel Scherer, Xavier Leroy, Damien Doligez, + Frédéric Bour) + +### Manual and documentation: + +- PR#6597, GPR#1030: add forward references to language extensions + that extend non-terminal symbols in the language reference section. + (Florian Angeletti, review by Gabriel Scherer) + +- PR#7497, GPR#1095: manual, enable numbering for table of contents + (Florian Angeletti, request by Daniel Bünzli) + +- PR#7539, GPR#1181: manual, update dead links in ocamldoc chapter + (Florian Angeletti) + +- GPR#633: manpage and manual documentation for the `-opaque` option + (Konstantin Romanov, Gabriel Scherer, review by Mark Shinwell) + +- GPR#916: new tool lintapidiff, use it to update the manual with + @since annotations for API changes introduced between 4.00-4.05. + (Edwin Török, review by Gabriel Scherer, discussion with Alain Frisch, + David Allsopp, Sébastien Hinderer, Damien Doligez and Xavier Leroy) + +- GPR#939: activate the caml_example environment in the language + extensions section of the manual. Convert some existing code + examples to this format. + (Florian Angeletti) + +- GPR#1082: clarify that the use of quoted string for preprocessed + foreign quotations still requires the use of an extension node + [%foo ...] to mark non-standard interpretation. + (Gabriel Scherer, request by Matthew Wahab in GPR#1066, + review by Florian Angeletti) + +- add a HACKING.adoc file to contain various tips and tricks for + people hacking on the repository. See also CONTRIBUTING.md for + advice on sending contributions upstream. + (Gabriel Scherer and Gabriel Radanne, review by David Allsopp, + inspired by John Whitington) + +### Other libraries: + +- PR#7158: Event.sync, Mutex.create, Condition.create cause too many GCs. + The fix is to no longer consider mutexes and condition variables + as rare kernel resources. + (Xavier Leroy) + +- PR#7264: document the different behaviors of Unix.lockf under POSIX + and under Win32. + (Xavier Leroy, report by David Allsopp) + +- MPR#7339, GPR#787: Support the '0 dimension' case for bigarrays + (see Bigarray documentation) + (Laurent Mazare, + review by Gabriel Scherer, Alain Frisch and Hezekiah M. Carty) + +* PR#7342, GPR#797: fix Unix.read on pipes with no data left on Windows + it previously raised an EPIPE error, it now returns 0 like other OSes + (Jonathan Protzenko) + +- GPR#650: in the Unix library, add `?cloexec:bool` optional arguments to + functions that create file descriptors (`dup`, `dup2`, `pipe`, `socket`, + `socketpair`, `accept`). Implement these optional arguments in the + most atomic manner provided by the operating system to set (or clear) + the close-on-exec flag at the same time the file descriptor is created, + reducing the risk of race conditions with `exec` or `create_process` + calls running in other threads, and improving security. Also: add a + `O_KEEPEXEC` flag for `openfile` by symmetry with `O_CLOEXEC`. + (Xavier Leroy) + +- GPR#996: correctly update caml_top_of_stack in systhreads + (Fabrice Le Fessant) + +### Toplevel: + +- PR#7060, GPR#1035: Print exceptions in installed custom printers + (Tadeu Zagallo, review by David Allsopp) + +### Tools: + +- PR#5163: ocamlobjinfo, dump globals defined by bytecode executables + (Stéphane Glondu) + +- PR#7333: ocamldoc, use the first sentence of text file as + a short description in overviews. + (Florian Angeletti) + +- GPR#848: ocamldoc, escape link targets in HTML output + (Etienne Millon, review by Gabriel Scherer, Florian Angeletti and + Daniel Bünzli) + +- GPR#986: ocamldoc, use relative paths in error message + to solve ocamlbuild+doc usability issue (ocaml/ocamlbuild#79) + (Gabriel Scherer, review by Florian Angeletti, discussion with Daniel Bünzli) + +- GPR#1017: ocamldoc, add an option to detect code fragments that could be + transformed into a cross-reference to a known element. + (Florian Angeletti, review and suggestion by David Allsopp) + +- clarify ocamldoc text parsing error messages + (Gabriel Scherer) + +### Compiler distribution build system: + +- PR#7377: remove -std=gnu99 for newer gcc versions + (Damien Doligez, report by ygrek) + +- GPR#693: fail on unexpected errors or warnings within caml_example + environment. + (Florian Angeletti) + +- GPR#803: new ocamllex-based tool to extract bytecode compiler + opcode information from C headers. + (Nicolas Ojeda Bar) + +- GPR#827: install missing mli and cmti files, new make target + install-compiler-sources for installation of compiler-libs ml files + (Hendrik Tews) + +- GPR#887: allow -with-frame-pointers if clang is used as compiler on Linux + (Bernhard Schommer) + +- GPR#898: fix locale-dependence of primitive list order, + detected through reproducible-builds.org. + (Hannes Mehnert, review by Gabriel Scherer and Ximin Luo) + +- GPR#907: Remove unused variable from the build system + (Sébastien Hinderer, review by whitequark, Gabriel Scherer, Adrien Nader) + +- GPR#911: Clarify the use of C compiler related variables in the build system. + (Sébastien Hinderer, review by Adrien Nader, Alain Frisch, David Allsopp) + +- GPR#919: use clang as preprocessor assembler if clang is used as compiler + (Bernhard Schommer) + +- GPR#927: improve the detection of hashbang support in the configure script + (Armaël Guéneau) + +- GPR#932: install ocaml{c,lex}->ocaml{c,lex}.byte symlink correctly + when the opt target is built but opt.opt target is not. + (whitequark) + +- GPR#935: allow build in Android's termux + (ygrek, review by Gabriel Scherer) + +- GPR#984: Fix compilation of compiler distribution when Spacetime + enabled + (Mark Shinwell) + +- GPR#991: On Windows, fix installation when native compiler is not + built + (Sébastien Hinderer, review by David Allsopp) + +- GPR#1033: merge Unix and Windows build systems in the root directory + (Sébastien Hinderer, review by Damien Doligez and Adrien Nader) + +- GPR#1047: Make .depend files generated for C sources more portable + (Sébastien Hinderer, review by Xavier Leroy and David Allsopp) + +- GPR#1076: Simplify ocamlyacc's build system + (Sébastien Hinderer, review by David Allsopp) + +### Compiler distribution build system: Makefile factorization + +The compiler distribution build system (the set of Makefiles used to +build the compiler distribution) traditionally had separate Makefiles +for Unix and Windows, which lead to some amount of duplication and +subtle differences and technical debt in general -- for people working +on the compiler distribution, but also cross-compilation or porting to +new systems. During the 4.05 development period, Sébastien Hinderer +worked on harmonizing the build rules and merging the two build +systems. + +* Some changes were made to the config/Makefile file which + is exported as $(ocamlc -where)/Makefile.config, and on + which some advanced users might rely. The changes are + as follows: + - a BYTERUN variable was added that points to the installed ocamlrun + - the PARTIALLD variable was removed (PACKLD is more complete) + - the always-empty DLLCCCOMPOPTS was removed + - the SHARED variable was removed; its value is "shared" or "noshared", + which duplicates the existing and more convenient + SUPPORTS_SHARED_LIBRARIES variable whose value is "true" or "false". + + Note that Makefile.config may change further in the future and relying + on it is a bit fragile. We plan to make `ocamlc -config` easier to use + for scripting purposes, and have a stable interface there. If you rely + on Makefile.config, you may want to get in touch with Sébastien Hinderer + or participate to MPR#7116 (Allow easy retrieval of Makefile.config's values) + or MPR#7172 (More information in ocamlc -config). + +The complete list of changes is listed below. + +- GPR#705: update Makefile.nt so that ocamlnat compiles + for non-Cygwin Windows ports. + (Sébastien Hinderer, review by Alain Frisch) + +- GPR#729: Make sure ocamlnat is built with a $(EXE) extension, merge + rules between Unix and Windows Makefiles + (Sébastien Hinderer, review by Alain Frisch) + +- GPR#762: Merge build systems in the yacc/ directory. + (Sébastien Hinderer, review by David Allsopp, Alain Frisch) + +- GPR#764: Merge build systems in the debugger/ directory. + (Sébastien Hinderer, review by Alain Frisch) + +- GPR#785: Merge build systems in otherlibs/systhreads/ + (Sébastien Hinderer, review by Alain Frisch, David Allsopp, + testing and regression fix by Jérémie Dimino) + +- GPR#788: Merge build systems in subdirectories of otherlibs/. + (Sébastien Hinderer, review by Alain Frisch) + +- GPR#808, GPR#906: Merge Unix and Windows build systems + in the ocamldoc/ directory + (Sébastien Hinderer, review by Alain Frisch) + +- GPR#812: Merge build systems in the tools/ subdirectory + (Sébastien Hinderer, review by Alain Frisch) + +- GPR#866: Merge build systems in the stdlib/ directory + (Sébastien Hinderer, review by David Allsopp and Adrien Nader) + +- GPR#941: Merge Unix and Windows build systems in the asmrun/ directory + (Sébastien Hinderer, review by Mark Shinwell, Adrien Nader, + Xavier Leroy, David Allsopp, Damien Doligez) + +- GPR#981: Merge build systems in the byterun/ directory + (Sébastien Hinderer, review by Adrien Nader) + +- GPR#1033, GPR#1048: Merge build systems in the root directory + (Sébastien Hinderer, review by Adrien Nader and Damien Doligez, + testing and regression fix by Andreas Hauptmann) + +### Internal/compiler-libs changes: + +- GPR#673: distinguish initialization of block fields from mutation in lambda. + (Frédéric Bour, review by Xavier Leroy, Stephen Dolan and Mark Shinwell) + +- GPR#744, GPR#781: fix duplicate self-reference in imported cmi_crcs + list in .cmti files + avoid rebuilding cmi_info record when creating + .cmti files + (Alain Frisch, report by Daniel Bünzli, review by Jérémie Dimino) + +- GPR#881: change `Outcometree.out_variant` to be more general. + `Ovar_name of out_ident * out_type list` becomes `Ovar_type of out_type`. + (Valentin Gatien-Baron) + +- GPR#908: refactor PIC-handling in the s390x backend + (Gabriel Scherer) + +### Bug fixes + +- PR#5115: protect all byterun/fail.c functions against + uninitialized caml_global_data (only changes the bytecode behavior) + (Gabriel Scherer, review by Xavier Leroy) + +- PR#6136, GPR#967: Fix Closure so that overapplication evaluation order + matches the bytecode compiler and Flambda. + (Mark Shinwell, report by Jeremy Yallop, review by Frédéric Bour) + +- PR#6550, GPR#1094: Allow creation of empty .cmxa files on macOS + (Mark Shinwell) + +- PR#6594, GPR#955: Remove "Istore_symbol" specific operation on x86-64. + This is more robust and in particular avoids assembly failures on Win64. + (Mark Shinwell, review by Xavier Leroy, testing by David Allsopp and + Olivier Andrieu) + +- PR#6903: Unix.execvpe doesn't change environment on Cygwin + (Xavier Leroy) + +- PR#6987: Strange error message probably caused by universal variable escape + (with polymorphic variants) + (report by Leo White) + +- PR#7216, GPR#949: don't require double parens in Functor((val x)) + (Jacques Garrigue, review by Valentin Gatien-Baron) + +- PR#7331: ocamldoc, avoid infinite loop in presence of self alias, + i.e. module rec M:sig end = M + (Florian Angeletti, review Gabriel Scherer) + +- PR#7346, GPR#966: Fix evaluation order problem whereby expressions could + be incorrectly re-ordered when compiling with Flambda. This also fixes one + example of evaluation order in the native code compiler not matching the + bytecode compiler (even when not using Flambda) + (Mark Shinwell, Leo White, code review by Pierre Chambart) + +- PR#7348: Private row variables can escape their scope + (Jacques Garrigue, report by Leo White) + +- PR#7407: Two not-quite-standard C idioms rejected by SUNWSPro compilers + (Xavier Leroy) + +- PR#7421: Soundness bug with GADTs and lazy + (Jacques Garrigue, report by Leo White) + +- PR#7424: Typechecker diverges on unboxed type declaration + (Jacques Garrigue, report by Stephen Dolan) + +- PR#7426, GPR#965: Fix fatal error during object compilation (also + introduces new [Pfield_computed] and [Psetfield_computed] primitives) + (Mark Shinwell) + +- PR#7427, GPR#959: Don't delete let bodies in Cmmgen + (Mark Shinwell) + +- PR#7432: Linking modules compiled with -labels and -nolabels is not safe + (Jacques Garrigue, report by Jeremy Yallop) + +- PR#7437: typing assert failure with nonrec priv + (Jacques Garrigue, report by Anil Madhavapeddy) + +- PR#7438: warning +34 exposes #row with private types + (Alain Frisch, report by Anil Madhavapeddy) + +- PR#7443, GPR#990: spurious unused open warning with local open in patterns + (Florian Angeletti, report by Gabriel Scherer) + +- PR#7504: fix warning 8 with unconstrained records + (Florian Angeletti, report by John Whitington) + +- PR#7456, GPR#1092: fix slow compilation on source files containing a lot + of similar debugging information location entries + (Mark Shinwell) + +- GPR#805, GPR#815, GPR#833: check for integer overflow in String.concat + (Jeremy Yallop, + review by Damien Doligez, Alain Frisch, Daniel Bünzli, Fabrice Le Fessant) + +- GPR#810: check for integer overflow in Array.concat + (Jeremy Yallop) + +- GPR#814: fix the Buffer.add_substring bounds check to handle overflow + (Jeremy Yallop) + +- GPR#881: short-paths did not apply to some polymorphic variants + (Valentin Gatien-Baron, review by Leo White) + +- GPR#886: Fix Ctype.moregeneral's handling of row_name + (Leo White) + +- GPR#934: check for integer overflow in Bytes.extend + (Jeremy Yallop, review by Gabriel Scherer) + +- GPR#956: Keep possibly-effectful expressions when optimizing multiplication + by zero. + (Jeremy Yallop) + +- GPR#977: Catch Out_of_range in ocamldebug's "list" command + (Yunxing Dai) + +- GPR#983: Avoid removing effectful expressions in Closure, and + eliminate more non-effectful ones + (Alain Frisch, review by Mark Shinwell and Gabriel Scherer) + +- GPR#987: alloc_sockaddr: don't assume a null terminator. It is not inserted + on macOS by system calls that fill in a struct sockaddr (e.g. getsockname). + (Anton Bachin) + +- GPR#998: Do not delete unused closures in un_anf.ml. + (Leo White) + +- GPR#1019: Fix fatal error in Flambda mode "[functions] does not map set of + closures ID" + (Pierre Chambart, code review by Mark Shinwell and Leo White) + +- GPR#1075: Ensure that zero-sized float arrays have zero tags. + (Mark Shinwell, Leo White) + +* GPR#1088: Gc.minor_words now returns accurate numbers. + (Stephen Dolan) + +OCaml 4.04.2 (23 Jun 2017): +--------------------------- + +### Security fix: + +- PR#7557: Local privilege escalation issue with ocaml binaries. + (Damien Doligez, report by Eric Milliken, review by Xavier Leroy) + +OCaml 4.04.1 (14 Apr 2017): +--------------------------- + +- PR#7501, GPR#1089: Consider arrays of length zero as constants + when using Flambda. + (Pierre Chambart, review by Mark Shinwell and Leo White) + +### Standard library: + +- PR#7403, GPR#894: fix a bug in Set.map as introduced in 4.04.0 + (Gabriel Scherer, report by Thomas Leonard) + +### Tools: + +- PR#7411: ocamldoc, avoid nested
 tags in module description.
+  (Florian Angeletti, report by user 'kosik')
+
+- PR#7488: ocamldoc, wrong Latex output for variant types
+  with constructors without arguments.
+  (Florian Angeletti, report by Xavier Leroy)
+
+### Build system:
+
+- PR#7373, GPR#1023: New flexlink target in Makefile.nt to bootstrap the
+  flexlink binary only, rather than the flexlink binary and the FlexDLL C
+  objects.
+  (David Allsopp)
+
+### Bug fixes
+
+- PR#7369: Str.regexp raises "Invalid_argument: index out of bounds"
+  (Damien Doligez, report by John Whitington)
+
+- PR#7373, GPR#1023: Fix ocamlmklib with bootstrapped FlexDLL. Bootstrapped
+  FlexDLL objects are now installed to a subdirectory flexdll of the Standard
+  Library which allows the compilers to pick them up explicitly and also
+  ocamlmklib to include them without unnecessarily adding the entire Standard
+  Library.
+  (David Allsopp)
+
+- PR#7385, GPR#1057: fix incorrect timestamps returned by Unix.stat on Windows
+  when either TZ is set or system date is in DST.
+  (David Allsopp, report and initial fix by Nicolás Ojeda Bär, review and
+   superior implementation suggestion by Xavier Leroy)
+
+- PR#7405, GPR#903: s390x: Fix address of caml_raise_exn in native dynlink modules
+  (Richard Jones, review by Xavier Leroy)
+
+- PR#7417, GPR#930: ensure 16 byte stack alignment inside caml_allocN on x86-64
+  for ocaml build with WITH_FRAME_POINTERS defined
+  (Christoph Cullmann)
+
+- PR#7456, GPR#1092: fix slow compilation on source files containing a lot
+  of similar debugging information location entries
+  (Mark Shinwell)
+
+- PR#7457: a case of double free in the systhreads library (POSIX implementation)
+  (Xavier Leroy, report by Chet Murthy)
+
+- PR#7460, GPR#1011: catch uncaught exception when unknown files are passed
+  as argument (regression in 4.04.0)
+  (Bernhard Schommer, review by Florian Angeletti and Gabriel Scherer,
+   report by Stephen Dolan)
+
+- PR#7505: Memory cannot be released after calling
+    Bigarray.Genarray.change_layout.
+  (Damien Doligez and Xavier Leroy, report by Liang Wang)
+
+- PR#7511, GPR#1133: Unboxed type with unboxed argument should not be accepted
+  (Damien Doligez, review by Jeremy Yallop and Leo White)
+
+- GPR#912: Fix segfault in Unix.create_process on Windows caused by wrong header
+  configuration.
+  (David Allsopp)
+
+- GPR#980: add dynlink options to ocamlbytecomp.cmxa to allow ocamlopt.opt
+  to load plugins. See http://github.com/OCamlPro/ocamlc-plugins for examples.
+  (Fabrice Le Fessant, review by David Allsopp)
+
+- GPR#992: caml-types.el: Fix missing format argument, so that it can show kind
+  of call at point correctly.
+  (Chunhui He)
+
+- GPR#1043: Allow Windows CRLF line-endings in ocamlyacc on Unix and Cygwin.
+  (David Allsopp, review by Damien Doligez and Xavier Leroy)
+
+- GPR#1072: Fix segfault in Sys.runtime_parameters when exception backtraces
+  are enabled.
+  (Olivier Andrieu)
+
+OCaml 4.04.0 (4 Nov 2016):
+--------------------------
 
 (Changes that can break existing programs are marked with a "*")
 
@@ -16,7 +679,7 @@ OCaml 4.04.0:
   (Alain Frisch)
 
 - GPR#508: Allow shortcut for extension on semicolons: ;%foo
-  (Jeremie Dimino)
+  (Jérémie Dimino)
 
 - GPR#606: optimized representation for immutable records with a single
   field, and concrete types with a single constructor with a single argument.
@@ -65,10 +728,6 @@ OCaml 4.04.0:
 
 ### Standard library:
 
-- GPR#473: Provide `Sys.backend_type` so that user can write backend-specific
-  code in some cases (for example,  code generator).
-  (Hongbo Zhang)
-
 - PR#6279, GPR#553: implement Set.map
   (Gabriel Scherer)
 
@@ -76,6 +735,10 @@ OCaml 4.04.0:
   "transitive" heap size of a value
   (Alain Frisch, review by Mark Shinwell and Damien Doligez)
 
+- GPR#473: Provide `Sys.backend_type` so that user can write backend-specific
+  code in some cases (for example,  code generator).
+  (Hongbo Zhang)
+
 - GPR#589: Add a non-allocating function to recover the number of
   allocated minor words.
   (Pierre Chambart, review by Damien Doligez and Gabriel Scherer)
@@ -84,9 +747,25 @@ OCaml 4.04.0:
   (Alain Frisch)
 
 - GPR#669: Filename.extension and Filename.remove_extension
-  (Alain Frisch, request by Edgar Aroutiounian, review by Daniel Bunzli
+  (Alain Frisch, request by Edgar Aroutiounian, review by Daniel Bünzli
   and Damien Doligez)
 
+- GPR#674: support unknown Sys.os_type in Filename, defaulting to Unix
+  (Filename would previously fail at initialization time for
+   Sys.os_type values other than "Unix", "Win32" and "Cygwin";
+   mirage-os uses "xen")
+  (Anil Madhavapeddy)
+
+- GPR#772 %string_safe_set and %string_unsafe_set are deprecated aliases
+  for %bytes_safe_set and %bytes_unsafe_set.
+  (Hongbo Zhang and Damien Doligez)
+
+### Other libraries
+
+- MPR#4834, GPR#592: Add a Biggarray.Genarray.change_layout function
+  to switch bigarrays between C and fortran layouts.
+  (Guillaume Hennequin, review by Florian Angeletti)
+
 ### Code generation and optimizations:
 
 - PR#4747, GPR#328: Optimize Hashtbl by using in-place updates of its
@@ -95,7 +774,7 @@ OCaml 4.04.0:
   slower
   (Alain Frisch)
 
-* PR#6217, GPR#538: Optimize performance of record update:
+- PR#6217, GPR#538: Optimize performance of record update:
   no more performance cliff when { foo with t1 = ..; t2 = ...; ... }
   hits 6 updated fields
   (Olivier Nicole, review by Thomas Braibant and Pierre Chambart)
@@ -111,6 +790,10 @@ OCaml 4.04.0:
   not always preserve the arguments
   (Pierre Chambart, Mark Shinwell, report by Simon Cruanes)
 
+- PR#7328, GPR#702: Do not eliminate boxed int divisions by zero and
+  avoid checking twice if divisor is zero with flambda.
+  (Pierre Chambart, report by Jeremy Yallop)
+
 - GPR#427: Obj.is_block is now an inlined OCaml function instead of a
   C external.  This should be faster.
   (Demi Obenour)
@@ -121,10 +804,6 @@ OCaml 4.04.0:
 - GPR#602: Do not generate dummy code to force module linking
   (Pierre Chambart, reviewed by Jacques Garrigue)
 
-- PR#7328, GPR#702: Do not eliminate boxed int divisions by zero and
-  avoid checking twice if divisor is zero with flambda.
-  (Pierre Chambart, report by Jeremy Yallop)
-
 - GPR#703: Optimize some constant string operations when the "-safe-string"
   configure time option is enabled.
   (Pierre Chambart)
@@ -150,6 +829,10 @@ OCaml 4.04.0:
 
 ### Runtime system:
 
+- PR#7203, GPR#534: Add a new primitive caml_alloc_float_array to allocate an
+  array of floats
+  (Thomas Braibant)
+
 - PR#7210, GPR#562: Allows to register finalisation function that are
   called only when a value will never be reachable anymore. The
   drawbacks compared to the existing one is that the finalisation
@@ -157,6 +840,14 @@ OCaml 4.04.0:
   are registered with `GC.finalise_last`
   (François Bobot reviewed by Damien Doligez and Leo White)
 
+- GPR#247: In previous OCaml versions, inlining caused stack frames to
+  disappear from stacktraces. This made debugging harder in presence of
+  optimizations, and flambda was going to make this worse. The debugging
+  information produced by the compiler now enables the reconstruction of the
+  original backtrace. Use `Printexc.get_raw_backtrace_next_slot` to traverse
+  the list of inlined stack frames.
+  (Frédéric Bour, review by Mark Shinwell and Xavier Leroy)
+
 - GPR#590: Do not perform compaction if the real overhead is less than expected
   (Thomas Braibant)
 
@@ -203,12 +894,6 @@ OCaml 4.04.0:
 
 - GPR#585: Spacetime, a new memory profiler (Mark Shinwell, Leo White)
 
-### Runtime system:
-
-- PR#7203, GPR#534: Add a new primitive caml_alloc_float_array to allocate an
-  array of floats
-  (Thomas Braibant)
-
 ### Manual and documentation:
 
 - PR#7007, PR#7311: document the existence of OCAMLPARAM and
@@ -232,10 +917,10 @@ OCaml 4.04.0:
 - PR#7355: Gc.finalise and lazy values
   (Jeremy Yallop)
 
-- GPR#841: Document that [Store_field] must not be used to populate
+- GPR#842: Document that [Store_field] must not be used to populate
   arrays of values declared using [CAMLlocalN] (Mark Shinwell)
 
-### Build system:
+### Compiler distribution build system:
 
 - GPR#324: Compiler developers: Adding new primitives to the
   standard runtime doesn't require anymore to run `make bootstrap`
@@ -255,6 +940,9 @@ OCaml 4.04.0:
   built.
   (Demi Obenour)
 
+- GPR#525: fix build on OpenIndiana
+  (Sergey Avseyev, review by Damien Doligez)
+
 - GPR#687: "./configure -safe-string" to get a system where
   "-unsafe-string" is not allowed, thus giving stronger non-local
   guarantees about immutability of strings
@@ -373,9 +1061,6 @@ OCaml 4.04.0:
 
 - GPR#880: Fix [@@inline] with default parameters in flambda (Leo White)
 
-- GPR#525: fix build on OpenIndiana
-  (Sergey Avseyev, review by Damien Doligez)
-
 ### Internal/compiler-libs changes:
 
 - PR#7200, GPR#539: Improve, fix, and add test for parsing/pprintast.ml
@@ -446,7 +1131,7 @@ OCaml 4.03.0 (25 Apr 2016):
 
 - GPR#112: octal escape sequences for char and string literals
   "Make it \o033[1mBOLD\o033[0m"
-  (Rafaël Bocquet, request by John Whitingthon)
+  (Rafaël Bocquet, request by John Whitington)
 
 - GPR#167: allow to annotate externals' arguments and result types so
   they can be unboxed or untagged: [@unboxed], [@untagged]. Supports
@@ -683,10 +1368,6 @@ OCaml 4.03.0 (25 Apr 2016):
   caml_fill_bytes and caml_create_bytes for migration
   (Hongbo Zhang, review by Damien Doligez, Alain Frisch, and Hugo Heuzard)
 
-- GPR#772 %string_safe_set and %string_unsafe_set are deprecated aliases
-  for %bytes_safe_set and %bytes_unsafe_set.
-  (Hongbo Zhang and Damien Doligez)
-
 - PR#3612, PR#92: allow allocating custom block with finalizers
   in the minor heap.
   (Pierre Chambart)
@@ -727,7 +1408,7 @@ OCaml 4.03.0 (25 Apr 2016):
 
 * GPR#297: Several changes to improve the worst-case GC pause time.
   Changes Gc.control and Gc.major_slice and adds functions to the Gc module.
-  (Damien Doligez, with help from Francois Bobot, Thomas Braibant, Leo White)
+  (Damien Doligez, with help from François Bobot, Thomas Braibant, Leo White)
 
 - GPR#325: Add v=0x400 flag to OCAMLRUNPARAM to display GC stats on exit
   (Louis Gesbert, review by Alain Frisch)
@@ -1128,7 +1809,7 @@ OCaml 4.03.0 (25 Apr 2016):
   (Jacques Garrigue, report by Leo White)
 
 - PR#6954: Infinite loop in type checker with module aliases
-  (Jacques Garrigue, report by Mark Mottl)
+  (Jacques Garrigue, report by Markus Mottl)
 
 - PR#6972, GPR#276: 4.02.3 regression on documentation comments in .cmt files
   (Leo White, report by Olivier Andrieu)
@@ -1262,7 +1943,7 @@ OCaml 4.03.0 (25 Apr 2016):
   (Krzysztof Pszeniczny)
 
 - GPR#205: Clear caml_backtrace_last_exn before registering as root
-  (report and fix by Frederic Bour)
+  (report and fix by Frédéric Bour)
 
 - GPR#220: minor -dsource error on recursive modules
   (Hongbo Zhang)
@@ -1591,7 +2272,7 @@ Bug fixes:
 - PR#6669: fix 4.02 regression in toplevel printing of lazy values
   (Leo White, review by Gabriel Scherer)
 - PR#6671: Windows: environment variable 'TZ' affects Unix.gettimeofday
-  (Mickael Delahaye and Damien Doligez)
+  (Mickaël Delahaye and Damien Doligez)
 - PR#6680: Missing parentheses in warning about polymorphic variant value
   (Jacques Garrigue and Gabriel Scherer, report by Philippe Veber)
 - PR#6686: Bug in [subst_boxed_number]
@@ -4247,7 +4928,7 @@ Standard library:
 - Module Printf:
     added %S and %C formats (quoted, escaped strings and characters);
     added kprintf (calls user-specified continuation on formatted string).
-- Module Queue: faster implementation (courtesy of Francois Pottier).
+- Module Queue: faster implementation (courtesy of François Pottier).
 - Module Random: added Random.bool.
 - Module Stack: added Stack.is_empty.
 - Module Pervasives:
@@ -5480,7 +6161,7 @@ Objective Caml 1.01 (12 Jun 1996):
 Objective Caml 1.00 (9 May 1996):
 ---------------------------------
 
-* Merge of Jerome Vouillon and Didier Remy's object-oriented
+* Merge of Jérôme Vouillon and Didier Rémy's object-oriented
 extensions.
 
 * All libraries: all "new" functions renamed to "create" because "new"
diff --git a/HACKING.adoc b/HACKING.adoc
new file mode 100644
index 00000000..44557b02
--- /dev/null
+++ b/HACKING.adoc
@@ -0,0 +1,260 @@
+= Hacking the compiler 🐫
+
+This document is a work-in-progress attempt to provide useful
+information for people willing to inspect or modify the compiler
+distribution's codebase. Feel free to improve it by sending change
+proposals for it.
+
+If you already have a patch that you would like to contribute to the
+official distribution, please see link:CONTRIBUTING.md[].
+
+=== Your first compiler modification
+
+1. Create a new git branch to store your changes.
++
+----
+git checkout -b my-modification
+----
+
+2. Consult link:INSTALL.adoc[] for build instructions. Here is the gist of it:
++
+----
+./configure
+make world.opt
+----
+
+3. Try the newly built compiler binaries `ocamlc`, `ocamlopt` or their
+`.opt` version. To try the toplevel, use:
++
+----
+make runtop
+----
+
+4. Hack frenetically and keep rebuilding.
+
+5. Run the testsuite from time to time.
++
+----
+make tests
+----
+
+5. Install in a new opam switch to try things out:
++
+----
+opam compiler-conf install
+----
+
+6. You did it, Well done! Consult link:CONTRIBUTING.md[] to send your contribution upstream.
+
+See our <> for various helpful details,
+for example on how to automatically <> from a compiler branch.
+
+=== What to do
+
+There is always a lot of potential tasks, both for old and
+newcomers. Here are various potential projects:
+
+* http://caml.inria.fr/mantis/view_all_bug_page.php[The OCaml
+  bugtracker] contains reported bugs and feature requests. Some
+  changes that should be accessible to newcomers are marked with the
+  tag
+  http://caml.inria.fr/mantis/search.php?project_id=1&sticky_issues=1&sortby=last_updated&dir=DESC&highlight_changed=24&hide_status_id=90&tag_string=junior_job[junior_job].
+
+* The
+  https://github.com/ocamllabs/compiler-hacking/wiki/Things-to-work-on[OCaml
+  Labs compiler-hacking wiki] contains various ideas of changes to
+  propose, some easy, some requiring a fair amount of work.
+
+* Documentation improvements are always much appreciated, either in
+  the various `.mli` files or in the official manual
+  (See link:manual/README.md[]). If you invest effort in understanding
+  a part of the codebase, submitting a pull request that adds
+  clarifying comments can be an excellent contribution to help you,
+  next time, and other code readers.
+
+* The https://github.com/ocaml/ocaml[github project] contains a lot of
+  pull requests, many of them being in dire need of a review -- we
+  have more people willing to contribute changes than to review
+  someone else's change. Picking one of them, trying to understand the
+  code (looking at the code around it) and asking questions about what
+  you don't understand or what feels odd is super-useful. It helps the
+  contribution process, and it is also an excellent way to get to know
+  various parts of the compiler from the angle of a specific aspect or
+  feature.
++
+Again, reviewing small or medium-sized pull requests is accessible to
+anyone with OCaml programming experience, and helps maintainers and
+other contributors. If you also submit pull requests yourself, a good
+discipline is to review at least as many pull requests as you submit.
+
+== Structure of the compiler
+
+The compiler codebase can be intimidating at first sight. Here are
+a few pointers to get started.
+
+=== Compilation pipeline
+
+==== The driver -- link:driver/[]
+
+The driver contains the "main" function of the compilers that drive
+compilation. It parses the command-line arguments and composes the
+required compiler passes by calling functions from the various parts
+of the compiler described below.
+
+==== Parsing -- link:parsing/[]
+
+Parses source files and produces an Abstract Syntax Tree (AST)
+(link:parsing/parsetree.mli[] has lot of helpful comments). See
+link:parsing/HACKING.adoc[].
+
+The logic for Camlp4 and Ppx preprocessing is not in link:parsing/[],
+but in link:driver/[], see link:driver/pparse.mli[],
+link:driver/pparse.mli[].
+
+==== Typing -- link:typing/[]
+
+Type-checks the AST and produces a typed representation of the program
+(link:parsing/typedtree.mli[] has some helpful comments). See
+link:typing/HACKING.adoc[].
+
+==== The bytecode compiler -- link:bytecomp/[]
+
+==== The native compiler -- link:middle_end/[] and link:asmcomp/[]
+
+=== Runtime system
+
+=== Libraries
+
+link:stdlib/[]:: The standard library. Each file is largely
+independent and should not need further knowledge.
+
+link:otherlibs/[]:: External libraries such as `unix`, `threads`,
+`dynlink`, `str` and `bigarray`.
+
+=== Tools
+
+link:lex/[]:: The `ocamllex` lexer generator.
+
+link:yacc/[]:: The `ocamlyacc` parser generator. We do not recommend
+using it for user projects in need of a parser generator. Please
+consider using and contributing to
+link:http://gallium.inria.fr/~fpottier/menhir/[menhir] instead, which
+has tons of extra features, lets you write more readable grammars, and
+has excellent documentation.
+
+=== Complete file listing
+
+  Changes::               what's new with each release
+  configure::             configure script
+  CONTRIBUTING.md::       how to contribute to OCaml
+  HACKING.adoc::          this file
+  INSTALL.adoc::          instructions for installation
+  LICENSE::               license and copyright notice
+  Makefile::              main Makefile
+  Makefile.nt::           Windows Makefile (deprecated)
+  Makefile.shared::       common Makefile
+  Makefile.tools::        used by manual/ and testsuite/ Makefiles
+  README.adoc::           general information on the compiler distribution
+  README.win32.adoc::     general information on the Windows ports of OCaml
+  VERSION::               version string
+  asmcomp/::              native-code compiler and linker
+  asmrun/::               native-code runtime library
+  boot/::                 bootstrap compiler
+  bytecomp/::             bytecode compiler and linker
+  byterun/::              bytecode interpreter and runtime system
+  compilerlibs/::         the OCaml compiler as a library
+  config/::               configuration files
+  debugger/::             source-level replay debugger
+  driver/::               driver code for the compilers
+  emacs/::                editing mode and debugger interface for GNU Emacs
+  experimental/::         experiments not built by default
+  flexdll/::              git submodule -- see link:README.win32.adoc[]
+  lex/::                  lexer generator
+  man/::                  man pages
+  manual/::               system to generate the manual
+  middle_end/::           the flambda optimisation phase
+  ocamldoc/::             documentation generator
+  otherlibs/::            several additional libraries
+  parsing/::              syntax analysis -- see link:parsing/HACKING.adoc[]
+  stdlib/::               standard library
+  testsuite/::            tests -- see link:testsuite/HACKING.adoc[]
+  tools/::                various utilities
+  toplevel/::             interactive system
+  typing/::               typechecking -- see link:typing/HACKING.adoc[]
+  utils/::                utility libraries
+  yacc/::                 parser generator
+
+== Development tips and tricks
+
+=== opam compiler script
+
+The separately-distributed script
+https://github.com/gasche/opam-compiler-conf[`opam-compiler-conf`] can
+be used to easily build opam switches out of a git branch of the
+compiler distribution. This lets you easily install and test opam
+packages from an under-modification compiler version.
+
+=== Useful Makefile targets
+
+Besides the targets listed in link:INSTALL.adoc[] for build and
+installation, the following targets may be of use:
+
+`make runtop` :: builds and runs the ocaml toplevel of the distribution
+                          (optionally uses `rlwrap` for readline+history support)
+`make natruntop`:: builds and runs the native ocaml toplevel (experimental)
+
+`make partialclean`:: Clean the OCaml files but keep the compiled C files.
+
+`make depend`:: Regenerate the `.depend` file. Should be used each time new dependencies are added between files.
+
+`make -C testsuite parallel`:: see link:testsuite/HACKING.adoc[]
+
+=== Bootstrapping
+
+The OCaml compiler is bootstrapped. This means that
+previously-compiled bytecode versions of the compiler, dependency
+generator and lexer are included in the repository under the
+link:boot/[] directory. These bytecode images are used once the
+bytecode runtime (which is written in C) has been built to compile the
+standard library and then to build a fresh compiler. Details can be
+found in link:INSTALL.adoc#bootstrap[INSTALL.adoc].
+
+=== Continuous integration
+
+==== Github's CI: Travis and AppVeyor
+
+==== INRIA's Continuous Integration (CI)
+
+INRIA provides a Jenkins continuous integration service that OCaml
+uses, see link:https://ci.inria.fr/ocaml/[]. It provides a wider
+architecture support (MSVC and MinGW, a zsystems s390x machine, and
+various MacOS versions) than the Travis/AppVeyor testing on github,
+but only runs on commits to the trunk or release branches, not on every
+PR.
+
+You do not need to be an INRIA employee to open an account on this
+jenkins service; anyone can create an account there to access build
+logs, enable email notifications, and manually restart builds. If you
+would like to do this but have trouble doing it, please contact Damien
+Doligez or Gabriel Scherer.
+
+==== Running INRIA's CI on a github Pull Request (PR)
+
+If you have suspicions that a PR may fail on exotic architectures
+(it touches the build system or the backend code generator,
+for example) and would like to get wider testing than github's CI
+provides, it is possible to manually start INRIA's CI on arbitrary git
+branches by pushing to a `precheck` branch of the main repository.
+
+This is done by pushing to a specific github repository that the CI
+watches, namely
+link:https://github.com/ocaml/precheck[ocaml/precheck]. You thus need
+to have write/push/commit access to this repository to perform this operation.
+
+Just checkout the commit/branch you want to test, then run
+
+ git push --force git@github.com:ocaml/precheck.git HEAD:trunk
+
+(This is the syntax to push the current `HEAD` state into the `trunk`
+reference on the specified remote.)
\ No newline at end of file
diff --git a/INSTALL.adoc b/INSTALL.adoc
index cdea168d..835d21b9 100644
--- a/INSTALL.adoc
+++ b/INSTALL.adoc
@@ -1,4 +1,4 @@
-= Installing OCaml on a Unix(-like) machine =
+= Installing OCaml from sources on a Unix(-like) machine =
 
 == PREREQUISITES
 
@@ -54,6 +54,8 @@ The `configure` script accepts the following options:
 
 `-no-curses`::
         Do not use the curses library.
+        The only use for this is to highlight errors in the toplevel using
+        'standout' mode, e.g. underline, rather than with '^' on a newline.
 
 `-host `::                (default: determined automatically)
         The type of the host machine, in GNU's "configuration name" format
@@ -208,6 +210,7 @@ fairly verbose; consider redirecting the output to a file:
         make world > log.world 2>&1     # in sh
         make world >& log.world         # in csh
 
+[[bootstrap]]
 3. (Optional) To be sure everything works well, you can try to bootstrap the
    system -- that is, to recompile all OCaml sources with the newly created
    compiler. From the top directory, do:
diff --git a/Makefile b/Makefile
index 85be2db2..92556ef4 100644
--- a/Makefile
+++ b/Makefile
@@ -15,122 +15,405 @@
 
 # The main Makefile
 
-MAKEREC=$(MAKE)
-include Makefile.shared
+# Hard bootstrap how-to:
+# (only necessary in some cases, for example if you remove some primitive)
+#
+# make coreboot     [old system -- you were in a stable state]
+# 
+# make clean runtime coreall
+# 
+# make clean runtime coreall
+# make coreboot [new system -- now in a stable state]
 
-SHELL=/bin/sh
-MKDIR=mkdir -p
+include config/Makefile
 
 # For users who don't read the INSTALL file
+.PHONY: defaultentry
 defaultentry:
+ifeq "$(UNIX_OR_WIN32)" "unix"
 	@echo "Please refer to the installation instructions in file INSTALL."
 	@echo "If you've just unpacked the distribution, something like"
 	@echo "	./configure"
 	@echo "	make world.opt"
 	@echo "	make install"
 	@echo "should work.  But see the file INSTALL for more details."
+else
+	@echo "Please refer to the instructions in file README.win32.adoc."
+endif
 
-# Recompile the system using the bootstrap compiler
-all:
-	$(MAKE) runtime
-	$(MAKE) coreall
-	$(MAKE) ocaml
-	$(MAKE) otherlibraries $(WITH_DEBUGGER) \
-	  $(WITH_OCAMLDOC)
+MKDIR=mkdir -p
+ifeq "$(UNIX_OR_WIN32)" "win32"
+LN = cp
+else
+LN = ln -sf
+endif
+
+CAMLRUN ?= boot/ocamlrun
+CAMLYACC ?= boot/ocamlyacc
+include stdlib/StdlibModules
+
+CAMLC=$(CAMLRUN) boot/ocamlc -g -nostdlib -I boot -use-prims byterun/primitives
+CAMLOPT=$(CAMLRUN) ./ocamlopt -g -nostdlib -I stdlib -I otherlibs/dynlink
+ARCHES=amd64 i386 arm arm64 power sparc s390x
+INCLUDES=-I utils -I parsing -I typing -I bytecomp -I middle_end \
+        -I middle_end/base_types -I asmcomp -I driver -I toplevel
+
+COMPFLAGS=-strict-sequence -principal -absname -w +a-4-9-41-42-44-45-48 \
+	  -warn-error A \
+          -bin-annot -safe-string -strict-formats $(INCLUDES)
+LINKFLAGS=
+
+ifeq "$(strip $(NATDYNLINKOPTS))" ""
+OCAML_NATDYNLINKOPTS=
+else
+OCAML_NATDYNLINKOPTS = -ccopt "$(NATDYNLINKOPTS)"
+endif
+
+ifeq "$(strip $(BYTECCLINKOPTS))" ""
+OCAML_BYTECCLINKOPTS=
+else
+OCAML_BYTECCLINKOPTS = -ccopt "$(BYTECCLINKOPTS)"
+endif
+
+YACCFLAGS=-v --strict
+CAMLLEX=$(CAMLRUN) boot/ocamllex
+CAMLDEP=$(CAMLRUN) tools/ocamldep
+DEPFLAGS=$(INCLUDES)
+
+OCAMLDOC_OPT=$(WITH_OCAMLDOC:=.opt)
+
+UTILS=utils/config.cmo utils/misc.cmo \
+  utils/identifiable.cmo utils/numbers.cmo utils/arg_helper.cmo \
+  utils/clflags.cmo utils/tbl.cmo utils/timings.cmo \
+  utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
+  utils/consistbl.cmo \
+  utils/strongly_connected_components.cmo \
+  utils/targetint.cmo
+
+PARSING=parsing/location.cmo parsing/longident.cmo \
+  parsing/docstrings.cmo parsing/syntaxerr.cmo \
+  parsing/ast_helper.cmo parsing/parser.cmo \
+  parsing/lexer.cmo parsing/parse.cmo parsing/printast.cmo \
+  parsing/pprintast.cmo \
+  parsing/ast_mapper.cmo parsing/ast_iterator.cmo parsing/attr_helper.cmo \
+  parsing/builtin_attributes.cmo parsing/ast_invariants.cmo parsing/depend.cmo
+
+TYPING=typing/ident.cmo typing/path.cmo \
+  typing/primitive.cmo typing/types.cmo \
+  typing/btype.cmo typing/oprint.cmo \
+  typing/subst.cmo typing/predef.cmo \
+  typing/datarepr.cmo typing/cmi_format.cmo typing/env.cmo \
+  typing/typedtree.cmo typing/printtyped.cmo typing/ctype.cmo \
+  typing/printtyp.cmo typing/includeclass.cmo \
+  typing/mtype.cmo typing/envaux.cmo typing/includecore.cmo \
+  typing/typedtreeIter.cmo typing/typedtreeMap.cmo \
+  typing/tast_mapper.cmo \
+  typing/cmt_format.cmo typing/untypeast.cmo \
+  typing/includemod.cmo typing/typetexp.cmo typing/parmatch.cmo \
+  typing/stypes.cmo typing/typedecl.cmo typing/typecore.cmo \
+  typing/typeclass.cmo \
+  typing/typemod.cmo
+
+COMP=bytecomp/lambda.cmo bytecomp/printlambda.cmo \
+  bytecomp/semantics_of_primitives.cmo \
+  bytecomp/typeopt.cmo bytecomp/switch.cmo bytecomp/matching.cmo \
+  bytecomp/translobj.cmo bytecomp/translattribute.cmo \
+  bytecomp/translcore.cmo \
+  bytecomp/translclass.cmo bytecomp/translmod.cmo \
+  bytecomp/simplif.cmo bytecomp/runtimedef.cmo \
+  driver/pparse.cmo driver/main_args.cmo \
+  driver/compenv.cmo driver/compmisc.cmo
+
+COMMON=$(UTILS) $(PARSING) $(TYPING) $(COMP)
+
+BYTECOMP=bytecomp/meta.cmo bytecomp/instruct.cmo bytecomp/bytegen.cmo \
+  bytecomp/printinstr.cmo bytecomp/opcodes.cmo bytecomp/emitcode.cmo \
+  bytecomp/bytesections.cmo bytecomp/dll.cmo bytecomp/symtable.cmo \
+  bytecomp/bytelink.cmo bytecomp/bytelibrarian.cmo bytecomp/bytepackager.cmo \
+  driver/compdynlink.cmo driver/compplugin.cmo \
+  driver/errors.cmo driver/compile.cmo
+
+ARCH_SPECIFIC =\
+  asmcomp/arch.ml asmcomp/proc.ml asmcomp/CSE.ml asmcomp/selection.ml \
+  asmcomp/scheduling.ml asmcomp/reload.ml
+
+INTEL_ASM=\
+  asmcomp/x86_proc.cmo \
+  asmcomp/x86_dsl.cmo \
+  asmcomp/x86_gas.cmo \
+  asmcomp/x86_masm.cmo
+
+ARCH_SPECIFIC_ASMCOMP=
+ifeq ($(ARCH),i386)
+ARCH_SPECIFIC_ASMCOMP=$(INTEL_ASM)
+endif
+ifeq ($(ARCH),amd64)
+ARCH_SPECIFIC_ASMCOMP=$(INTEL_ASM)
+endif
+
+ASMCOMP=\
+  $(ARCH_SPECIFIC_ASMCOMP) \
+  asmcomp/arch.cmo \
+  asmcomp/cmm.cmo asmcomp/printcmm.cmo \
+  asmcomp/reg.cmo asmcomp/mach.cmo asmcomp/proc.cmo \
+  asmcomp/clambda.cmo asmcomp/printclambda.cmo \
+  asmcomp/export_info.cmo \
+  asmcomp/export_info_for_pack.cmo \
+  asmcomp/compilenv.cmo \
+  asmcomp/closure.cmo \
+  asmcomp/build_export_info.cmo \
+  asmcomp/closure_offsets.cmo \
+  asmcomp/flambda_to_clambda.cmo \
+  asmcomp/import_approx.cmo \
+  asmcomp/un_anf.cmo \
+  asmcomp/afl_instrument.cmo \
+  asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \
+  asmcomp/printmach.cmo asmcomp/selectgen.cmo \
+  asmcomp/spacetime_profiling.cmo asmcomp/selection.cmo \
+  asmcomp/comballoc.cmo \
+  asmcomp/CSEgen.cmo asmcomp/CSE.cmo \
+  asmcomp/liveness.cmo \
+  asmcomp/spill.cmo asmcomp/split.cmo \
+  asmcomp/interf.cmo asmcomp/coloring.cmo \
+  asmcomp/reloadgen.cmo asmcomp/reload.cmo \
+  asmcomp/deadcode.cmo \
+  asmcomp/printlinear.cmo asmcomp/linearize.cmo \
+  asmcomp/schedgen.cmo asmcomp/scheduling.cmo \
+  asmcomp/branch_relaxation_intf.cmo \
+  asmcomp/branch_relaxation.cmo \
+  asmcomp/emitaux.cmo asmcomp/emit.cmo asmcomp/asmgen.cmo \
+  asmcomp/asmlink.cmo asmcomp/asmlibrarian.cmo asmcomp/asmpackager.cmo \
+  driver/opterrors.cmo driver/optcompile.cmo
+
+MIDDLE_END=\
+  middle_end/debuginfo.cmo \
+  middle_end/base_types/tag.cmo \
+  middle_end/base_types/linkage_name.cmo \
+  middle_end/base_types/compilation_unit.cmo \
+  middle_end/base_types/variable.cmo \
+  middle_end/base_types/mutable_variable.cmo \
+  middle_end/base_types/id_types.cmo \
+  middle_end/base_types/set_of_closures_id.cmo \
+  middle_end/base_types/set_of_closures_origin.cmo \
+  middle_end/base_types/closure_element.cmo \
+  middle_end/base_types/closure_id.cmo \
+  middle_end/base_types/var_within_closure.cmo \
+  middle_end/base_types/static_exception.cmo \
+  middle_end/base_types/export_id.cmo \
+  middle_end/base_types/symbol.cmo \
+  middle_end/pass_wrapper.cmo \
+  middle_end/allocated_const.cmo \
+  middle_end/projection.cmo \
+  middle_end/flambda.cmo \
+  middle_end/flambda_iterators.cmo \
+  middle_end/flambda_utils.cmo \
+  middle_end/inlining_cost.cmo \
+  middle_end/effect_analysis.cmo \
+  middle_end/freshening.cmo \
+  middle_end/simple_value_approx.cmo \
+  middle_end/lift_code.cmo \
+  middle_end/closure_conversion_aux.cmo \
+  middle_end/closure_conversion.cmo \
+  middle_end/initialize_symbol_to_let_symbol.cmo \
+  middle_end/lift_let_to_initialize_symbol.cmo \
+  middle_end/find_recursive_functions.cmo \
+  middle_end/invariant_params.cmo \
+  middle_end/inconstant_idents.cmo \
+  middle_end/alias_analysis.cmo \
+  middle_end/lift_constants.cmo \
+  middle_end/share_constants.cmo \
+  middle_end/simplify_common.cmo \
+  middle_end/remove_unused_arguments.cmo \
+  middle_end/remove_unused_closure_vars.cmo \
+  middle_end/remove_unused_program_constructs.cmo \
+  middle_end/simplify_boxed_integer_ops.cmo \
+  middle_end/simplify_primitives.cmo \
+  middle_end/inlining_stats_types.cmo \
+  middle_end/inlining_stats.cmo \
+  middle_end/inline_and_simplify_aux.cmo \
+  middle_end/remove_free_vars_equal_to_args.cmo \
+  middle_end/extract_projections.cmo \
+  middle_end/augment_specialised_args.cmo \
+  middle_end/unbox_free_vars_of_closures.cmo \
+  middle_end/unbox_specialised_args.cmo \
+  middle_end/unbox_closures.cmo \
+  middle_end/inlining_transforms.cmo \
+  middle_end/inlining_decision.cmo \
+  middle_end/inline_and_simplify.cmo \
+  middle_end/ref_to_variables.cmo \
+  middle_end/flambda_invariants.cmo \
+  middle_end/middle_end.cmo
+
+TOPLEVEL=toplevel/genprintval.cmo toplevel/toploop.cmo \
+  toplevel/trace.cmo toplevel/topdirs.cmo toplevel/topmain.cmo
+
+OPTTOPLEVEL=toplevel/genprintval.cmo toplevel/opttoploop.cmo \
+  toplevel/opttopdirs.cmo toplevel/opttopmain.cmo
+BYTESTART=driver/main.cmo
+
+OPTSTART=driver/optmain.cmo
+
+TOPLEVELSTART=toplevel/topstart.cmo
+
+OPTTOPLEVELSTART=toplevel/opttopstart.cmo
+
+PERVASIVES=$(STDLIB_MODULES) outcometree topdirs toploop
 
-# Compile everything the first time
-world:
-	$(MAKE) coldstart
-	$(MAKE) all
+LIBFILES=stdlib.cma std_exit.cmo *.cmi camlheader
 
-# Compile also native code compiler and libraries, fast
-world.opt:
-	$(MAKE) coldstart
-	$(MAKE) opt.opt
+MAXSAVED=boot/Saved/Saved.prev/Saved.prev/Saved.prev/Saved.prev/Saved.prev
 
-reconfigure:
-	./configure $(CONFIGURE_ARGS)
+COMPLIBDIR=$(LIBDIR)/compiler-libs
 
-# Hard bootstrap how-to:
-# (only necessary in some cases, for example if you remove some primitive)
-#
-# make coreboot     [old system -- you were in a stable state]
-# 
-# make clean runtime coreall
-# 
-# make clean runtime coreall
-# make coreboot [new system -- now in a stable state]
+INSTALL_BINDIR=$(DESTDIR)$(BINDIR)
+INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
+INSTALL_COMPLIBDIR=$(DESTDIR)$(COMPLIBDIR)
+INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR)
+INSTALL_MANDIR=$(DESTDIR)$(MANDIR)
+INSTALL_FLEXDLL=$(INSTALL_LIBDIR)/flexdll
+
+RUNTOP=./byterun/ocamlrun ./ocaml \
+  -nostdlib -I stdlib \
+  -noinit $(TOPFLAGS) \
+  -I otherlibs/$(UNIXLIB)
+NATRUNTOP=./ocamlnat$(EXE) -nostdlib -I stdlib -noinit $(TOPFLAGS)
+ifeq "UNIX_OR_WIN32" "unix"
+EXTRAPATH=
+else
+EXTRAPATH = PATH="otherlibs/win32unix:$(PATH)"
+endif
+
+BOOT_FLEXLINK_CMD=
+
+ifeq "$(UNIX_OR_WIN32)" "win32"
+FLEXDLL_SUBMODULE_PRESENT := $(wildcard flexdll/Makefile)
+ifeq "$(FLEXDLL_SUBMODULE_PRESENT)" ""
+  BOOT_FLEXLINK_CMD=
+  FLEXDLL_DIR=
+else
+  BOOT_FLEXLINK_CMD = FLEXLINK_CMD="../boot/ocamlrun ../flexdll/flexlink.exe"
+  CAMLOPT := OCAML_FLEXLINK="boot/ocamlrun flexdll/flexlink.exe" $(CAMLOPT)
+  FLEXDLL_DIR=$(if $(wildcard flexdll/flexdll_*.$(O)),"+flexdll")
+endif
+else
+  FLEXDLL_DIR=
+endif
 
-# Core bootstrapping cycle
-coreboot:
-# Save the original bootstrap compiler
-	$(MAKE) backup
-# Promote the new compiler but keep the old runtime
-# This compiler runs on boot/ocamlrun and produces bytecode for
-# byterun/ocamlrun
-	$(MAKE) promote-cross
-# Rebuild ocamlc and ocamllex (run on byterun/ocamlrun)
-	$(MAKE) partialclean
-	$(MAKE) ocamlc ocamllex ocamltools
-# Rebuild the library (using byterun/ocamlrun ./ocamlc)
-	$(MAKE) library-cross
-# Promote the new compiler and the new runtime
-	$(MAKE) CAMLRUN=byterun/ocamlrun promote
-# Rebuild the core system
-	$(MAKE) partialclean
-	$(MAKE) core
-# Check if fixpoint reached
-	$(MAKE) compare
+# The configuration file
 
-# Bootstrap and rebuild the whole system.
-# The compilation of ocaml will fail if the runtime has changed.
-# Never mind, just do make bootstrap to reach fixpoint again.
-bootstrap:
-	$(MAKE) coreboot
-	$(MAKE) all
-	$(MAKE) compare
+utils/config.ml: utils/config.mlp config/Makefile
+	sed -e 's|%%AFL_INSTRUMENT%%|$(AFL_INSTRUMENT)|' \
+	    -e 's|%%ARCH%%|$(ARCH)|' \
+	    -e 's|%%ARCMD%%|$(ARCMD)|' \
+	    -e 's|%%ASM%%|$(ASM)|' \
+	    -e 's|%%ASM_CFI_SUPPORTED%%|$(ASM_CFI_SUPPORTED)|' \
+	    -e 's|%%BYTECCLIBS%%|$(BYTECCLIBS)|' \
+	    -e 's|%%BYTECODE_C_COMPILER%%|$(BYTECODE_C_COMPILER)|' \
+	    -e 's|%%BYTERUN%%|$(BYTERUN)|' \
+	    -e 's|%%CCOMPTYPE%%|$(CCOMPTYPE)|' \
+	    -e 's|%%CC_PROFILE%%|$(CC_PROFILE)|' \
+	    -e 's|%%EXT_ASM%%|$(EXT_ASM)|' \
+	    -e 's|%%EXT_DLL%%|$(EXT_DLL)|' \
+	    -e 's|%%EXT_EXE%%|$(EXE)|' \
+	    -e 's|%%EXT_LIB%%|$(EXT_LIB)|' \
+	    -e 's|%%EXT_OBJ%%|$(EXT_OBJ)|' \
+	    -e 's|%%FLAMBDA%%|$(FLAMBDA)|' \
+	    -e 's|%%FLEXLINK_FLAGS%%|$(subst \,\\,$(FLEXLINK_FLAGS))|' \
+	    -e 's|%%FLEXDLL_DIR%%|$(FLEXDLL_DIR)|' \
+	    -e 's|%%HOST%%|$(HOST)|' \
+	    -e 's|%%LIBDIR%%|$(LIBDIR)|' \
+	    -e 's|%%LIBUNWIND_AVAILABLE%%|$(LIBUNWIND_AVAILABLE)|' \
+	    -e 's|%%LIBUNWIND_LINK_FLAGS%%|$(LIBUNWIND_LINK_FLAGS)|' \
+	    -e 's|%%MKDLL%%|$(subst \,\\,$(MKDLL))|' \
+	    -e 's|%%MKEXE%%|$(subst \,\\,$(MKEXE))|' \
+	    -e 's|%%MKMAINDLL%%|$(subst \,\\,$(MKMAINDLL))|' \
+	    -e 's|%%MODEL%%|$(MODEL)|' \
+	    -e 's|%%NATIVECCLIBS%%|$(NATIVECCLIBS)|' \
+	    -e 's|%%NATIVE_C_COMPILER%%|$(NATIVE_C_COMPILER)|' \
+	    -e 's|%%PACKLD%%|$(PACKLD)|' \
+	    -e 's|%%PROFILING%%|$(PROFILING)|' \
+	    -e 's|%%PROFINFO_WIDTH%%|$(PROFINFO_WIDTH)|' \
+	    -e 's|%%RANLIBCMD%%|$(RANLIBCMD)|' \
+	    -e 's|%%SAFE_STRING%%|$(SAFE_STRING)|' \
+	    -e 's|%%SYSTEM%%|$(SYSTEM)|' \
+	    -e 's|%%SYSTHREAD_SUPPORT%%|$(SYSTHREAD_SUPPORT)|' \
+	    -e 's|%%TARGET%%|$(TARGET)|' \
+	    -e 's|%%WITH_FRAME_POINTERS%%|$(WITH_FRAME_POINTERS)|' \
+	    -e 's|%%WITH_PROFINFO%%|$(WITH_PROFINFO)|' \
+	    -e 's|%%WITH_SPACETIME%%|$(WITH_SPACETIME)|' \
+	    $< > $@
 
-LIBFILES=stdlib.cma std_exit.cmo *.cmi camlheader
+ifeq "$(UNIX_OR_WIN32)" "unix"
+.PHONY: reconfigure
+reconfigure:
+	./configure $(CONFIGURE_ARGS)
+endif
+
+.PHONY: partialclean
+partialclean::
+	rm -f utils/config.ml
+
+.PHONY: beforedepend
+beforedepend:: utils/config.ml
 
 # Start up the system from the distribution compiler
+.PHONY: coldstart
 coldstart:
-	cd byterun; $(MAKE) all
+	$(MAKE) -C byterun $(BOOT_FLEXLINK_CMD) all
 	cp byterun/ocamlrun$(EXE) boot/ocamlrun$(EXE)
-	cd yacc; $(MAKE) all
+	$(MAKE) -C yacc $(BOOT_FLEXLINK_CMD) all
 	cp yacc/ocamlyacc$(EXE) boot/ocamlyacc$(EXE)
-	cd stdlib; \
-	  $(MAKE) COMPILER="../boot/ocamlc -use-prims ../byterun/primitives" all
+	$(MAKE) -C stdlib $(BOOT_FLEXLINK_CMD) \
+	  COMPILER="../boot/ocamlc -use-prims ../byterun/primitives" all
 	cd stdlib; cp $(LIBFILES) ../boot
-	if test -f boot/libcamlrun.a; then :; else \
-	  ln -s ../byterun/libcamlrun.a boot/libcamlrun.a; fi
-	if test -d stdlib/caml; then :; else \
-	  ln -s ../byterun/caml stdlib/caml; fi
-
-# Build the core system: the minimum needed to make depend and bootstrap
-core:
-	$(MAKE) coldstart
-	$(MAKE) coreall
+	cd boot; $(LN) ../byterun/libcamlrun.$(A) .
 
 # Recompile the core system using the bootstrap compiler
+.PHONY: coreall
 coreall:
 	$(MAKE) ocamlc
 	$(MAKE) ocamllex ocamlyacc ocamltools library
 
+# Build the core system: the minimum needed to make depend and bootstrap
+.PHONY: core
+core:
+ifeq "$(UNIX_OR_WIN32)" "unix"
+	$(MAKE) coldstart
+else # Windows, to be fixed!
+	$(MAKE) runtime
+endif
+	$(MAKE) coreall
+
 # Save the current bootstrap compiler
-MAXSAVED=boot/Saved/Saved.prev/Saved.prev/Saved.prev/Saved.prev/Saved.prev
+.PHONY: backup
 backup:
-	if test -d boot/Saved; then : ; else mkdir boot/Saved; fi
-	if test -d $(MAXSAVED); then rm -r $(MAXSAVED); else : ; fi
+	$(MKDIR) boot/Saved
+	if test -d $(MAXSAVED); then rm -r $(MAXSAVED); fi
 	mv boot/Saved boot/Saved.prev
 	mkdir boot/Saved
 	mv boot/Saved.prev boot/Saved/Saved.prev
 	cp boot/ocamlrun$(EXE) boot/Saved
-	mv boot/ocamlc boot/ocamllex boot/ocamlyacc$(EXE) boot/ocamldep \
-	   boot/Saved
+	cd boot; mv ocamlc ocamllex ocamlyacc$(EXE) ocamldep Saved
 	cd boot; cp $(LIBFILES) Saved
 
+# Restore the saved bootstrap compiler if a problem arises
+.PHONY: restore
+restore:
+	cd boot; mv Saved/* .; rmdir Saved; mv Saved.prev Saved
+
+# Check if fixpoint reached
+.PHONY: compare
+compare:
+	@if $(CAMLRUN) tools/cmpbyt boot/ocamlc ocamlc \
+         && $(CAMLRUN) tools/cmpbyt boot/ocamllex lex/ocamllex \
+         && $(CAMLRUN) tools/cmpbyt boot/ocamldep tools/ocamldep; \
+	then echo "Fixpoint reached, bootstrap succeeded."; \
+	else echo "Fixpoint not reached, try one more bootstrapping cycle."; \
+	fi
+
 # Promote the newly compiled system to the rank of cross compiler
 # (Runs on the old runtime, produces code for the new runtime)
+.PHONY: promote-cross
 promote-cross:
 	$(CAMLRUN) tools/stripdebug ocamlc boot/ocamlc
 	$(CAMLRUN) tools/stripdebug lex/ocamllex boot/ocamllex
@@ -140,41 +423,36 @@ promote-cross:
 
 # Promote the newly compiled system to the rank of bootstrap compiler
 # (Runs on the new runtime, produces code for the new runtime)
+.PHONY: promote
 promote: promote-cross
 	cp byterun/ocamlrun$(EXE) boot/ocamlrun$(EXE)
 
-# Restore the saved bootstrap compiler if a problem arises
-restore:
-	mv boot/Saved/* boot
-	rmdir boot/Saved
-	mv boot/Saved.prev boot/Saved
-
-# Check if fixpoint reached
-compare:
-	@if $(CAMLRUN) tools/cmpbyt boot/ocamlc ocamlc \
-         && $(CAMLRUN) tools/cmpbyt boot/ocamllex lex/ocamllex \
-         && $(CAMLRUN) tools/cmpbyt boot/ocamldep tools/ocamldep; \
-	then echo "Fixpoint reached, bootstrap succeeded."; \
-	else echo "Fixpoint not reached, try one more bootstrapping cycle."; \
-	fi
-
 # Remove old bootstrap compilers
+.PHONY: cleanboot
 cleanboot:
 	rm -rf boot/Saved/Saved.prev/*
 
 # Compile the native-code compiler
-opt-core:
-	$(MAKE) runtimeopt
+.PHONY: opt-core
+opt-core: runtimeopt
 	$(MAKE) ocamlopt
 	$(MAKE) libraryopt
 
+.PHONY: opt
 opt:
+ifeq "$(UNIX_OR_WIN32)" "unix"
 	$(MAKE) runtimeopt
 	$(MAKE) ocamlopt
 	$(MAKE) libraryopt
 	$(MAKE) otherlibrariesopt ocamltoolsopt
+else
+	$(MAKE) opt-core
+	$(MAKE) otherlibrariesopt ocamltoolsopt
+endif
 
 # Native-code versions of the tools
+.PHONY: opt.opt
+ifeq "$(UNIX_OR_WIN32)" "unix"
 opt.opt:
 	$(MAKE) checkstack
 	$(MAKE) runtime
@@ -186,7 +464,12 @@ opt.opt:
 	$(MAKE) ocamlopt.opt
 	$(MAKE) otherlibrariesopt
 	$(MAKE) ocamllex.opt ocamltoolsopt ocamltoolsopt.opt $(OCAMLDOC_OPT)
+else
+opt.opt: core opt-core ocamlc.opt all ocamlopt.opt ocamllex.opt \
+         ocamltoolsopt ocamltoolsopt.opt otherlibrariesopt $(OCAMLDOC_OPT)
+endif
 
+.PHONY: base.opt
 base.opt:
 	$(MAKE) checkstack
 	$(MAKE) runtime
@@ -198,149 +481,289 @@ base.opt:
 	$(MAKE) ocamlopt.opt
 	$(MAKE) otherlibrariesopt
 
-# Installation
+# Core bootstrapping cycle
+.PHONY: coreboot
+coreboot:
+# Save the original bootstrap compiler
+	$(MAKE) backup
+# Promote the new compiler but keep the old runtime
+# This compiler runs on boot/ocamlrun and produces bytecode for
+# byterun/ocamlrun
+	$(MAKE) promote-cross
+# Rebuild ocamlc and ocamllex (run on byterun/ocamlrun)
+	$(MAKE) partialclean
+	$(MAKE) ocamlc ocamllex ocamltools
+# Rebuild the library (using byterun/ocamlrun ./ocamlc)
+	$(MAKE) library-cross
+# Promote the new compiler and the new runtime
+	$(MAKE) CAMLRUN=byterun/ocamlrun promote
+# Rebuild the core system
+	$(MAKE) partialclean
+	$(MAKE) core
+# Check if fixpoint reached
+	$(MAKE) compare
 
-COMPLIBDIR=$(LIBDIR)/compiler-libs
+# Recompile the system using the bootstrap compiler
 
-INSTALL_BINDIR=$(DESTDIR)$(BINDIR)
-INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
-INSTALL_COMPLIBDIR=$(DESTDIR)$(COMPLIBDIR)
-INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR)
-INSTALL_MANDIR=$(DESTDIR)$(MANDIR)
+.PHONY: all
+all: runtime
+	$(MAKE) coreall
+	$(MAKE) ocaml
+	$(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC)
 
+# Bootstrap and rebuild the whole system.
+# The compilation of ocaml will fail if the runtime has changed.
+# Never mind, just do make bootstrap to reach fixpoint again.
+.PHONY: bootstrap
+bootstrap: coreboot
+	$(MAKE) all
+	$(MAKE) compare
+
+# Compile everything the first time
+
+.PHONY: world
+world: coldstart
+	$(MAKE) all
+
+# Compile also native code compiler and libraries, fast
+.PHONY: world.opt
+world.opt: coldstart
+	$(MAKE) opt.opt
+
+# FlexDLL sources missing error messages
+# Different git mechanism displayed depending on whether this source tree came
+# from a git clone or a source tarball.
+
+flexdll/Makefile:
+	@echo In order to bootstrap FlexDLL, you need to place the sources in
+	@echo flexdll.
+	@echo This can either be done by downloading a source tarball from
+	@echo \  http://alain.frisch.fr/flexdll.html
+	@if [ -d .git ]; then \
+	  echo or by checking out the flexdll submodule with; \
+	  echo \  git submodule update --init; \
+	else \
+	  echo or by cloning the git repository; \
+	  echo \  git clone https://github.com/alainfrisch/flexdll.git; \
+	fi
+	@false
+
+.PHONY: flexdll
+flexdll: flexdll/Makefile flexlink
+	$(MAKE) -C flexdll \
+             MSVC_DETECT=0 CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false support
+
+# Bootstrapping flexlink - leaves a bytecode image of flexlink.exe in flexdll/
+.PHONY: flexlink
+flexlink: flexdll/Makefile
+	$(MAKE) -C byterun BOOTSTRAPPING_FLEXLINK=yes ocamlrun$(EXE)
+	cp byterun/ocamlrun$(EXE) boot/ocamlrun$(EXE)
+	$(MAKE) -C stdlib COMPILER=../boot/ocamlc stdlib.cma std_exit.cmo
+	cd stdlib && cp stdlib.cma std_exit.cmo *.cmi ../boot
+	$(MAKE) -C flexdll MSVC_DETECT=0 TOOLCHAIN=$(TOOLCHAIN) \
+	  TOOLPREF=$(TOOLPREF) CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false \
+	  OCAMLOPT="../boot/ocamlrun ../boot/ocamlc -I ../boot" \
+	  flexlink.exe
+	$(MAKE) -C byterun clean
+	$(MAKE) partialclean
+
+.PHONY: flexlink.opt
+flexlink.opt:
+	cd flexdll && \
+	mv flexlink.exe flexlink && \
+	$(MAKE) OCAML_FLEXLINK="../boot/ocamlrun ./flexlink" MSVC_DETECT=0 \
+	           TOOLCHAIN=$(TOOLCHAIN) TOOLPREF=$(TOOLPREF) \
+	           OCAMLOPT="../ocamlopt.opt -I ../stdlib" flexlink.exe && \
+	mv flexlink.exe flexlink.opt && \
+	mv flexlink flexlink.exe
+
+.PHONY: install-flexdll
+install-flexdll:
+	cat stdlib/camlheader flexdll/flexlink.exe > \
+	  "$(INSTALL_BINDIR)/flexlink.exe"
+ifneq "$(filter-out mingw,$(TOOLCHAIN))" ""
+	cp flexdll/default$(filter-out _i386,_$(ARCH)).manifest \
+    "$(INSTALL_BINDIR)/"
+endif
+	if test -n "$(wildcard flexdll/flexdll_*.$(O))" ; then \
+	  $(MKDIR) "$(INSTALL_FLEXDLL)" ; \
+	  cp flexdll/flexdll_*.$(O) "$(INSTALL_FLEXDLL)" ; \
+	fi
+
+# Installation
+.PHONY: install
 install:
-	if test -d $(INSTALL_BINDIR); then : ; \
-	  else $(MKDIR) $(INSTALL_BINDIR); fi
-	if test -d $(INSTALL_LIBDIR); then : ; \
-	  else $(MKDIR) $(INSTALL_LIBDIR); fi
-	if test -d $(INSTALL_STUBLIBDIR); then : ; \
-	  else $(MKDIR) $(INSTALL_STUBLIBDIR); fi
-	if test -d $(INSTALL_COMPLIBDIR); then : ; \
-	  else $(MKDIR) $(INSTALL_COMPLIBDIR); fi
-	if test -d $(INSTALL_MANDIR)/man$(MANEXT); then : ; \
-	  else $(MKDIR) $(INSTALL_MANDIR)/man$(MANEXT); fi
-	cp VERSION $(INSTALL_LIBDIR)/
-	cd $(INSTALL_LIBDIR); rm -f \
-	  dllbigarray$(EXT_DLL) dllnums$(EXT_DLL) dllthreads$(EXT_DLL) \
-	  dllunix$(EXT_DLL) dllgraphics$(EXT_DLL) dllstr$(EXT_DLL)
-	cd byterun; $(MAKE) install
-	cp ocamlc $(INSTALL_BINDIR)/ocamlc.byte$(EXE)
-	cp ocaml $(INSTALL_BINDIR)/ocaml$(EXE)
-	cd stdlib; $(MAKE) install
-	cp lex/ocamllex $(INSTALL_BINDIR)/ocamllex.byte$(EXE)
-	cp $(CAMLYACC)$(EXE) $(INSTALL_BINDIR)/ocamlyacc$(EXE)
-	cp utils/*.cmi utils/*.cmt utils/*.cmti \
-	   parsing/*.cmi parsing/*.cmt parsing/*.cmti \
-	   typing/*.cmi typing/*.cmt typing/*.cmti \
-	   bytecomp/*.cmi bytecomp/*.cmt bytecomp/*.cmti \
-	   driver/*.cmi driver/*.cmt driver/*.cmti \
-	   toplevel/*.cmi toplevel/*.cmt toplevel/*.cmti $(INSTALL_COMPLIBDIR)
+	$(MKDIR) "$(INSTALL_BINDIR)"
+	$(MKDIR) "$(INSTALL_LIBDIR)"
+	$(MKDIR) "$(INSTALL_STUBLIBDIR)"
+	$(MKDIR) "$(INSTALL_COMPLIBDIR)"
+	cp VERSION "$(INSTALL_LIBDIR)"
+	$(MAKE) -C byterun install
+	cp ocaml "$(INSTALL_BINDIR)/ocaml$(EXE)"
+	cp ocamlc "$(INSTALL_BINDIR)/ocamlc.byte$(EXE)"
+	$(MAKE) -C stdlib install
+	cp lex/ocamllex "$(INSTALL_BINDIR)/ocamllex.byte$(EXE)"
+	cp yacc/ocamlyacc$(EXE) "$(INSTALL_BINDIR)/ocamlyacc$(EXE)"
+	cp utils/*.cmi utils/*.cmt utils/*.cmti utils/*.mli \
+	   parsing/*.cmi parsing/*.cmt parsing/*.cmti parsing/*.mli \
+	   typing/*.cmi typing/*.cmt typing/*.cmti typing/*.mli \
+	   bytecomp/*.cmi bytecomp/*.cmt bytecomp/*.cmti bytecomp/*.mli \
+	   driver/*.cmi driver/*.cmt driver/*.cmti driver/*.mli \
+	   toplevel/*.cmi toplevel/*.cmt toplevel/*.cmti toplevel/*.mli \
+	   "$(INSTALL_COMPLIBDIR)"
 	cp compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
 	   compilerlibs/ocamltoplevel.cma $(BYTESTART) $(TOPLEVELSTART) \
-	   $(INSTALL_COMPLIBDIR)
-	cp expunge $(INSTALL_LIBDIR)/expunge$(EXE)
-	cp toplevel/topdirs.cmi $(INSTALL_LIBDIR)
-	cd tools; $(MAKE) install
-	-cd man; $(MAKE) install
+	   "$(INSTALL_COMPLIBDIR)"
+	cp expunge "$(INSTALL_LIBDIR)/expunge$(EXE)"
+	cp toplevel/topdirs.cmi toplevel/topdirs.cmt toplevel/topdirs.cmti \
+           toplevel/topdirs.mli "$(INSTALL_LIBDIR)"
+	$(MAKE) -C tools install
+ifeq "$(UNIX_OR_WIN32)" "unix" # Install manual pages only on Unix
+	$(MKDIR) "$(INSTALL_MANDIR)/man$(MANEXT)"
+	-$(MAKE) -C man install
+endif
 	for i in $(OTHERLIBRARIES); do \
-	  (cd otherlibs/$$i; $(MAKE) install) || exit $$?; \
+	  $(MAKE) -C otherlibs/$$i install || exit $$?; \
 	done
-	if test -n "$(WITH_OCAMLDOC)"; then (cd ocamldoc; $(MAKE) install); fi
-	if test -n "$(WITH_DEBUGGER)"; then (cd debugger; $(MAKE) install); fi
-	cp config/Makefile $(INSTALL_LIBDIR)/Makefile.config
+	if test -n "$(WITH_OCAMLDOC)"; then \
+	  $(MAKE) -C ocamldoc install; \
+	fi
+	if test -n "$(WITH_DEBUGGER)"; then \
+	  $(MAKE) -C debugger install; \
+	fi
+ifeq "$(UNIX_OR_WIN32)" "win32"
+	if test -n "$(FLEXDLL_SUBMODULE_PRESENT)"; then \
+	  $(MAKE) install-flexdll; \
+	fi
+endif
+	cp config/Makefile "$(INSTALL_LIBDIR)/Makefile.config"
 	if test -f ocamlopt; then $(MAKE) installopt; else \
-	   cd $(INSTALL_BINDIR); \
-	   ln -sf ocamlc.byte$(EXE) ocamlc$(EXE); \
-	   ln -sf ocamllex.byte$(EXE) ocamllex$(EXE); \
-	   fi
+	   cd "$(INSTALL_BINDIR)"; \
+	   $(LN) ocamlc.byte$(EXE) ocamlc$(EXE); \
+	   $(LN) ocamllex.byte$(EXE) ocamllex$(EXE); \
+	fi
 
 # Installation of the native-code compiler
+.PHONY: installopt
 installopt:
-	cd asmrun; $(MAKE) install
-	cp ocamlopt $(INSTALL_BINDIR)/ocamlopt.byte$(EXE)
-	cd stdlib; $(MAKE) installopt
+	$(MAKE) -C asmrun install
+	cp ocamlopt "$(INSTALL_BINDIR)/ocamlopt.byte$(EXE)"
+	$(MAKE) -C stdlib installopt
 	cp middle_end/*.cmi middle_end/*.cmt middle_end/*.cmti \
-		$(INSTALL_COMPLIBDIR)
+	    middle_end/*.mli \
+		"$(INSTALL_COMPLIBDIR)"
 	cp middle_end/base_types/*.cmi middle_end/base_types/*.cmt \
-		middle_end/base_types/*.cmti $(INSTALL_COMPLIBDIR)
-	cp asmcomp/*.cmi asmcomp/*.cmt asmcomp/*.cmti $(INSTALL_COMPLIBDIR)
-	cp compilerlibs/ocamloptcomp.cma $(OPTSTART) $(INSTALL_COMPLIBDIR)
-	if test -n "$(WITH_OCAMLDOC)"; then (cd ocamldoc; $(MAKE) installopt); \
-		else :; fi
-	for i in $(OTHERLIBRARIES); \
-	  do (cd otherlibs/$$i; $(MAKE) installopt) || exit $$?; done
+	    middle_end/base_types/*.cmti middle_end/base_types/*.mli \
+		"$(INSTALL_COMPLIBDIR)"
+	cp asmcomp/*.cmi asmcomp/*.cmt asmcomp/*.cmti asmcomp/*.mli \
+		"$(INSTALL_COMPLIBDIR)"
+	cp compilerlibs/ocamloptcomp.cma $(OPTSTART) "$(INSTALL_COMPLIBDIR)"
+	if test -n "$(WITH_OCAMLDOC)"; then \
+	  $(MAKE) -C ocamldoc installopt; \
+	fi
+	for i in $(OTHERLIBRARIES); do \
+	  $(MAKE) -C otherlibs/$$i installopt || exit $$?; \
+	done
 	if test -f ocamlopt.opt ; then $(MAKE) installoptopt; else \
-	   cd $(INSTALL_BINDIR); ln -sf ocamlopt.byte$(EXE) ocamlopt$(EXE); fi
-	cd tools; $(MAKE) installopt
+	   cd "$(INSTALL_BINDIR)"; \
+	   $(LN) ocamlc.byte$(EXE) ocamlc$(EXE); \
+	   $(LN) ocamlopt.byte$(EXE) ocamlopt$(EXE); \
+	   $(LN) ocamllex.byte$(EXE) ocamllex$(EXE); \
+	fi
+	$(MAKE) -C tools installopt
+	if test -f ocamlopt.opt -a -f flexdll/flexlink.opt ; then \
+	  cp -f flexdll/flexlink.opt "$(INSTALL_BINDIR)/flexlink$(EXE)" ; \
+	fi
+
+
 
+.PHONY: installoptopt
 installoptopt:
-	cp ocamlc.opt $(INSTALL_BINDIR)/ocamlc.opt$(EXE)
-	cp ocamlopt.opt $(INSTALL_BINDIR)/ocamlopt.opt$(EXE)
-	cp lex/ocamllex.opt $(INSTALL_BINDIR)/ocamllex.opt$(EXE)
-	cd $(INSTALL_BINDIR); \
-	   ln -sf ocamlc.opt$(EXE) ocamlc$(EXE); \
-	   ln -sf ocamlopt.opt$(EXE) ocamlopt$(EXE); \
-	   ln -sf ocamllex.opt$(EXE) ocamllex$(EXE)
+	cp ocamlc.opt "$(INSTALL_BINDIR)/ocamlc.opt$(EXE)"
+	cp ocamlopt.opt "$(INSTALL_BINDIR)/ocamlopt.opt$(EXE)"
+	cp lex/ocamllex.opt "$(INSTALL_BINDIR)/ocamllex.opt$(EXE)"
+	cd "$(INSTALL_BINDIR)"; \
+	   $(LN) ocamlc.opt$(EXE) ocamlc$(EXE); \
+	   $(LN) ocamlopt.opt$(EXE) ocamlopt$(EXE); \
+	   $(LN) ocamllex.opt$(EXE) ocamllex$(EXE)
 	cp utils/*.cmx parsing/*.cmx typing/*.cmx bytecomp/*.cmx \
-           driver/*.cmx asmcomp/*.cmx $(INSTALL_COMPLIBDIR)
-	cp compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.a \
-	   compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.a \
-	   compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.a \
-	   $(BYTESTART:.cmo=.cmx) $(BYTESTART:.cmo=.o) \
-	   $(OPTSTART:.cmo=.cmx) $(OPTSTART:.cmo=.o) \
-	   $(INSTALL_COMPLIBDIR)
-	if test -f ocamlnat ; then \
-	  cp ocamlnat $(INSTALL_BINDIR)/ocamlnat$(EXE); \
-	  cp toplevel/opttopdirs.cmi $(INSTALL_LIBDIR); \
+	   driver/*.cmx asmcomp/*.cmx "$(INSTALL_COMPLIBDIR)"
+	cp compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.$(A) \
+	   compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.$(A) \
+	   compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.$(A) \
+	   $(BYTESTART:.cmo=.cmx) $(BYTESTART:.cmo=.$(O)) \
+	   $(OPTSTART:.cmo=.cmx) $(OPTSTART:.cmo=.$(O)) \
+	   "$(INSTALL_COMPLIBDIR)"
+	if test -f ocamlnat$(EXE) ; then \
+	  cp ocamlnat$(EXE) "$(INSTALL_BINDIR)/ocamlnat$(EXE)"; \
+	  cp toplevel/opttopdirs.cmi "$(INSTALL_LIBDIR)"; \
 	  cp compilerlibs/ocamlopttoplevel.cmxa \
-	     compilerlibs/ocamlopttoplevel.a \
-	     $(OPTTOPLEVELSTART:.cmo=.cmx) $(OPTTOPLEVELSTART:.cmo=.o) \
-	     $(INSTALL_COMPLIBDIR); \
+	     compilerlibs/ocamlopttoplevel.$(A) \
+	     $(OPTTOPLEVELSTART:.cmo=.cmx) $(OPTTOPLEVELSTART:.cmo=.$(O)) \
+	     "$(INSTALL_COMPLIBDIR)"; \
 	fi
-	cd $(INSTALL_COMPLIBDIR) && $(RANLIB) ocamlcommon.a ocamlbytecomp.a \
-	   ocamloptcomp.a
+	cd "$(INSTALL_COMPLIBDIR)" && \
+	   $(RANLIB) ocamlcommon.$(A) ocamlbytecomp.$(A) ocamloptcomp.$(A)
+
+# Installation of the *.ml sources of compiler-libs
+.PHONY: install-compiler-sources
+install-compiler-sources:
+	cp utils/*.ml parsing/*.ml typing/*.ml bytecomp/*.ml driver/*.ml \
+	   toplevel/*.ml middle_end/*.ml middle_end/base_types/*.ml \
+	   asmcomp/*.ml $(INSTALL_COMPLIBDIR)
 
 # Run all tests
 
+.PHONY: tests
 tests: opt.opt
 	cd testsuite; $(MAKE) clean && $(MAKE) all
 
-# The clean target
+# Make clean in the test suite
+
+.PHONY: clean
+clean::
+	$(MAKE) -C testsuite clean
 
+# Build the manual latex files from the etex source files
+# (see manual/README.md)
+.PHONY: manual-pregen
+manual-pregen: opt.opt
+	cd manual; $(MAKE) clean && $(MAKE) pregen-etex
+
+# The clean target
 clean:: partialclean
 
 # Shared parts of the system
 
 compilerlibs/ocamlcommon.cma: $(COMMON)
-	$(CAMLC) -a -linkall -o $@ $(COMMON)
+	$(CAMLC) -a -linkall -o $@ $^
 partialclean::
 	rm -f compilerlibs/ocamlcommon.cma
 
 # The bytecode compiler
 
 compilerlibs/ocamlbytecomp.cma: $(BYTECOMP)
-	$(CAMLC) -a -o $@ $(BYTECOMP)
+	$(CAMLC) -a -o $@ $^
 partialclean::
 	rm -f compilerlibs/ocamlbytecomp.cma
 
 ocamlc: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma $(BYTESTART)
-	$(CAMLC) $(LINKFLAGS) -compat-32 -o ocamlc \
-	   compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
-	   $(BYTESTART)
+	$(CAMLC) $(LINKFLAGS) -compat-32 -o $@ $^
+
+partialclean::
+	rm -rf ocamlc
 
 # The native-code compiler
 
 compilerlibs/ocamloptcomp.cma: $(MIDDLE_END) $(ASMCOMP)
-	$(CAMLC) -a -o $@ $(MIDDLE_END) $(ASMCOMP)
+	$(CAMLC) -a -o $@ $^
 
 partialclean::
 	rm -f compilerlibs/ocamloptcomp.cma
 
 ocamlopt: compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
           compilerlibs/ocamlbytecomp.cma $(OPTSTART)
-	$(CAMLC) $(LINKFLAGS) -o ocamlopt \
-	  compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
-	  compilerlibs/ocamlbytecomp.cma $(OPTSTART)
+	$(CAMLC) $(LINKFLAGS) -o $@ $^
 
 partialclean::
 	rm -f ocamlopt
@@ -348,107 +771,56 @@ partialclean::
 # The toplevel
 
 compilerlibs/ocamltoplevel.cma: $(TOPLEVEL)
-	$(CAMLC) -a -o $@ $(TOPLEVEL)
+	$(CAMLC) -a -o $@ $^
 partialclean::
 	rm -f compilerlibs/ocamltoplevel.cma
 
-ocaml: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
-       compilerlibs/ocamltoplevel.cma $(TOPLEVELSTART) expunge
-	$(CAMLC) $(LINKFLAGS) -linkall -o ocaml.tmp \
-	  compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
-	  compilerlibs/ocamltoplevel.cma $(TOPLEVELSTART)
-	- $(CAMLRUN) ./expunge ocaml.tmp ocaml $(PERVASIVES)
-	rm -f ocaml.tmp
+ocaml_dependencies := \
+  compilerlibs/ocamlcommon.cma \
+  compilerlibs/ocamlbytecomp.cma \
+  compilerlibs/ocamltoplevel.cma $(TOPLEVELSTART)
+
+.INTERMEDIATE: ocaml.tmp
+ocaml.tmp: $(ocaml_dependencies)
+	$(CAMLC) $(LINKFLAGS) -linkall -o $@ $^
+
+ocaml: expunge ocaml.tmp
+	- $(CAMLRUN) $^ $@ $(PERVASIVES)
 
 partialclean::
 	rm -f ocaml
 
-RUNTOP=./byterun/ocamlrun ./ocaml -nostdlib -I stdlib -noinit $(TOPFLAGS)
-NATRUNTOP=./ocamlnat -nostdlib -I stdlib -noinit $(TOPFLAGS)
-
+.PHONY: runtop
 runtop:
+ifeq "$(UNIX_OR_WIN32)" "unix"
 	$(MAKE) runtime
 	$(MAKE) coreall
 	$(MAKE) ocaml
-	@rlwrap --help 2>/dev/null && rlwrap $(RUNTOP) || $(RUNTOP)
+else
+	$(MAKE) core
+	$(MAKE) ocaml
+endif
+	@rlwrap --help 2>/dev/null && $(EXTRAPATH) rlwrap $(RUNTOP) ||\
+	  $(EXTRAPATH) $(RUNTOP)
 
+.PHONY: natruntop
 natruntop:
 	$(MAKE) runtime
 	$(MAKE) coreall
 	$(MAKE) opt.opt
 	$(MAKE) ocamlnat
-	@rlwrap --help 2>/dev/null && rlwrap $(NATRUNTOP) || $(NATRUNTOP)
+	@rlwrap --help 2>/dev/null && $(EXTRAPATH) rlwrap $(NATRUNTOP) ||\
+	  $(EXTRAPATH) $(NATRUNTOP)
 
-# The native toplevel
-
-compilerlibs/ocamlopttoplevel.cmxa: $(OPTTOPLEVEL:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(OPTTOPLEVEL:.cmo=.cmx)
-partialclean::
-	rm -f compilerlibs/ocamlopttoplevel.cmxa
-
-ocamlnat: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
-    compilerlibs/ocamlbytecomp.cmxa \
-    compilerlibs/ocamlopttoplevel.cmxa \
-    $(OPTTOPLEVELSTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -linkall -o $@ $^
-
-partialclean::
-	rm -f ocamlnat
-
-toplevel/opttoploop.cmx: otherlibs/dynlink/dynlink.cmxa
+# Native dynlink
 
 otherlibs/dynlink/dynlink.cmxa: otherlibs/dynlink/natdynlink.ml
-	cd otherlibs/dynlink && $(MAKE) allopt
-
-# The configuration file
-
-utils/config.ml: utils/config.mlp config/Makefile
-	@rm -f utils/config.ml
-	sed -e 's|%%LIBDIR%%|$(LIBDIR)|' \
-	    -e 's|%%BYTERUN%%|$(BINDIR)/ocamlrun|' \
-	    -e 's|%%CCOMPTYPE%%|cc|' \
-	    -e 's|%%BYTECC%%|$(BYTECC) $(BYTECCCOMPOPTS) $(SHAREDCCCOMPOPTS)|' \
-	    -e 's|%%NATIVECC%%|$(NATIVECC) $(NATIVECCCOMPOPTS)|' \
-	    -e '/c_compiler =/s| -Werror||' \
-	    -e 's|%%PACKLD%%|$(PACKLD)|' \
-	    -e 's|%%BYTECCLIBS%%|$(BYTECCLIBS)|' \
-	    -e 's|%%NATIVECCLIBS%%|$(NATIVECCLIBS)|' \
-	    -e 's|%%RANLIBCMD%%|$(RANLIBCMD)|' \
-	    -e 's|%%ARCMD%%|$(ARCMD)|' \
-	    -e 's|%%CC_PROFILE%%|$(CC_PROFILE)|' \
-	    -e 's|%%ARCH%%|$(ARCH)|' \
-	    -e 's|%%MODEL%%|$(MODEL)|' \
-	    -e 's|%%SYSTEM%%|$(SYSTEM)|' \
-	    -e 's|%%EXT_OBJ%%|.o|' \
-	    -e 's|%%EXT_ASM%%|.s|' \
-	    -e 's|%%EXT_LIB%%|.a|' \
-	    -e 's|%%EXT_DLL%%|$(EXT_DLL)|' \
-	    -e 's|%%SYSTHREAD_SUPPORT%%|$(SYSTHREAD_SUPPORT)|' \
-	    -e 's|%%ASM%%|$(ASM)|' \
-	    -e 's|%%ASM_CFI_SUPPORTED%%|$(ASM_CFI_SUPPORTED)|' \
-	    -e 's|%%WITH_FRAME_POINTERS%%|$(WITH_FRAME_POINTERS)|' \
-	    -e 's|%%WITH_SPACETIME%%|$(WITH_SPACETIME)|' \
-	    -e 's|%%PROFINFO_WIDTH%%|$(PROFINFO_WIDTH)|' \
-	    -e 's|%%LIBUNWIND_AVAILABLE%%|$(LIBUNWIND_AVAILABLE)|' \
-	    -e 's|%%LIBUNWIND_LINK_FLAGS%%|$(LIBUNWIND_LINK_FLAGS)|' \
-	    -e 's|%%MKDLL%%|$(MKDLL)|' \
-	    -e 's|%%MKEXE%%|$(MKEXE)|' \
-	    -e 's|%%MKMAINDLL%%|$(MKMAINDLL)|' \
-	    -e 's|%%HOST%%|$(HOST)|' \
-	    -e 's|%%TARGET%%|$(TARGET)|' \
-	    -e 's|%%FLAMBDA%%|$(FLAMBDA)|' \
-	    -e 's|%%SAFE_STRING%%|$(SAFE_STRING)|' \
-	    utils/config.mlp > utils/config.ml
-
-partialclean::
-	rm -f utils/config.ml
-
-beforedepend:: utils/config.ml
+	$(MAKE) -C otherlibs/dynlink allopt
 
 # The parser
 
 parsing/parser.mli parsing/parser.ml: parsing/parser.mly
-	$(CAMLYACC) $(YACCFLAGS) parsing/parser.mly
+	$(CAMLYACC) $(YACCFLAGS) $<
 
 partialclean::
 	rm -f parsing/parser.mli parsing/parser.ml parsing/parser.output
@@ -458,7 +830,7 @@ beforedepend:: parsing/parser.mli parsing/parser.ml
 # The lexer
 
 parsing/lexer.ml: parsing/lexer.mll
-	$(CAMLLEX) parsing/lexer.mll
+	$(CAMLLEX) $<
 
 partialclean::
 	rm -f parsing/lexer.ml
@@ -468,22 +840,21 @@ beforedepend:: parsing/lexer.ml
 # Shared parts of the system compiled with the native-code compiler
 
 compilerlibs/ocamlcommon.cmxa: $(COMMON:.cmo=.cmx)
-	$(CAMLOPT) -a -linkall -o $@ $(COMMON:.cmo=.cmx)
+	$(CAMLOPT) -a -linkall -o $@ $^
 partialclean::
-	rm -f compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.a
+	rm -f compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.$(A)
 
 # The bytecode compiler compiled with the native-code compiler
 
 compilerlibs/ocamlbytecomp.cmxa: $(BYTECOMP:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(BYTECOMP:.cmo=.cmx)
+	$(CAMLOPT) -a $(OCAML_NATDYNLINKOPTS) -o $@ $^
 partialclean::
-	rm -f compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.a
+	rm -f compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.$(A)
 
 ocamlc.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlbytecomp.cmxa \
             $(BYTESTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -ccopt "$(BYTECCLINKOPTS)" -o ocamlc.opt \
-	  compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlbytecomp.cmxa \
-	  $(BYTESTART:.cmo=.cmx) -cclib "$(BYTECCLIBS)"
+	$(CAMLOPT) $(LINKFLAGS) $(OCAML_BYTECCLINKOPTS) -o $@ \
+	  $^ -cclib "$(BYTECCLIBS)"
 
 partialclean::
 	rm -f ocamlc.opt
@@ -491,17 +862,14 @@ partialclean::
 # The native-code compiler compiled with itself
 
 compilerlibs/ocamloptcomp.cmxa: $(MIDDLE_END:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(MIDDLE_END:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx)
+	$(CAMLOPT) -a -o $@ $^
 partialclean::
-	rm -f compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.a
+	rm -f compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.$(A)
 
 ocamlopt.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
               compilerlibs/ocamlbytecomp.cmxa  \
               $(OPTSTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -o ocamlopt.opt \
-	   compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
-	   compilerlibs/ocamlbytecomp.cmxa  \
-	   $(OPTSTART:.cmo=.cmx)
+	$(CAMLOPT) $(LINKFLAGS) -o $@ $^
 
 partialclean::
 	rm -f ocamlopt.opt
@@ -509,30 +877,19 @@ partialclean::
 $(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(MIDDLE_END:.cmo=.cmx) \
 $(ASMCOMP:.cmo=.cmx): ocamlopt
 
-# The numeric opcodes
-
-bytecomp/opcodes.ml: byterun/caml/instruct.h
-	sed -n -e '/^enum/p' -e 's/,//g' -e '/^  /p' byterun/caml/instruct.h | \
-	awk -f tools/make-opcodes > bytecomp/opcodes.ml
-
-partialclean::
-	rm -f bytecomp/opcodes.ml
-
-beforedepend:: bytecomp/opcodes.ml
-
 # The predefined exceptions and primitives
 
 byterun/primitives:
-	cd byterun; $(MAKE) primitives
+	$(MAKE) -C byterun primitives
 
 bytecomp/runtimedef.ml: byterun/primitives byterun/caml/fail.h
 	(echo 'let builtin_exceptions = [|'; \
-	 sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$$|  \1;|p' \
-	     byterun/caml/fail.h; \
+	 cat byterun/caml/fail.h | tr -d '\r' | \
+	 sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$$|  \1;|p'; \
 	 echo '|]'; \
 	 echo 'let builtin_primitives = [|'; \
 	 sed -e 's/.*/  "&";/' byterun/primitives; \
-	 echo '|]') > bytecomp/runtimedef.ml
+	 echo '|]') > $@
 
 partialclean::
 	rm -f bytecomp/runtimedef.ml
@@ -541,174 +898,210 @@ beforedepend:: bytecomp/runtimedef.ml
 
 # Choose the right machine-dependent files
 
-asmcomp/arch.ml: asmcomp/$(ARCH_OCAMLOPT)/arch.ml
-	ln -s $(ARCH_OCAMLOPT)/arch.ml asmcomp/arch.ml
+asmcomp/arch.ml: asmcomp/$(ARCH)/arch.ml
+	cd asmcomp; $(LN) $(ARCH)/arch.ml .
 
-asmcomp/proc.ml: asmcomp/$(ARCH_OCAMLOPT)/proc.ml
-	ln -s $(ARCH_OCAMLOPT)/proc.ml asmcomp/proc.ml
+asmcomp/proc.ml: asmcomp/$(ARCH)/proc.ml
+	cd asmcomp; $(LN) $(ARCH)/proc.ml .
 
-asmcomp/selection.ml: asmcomp/$(ARCH_OCAMLOPT)/selection.ml
-	ln -s $(ARCH_OCAMLOPT)/selection.ml asmcomp/selection.ml
+asmcomp/selection.ml: asmcomp/$(ARCH)/selection.ml
+	cd asmcomp; $(LN) $(ARCH)/selection.ml .
 
-asmcomp/CSE.ml: asmcomp/$(ARCH_OCAMLOPT)/CSE.ml
-	ln -s $(ARCH_OCAMLOPT)/CSE.ml asmcomp/CSE.ml
+asmcomp/CSE.ml: asmcomp/$(ARCH)/CSE.ml
+	cd asmcomp; $(LN) $(ARCH)/CSE.ml .
 
-asmcomp/reload.ml: asmcomp/$(ARCH_OCAMLOPT)/reload.ml
-	ln -s $(ARCH_OCAMLOPT)/reload.ml asmcomp/reload.ml
+asmcomp/reload.ml: asmcomp/$(ARCH)/reload.ml
+	cd asmcomp; $(LN) $(ARCH)/reload.ml .
 
-asmcomp/scheduling.ml: asmcomp/$(ARCH_OCAMLOPT)/scheduling.ml
-	ln -s $(ARCH_OCAMLOPT)/scheduling.ml asmcomp/scheduling.ml
+asmcomp/scheduling.ml: asmcomp/$(ARCH)/scheduling.ml
+	cd asmcomp; $(LN) $(ARCH)/scheduling.ml .
 
 # Preprocess the code emitters
 
-asmcomp/emit.ml: asmcomp/$(ARCH_OCAMLOPT)/emit.mlp tools/cvt_emit
-	echo \# 1 \"$(ARCH_OCAMLOPT)/emit.mlp\" > asmcomp/emit.ml
-	$(CAMLRUN) tools/cvt_emit >asmcomp/emit.ml \
-	|| { rm -f asmcomp/emit.ml; exit 2; }
+asmcomp/emit.ml: asmcomp/$(ARCH)/emit.mlp tools/cvt_emit
+	echo \# 1 \"$(ARCH)/emit.mlp\" > $@
+	$(CAMLRUN) tools/cvt_emit < $< >> $@ \
+	|| { rm -f $@; exit 2; }
+
+partialclean::
+	rm -f asmcomp/emit.ml
+
+beforedepend:: asmcomp/emit.ml
 
 tools/cvt_emit: tools/cvt_emit.mll
-	cd tools && $(MAKE) cvt_emit
+	$(MAKE) -C tools cvt_emit
 
 # The "expunge" utility
 
 expunge: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
          toplevel/expunge.cmo
-	$(CAMLC) $(LINKFLAGS) -o expunge compilerlibs/ocamlcommon.cma \
-	         compilerlibs/ocamlbytecomp.cma toplevel/expunge.cmo
+	$(CAMLC) $(LINKFLAGS) -o $@ $^
 
 partialclean::
 	rm -f expunge
 
 # The runtime system for the bytecode compiler
 
-runtime:
-	cd byterun; $(MAKE) all
-	if test -f stdlib/libcamlrun.a; then :; else \
-	  ln -s ../byterun/libcamlrun.a stdlib/libcamlrun.a; fi
+.PHONY: runtime
+runtime: stdlib/libcamlrun.$(A)
 
+.PHONY: makeruntime
+makeruntime:
+	$(MAKE) -C byterun $(BOOT_FLEXLINK_CMD) all
+byterun/libcamlrun.$(A): makeruntime ;
+stdlib/libcamlrun.$(A): byterun/libcamlrun.$(A)
+	cd stdlib; $(LN) ../byterun/libcamlrun.$(A) .
 clean::
-	cd byterun; $(MAKE) clean
-	rm -f stdlib/libcamlrun.a
-	rm -f stdlib/caml
+	$(MAKE) -C byterun clean
+	rm -f stdlib/libcamlrun.$(A)
 
+.PHONY: alldepend
 alldepend::
-	cd byterun; $(MAKE) depend
+	$(MAKE) -C byterun depend
 
 # The runtime system for the native-code compiler
 
-runtimeopt: makeruntimeopt
-	cp asmrun/libasmrun.a stdlib/libasmrun.a
+.PHONY: runtimeopt
+runtimeopt: stdlib/libasmrun.$(A)
 
+.PHONY: makeruntimeopt
 makeruntimeopt:
-	cd asmrun; $(MAKE) all
-
+	$(MAKE) -C asmrun $(BOOT_FLEXLINK_CMD) all
+asmrun/libasmrun.$(A): makeruntimeopt ;
+stdlib/libasmrun.$(A): asmrun/libasmrun.$(A)
+	cp $< $@
 clean::
-	cd asmrun; $(MAKE) clean
-	rm -f stdlib/libasmrun.a
-
+	$(MAKE) -C asmrun clean
+	rm -f stdlib/libasmrun.$(A)
 alldepend::
-	cd asmrun; $(MAKE) depend
+	$(MAKE) -C asmrun depend
 
-# The library
+# The standard library
 
+.PHONY: library
 library: ocamlc
-	cd stdlib; $(MAKE) all
+	$(MAKE) -C stdlib $(BOOT_FLEXLINK_CMD) all
 
+.PHONY: library-cross
 library-cross:
-	cd stdlib; $(MAKE) CAMLRUN=../byterun/ocamlrun all
+	$(MAKE) -C stdlib $(BOOT_FLEXLINK_CMD) CAMLRUN=../byterun/ocamlrun all
 
+.PHONY: libraryopt
 libraryopt:
-	cd stdlib; $(MAKE) allopt
+	$(MAKE) -C stdlib $(BOOT_FLEXLINK_CMD) allopt
 
 partialclean::
-	cd stdlib; $(MAKE) clean
+	$(MAKE) -C stdlib clean
 
 alldepend::
-	cd stdlib; $(MAKE) depend
+	$(MAKE) -C stdlib depend
 
 # The lexer and parser generators
 
+.PHONY: ocamllex
 ocamllex: ocamlyacc ocamlc
-	cd lex; $(MAKE) all
+	$(MAKE) -C lex all
 
+.PHONY: ocamllex.opt
 ocamllex.opt: ocamlopt
-	cd lex; $(MAKE) allopt
+	$(MAKE) -C lex allopt
 
 partialclean::
-	cd lex; $(MAKE) clean
+	$(MAKE) -C lex clean
 
 alldepend::
-	cd lex; $(MAKE) depend
+	$(MAKE) -C lex depend
 
+.PHONY: ocamlyacc
 ocamlyacc:
-	cd yacc; $(MAKE) all
+	$(MAKE) -C yacc $(BOOT_FLEXLINK_CMD) all
 
 clean::
-	cd yacc; $(MAKE) clean
+	$(MAKE) -C yacc clean
 
 # OCamldoc
 
+.PHONY: ocamldoc
 ocamldoc: ocamlc ocamlyacc ocamllex otherlibraries
-	cd ocamldoc && $(MAKE) all
+	$(MAKE) -C ocamldoc all
 
+.PHONY: ocamldoc.opt
 ocamldoc.opt: ocamlc.opt ocamlyacc ocamllex
-	cd ocamldoc && $(MAKE) opt.opt
+	$(MAKE) -C ocamldoc opt.opt
 
 # Documentation
 
+.PHONY: html_doc
 html_doc: ocamldoc
-	make -C ocamldoc html_doc
+	$(MAKE) -C ocamldoc $@
 	@echo "documentation is in ./ocamldoc/stdlib_html/"
 
 partialclean::
-	cd ocamldoc && $(MAKE) clean
+	$(MAKE) -C ocamldoc clean
 
 alldepend::
-	cd ocamldoc && $(MAKE) depend
+	$(MAKE) -C ocamldoc depend
 
 # The extra libraries
 
+.PHONY: otherlibraries
 otherlibraries: ocamltools
 	for i in $(OTHERLIBRARIES); do \
-	  (cd otherlibs/$$i; $(MAKE) all) || exit $$?; \
+	  ($(MAKE) -C otherlibs/$$i all) || exit $$?; \
 	done
 
+.PHONY: otherlibrariesopt
 otherlibrariesopt:
 	for i in $(OTHERLIBRARIES); do \
-	  (cd otherlibs/$$i; $(MAKE) allopt) || exit $$?; \
+	  ($(MAKE) -C otherlibs/$$i allopt) || exit $$?; \
 	done
 
 partialclean::
 	for i in $(OTHERLIBRARIES); do \
-	  (cd otherlibs/$$i && $(MAKE) partialclean); \
+	  ($(MAKE) -C otherlibs/$$i partialclean); \
 	done
 
 clean::
-	for i in $(OTHERLIBRARIES); do (cd otherlibs/$$i && $(MAKE) clean); done
+	for i in $(OTHERLIBRARIES); do \
+	  ($(MAKE) -C otherlibs/$$i clean); \
+	done
 
 alldepend::
-	for i in $(OTHERLIBRARIES); do (cd otherlibs/$$i; $(MAKE) depend); done
+	for i in $(OTHERLIBRARIES); do \
+	  ($(MAKE) -C otherlibs/$$i depend); \
+	done
 
 # The replay debugger
 
+.PHONY: ocamldebugger
 ocamldebugger: ocamlc ocamlyacc ocamllex otherlibraries
-	cd debugger; $(MAKE) all
+	$(MAKE) -C debugger all
 
 partialclean::
-	cd debugger; $(MAKE) clean
+	$(MAKE) -C debugger clean
 
 alldepend::
-	cd debugger; $(MAKE) depend
+	$(MAKE) -C debugger depend
 
 # Check that the stack limit is reasonable.
-
+ifeq "$(UNIX_OR_WIN32)" "unix"
+.PHONY: checkstack
 checkstack:
-	@if $(MKEXE) -o tools/checkstack$(EXE) tools/checkstack.c; \
+	if $(MKEXE) -o tools/checkstack$(EXE) tools/checkstack.c; \
 	  then tools/checkstack$(EXE); \
 	  else :; \
 	fi
-	@rm -f tools/checkstack
+	rm -f tools/checkstack$(EXE)
+endif
+
+# Lint @since and @deprecated annotations
+
+.PHONY: lintapidiff
+lintapidiff:
+	$(MAKE) -C tools lintapidiff.opt
+	git ls-files -- 'otherlibs/*/*.mli' 'stdlib/*.mli' |\
+	    grep -Ev internal\|obj\|spacetime\|stdLabels\|moreLabels |\
+	    tools/lintapidiff.opt $(shell git tag|grep '^[0-9]*.[0-9]*.[0-9]*$$'|grep -v '^[12].')
 
 # Make clean in the test suite
 
@@ -716,7 +1109,8 @@ clean::
 	cd testsuite; $(MAKE) clean
 
 # Make MacOS X package
-
+ifeq "$(UNIX_OR_WIN32)" "unix"
+.PHONY: package-macosx
 package-macosx:
 	sudo rm -rf package-macosx/root
 	$(MAKE) PREFIX="`pwd`"/package-macosx/root install
@@ -725,6 +1119,142 @@ package-macosx:
 
 clean::
 	rm -rf package-macosx/*.pkg package-macosx/*.dmg
+endif
+
+# The middle end (whose .cma library is currently only used for linking
+# the "ocamlobjinfo" program, since we cannot depend on the whole native code
+# compiler for "make world" and the list of dependencies for
+# asmcomp/export_info.cmo is long).
+
+compilerlibs/ocamlmiddleend.cma: $(MIDDLE_END)
+	$(CAMLC) -a -o $@ $^
+compilerlibs/ocamlmiddleend.cmxa: $(MIDDLE_END:%.cmo=%.cmx)
+	$(CAMLOPT) -a -o $@ $^
+partialclean::
+	rm -f compilerlibs/ocamlmiddleend.cma \
+	      compilerlibs/ocamlmiddleend.cmxa \
+	      compilerlibs/ocamlmiddleend.$(A)
+
+# Tools
+
+.PHONY: ocamltools
+ocamltools: ocamlc ocamlyacc ocamllex asmcomp/cmx_format.cmi \
+            asmcomp/printclambda.cmo compilerlibs/ocamlmiddleend.cma \
+            asmcomp/export_info.cmo
+	$(MAKE) -C tools all
+
+.PHONY: ocamltoolsopt
+ocamltoolsopt: ocamlopt
+	$(MAKE) -C tools opt
+
+.PHONY: ocamltoolsopt.opt
+ocamltoolsopt.opt: ocamlc.opt ocamlyacc ocamllex.opt asmcomp/cmx_format.cmi \
+                   asmcomp/printclambda.cmx compilerlibs/ocamlmiddleend.cmxa \
+                   asmcomp/export_info.cmx
+	$(MAKE) -C tools opt.opt
+
+partialclean::
+	$(MAKE) -C tools clean
+
+alldepend::
+	$(MAKE) -C tools depend
+
+## Test compilation of backend-specific parts
+
+partialclean::
+	rm -f $(ARCH_SPECIFIC)
+
+beforedepend:: $(ARCH_SPECIFIC)
+
+# This rule provides a quick way to check that machine-dependent
+# files compiles fine for a foreign architecture (passed as ARCH=xxx).
+
+.PHONY: check_arch
+check_arch:
+	@echo "========= CHECKING asmcomp/$(ARCH) =============="
+	@rm -f $(ARCH_SPECIFIC) asmcomp/emit.ml asmcomp/*.cm*
+	@$(MAKE) compilerlibs/ocamloptcomp.cma \
+	            >/dev/null
+	@rm -f $(ARCH_SPECIFIC) asmcomp/emit.ml asmcomp/*.cm*
+
+.PHONY: check_all_arches
+check_all_arches:
+	@STATUS=0; \
+	 for i in $(ARCHES); do \
+	   $(MAKE) --no-print-directory check_arch ARCH=$$i || STATUS=1; \
+	 done; \
+	 exit $$STATUS
+
+# Compiler Plugins
+
+DYNLINK_DIR=otherlibs/dynlink
+
+driver/compdynlink.mlbyte: $(DYNLINK_DIR)/dynlink.ml driver/compdynlink.mli
+	grep -v 'REMOVE_ME for ../../debugger/dynlink.ml' \
+	     $(DYNLINK_DIR)/dynlink.ml >driver/compdynlink.mlbyte
+
+ifeq ($(NATDYNLINK),true)
+driver/compdynlink.mlopt: $(DYNLINK_DIR)/natdynlink.ml driver/compdynlink.mli
+	cp $(DYNLINK_DIR)/natdynlink.ml driver/compdynlink.mlopt
+else
+driver/compdynlink.mlopt: driver/compdynlink.mlno driver/compdynlink.mli
+	cp driver/compdynlink.mlno driver/compdynlink.mlopt
+endif
+
+driver/compdynlink.mli: $(DYNLINK_DIR)/dynlink.mli
+	cp $(DYNLINK_DIR)/dynlink.mli driver/compdynlink.mli
+
+driver/compdynlink.cmo: driver/compdynlink.mlbyte driver/compdynlink.cmi
+	$(CAMLC) $(COMPFLAGS) -c -impl $<
+
+driver/compdynlink.cmx: driver/compdynlink.mlopt driver/compdynlink.cmi
+	$(CAMLOPT) $(COMPFLAGS) -c -impl $<
+
+beforedepend:: driver/compdynlink.mlbyte driver/compdynlink.mlopt \
+               driver/compdynlink.mli
+partialclean::
+	rm -f driver/compdynlink.mlbyte
+	rm -f driver/compdynlink.mli
+	rm -f driver/compdynlink.mlopt
+
+# The native toplevel
+
+compilerlibs/ocamlopttoplevel.cmxa: $(OPTTOPLEVEL:.cmo=.cmx)
+	$(CAMLOPT) -a -o $@ $^
+partialclean::
+	rm -f compilerlibs/ocamlopttoplevel.cmxa
+
+# When the native toplevel executable has an extension (e.g. ".exe"),
+# provide a phony 'ocamlnat' synonym
+
+ifneq ($(EXE),)
+.PHONY: ocamlnat
+ocamlnat: ocamlnat$(EXE)
+endif
+
+ocamlnat$(EXE): compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
+    compilerlibs/ocamlbytecomp.cmxa \
+    compilerlibs/ocamlopttoplevel.cmxa \
+    $(OPTTOPLEVELSTART:.cmo=.cmx)
+	$(CAMLOPT) $(LINKFLAGS) -linkall -o $@ $^
+
+partialclean::
+	rm -f ocamlnat$(EXE)
+
+toplevel/opttoploop.cmx: otherlibs/dynlink/dynlink.cmxa
+
+# The numeric opcodes
+
+bytecomp/opcodes.ml: byterun/caml/instruct.h tools/make_opcodes
+	$(CAMLRUN) tools/make_opcodes -opcodes < $< > $@
+
+tools/make_opcodes: tools/make_opcodes.mll
+	$(MAKE) -C tools make_opcodes
+
+partialclean::
+	rm -f bytecomp/opcodes.ml
+
+beforedepend:: bytecomp/opcodes.ml
 
 # Default rules
 
@@ -741,40 +1271,35 @@ clean::
 
 partialclean::
 	for d in utils parsing typing bytecomp asmcomp middle_end \
-	         middle_end/base_types driver toplevel tools; \
-	  do rm -f $$d/*.cm[ioxt] $$d/*.cmti $$d/*.annot $$d/*.[so] $$d/*~; done
+	         middle_end/base_types driver toplevel tools; do \
+	  rm -f $$d/*.cm[ioxt] $$d/*.cmti $$d/*.annot $$d/*.$(S) \
+	    $$d/*.$(O) $$d/*.$(SO) $d/*~; \
+	done
 	rm -f *~
 
+.PHONY: depend
 depend: beforedepend
 	(for d in utils parsing typing bytecomp asmcomp middle_end \
 	 middle_end/base_types driver toplevel; \
-	 do $(CAMLDEP) $(DEPFLAGS) $$d/*.mli $$d/*.ml; \
+	 do $(CAMLDEP) -slash $(DEPFLAGS) $$d/*.mli $$d/*.ml; \
 	 done) > .depend
-	$(CAMLDEP) $(DEPFLAGS) -native \
+	$(CAMLDEP) -slash $(DEPFLAGS) -native \
 		-impl driver/compdynlink.mlopt >> .depend
-	$(CAMLDEP) $(DEPFLAGS) -bytecode \
+	$(CAMLDEP) -slash $(DEPFLAGS) -bytecode \
 		-impl driver/compdynlink.mlbyte >> .depend
 
 alldepend:: depend
 
-distclean:
-	$(MAKE) clean
-	rm -f boot/ocamlrun boot/ocamlrun.exe boot/camlheader boot/ocamlyacc \
-	      boot/*.cm* boot/libcamlrun.a
+.PHONY: distclean
+distclean: clean
+	rm -f asmrun/.depend.nt byterun/.depend.nt \
+	            otherlibs/bigarray/.depend.nt  \
+		    otherlibs/str/.depend.nt
+	rm -f boot/ocamlrun boot/ocamlrun$(EXE) boot/camlheader \
+	      boot/ocamlyacc boot/*.cm* boot/libcamlrun.$(A)
 	rm -f config/Makefile config/m.h config/s.h
 	rm -f tools/*.bak
 	rm -f ocaml ocamlc
 	rm -f testsuite/_log
 
-.PHONY: all backup bootstrap checkstack clean
-.PHONY: partialclean beforedepend alldepend cleanboot coldstart
-.PHONY: compare core coreall
-.PHONY: coreboot defaultentry depend distclean install installopt
-.PHONY: library library-cross libraryopt
-.PHONY: ocamldebugger ocamldoc
-.PHONY: ocamldoc.opt ocamllex ocamllex.opt ocamltools ocamltoolsopt
-.PHONY: ocamltoolsopt.opt ocamlyacc opt-core opt opt.opt otherlibraries
-.PHONY: otherlibrariesopt package-macosx promote promote-cross
-.PHONY: restore runtime runtimeopt makeruntimeopt world world.opt
-
 include .depend
diff --git a/Makefile.nt b/Makefile.nt
index 4207c996..ed9900bb 100644
--- a/Makefile.nt
+++ b/Makefile.nt
@@ -13,755 +13,4 @@
 #*                                                                        *
 #**************************************************************************
 
-# The main Makefile
-
-include Makefile.shared
-
-# For users who don't read the INSTALL file
-defaultentry:
-	@echo "Please refer to the instructions in file README.win32.adoc."
-
-FLEXDLL_SUBMODULE_PRESENT:=$(wildcard flexdll/Makefile)
-ifeq "$(FLEXDLL_SUBMODULE_PRESENT)" ""
-  BOOT_FLEXLINK_CMD=
-else
-  BOOT_FLEXLINK_CMD=FLEXLINK_CMD="../boot/ocamlrun ../flexdll/flexlink.exe"
-  CAMLOPT:=OCAML_FLEXLINK="boot/ocamlrun flexdll/flexlink.exe" $(CAMLOPT)
-endif
-
-# FlexDLL sources missing error messages
-# Different git mechanism displayed depending on whether this source tree came
-# from a git clone or a source tarball.
-
-flexdll/Makefile:
-	@echo In order to bootstrap FlexDLL, you need to place the sources in
-	@echo flexdll.
-	@echo This can either be done by downloading a source tarball from
-	@echo \  http://alain.frisch.fr/flexdll.html
-	@if [ -d .git ]; then \
-	  echo or by checking out the flexdll submodule with; \
-	  echo \  git submodule update --init; \
-	else \
-	  echo or by cloning the git repository; \
-	  echo \  git clone https://github.com/alainfrisch/flexdll.git; \
-	fi
-	@false
-
-# Bootstrapping FlexDLL - leaves a bytecode image of flexlink.exe in flexdll/
-flexdll: flexdll/Makefile
-	cd byterun && $(MAKEREC) BOOTSTRAPPING_FLEXLINK=yes ocamlrun$(EXE)
-	cp byterun/ocamlrun.exe boot/ocamlrun.exe
-	cd stdlib && $(MAKEREC) COMPILER=../boot/ocamlc stdlib.cma std_exit.cmo
-	cd stdlib && cp stdlib.cma std_exit.cmo *.cmi ../boot
-	cd flexdll && \
-	 $(MAKECMD) MSVC_DETECT=0 TOOLCHAIN=$(TOOLCHAIN) TOOLPREF=$(TOOLPREF) \
-	            CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false \
-	            OCAMLOPT="../boot/ocamlrun ../boot/ocamlc -I ../boot" \
-	            flexlink.exe support
-	cd byterun && $(MAKEREC) clean
-	$(MAKEREC) partialclean
-
-flexlink.opt:
-	cd flexdll && \
-	mv flexlink.exe flexlink && \
-	$(MAKECMD) OCAML_FLEXLINK="../boot/ocamlrun ./flexlink" MSVC_DETECT=0 \
-	           TOOLCHAIN=$(TOOLCHAIN) TOOLPREF=$(TOOLPREF) \
-	           OCAMLOPT="../ocamlopt.opt -I ../stdlib" flexlink.exe && \
-	mv flexlink.exe flexlink.opt && \
-	mv flexlink flexlink.exe
-
-# Recompile the system using the bootstrap compiler
-all: runtime ocamlc ocamllex ocamlyacc ocamltools library ocaml \
-  otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC)
-
-# The compilation of ocaml will fail if the runtime has changed.
-# Never mind, just do make bootstrap to reach fixpoint again.
-
-# Compile everything the first time
-world: coldstart all
-
-# Core bootstrapping cycle
-coreboot:
-# Save the original bootstrap compiler
-	$(MAKEREC) backup
-# Promote the new compiler but keep the old runtime
-# This compiler runs on boot/ocamlrun and produces bytecode for
-# byterun/ocamlrun
-	$(MAKEREC) promote-cross
-# Rebuild ocamlc and ocamllex (run on byterun/ocamlrun)
-	$(MAKEREC) partialclean
-	$(MAKEREC) ocamlc ocamllex ocamltools
-# Rebuild the library (using byterun/ocamlrun ./ocamlc)
-	$(MAKEREC) library-cross
-# Promote the new compiler and the new runtime
-	$(MAKEREC) promote
-# Rebuild the core system
-	$(MAKEREC) partialclean
-	$(MAKEREC) core
-# Check if fixpoint reached
-	$(MAKEREC) compare
-
-# Do a complete bootstrapping cycle
-bootstrap:
-	$(MAKEREC) coreboot
-	$(MAKEREC) all
-	$(MAKEREC) compare
-
-LIBFILES=stdlib.cma std_exit.cmo *.cmi camlheader
-
-# Start up the system from the distribution compiler
-coldstart:
-	cd byterun ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
-	cp byterun/ocamlrun.exe boot/ocamlrun.exe
-	cd yacc ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
-	cp yacc/ocamlyacc.exe boot/ocamlyacc.exe
-	cd stdlib ; \
-	  $(MAKEREC) $(BOOT_FLEXLINK_CMD) \
-	             COMPILER="../boot/ocamlc -use-prims ../byterun/primitives"\
-	             all
-	cd stdlib ; cp $(LIBFILES) ../boot
-
-# Build the core system: the minimum needed to make depend and bootstrap
-core: runtime ocamlc ocamllex ocamlyacc ocamltools library
-
-# Save the current bootstrap compiler
-MAXSAVED=boot/Saved/Saved.prev/Saved.prev/Saved.prev/Saved.prev/Saved.prev
-backup:
-	mkdir -p boot/Saved
-	if test -d $(MAXSAVED); then rm -r $(MAXSAVED); fi
-	mv boot/Saved boot/Saved.prev
-	mkdir boot/Saved
-	mv boot/Saved.prev boot/Saved/Saved.prev
-	cp boot/ocamlrun.exe boot/Saved/ocamlrun.exe
-	cd boot ; mv ocamlc ocamllex ocamldep ocamlyacc.exe Saved
-	cd boot ; cp $(LIBFILES) Saved
-
-# Promote the newly compiled system to the rank of cross compiler
-# (Runs on the old runtime, produces code for the new runtime)
-promote-cross:
-	$(CAMLRUN) tools/stripdebug ocamlc boot/ocamlc
-	$(CAMLRUN) tools/stripdebug lex/ocamllex boot/ocamllex
-	cp yacc/ocamlyacc.exe boot/ocamlyacc.exe
-	$(CAMLRUN) tools/stripdebug tools/ocamldep boot/ocamldep
-	cd stdlib ; cp $(LIBFILES) ../boot
-
-# Promote the newly compiled system to the rank of bootstrap compiler
-# (Runs on the new runtime, produces code for the new runtime)
-promote: promote-cross
-	cp byterun/ocamlrun.exe boot/ocamlrun.exe
-
-# Restore the saved bootstrap compiler if a problem arises
-restore:
-	cd boot/Saved ; mv * ..
-	rmdir boot/Saved
-	mv boot/Saved.prev boot/Saved
-
-# Check if fixpoint reached
-compare:
-	@if $(CAMLRUN) tools/cmpbyt boot/ocamlc ocamlc \
-         && $(CAMLRUN) tools/cmpbyt boot/ocamllex lex/ocamllex \
-         && $(CAMLRUN) tools/cmpbyt boot/ocamldep tools/ocamldep; \
-	then echo "Fixpoint reached, bootstrap succeeded."; \
-	else echo "Fixpoint not reached, try one more bootstrapping cycle."; \
-	fi
-
-# Remove old bootstrap compilers
-cleanboot:
-	rm -rf boot/Saved/Saved.prev/*
-
-# Compile the native-code compiler
-opt-core:
-	$(MAKEREC) runtimeopt
-	$(MAKEREC) ocamlopt
-	$(MAKEREC) libraryopt
-
-opt:
-	$(MAKEREC) opt-core
-	$(MAKEREC) otherlibrariesopt ocamltoolsopt
-
-# Native-code versions of the tools
-# If the submodule is initialised, then opt.opt will build a native flexlink
-opt.opt: core opt-core ocamlc.opt all ocamlopt.opt ocamllex.opt \
-         ocamltoolsopt ocamltoolsopt.opt otherlibrariesopt $(OCAMLDOC_OPT) \
-         $(if $(wildcard flexdll/Makefile),flexlink.opt)
-
-# Complete build using fast compilers
-world.opt: coldstart opt.opt
-
-# Installation
-
-COMPLIBDIR=$(LIBDIR)/compiler-libs
-
-INSTALL_BINDIR=$(DESTDIR)$(BINDIR)
-INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
-INSTALL_COMPLIBDIR=$(DESTDIR)$(COMPLIBDIR)
-INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR)
-INSTALL_MANDIR=$(DESTDIR)$(MANDIR)
-INSTALL_DISTRIB=$(DESTDIR)$(PREFIX)
-
-install: installbyt installopt
-
-installbyt:
-	mkdir -p "$(INSTALL_BINDIR)"
-	mkdir -p "$(INSTALL_LIBDIR)"
-	mkdir -p "$(INSTALL_STUBLIBDIR)"
-	mkdir -p "$(INSTALL_COMPLIBDIR)"
-	cp VERSION "$(INSTALL_LIBDIR)/"
-	cd byterun ; $(MAKEREC) install
-	cp ocamlc "$(INSTALL_BINDIR)/ocamlc.exe"
-	cp ocaml "$(INSTALL_BINDIR)/ocaml.exe"
-	cp ocamlc "$(INSTALL_BINDIR)/ocamlc.byte.exe"
-	cd stdlib ; $(MAKEREC) install
-	cp lex/ocamllex "$(INSTALL_BINDIR)/ocamllex.exe"
-	cp yacc/ocamlyacc.exe "$(INSTALL_BINDIR)/ocamlyacc.exe"
-	cp lex/ocamllex "$(INSTALL_BINDIR)/ocamllex.byte.exe"
-	cp utils/*.cmi utils/*.cmt utils/*.cmti \
-	   parsing/*.cmi parsing/*.cmt parsing/*.cmti \
-	   typing/*.cmi typing/*.cmt typing/*.cmti \
-	   bytecomp/*.cmi bytecomp/*.cmt bytecomp/*.cmti \
-	   driver/*.cmi driver/*.cmt driver/*.cmti \
-	   toplevel/*.cmi toplevel/*.cmt toplevel/*.cmti "$(INSTALL_COMPLIBDIR)"
-	cp compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
-	   compilerlibs/ocamltoplevel.cma $(BYTESTART) $(TOPLEVELSTART) \
-	   "$(INSTALL_COMPLIBDIR)"
-	cp expunge "$(INSTALL_LIBDIR)/expunge.exe"
-	cp toplevel/topdirs.cmi "$(INSTALL_LIBDIR)"
-	cd tools ; $(MAKEREC) install
-	for i in $(OTHERLIBRARIES); do \
-	  $(MAKEREC) -C otherlibs/$$i install || exit $$?; \
-	done
-	if test -n "$(WITH_OCAMLDOC)"; then \
-	  (cd ocamldoc; $(MAKEREC) install); \
-	fi
-	if test -n "$(WITH_DEBUGGER)"; then \
-	  (cd debugger; $(MAKEREC) install); \
-	fi
-	if test -n "$(FLEXDLL_SUBMODULE_PRESENT)"; then \
-	  $(MAKEREC) install-flexdll; \
-	fi
-	cp config/Makefile "$(INSTALL_LIBDIR)/Makefile.config"
-	if test -n "$(INSTALL_DISTRIB)"; then \
-	   cp README.adoc "$(INSTALL_DISTRIB)/Readme.general.txt"; \
-	   cp README.win32.adoc "$(INSTALL_DISTRIB)/Readme.windows.txt"; \
-	   cp LICENSE "$(INSTALL_DISTRIB)/License.txt"; \
-	   cp Changes "$(INSTALL_DISTRIB)/Changes.txt"; \
-	fi
-
-install-flexdll:
-# The $(if ...) installs the correct .manifest file for MSVC and MSVC64
-# (GNU make doesn't have ifeq as a function, hence slightly convoluted use of
-#  filter-out)
-	cp flexdll/flexlink.exe \
-	   $(if $(filter-out mingw,$(TOOLCHAIN)),\
-	     flexdll/default$(filter-out _i386,_$(ARCH)).manifest) \
-	   $(INSTALL_BINDIR)/
-	cp flexdll/flexdll_*.$(O) $(INSTALL_LIBDIR)
-
-# Installation of the native-code compiler
-installopt:
-	cd asmrun && $(MAKEREC) install
-	cp ocamlopt "$(INSTALL_BINDIR)/ocamlopt.exe"
-	cp ocamlopt "$(INSTALL_BINDIR)/ocamlopt.byte.exe"
-	cd stdlib && $(MAKEREC) installopt
-	cp middle_end/*.cmi middle_end/*.cmt middle_end/*.cmti \
-		"$(INSTALL_COMPLIBDIR)"
-	cp middle_end/base_types/*.cmi middle_end/base_types/*.cmt \
-		middle_end/base_types/*.cmti "$(INSTALL_COMPLIBDIR)"
-	cp asmcomp/*.cmi asmcomp/*.cmt asmcomp/*.cmti "$(INSTALL_COMPLIBDIR)"
-	cp compilerlibs/ocamloptcomp.cma $(OPTSTART) "$(INSTALL_COMPLIBDIR)"
-	if test -n "$(WITH_OCAMLDOC)"; then \
-	  (cd ocamldoc && $(MAKEREC) installopt); \
-	fi
-	for i in $(OTHERLIBRARIES); do \
-	  $(MAKEREC) -C otherlibs/$$i installopt || exit $$?; \
-	done
-	if test -f ocamlopt.opt ; then $(MAKEREC) installoptopt; fi
-	cd tools; $(MAKEREC) installopt
-	if test -f ocamlopt.opt -a -f flexdll/flexlink.opt ; then \
-	  cp -f flexdll/flexlink.opt $(INSTALL_BINDIR)/flexlink.exe ; \
-	fi
-
-installoptopt:
-	cp ocamlc.opt "$(INSTALL_BINDIR)/ocamlc.opt$(EXE)"
-	cp ocamlopt.opt "$(INSTALL_BINDIR)/ocamlopt.opt$(EXE)"
-	cp lex/ocamllex.opt "$(INSTALL_BINDIR)/ocamllex.opt$(EXE)"
-	cp ocamlc.opt "$(INSTALL_BINDIR)/ocamlc$(EXE)"
-	cp ocamlopt.opt "$(INSTALL_BINDIR)/ocamlopt$(EXE)"
-	cp lex/ocamllex.opt "$(INSTALL_BINDIR)/ocamllex$(EXE)"
-	cp utils/*.cmx parsing/*.cmx typing/*.cmx bytecomp/*.cmx \
-           driver/*.cmx asmcomp/*.cmx "$(INSTALL_COMPLIBDIR)"
-	cp compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.$(A) \
-           compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.$(A) \
-           compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.$(A) \
-           $(BYTESTART:.cmo=.cmx) $(BYTESTART:.cmo=.$(O)) \
-           $(OPTSTART:.cmo=.cmx) $(OPTSTART:.cmo=.$(O)) \
-           "$(INSTALL_COMPLIBDIR)"
-
-# Run all tests
-
-tests: opt.opt
-	cd testsuite && $(MAKE) clean && $(MAKE) all
-
-# The clean target
-
-clean:: partialclean
-
-# The compiler
-
-compilerlibs/ocamlcommon.cma: $(COMMON)
-	$(CAMLC) -a -o $@ $(COMMON)
-partialclean::
-	rm -f compilerlibs/ocamlcommon.cma
-
-# The bytecode compiler
-
-compilerlibs/ocamlbytecomp.cma: $(BYTECOMP)
-	$(CAMLC) -a -o $@ $(BYTECOMP)
-partialclean::
-	rm -f compilerlibs/ocamlbytecomp.cma
-
-ocamlc: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma $(BYTESTART)
-	$(CAMLC) $(LINKFLAGS) -compat-32 -o ocamlc \
-	         compilerlibs/ocamlcommon.cma \
-	         compilerlibs/ocamlbytecomp.cma $(BYTESTART)
-
-partialclean::
-	rm -f ocamlc
-
-# The native-code compiler
-
-compilerlibs/ocamloptcomp.cma: $(MIDDLE_END) $(ASMCOMP)
-	$(CAMLC) -a -o $@ $(MIDDLE_END) $(ASMCOMP)
-partialclean::
-	rm -f compilerlibs/ocamloptcomp.cma
-
-ocamlopt: compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
-          compilerlibs/ocamlbytecomp.cma $(OPTSTART)
-	$(CAMLC) $(LINKFLAGS) -o ocamlopt \
-          compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
-	  compilerlibs/ocamlbytecomp.cma $(OPTSTART)
-
-partialclean::
-	rm -f ocamlopt
-
-# The toplevel
-
-compilerlibs/ocamltoplevel.cma: $(TOPLEVEL)
-	$(CAMLC) -a -o $@ $(TOPLEVEL)
-partialclean::
-	rm -f compilerlibs/ocamltoplevel.cma
-
-ocaml: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
-       compilerlibs/ocamltoplevel.cma $(TOPLEVELSTART) expunge
-	$(CAMLC) $(LINKFLAGS) -linkall -o ocaml.tmp \
-          compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
-          compilerlibs/ocamltoplevel.cma $(TOPLEVELSTART)
-	- $(CAMLRUN) ./expunge ocaml.tmp ocaml $(PERVASIVES)
-	rm -f ocaml.tmp
-
-partialclean::
-	rm -f ocaml
-
-# The native toplevel
-
-compilerlibs/ocamlopttoplevel.cmxa: $(OPTTOPLEVEL:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(OPTTOPLEVEL:.cmo=.cmx)
-partialclean::
-	rm -f compilerlibs/ocamlopttoplevel.cmxa
-
-ocamlnat: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
-    compilerlibs/ocamlbytecomp.cmxa \
-    compilerlibs/ocamlopttoplevel.cmxa \
-    $(OPTTOPLEVELSTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -linkall -o $@ $^
-
-toplevel/opttoploop.cmx: otherlibs/dynlink/dynlink.cmxa
-
-otherlibs/dynlink/dynlink.cmxa: otherlibs/dynlink/natdynlink.ml
-	cd otherlibs/dynlink && $(MAKEREC) allopt
-
-
-# The configuration file
-
-utils/config.ml: utils/config.mlp config/Makefile
-	@rm -f utils/config.ml
-	sed -e "s|%%LIBDIR%%|$(LIBDIR)|" \
-	    -e "s|%%BYTERUN%%|ocamlrun|" \
-	    -e 's|%%CCOMPTYPE%%|$(CCOMPTYPE)|' \
-	    -e "s|%%BYTECC%%|$(BYTECC) $(BYTECCCOMPOPTS)|" \
-	    -e "s|%%NATIVECC%%|$(NATIVECC) $(NATIVECCCOMPOPTS)|" \
-	    -e "s|%%PARTIALLD%%|$(PARTIALLD)|" \
-	    -e "s|%%PACKLD%%|$(PACKLD)|" \
-	    -e "s|%%BYTECCLIBS%%|$(BYTECCLIBS)|" \
-	    -e "s|%%NATIVECCLIBS%%|$(NATIVECCLIBS)|" \
-	    -e 's|%%RANLIBCMD%%|$(RANLIBCMD)|' \
-	    -e 's|%%ARCMD%%|$(ARCMD)|' \
-	    -e 's|%%BINUTILS_NM%%|$(BINUTILS_NM)|' \
-	    -e 's|%%BINUTILS_OBJCOPY%%|$(BINUTILS_OBJCOPY)|' \
-	    -e "s|%%ARCH%%|$(ARCH)|" \
-	    -e "s|%%MODEL%%|$(MODEL)|" \
-	    -e "s|%%SYSTEM%%|$(SYSTEM)|" \
-	    -e "s|%%EXT_OBJ%%|.$(O)|" \
-	    -e "s|%%EXT_ASM%%|.$(S)|" \
-	    -e "s|%%EXT_LIB%%|.$(A)|" \
-	    -e "s|%%EXT_DLL%%|.dll|" \
-	    -e "s|%%SYSTHREAD_SUPPORT%%|true|" \
-	    -e 's|%%ASM%%|$(ASM)|' \
-	    -e 's|%%ASM_CFI_SUPPORTED%%|false|' \
-	    -e 's|%%WITH_FRAME_POINTERS%%|false|' \
-	    -e 's|%%WITH_SPACETIME%%|$(WITH_SPACETIME)|' \
-	    -e 's|%%PROFINFO_WIDTH%%|$(PROFINFO_WIDTH)|' \
-	    -e 's|%%LIBUNWIND_AVAILABLE%%|false|' \
-	    -e 's|%%LIBUNWIND_LINK_FLAGS%%||' \
-	    -e 's|%%MKDLL%%|$(MKDLL)|' \
-	    -e 's|%%MKEXE%%|$(MKEXE)|' \
-	    -e 's|%%MKMAINDLL%%|$(MKMAINDLL)|' \
-	    -e 's|%%CC_PROFILE%%||' \
-	    -e 's|%%HOST%%|$(HOST)|' \
-	    -e 's|%%TARGET%%|$(TARGET)|' \
-	    -e 's|%%FLAMBDA%%|$(FLAMBDA)|' \
-	    -e 's|%%SAFE_STRING%%|$(SAFE_STRING)|' \
-	    -e 's|%%FLEXLINK_FLAGS%%|$(FLEXLINK_FLAGS)|' \
-	    utils/config.mlp > utils/config.ml
-
-partialclean::
-	rm -f utils/config.ml
-
-beforedepend:: utils/config.ml
-
-# The parser
-
-parsing/parser.mli parsing/parser.ml: parsing/parser.mly
-	$(CAMLYACC) $(YACCFLAGS) parsing/parser.mly
-
-partialclean::
-	rm -f parsing/parser.mli parsing/parser.ml parsing/parser.output
-
-beforedepend:: parsing/parser.mli parsing/parser.ml
-
-# The lexer
-
-parsing/lexer.ml: parsing/lexer.mll
-	$(CAMLLEX) parsing/lexer.mll
-
-partialclean::
-	rm -f parsing/lexer.ml
-
-beforedepend:: parsing/lexer.ml
-
-# Shared parts of the system compiled with the native-code compiler
-
-compilerlibs/ocamlcommon.cmxa: $(COMMON:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(COMMON:.cmo=.cmx)
-partialclean::
-	rm -f compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.$(A)
-
-# The bytecode compiler compiled with the native-code compiler
-
-compilerlibs/ocamlbytecomp.cmxa: $(BYTECOMP:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(BYTECOMP:.cmo=.cmx)
-partialclean::
-	rm -f compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.$(A)
-
-ocamlc.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlbytecomp.cmxa \
-            $(BYTESTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -ccopt "$(BYTECCLINKOPTS)" -o ocamlc.opt \
-          compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlbytecomp.cmxa \
-          $(BYTESTART:.cmo=.cmx) -cclib "$(BYTECCLIBS)"
-
-partialclean::
-	rm -f ocamlc.opt
-
-# The native-code compiler compiled with itself
-
-compilerlibs/ocamloptcomp.cmxa: $(MIDDLE_END:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(MIDDLE_END:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx)
-partialclean::
-	rm -f compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.$(A)
-
-ocamlopt.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
-              compilerlibs/ocamlbytecomp.cmxa \
-              $(OPTSTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -o ocamlopt.opt \
-          compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
-	  compilerlibs/ocamlbytecomp.cmxa \
-          $(OPTSTART:.cmo=.cmx)
-
-partialclean::
-	rm -f ocamlopt.opt
-
-$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(MIDDLE_END:.cmo=.cmx) \
-$(ASMCOMP:.cmo=.cmx): ocamlopt
-
-# The numeric opcodes
-
-bytecomp/opcodes.ml: byterun/caml/instruct.h
-	sed -n -e "/^enum/p" -e "s|,||g" -e "/^  /p" byterun/caml/instruct.h | \
-	gawk -f tools/make-opcodes > bytecomp/opcodes.ml
-
-partialclean::
-	rm -f bytecomp/opcodes.ml
-
-beforedepend:: bytecomp/opcodes.ml
-
-# The predefined exceptions and primitives
-
-byterun/primitives:
-	cd byterun ; $(MAKEREC) primitives
-
-bytecomp/runtimedef.ml: byterun/primitives byterun/caml/fail.h
-	(echo 'let builtin_exceptions = [|'; \
-	 sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$$|  \1;|p' \
-	     byterun/caml/fail.h; \
-	 echo '|]'; \
-	 echo 'let builtin_primitives = [|'; \
-	 sed -e 's/.*/  "&";/' byterun/primitives; \
-	 echo '|]') > bytecomp/runtimedef.ml
-
-partialclean::
-	rm -f bytecomp/runtimedef.ml
-
-beforedepend:: bytecomp/runtimedef.ml
-
-# Choose the right machine-dependent files
-
-asmcomp/arch.ml: asmcomp/$(ARCH)/arch.ml
-	cp asmcomp/$(ARCH)/arch.ml asmcomp/arch.ml
-
-partialclean::
-	rm -f asmcomp/arch.ml
-
-beforedepend:: asmcomp/arch.ml
-
-asmcomp/proc.ml: asmcomp/$(ARCH)/proc.ml
-	cp asmcomp/$(ARCH)/proc.ml asmcomp/proc.ml
-
-partialclean::
-	rm -f asmcomp/proc.ml
-
-beforedepend:: asmcomp/proc.ml
-
-asmcomp/selection.ml: asmcomp/$(ARCH)/selection.ml
-	cp asmcomp/$(ARCH)/selection.ml asmcomp/selection.ml
-
-partialclean::
-	rm -f asmcomp/selection.ml
-
-beforedepend:: asmcomp/selection.ml
-
-asmcomp/CSE.ml: asmcomp/$(ARCH)/CSE.ml
-	cp asmcomp/$(ARCH)/CSE.ml asmcomp/CSE.ml
-
-partialclean::
-	rm -f asmcomp/CSE.ml
-
-beforedepend:: asmcomp/CSE.ml
-
-asmcomp/reload.ml: asmcomp/$(ARCH)/reload.ml
-	cp asmcomp/$(ARCH)/reload.ml asmcomp/reload.ml
-
-partialclean::
-	rm -f asmcomp/reload.ml
-
-beforedepend:: asmcomp/reload.ml
-
-asmcomp/scheduling.ml: asmcomp/$(ARCH)/scheduling.ml
-	cp asmcomp/$(ARCH)/scheduling.ml asmcomp/scheduling.ml
-
-partialclean::
-	rm -f asmcomp/scheduling.ml
-
-beforedepend:: asmcomp/scheduling.ml
-
-# Preprocess the code emitters
-
-asmcomp/emit.ml: asmcomp/$(ARCH)/emit.mlp tools/cvt_emit
-	$(CAMLRUN) tools/cvt_emit < asmcomp/$(ARCH)/emit.mlp > asmcomp/emit.ml
-
-partialclean::
-	rm -f asmcomp/emit.ml
-
-beforedepend:: asmcomp/emit.ml
-
-tools/cvt_emit: tools/cvt_emit.mll
-	cd tools ; $(MAKEREC) cvt_emit
-
-# The "expunge" utility
-
-expunge: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
-         toplevel/expunge.cmo
-	$(CAMLC) $(LINKFLAGS) -o expunge compilerlibs/ocamlcommon.cma \
-	         compilerlibs/ocamlbytecomp.cma toplevel/expunge.cmo
-
-partialclean::
-	rm -f expunge
-
-# The runtime system for the bytecode compiler
-
-runtime: makeruntime stdlib/libcamlrun.$(A)
-
-makeruntime:
-	cd byterun ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
-stdlib/libcamlrun.$(A): byterun/libcamlrun.$(A)
-	cp byterun/libcamlrun.$(A) stdlib/libcamlrun.$(A)
-clean::
-	cd byterun ; $(MAKEREC) clean
-	rm -f stdlib/libcamlrun.$(A)
-alldepend::
-	cd byterun ; $(MAKEREC) depend
-
-# The runtime system for the native-code compiler
-
-runtimeopt: makeruntimeopt stdlib/libasmrun.$(A)
-
-makeruntimeopt:
-	cd asmrun ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
-stdlib/libasmrun.$(A): asmrun/libasmrun.$(A)
-	cp asmrun/libasmrun.$(A) stdlib/libasmrun.$(A)
-clean::
-	cd asmrun ; $(MAKEREC) clean
-	rm -f stdlib/libasmrun.$(A)
-alldepend::
-	cd asmrun ; $(MAKEREC) depend
-
-# The library
-
-library:
-	cd stdlib && $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
-library-cross:
-	cd stdlib \
-	&& $(MAKEREC) $(BOOT_FLEXLINK_CMD) CAMLRUN=../byterun/ocamlrun all
-libraryopt:
-	cd stdlib && $(MAKEREC) $(BOOT_FLEXLINK_CMD) allopt
-partialclean::
-	cd stdlib && $(MAKEREC) clean
-alldepend::
-	cd stdlib && $(MAKEREC) depend
-
-# The lexer and parser generators
-
-ocamllex:
-	cd lex ; $(MAKEREC) all
-ocamllex.opt:
-	cd lex ; $(MAKEREC) allopt
-partialclean::
-	cd lex ; $(MAKEREC) clean
-alldepend::
-	cd lex ; $(MAKEREC) depend
-
-ocamlyacc:
-	cd yacc ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
-clean::
-	cd yacc ; $(MAKEREC) clean
-
-# OCamldoc
-
-ocamldoc:
-	cd ocamldoc ; $(MAKEREC) all
-ocamldoc.opt:
-	cd ocamldoc ; $(MAKEREC) opt.opt
-partialclean::
-	cd ocamldoc ; $(MAKEREC) clean
-alldepend::
-	cd ocamldoc ; $(MAKEREC) depend
-
-# The extra libraries
-
-otherlibraries:
-	for i in $(OTHERLIBRARIES); do \
-	  $(MAKEREC) -C otherlibs/$$i all || exit $$?; \
-	done
-otherlibrariesopt:
-	for i in $(OTHERLIBRARIES); \
-	  do $(MAKEREC) -C otherlibs/$$i allopt || exit $$?; \
-	done
-partialclean::
-	for i in $(OTHERLIBRARIES); \
-	  do $(MAKEREC) -C otherlibs/$$i partialclean || exit $$?; \
-	done
-clean::
-	for i in $(OTHERLIBRARIES); do \
-	  $(MAKEREC) -C otherlibs/$$i clean || exit $$?; \
-	done
-alldepend::
-	for i in $(OTHERLIBRARIES); do \
-	  $(MAKEREC) -C otherlibs/$$i depend || exit $$?; \
-	done
-
-# The replay debugger
-
-ocamldebugger: ocamlc ocamlyacc ocamllex
-	cd debugger; $(MAKEREC) all
-partialclean::
-	cd debugger; $(MAKEREC) clean
-alldepend::
-	cd debugger; $(MAKEREC) depend
-
-# Make clean in the test suite
-
-clean::
-	cd testsuite; $(MAKE) clean
-
-# Default rules
-
-.SUFFIXES: .ml .mli .cmo .cmi .cmx
-
-.ml.cmo:
-	$(CAMLC) $(COMPFLAGS) -c $<
-
-.mli.cmi:
-	$(CAMLC) $(COMPFLAGS) -c $<
-
-.ml.cmx:
-	$(CAMLOPT) $(COMPFLAGS) -c $<
-
-partialclean::
-	rm -f utils/*.cm* utils/*.$(O) utils/*.$(S)
-	rm -f parsing/*.cm* parsing/*.$(O) parsing/*.$(S)
-	rm -f typing/*.cm* typing/*.$(O) typing/*.$(S)
-	rm -f bytecomp/*.cm* bytecomp/*.$(O) bytecomp/*.$(S)
-	rm -f asmcomp/*.cm* asmcomp/*.$(O) asmcomp/*.$(S)
-	rm -f middle_end/*.cm* middle_end/*.$(O) middle_end/*.$(S)
-	rm -f middle_end/base_types/*.cm* middle_end/base_types/*.$(O) \
-	      middle_end/base_types/*.$(S)
-	rm -f driver/*.cm* driver/*.$(O) driver/*.$(S)
-	rm -f toplevel/*.cm* toplevel/*.$(O) toplevel/*.$(S)
-	rm -f tools/*.cm* tools/*.$(O) tools/*.$(S)
-
-depend: beforedepend
-	(for d in utils parsing typing bytecomp asmcomp middle_end \
-	 middle_end/base_types driver toplevel; \
-	 do $(CAMLDEP) -slash $(DEPFLAGS) $$d/*.mli $$d/*.ml; \
-	 done) > .depend
-	$(CAMLDEP) -slash $(DEPFLAGS) -native \
-		-impl driver/compdynlink.mlopt >> .depend
-	$(CAMLDEP) -slash $(DEPFLAGS) -bytecode \
-		-impl driver/compdynlink.mlbyte >> .depend
-
-alldepend:: depend
-
-distclean:
-	$(MAKEREC) clean
-	rm -f asmrun/.depend.nt byterun/.depend.nt \
-	            otherlibs/bigarray/.depend.nt  \
-		    otherlibs/str/.depend.nt
-	rm -f boot/ocamlrun boot/ocamlrun.exe boot/camlheader boot/ocamlyacc \
-	      boot/*.cm* boot/libcamlrun.a
-	rm -f config/Makefile config/m.h config/s.h
-	rm -f tools/*.bak
-	rm -f ocaml ocamlc
-	rm -f testsuite/_log
-
-.PHONY: all backup bootstrap checkstack clean
-.PHONY: partialclean beforedepend alldepend cleanboot coldstart
-.PHONY: compare core coreall
-.PHONY: coreboot defaultentry depend distclean install installopt
-.PHONY: library library-cross libraryopt
-.PHONY: ocamldebugger ocamldoc
-.PHONY: ocamldoc.opt ocamllex ocamllex.opt ocamltools ocamltoolsopt
-.PHONY: ocamltoolsopt.opt ocamlyacc opt-core opt opt.opt otherlibraries
-.PHONY: otherlibrariesopt promote promote-cross
-.PHONY: restore runtime runtimeopt makeruntimeopt world world.opt
-.PHONY: flexdll flexlink.opt flexdll-common-err flexdll-repo
-
-include .depend
+include Makefile
diff --git a/Makefile.shared b/Makefile.shared
deleted file mode 100644
index 5ffccb4a..00000000
--- a/Makefile.shared
+++ /dev/null
@@ -1,318 +0,0 @@
-#**************************************************************************
-#*                                                                        *
-#*                                 OCaml                                  *
-#*                                                                        *
-#*            Xavier Leroy, projet Cristal, INRIA Rocquencourt            *
-#*                                                                        *
-#*   Copyright 1999 Institut National de Recherche en Informatique et     *
-#*     en Automatique.                                                    *
-#*                                                                        *
-#*   All rights reserved.  This file is distributed under the terms of    *
-#*   the GNU Lesser General Public License version 2.1, with the          *
-#*   special exception on linking described in the file LICENSE.          *
-#*                                                                        *
-#**************************************************************************
-
-# For users who don't read the INSTALL file
-defaultentry:
-
-# The main Makefile, fragments shared between Makefile and Makefile.nt
-include config/Makefile
-CAMLRUN ?= boot/ocamlrun
-CAMLYACC ?= boot/ocamlyacc
-include stdlib/StdlibModules
-
-CAMLC=$(CAMLRUN) boot/ocamlc -g -nostdlib -I boot -use-prims byterun/primitives
-CAMLOPT=$(CAMLRUN) ./ocamlopt -g -nostdlib -I stdlib -I otherlibs/dynlink
-COMPFLAGS=-strict-sequence -principal -absname -w +a-4-9-41-42-44-45-48 \
-	  -warn-error A \
-          -bin-annot -safe-string -strict-formats $(INCLUDES)
-LINKFLAGS=
-
-YACCFLAGS=-v --strict
-CAMLLEX=$(CAMLRUN) boot/ocamllex
-CAMLDEP=$(CAMLRUN) tools/ocamldep
-DEPFLAGS=$(INCLUDES)
-
-OCAMLBUILDBYTE=$(WITH_OCAMLBUILD:=.byte)
-OCAMLBUILDNATIVE=$(WITH_OCAMLBUILD:=.native)
-
-OCAMLDOC_OPT=$(WITH_OCAMLDOC:=.opt)
-
-INCLUDES=-I utils -I parsing -I typing -I bytecomp -I middle_end \
-        -I middle_end/base_types -I asmcomp -I driver -I toplevel
-
-UTILS=utils/config.cmo utils/misc.cmo \
-  utils/identifiable.cmo utils/numbers.cmo utils/arg_helper.cmo \
-  utils/clflags.cmo utils/tbl.cmo utils/timings.cmo \
-  utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
-  utils/consistbl.cmo \
-  utils/strongly_connected_components.cmo
-
-PARSING=parsing/location.cmo parsing/longident.cmo \
-  parsing/docstrings.cmo parsing/ast_helper.cmo \
-  parsing/syntaxerr.cmo parsing/parser.cmo \
-  parsing/lexer.cmo parsing/parse.cmo parsing/printast.cmo \
-  parsing/pprintast.cmo \
-  parsing/ast_mapper.cmo parsing/ast_iterator.cmo parsing/attr_helper.cmo \
-  parsing/builtin_attributes.cmo parsing/ast_invariants.cmo parsing/depend.cmo
-
-TYPING=typing/ident.cmo typing/path.cmo \
-  typing/primitive.cmo typing/types.cmo \
-  typing/btype.cmo typing/oprint.cmo \
-  typing/subst.cmo typing/predef.cmo \
-  typing/datarepr.cmo typing/cmi_format.cmo typing/env.cmo \
-  typing/typedtree.cmo typing/printtyped.cmo typing/ctype.cmo \
-  typing/printtyp.cmo typing/includeclass.cmo \
-  typing/mtype.cmo typing/envaux.cmo typing/includecore.cmo \
-  typing/typedtreeIter.cmo typing/typedtreeMap.cmo \
-  typing/tast_mapper.cmo \
-  typing/cmt_format.cmo typing/untypeast.cmo \
-  typing/includemod.cmo typing/typetexp.cmo typing/parmatch.cmo \
-  typing/stypes.cmo typing/typedecl.cmo typing/typecore.cmo \
-  typing/typeclass.cmo \
-  typing/typemod.cmo
-
-COMP=bytecomp/lambda.cmo bytecomp/printlambda.cmo \
-  bytecomp/typeopt.cmo bytecomp/switch.cmo bytecomp/matching.cmo \
-  bytecomp/translobj.cmo bytecomp/translattribute.cmo \
-  bytecomp/translcore.cmo \
-  bytecomp/translclass.cmo bytecomp/translmod.cmo \
-  bytecomp/simplif.cmo bytecomp/runtimedef.cmo \
-  driver/pparse.cmo driver/main_args.cmo \
-  driver/compenv.cmo driver/compmisc.cmo
-
-COMMON=$(UTILS) $(PARSING) $(TYPING) $(COMP)
-
-BYTECOMP=bytecomp/meta.cmo bytecomp/instruct.cmo bytecomp/bytegen.cmo \
-  bytecomp/printinstr.cmo bytecomp/opcodes.cmo bytecomp/emitcode.cmo \
-  bytecomp/bytesections.cmo bytecomp/dll.cmo bytecomp/symtable.cmo \
-  bytecomp/bytelink.cmo bytecomp/bytelibrarian.cmo bytecomp/bytepackager.cmo \
-  driver/compdynlink.cmo driver/compplugin.cmo \
-  driver/errors.cmo driver/compile.cmo
-
-INTEL_ASM=\
-  asmcomp/x86_proc.cmo \
-  asmcomp/x86_dsl.cmo \
-  asmcomp/x86_gas.cmo \
-  asmcomp/x86_masm.cmo
-
-ARCH_SPECIFIC_ASMCOMP=
-ifeq ($(ARCH),i386)
-ARCH_SPECIFIC_ASMCOMP=$(INTEL_ASM)
-endif
-ifeq ($(ARCH),amd64)
-ARCH_SPECIFIC_ASMCOMP=$(INTEL_ASM)
-endif
-
-ASMCOMP=\
-  $(ARCH_SPECIFIC_ASMCOMP) \
-  asmcomp/arch.cmo \
-  asmcomp/cmm.cmo asmcomp/printcmm.cmo \
-  asmcomp/reg.cmo asmcomp/mach.cmo asmcomp/proc.cmo \
-  asmcomp/clambda.cmo asmcomp/printclambda.cmo \
-  asmcomp/export_info.cmo \
-  asmcomp/export_info_for_pack.cmo \
-  asmcomp/compilenv.cmo \
-  asmcomp/closure.cmo \
-  asmcomp/build_export_info.cmo \
-  asmcomp/closure_offsets.cmo \
-  asmcomp/flambda_to_clambda.cmo \
-  asmcomp/import_approx.cmo \
-  asmcomp/un_anf.cmo \
-  asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \
-  asmcomp/printmach.cmo asmcomp/selectgen.cmo \
-  asmcomp/spacetime_profiling.cmo asmcomp/selection.cmo \
-  asmcomp/comballoc.cmo \
-  asmcomp/CSEgen.cmo asmcomp/CSE.cmo \
-  asmcomp/liveness.cmo \
-  asmcomp/spill.cmo asmcomp/split.cmo \
-  asmcomp/interf.cmo asmcomp/coloring.cmo \
-  asmcomp/reloadgen.cmo asmcomp/reload.cmo \
-  asmcomp/deadcode.cmo \
-  asmcomp/printlinear.cmo asmcomp/linearize.cmo \
-  asmcomp/schedgen.cmo asmcomp/scheduling.cmo \
-  asmcomp/branch_relaxation_intf.cmo \
-  asmcomp/branch_relaxation.cmo \
-  asmcomp/emitaux.cmo asmcomp/emit.cmo asmcomp/asmgen.cmo \
-  asmcomp/asmlink.cmo asmcomp/asmlibrarian.cmo asmcomp/asmpackager.cmo \
-  driver/opterrors.cmo driver/optcompile.cmo
-
-MIDDLE_END=\
-  middle_end/debuginfo.cmo \
-  middle_end/base_types/tag.cmo \
-  middle_end/base_types/linkage_name.cmo \
-  middle_end/base_types/compilation_unit.cmo \
-  middle_end/base_types/variable.cmo \
-  middle_end/base_types/mutable_variable.cmo \
-  middle_end/base_types/id_types.cmo \
-  middle_end/base_types/set_of_closures_id.cmo \
-  middle_end/base_types/set_of_closures_origin.cmo \
-  middle_end/base_types/closure_element.cmo \
-  middle_end/base_types/closure_id.cmo \
-  middle_end/base_types/var_within_closure.cmo \
-  middle_end/base_types/static_exception.cmo \
-  middle_end/base_types/export_id.cmo \
-  middle_end/base_types/symbol.cmo \
-  middle_end/pass_wrapper.cmo \
-  middle_end/semantics_of_primitives.cmo \
-  middle_end/allocated_const.cmo \
-  middle_end/projection.cmo \
-  middle_end/flambda.cmo \
-  middle_end/flambda_iterators.cmo \
-  middle_end/flambda_utils.cmo \
-  middle_end/inlining_cost.cmo \
-  middle_end/effect_analysis.cmo \
-  middle_end/freshening.cmo \
-  middle_end/simple_value_approx.cmo \
-  middle_end/lift_code.cmo \
-  middle_end/closure_conversion_aux.cmo \
-  middle_end/closure_conversion.cmo \
-  middle_end/initialize_symbol_to_let_symbol.cmo \
-  middle_end/lift_let_to_initialize_symbol.cmo \
-  middle_end/find_recursive_functions.cmo \
-  middle_end/invariant_params.cmo \
-  middle_end/inconstant_idents.cmo \
-  middle_end/alias_analysis.cmo \
-  middle_end/lift_constants.cmo \
-  middle_end/share_constants.cmo \
-  middle_end/simplify_common.cmo \
-  middle_end/remove_unused_arguments.cmo \
-  middle_end/remove_unused_closure_vars.cmo \
-  middle_end/remove_unused_program_constructs.cmo \
-  middle_end/simplify_boxed_integer_ops.cmo \
-  middle_end/simplify_primitives.cmo \
-  middle_end/inlining_stats_types.cmo \
-  middle_end/inlining_stats.cmo \
-  middle_end/inline_and_simplify_aux.cmo \
-  middle_end/remove_free_vars_equal_to_args.cmo \
-  middle_end/extract_projections.cmo \
-  middle_end/augment_specialised_args.cmo \
-  middle_end/unbox_free_vars_of_closures.cmo \
-  middle_end/unbox_specialised_args.cmo \
-  middle_end/unbox_closures.cmo \
-  middle_end/inlining_transforms.cmo \
-  middle_end/inlining_decision.cmo \
-  middle_end/inline_and_simplify.cmo \
-  middle_end/ref_to_variables.cmo \
-  middle_end/flambda_invariants.cmo \
-  middle_end/middle_end.cmo
-
-TOPLEVEL=toplevel/genprintval.cmo toplevel/toploop.cmo \
-  toplevel/trace.cmo toplevel/topdirs.cmo toplevel/topmain.cmo
-
-OPTTOPLEVEL=toplevel/genprintval.cmo toplevel/opttoploop.cmo \
-  toplevel/opttopdirs.cmo toplevel/opttopmain.cmo
-BYTESTART=driver/main.cmo
-
-OPTSTART=driver/optmain.cmo
-
-TOPLEVELSTART=toplevel/topstart.cmo
-
-OPTTOPLEVELSTART=toplevel/opttopstart.cmo
-
-PERVASIVES=$(STDLIB_MODULES) outcometree topdirs toploop
-
-
-# The middle end (whose .cma library is currently only used for linking
-# the "ocamlobjinfo" program, since we cannot depend on the whole native code
-# compiler for "make world" and the list of dependencies for
-# asmcomp/export_info.cmo is long).
-
-compilerlibs/ocamlmiddleend.cma: $(MIDDLE_END)
-	$(CAMLC) -a -o $@ $(MIDDLE_END)
-compilerlibs/ocamlmiddleend.cmxa: $(MIDDLE_END:%.cmo=%.cmx)
-	$(CAMLOPT) -a -o $@ $^
-partialclean::
-	rm -f compilerlibs/ocamlmiddleend.cma compilerlibs/ocamlmiddleend.cmxa \
-	      compilerlibs/ocamlmiddleend.$(A)
-
-
-# Tools
-
-ocamltools: ocamlc ocamlyacc ocamllex asmcomp/cmx_format.cmi \
-            asmcomp/printclambda.cmo compilerlibs/ocamlmiddleend.cma \
-            asmcomp/export_info.cmo
-	+cd tools ; $(MAKEREC) all
-
-ocamltoolsopt: ocamlopt
-	+cd tools; $(MAKEREC) opt
-
-ocamltoolsopt.opt: ocamlc.opt ocamlyacc ocamllex.opt asmcomp/cmx_format.cmi \
-                   asmcomp/printclambda.cmx compilerlibs/ocamlmiddleend.cmxa \
-                   asmcomp/export_info.cmx
-	+cd tools; $(MAKEREC) opt.opt
-
-partialclean::
-	+cd tools; $(MAKEREC) clean
-
-alldepend::
-	+cd tools; $(MAKEREC) depend
-
-#config/Makefile: configure
-#	./configure $(CONFIGURE_ARGS)
-
-## Test compilation of backend-specific parts
-
-ARCH_SPECIFIC = \
-  asmcomp/arch.ml asmcomp/proc.ml asmcomp/CSE.ml asmcomp/selection.ml \
-  asmcomp/scheduling.ml asmcomp/reload.ml asmcomp/scheduling.ml \
-  asmcomp/emit.ml
-
-partialclean::
-	rm -f $(ARCH_SPECIFIC)
-
-beforedepend:: $(ARCH_SPECIFIC)
-
-ARCH_OCAMLOPT:=$(ARCH)
-
-.PHONY: check_arch check_all_arches
-
-# This rule provides a quick way to check that machine-dependent
-# files compiles fine for a foreign architecture (passed as ARCH=xxx).
-
-check_arch:
-	@echo "========= CHECKING asmcomp/$(ARCH) =============="
-	@rm -f $(ARCH_SPECIFIC) asmcomp/*.cm*
-	@$(MAKEREC) ARCH_OCAMLOPT=$(ARCH) compilerlibs/ocamloptcomp.cma \
-	            >/dev/null
-	@rm -f $(ARCH_SPECIFIC) asmcomp/*.cm*
-
-ARCHES=amd64 i386 arm arm64 power sparc s390x
-
-check_all_arches:
-	@for i in $(ARCHES); do \
-	  $(MAKEREC) --no-print-directory check_arch ARCH=$$i; \
-	done
-
-# Compiler Plugins
-
-DYNLINK_DIR=otherlibs/dynlink
-
-driver/compdynlink.mlbyte: $(DYNLINK_DIR)/dynlink.ml driver/compdynlink.mli
-	grep -v 'REMOVE_ME for ../../debugger/dynlink.ml' \
-	     $(DYNLINK_DIR)/dynlink.ml >driver/compdynlink.mlbyte
-
-ifeq ($(NATDYNLINK),true)
-driver/compdynlink.mlopt: $(DYNLINK_DIR)/natdynlink.ml driver/compdynlink.mli
-	cp $(DYNLINK_DIR)/natdynlink.ml driver/compdynlink.mlopt
-else
-driver/compdynlink.mlopt: driver/compdynlink.mlno driver/compdynlink.mli
-	cp driver/compdynlink.mlno driver/compdynlink.mlopt
-endif
-
-driver/compdynlink.mli: $(DYNLINK_DIR)/dynlink.mli
-	cp $(DYNLINK_DIR)/dynlink.mli driver/compdynlink.mli
-
-driver/compdynlink.cmo: driver/compdynlink.mlbyte driver/compdynlink.cmi
-	$(CAMLC) $(COMPFLAGS) -c -impl $<
-
-driver/compdynlink.cmx: driver/compdynlink.mlopt driver/compdynlink.cmi
-	$(CAMLOPT) $(COMPFLAGS) -c -impl $<
-
-beforedepend:: driver/compdynlink.mlbyte driver/compdynlink.mlopt \
-               driver/compdynlink.mli
-partialclean::
-	rm -f driver/compdynlink.mlbyte
-	rm -f driver/compdynlink.mli
-	rm -f driver/compdynlink.mlopt
diff --git a/README.adoc b/README.adoc
index 480b0250..fe07edbb 100644
--- a/README.adoc
+++ b/README.adoc
@@ -43,47 +43,6 @@ OCaml is almost upwards compatible with Caml Special Light, except for a few
 additional reserved keywords that have forced some renaming of standard
 library functions.
 
-== Contents
-
-  Changes::               what's new with each release
-  configure::             configure script
-  CONTRIBUTING.md::       how to contribute to OCaml
-  INSTALL.adoc::          instructions for installation
-  LICENSE::               license and copyright notice
-  Makefile::              main Makefile
-  Makefile.nt::           MS Windows Makefile
-  Makefile.shared::       common Makefile
-  Makefile.tools::        used by manual/ and testsuite/ Makefiles
-  README.adoc::           this file
-  README.win32.adoc::     info on the MS Windows ports of OCaml
-  VERSION::               version string
-  asmcomp/::              native-code compiler and linker
-  asmrun/::               native-code runtime library
-  boot/::                 bootstrap compiler
-  bytecomp/::             bytecode compiler and linker
-  byterun/::              bytecode interpreter and runtime system
-  compilerlibs/::         the OCaml compiler as a library
-  config/::               autoconfiguration stuff
-  debugger/::             source-level replay debugger
-  driver/::               driver code for the compilers
-  emacs/::                editing mode and debugger interface for GNU Emacs
-  experimental/::         experiments not built by default
-  flexdll/::              empty (see README.win32.adoc)
-  lex/::                  lexer generator
-  man/::                  man pages
-  manual/::               system to generate the manual
-  middle_end/::           the flambda optimisation phase
-  ocamldoc/::             documentation generator
-  otherlibs/::            several external libraries
-  parsing/::              syntax analysis
-  stdlib/::               standard library
-  testsuite/::            tests
-  tools/::                various utilities
-  toplevel/::             interactive system
-  typing/::               typechecking
-  utils/::                utility libraries
-  yacc/::                 parser generator
-
 == Copyright
 
 All files marked "Copyright INRIA" in this distribution are copyright 1996,
@@ -94,9 +53,9 @@ the conditions stated in file LICENSE.
 
 == Installation
 
-See the file link:INSTALL.adoc[] for installation instructions on machines running Unix,
-Linux, OS X and Cygwin.  For native Microsoft Windows, see
-link:README.win32.adoc[].
+See the file link:INSTALL.adoc[] for installation instructions on
+machines running Unix, Linux, OS X and Cygwin.  For native Microsoft
+Windows, see link:README.win32.adoc[].
 
 == Documentation
 
@@ -154,4 +113,5 @@ using (machine type, etc).
 
 You can also contact the implementors directly at mailto:caml@inria.fr[].
 
-For information on contributing to OCaml, see the file CONTRIBUTING.md.
+For information on contributing to OCaml, see link:HACKING.adoc[] and
+link:CONTRIBUTING.md[].
diff --git a/README.win32.adoc b/README.win32.adoc
index 9d5238cc..e34b3346 100644
--- a/README.win32.adoc
+++ b/README.win32.adoc
@@ -26,10 +26,17 @@ Here is a summary of the main differences between these ports:
 |=====
 
 [[tb1]]
-(*):: Cygwin-generated `.exe` files refer to a DLL that is distributed under the
-GPL.  Thus, these `.exe` files can only be distributed under a license that is
-compatible with the GPL.  Executables generated by Microsoft Visual C++ or
-Mingw-w64 have no such restrictions.
+(*):: Executables generated by the native GCC package in Cygwin are linked with
+the Cygwin DLL and require this to be distributed with your programs.
+Executables generated by Microsoft Visual C++ or the Mingw-w64 compilers (even
+when run in Cygwin as `i686-w64-mingw32-gcc` or `x86_64-w64-mingw32-gcc`) are
+not linked against this DLL. Prior to Cygwin 2.5.2 (the Cygwin version can be
+obtained with `uname -r`) the Cygwin DLL is distributed under the GPL, requiring
+any programs linked with it to be distributed under a compatible licence. Since
+version 2.5.2, the Cygwin DLL is distributed under the LGPLv3 with a static
+linking exception meaning that, like executables generated by Microsoft Visual
+C++ or the Mingw-w64 compilers, generated executables may be distributed under
+terms of your choosing.
 
 [[tb2]]
 (**):: The debugger is supported but the "replay" functions are not enabled.
@@ -67,8 +74,8 @@ instructions on how to build FlexDLL from sources, including how to bootstrap
 FlexDLL and OCaml are given <>.  Unless you
 bootstrap FlexDLL, you will need to ensure that the directory to which you
 install FlexDLL is included in your `PATH` environment variable. Note: if you
-use Visual Studio 2015, the binary distribution of FlexDLL will not work and
-you must build it from sources.
+use Visual Studio 2015 or Visual Studio 2017, the binary distribution of
+FlexDLL will not work and you must build it from sources.
 
 The base bytecode system (ocamlc, ocaml, ocamllex, ocamlyacc, ...) of all three
 ports runs without any additional tools.
@@ -94,6 +101,7 @@ Visual C/C++ Compiler.
 | Visual Studio 2012 | 17.00.x.x    | 32/64-bit               |
 | Visual Studio 2013 | 18.00.x.x    | 32/64-bit               |
 | Visual Studio 2015 | 19.00.x.x    | 32/64-bit               |
+| Visual Studio 2017 | 19.10.x.x    | 32/64-bit               |
 |=====
 
 [[vs1]]
@@ -131,9 +139,9 @@ for 32-bit or:
 
 for 64-bit. For Visual Studio 2005-2013, you need to use one of the shortcuts in
 the "Visual Studio Tools" program group under the main program group for the
-version of Visual Studio you installed. For Visual Studio 2015, you need to use
-the shortcuts in the "Windows Desktop Command Prompts" group under the
-"Visual Studio Tools" group.
+version of Visual Studio you installed. For Visual Studio 2015 and 2017, you
+need to use the shortcuts in the "Windows Desktop Command Prompts" (2015) or
+"VC" (2017) group under the "Visual Studio Tools" group.
 
 Unlike `SetEnv` for the Windows SDK, the architecture is selected by using a
 different shortcut, rather than by running a command.
@@ -147,7 +155,7 @@ work with OCaml.
 
 For Visual Studio 2012 and 2013, both x86 and x64 Command Prompt shortcuts
 indicate if they are the "Native Tools" or "Cross Tools" versions. Visual Studio
-2015 makes the shortcuts even clearer by including the full name of the
+2015 and 2017 make the shortcuts even clearer by including the full name of the
 architecture.
 
 You cannot at present use a cross-compiler to compile 64-bit OCaml on 32-bit
@@ -179,7 +187,7 @@ the top-level of the OCaml distribution by running:
 
   eval $(tools/msvs-promote-path)
 
-If you forget to do this, `make -f Makefile.nt world` will fail relatively
+If you forget to do this, `make world` will fail relatively
 quickly as it will be unable to link `ocamlrun`.
 
 Now run:
@@ -199,9 +207,9 @@ for 64-bit. Then, edit `config/Makefile` as needed, following the comments in
 this file. Normally, the only variable that needs to be changed is `PREFIX`,
 which indicates where to install everything.
 
-Finally, use `make -f Makefile.nt` to build the system, e.g.
+Finally, use `make` to build the system, e.g.
 
-        make -f Makefile.nt world bootstrap opt opt.opt install
+        make world bootstrap opt opt.opt install
 
 After installing, it is not necessary to keep the Cygwin installation (although
 you may require it to build additional third party libraries and tools).  You
@@ -270,9 +278,9 @@ for 64-bit. Then, edit `config/Makefile` as needed, following the comments in
 this file. Normally, the only variable that needs to be changed is `PREFIX`,
 which indicates where to install everything.
 
-Finally, use `make -f Makefile.nt` to build the system, e.g.
+Finally, use `make` to build the system, e.g.
 
-        make -f Makefile.nt world bootstrap opt opt.opt install
+        make world bootstrap opt opt.opt install
 
 After installing, you will need to ensure that `ocamlopt` (or `ocamlc -custom`)
 can access the C compiler.  You can do this either by using OCaml from Cygwin's
@@ -318,16 +326,16 @@ done in one of three ways:
 OCaml is then compiled as normal for the port you require, except that before
 compiling `world`, you must compile `flexdll`, i.e.:
 
-  make -f Makefile.nt flexdll world [bootstrap] opt opt.opt install
+  make flexdll world [bootstrap] opt opt.opt install
 
- * `make -f Makefile.nt install` will install FlexDLL by placing `flexlink.exe`
+ * `make install` will install FlexDLL by placing `flexlink.exe`
    (and the default manifest file for the Microsoft port) in `bin/` and the
    FlexDLL object files in `lib/`.
- * If you don't include `make -f Makefile.nt opt.opt`, `flexlink.exe` will be a
-   bytecode program.  `make -f Makefile.nt install` always installs the "best"
+ * If you don't include `make opt.opt`, `flexlink.exe` will be a
+   bytecode program.  `make install` always installs the "best"
    `flexlink.exe` (i.e. there is never a `flexlink.opt.exe` installed).
  * If you have populated `flexdll/`, you *must* run
-   `make -f Makefile.nt flexdll`.  If you wish to revert to using an externally
+   `make flexdll`.  If you wish to revert to using an externally
    installed FlexDLL, you must erase the contents of `flexdll/` before
    compiling.
 
diff --git a/VERSION b/VERSION
index ed834ab2..fc8c4bfa 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-4.04.0
+4.05.0+rc1
 
 # The version string is the first line of this file.
 # It must be in the format described in stdlib/sys.mli
diff --git a/appveyor.yml b/appveyor.yml
index 7d4d8965..fbdb79ad 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -16,55 +16,66 @@
 platform:
   - x64
 
+image: Visual Studio 2015
+
 branches:
   only:
     - trunk
+    - 4.05
 
 # Do a shallow clone of the repo to speed up the build
 clone_depth: 1
 
 environment:
   global:
-    CYG_ROOT: C:/cygwin
+    CYG_ROOT: C:/cygwin64
     CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/
-    CYG_CACHE: C:/cygwin/var/cache/setup
+    CYG_CACHE: C:/cygwin64/var/cache/setup
+    OCAMLRUNPARAM: v=0,b
     OCAMLROOT: "%PROGRAMFILES%/OCaml"
+    OCAMLROOT2: "%PROGRAMFILES%/OCaml-mingw32"
 
 cache:
-  - C:\cygwin\var\cache\setup
+  - C:\cygwin64\var\cache\setup
 
 install:
-  - mkdir "%OCAMLROOT%"
-  - mkdir "%OCAMLROOT%/bin"
   - mkdir "%OCAMLROOT%/bin/flexdll"
-  - appveyor DownloadFile "http://alain.frisch.fr/flexdll/flexdll-bin-0.34.zip" -FileName "flexdll.zip"
+  - appveyor DownloadFile "http://alain.frisch.fr/flexdll/flexdll-bin-0.35.zip" -FileName "flexdll.zip"
+  - appveyor DownloadFile "http://alain.frisch.fr/flexdll/flexdll-0.35.tar.gz" -FileName "flexdll.tar.gz"
   - cinst 7zip.commandline
-  - 7za x -y flexdll.zip
-  - for %%F in (*.c *.h *.exe *.o *.obj) do copy %%F "%OCAMLROOT%\bin\flexdll"
+  - mkdir flexdll-tmp
+  - cd flexdll-tmp
+  - 7za x -y ..\flexdll.zip
+  - for %%F in (flexdll.h flexlink.exe default_amd64.manifest) do copy %%F "%OCAMLROOT%\bin\flexdll"
+  - cd ..
   # Make sure the Cygwin path comes before the Git one (otherwise
   # cygpath behaves crazily), but after the MSVC one.
-  - set Path=C:\cygwin\bin;%Path%
-  - '"%CYG_ROOT%\setup-x86.exe" -qnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P diffutils -P dos2unix -P gcc-core -P make -P ncurses >NUL'
+  - set Path=C:\cygwin64\bin;%OCAMLROOT%\bin\flexdll;%Path%
+  - '%CYG_ROOT%\bin\bash -lc "cygcheck -dc cygwin"'
+  - '"%CYG_ROOT%\setup-x86_64.exe" -qgnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P diffutils -P make -P mingw64-i686-gcc-core >NUL'
   - '%CYG_ROOT%\bin\bash -lc "cygcheck -dc cygwin"'
-  - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64
-  - set Path=%OCAMLROOT%\bin;%OCAMLROOT%\bin\flexdll;%Path%
+  - set OCAML_PREV_PATH=%PATH%
+  - set OCAML_PREV_LIB=%LIB%
+  - set OCAML_PREV_INCLUDE=%INCLUDE%
+  - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
 
 build_script:
-  - set PFPATH=%PROGRAMFILES%
-  - set FLEXDLLDIR=%OCAMLROOT%\bin\flexdll
-  - echo VCPATH="`cygpath -p '%Path%'`" > %CYG_ROOT%\tmp\msenv
-  - echo LIB="%LIB%" >> %CYG_ROOT%\tmp\msenv
-  - echo LIBPATH="%LIBPATH%" >> %CYG_ROOT%\tmp\msenv
-  - echo INCLUDE="%INCLUDE%;%FLEXDLLDIR%" >> %CYG_ROOT%\tmp\msenv
-  - echo FLPATH="`cygpath '%FLEXDLLDIR%'`" >> %CYG_ROOT%\tmp\msenv
-  - echo PATH="$VCPATH:$FLPATH:$PATH" >> %CYG_ROOT%\tmp\msenv
-  - echo export PATH LIB LIBPATH INCLUDE >> %CYG_ROOT%\tmp\msenv
-  - echo export OCAMLBUILD_FIND=/usr/bin/find >> %CYG_ROOT%\tmp\msenv
-  - "%CYG_ROOT%/bin/bash -lc \"tr -d '\\r'  ~/.msenv64\""
-  - "%CYG_ROOT%/bin/bash -lc \"echo '. ~/.msenv64' >> ~/.bash_profile\""
+  - "%CYG_ROOT%/bin/bash -lc \"echo 'eval $($APPVEYOR_BUILD_FOLDER/tools/msvs-promote-path)' >> ~/.bash_profile\""
   - '%CYG_ROOT%/bin/bash -lc "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh"'
+  - set PATH=%OCAML_PREV_PATH%
+  - set LIB=%OCAML_PREV_LIB%
+  - set INCLUDE=%OCAML_PREV_INCLUDE%
+  - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x86
+  - '%CYG_ROOT%/bin/bash -lc "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh msvc32-only"'
 
 test_script:
-  - ocamlc -version
+  - set PATH=%OCAML_PREV_PATH%
+  - set LIB=%OCAML_PREV_LIB%
+  - set INCLUDE=%OCAML_PREV_INCLUDE%
+  - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
+  - '%APPVEYOR_BUILD_FOLDER%\ocamlc.opt -version'
   - set CAML_LD_LIBRARY_PATH=%OCAMLROOT%/lib/stublibs
-  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER && make -f Makefile.nt tests"'
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER && make tests"'
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER/../build-mingw32 && make tests"'
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER && make install"'
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER/../build-mingw32 && make install"'
diff --git a/appveyor_build.sh b/appveyor_build.sh
index b188fc2e..e3c0454a 100644
--- a/appveyor_build.sh
+++ b/appveyor_build.sh
@@ -27,21 +27,69 @@ function run {
     fi
 }
 
+PREFIX="C:/Program Files/OCaml"
+
+wmic cpu get name
+
+if [[ $1 = "msvc32-only" ]] ; then
+  cd $APPVEYOR_BUILD_FOLDER/flexdll-0.35
+  make MSVC_DETECT=0 CHAINS=msvc MSVC_FLAGS="-nologo -MD -D_CRT_NO_DEPRECATE -GS- -WX" support
+  cp flexdll*_msvc.obj "$PREFIX/bin/flexdll"
+
+  cd $APPVEYOR_BUILD_FOLDER/../build-msvc32
+  cp config/m-nt.h config/m.h
+  cp config/s-nt.h config/s.h
+
+  eval $(tools/msvs-promote-path)
+
+  PREFIX="C:/Program Files/OCaml-msmvc32"
+  echo "Edit config/Makefile to set PREFIX=$PREFIX"
+  sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -WX\0/" config/Makefile.msvc > config/Makefile
+
+  run "make world" make world
+  run "make runtimeopt" make runtimeopt
+  run "make -C otherlibs/systhreads libthreadsnat.lib" make -C otherlibs/systhreads libthreadsnat.lib
+
+  exit 0
+fi
+
+cd $APPVEYOR_BUILD_FOLDER
+
+git worktree add ../build-mingw32 -b appveyor-build-mingw32
+git worktree add ../build-msvc32 -b appveyor-build-msvc32
+
+cd ../build-mingw32
+git submodule update --init flexdll
+
 cd $APPVEYOR_BUILD_FOLDER
 
+tar -xzf flexdll.tar.gz
+cd flexdll-0.35
+make MSVC_DETECT=0 CHAINS=msvc64 support
+cp flexdll*_msvc64.obj "$PREFIX/bin/flexdll"
+cd ..
+
 cp config/m-nt.h config/m.h
 cp config/s-nt.h config/s.h
-#cp config/Makefile.msvc config/Makefile
-cp config/Makefile.msvc64 config/Makefile
 
-PREFIX="C:/Program Files/OCaml"
-echo "Edit config/Makefile so set PREFIX=$PREFIX"
-cp config/Makefile config/Makefile.bak
-sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" config/Makefile.bak > config/Makefile
+echo "Edit config/Makefile to set PREFIX=$PREFIX"
+sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -WX\0/" config/Makefile.msvc64 > config/Makefile
+#run "Content of config/Makefile" cat config/Makefile
+
+run "make world" make world
+run "make bootstrap" make bootstrap
+run "make opt" make opt
+run "make opt.opt" make opt.opt
+
+cd ../build-mingw32
+
+cp config/m-nt.h config/m.h
+cp config/s-nt.h config/s.h
+
+PREFIX="C:/Program Files/OCaml-mingw32"
+echo "Edit config/Makefile to set PREFIX=$PREFIX"
+sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -Werror\0/" config/Makefile.mingw > config/Makefile
 #run "Content of config/Makefile" cat config/Makefile
 
-run "make world" make -f Makefile.nt world
-run "make bootstrap" make -f Makefile.nt bootstrap
-run "make opt" make -f Makefile.nt opt
-run "make opt.opt" make -f Makefile.nt opt.opt
-run "make install" make -f Makefile.nt install
+run "make flexdll" make flexdll
+run "make world.opt" make world.opt
diff --git a/asmcomp/CSEgen.ml b/asmcomp/CSEgen.ml
index 07b32f27..5ec6ebeb 100644
--- a/asmcomp/CSEgen.ml
+++ b/asmcomp/CSEgen.ml
@@ -349,9 +349,11 @@ method private cse n i =
   | Iloop(body) ->
       {i with desc = Iloop(self#cse empty_numbering body);
               next = self#cse empty_numbering i.next}
-  | Icatch(nfail, body, handler) ->
-      {i with desc = Icatch(nfail, self#cse n body,
-                            self#cse empty_numbering handler);
+  | Icatch(rec_flag, handlers, body) ->
+      let aux (nfail, handler) =
+        nfail, self#cse empty_numbering handler
+      in
+      {i with desc = Icatch(rec_flag, List.map aux handlers, self#cse n body);
               next = self#cse empty_numbering i.next}
   | Itrywith(body, handler) ->
       {i with desc = Itrywith(self#cse n body,
diff --git a/asmcomp/afl_instrument.ml b/asmcomp/afl_instrument.ml
new file mode 100644
index 00000000..d3d371cf
--- /dev/null
+++ b/asmcomp/afl_instrument.ml
@@ -0,0 +1,94 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                 Stephen Dolan, University of Cambridge                 *)
+(*                                                                        *)
+(*   Copyright 2016 Stephen Dolan.                                        *)
+(*                                                                        *)
+(*   All rights reserved.  This file is distributed under the terms of    *)
+(*   the GNU Lesser General Public License version 2.1, with the          *)
+(*   special exception on linking described in the file LICENSE.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Insert instrumentation for afl-fuzz *)
+
+open Lambda
+open Cmm
+
+let afl_area_ptr = Cconst_symbol "caml_afl_area_ptr"
+let afl_prev_loc = Cconst_symbol "caml_afl_prev_loc"
+let afl_map_size = 1 lsl 16
+
+let rec with_afl_logging b =
+  if !Clflags.afl_inst_ratio < 100 &&
+    Random.int 100 >= !Clflags.afl_inst_ratio then instrument b else
+  let instrumentation =
+    (* The instrumentation that afl-fuzz requires is:
+
+         cur_location = ;
+         shared_mem[cur_location ^ prev_location]++;
+         prev_location = cur_location >> 1;
+
+       See http://lcamtuf.coredump.cx/afl/technical_details.txt or
+       docs/technical_details.txt in afl-fuzz source for for a full
+       description of what's going on. *)
+    let cur_location = Random.int afl_map_size in
+    let cur_pos = Ident.create "pos" in
+    let afl_area = Ident.create "shared_mem" in
+    let op oper args = Cop (oper, args, Debuginfo.none) in
+    Clet(afl_area, op (Cload (Word_int, Asttypes.Mutable)) [afl_area_ptr],
+    Clet(cur_pos,  op Cxor [op (Cload (Word_int, Asttypes.Mutable))
+      [afl_prev_loc]; Cconst_int cur_location],
+    Csequence(
+      op (Cstore(Byte_unsigned, Assignment))
+         [op Cadda [Cvar afl_area; Cvar cur_pos];
+          op Cadda [op (Cload (Byte_unsigned, Asttypes.Mutable))
+                       [op Cadda [Cvar afl_area; Cvar cur_pos]];
+                    Cconst_int 1]],
+      op (Cstore(Word_int, Assignment))
+         [afl_prev_loc; Cconst_int (cur_location lsr 1)]))) in
+  Csequence(instrumentation, instrument b)
+
+and instrument = function
+  (* these cases add logging, as they may be targets of conditional branches *)
+  | Cifthenelse (cond, t, f) ->
+     Cifthenelse (instrument cond, with_afl_logging t, with_afl_logging f)
+  | Cloop e ->
+     Cloop (with_afl_logging e)
+  | Ctrywith (e, ex, handler) ->
+     Ctrywith (instrument e, ex, with_afl_logging handler)
+  | Cswitch (e, cases, handlers, dbg) ->
+     Cswitch (instrument e, cases, Array.map with_afl_logging handlers, dbg)
+
+  (* these cases add no logging, but instrument subexpressions *)
+  | Clet (v, e, body) -> Clet (v, instrument e, instrument body)
+  | Cassign (v, e) -> Cassign (v, instrument e)
+  | Ctuple es -> Ctuple (List.map instrument es)
+  | Cop (op, es, dbg) -> Cop (op, List.map instrument es, dbg)
+  | Csequence (e1, e2) -> Csequence (instrument e1, instrument e2)
+  | Ccatch (isrec, cases, body) ->
+     Ccatch (isrec,
+             List.map (fun (nfail, ids, e) -> nfail, ids, instrument e) cases,
+             instrument body)
+  | Cexit (ex, args) -> Cexit (ex, List.map instrument args)
+
+  (* these are base cases and have no logging *)
+  | Cconst_int _ | Cconst_natint _ | Cconst_float _
+  | Cconst_symbol _ | Cconst_pointer _ | Cconst_natpointer _
+  | Cblockheader _ | Cvar _ as c -> c
+
+let instrument_function c =
+  with_afl_logging c
+
+let instrument_initialiser c =
+  (* Each instrumented module calls caml_setup_afl at
+     initialisation, which is a no-op on the second and subsequent
+     calls *)
+  with_afl_logging
+    (Csequence
+       (Cop (Cextcall ("caml_setup_afl", typ_int, false, None),
+             [Cconst_int 0],
+             Debuginfo.none),
+        c))
diff --git a/asmcomp/afl_instrument.mli b/asmcomp/afl_instrument.mli
new file mode 100644
index 00000000..1eb439b2
--- /dev/null
+++ b/asmcomp/afl_instrument.mli
@@ -0,0 +1,4 @@
+(* Instrumentation for afl-fuzz *)
+
+val instrument_function : Cmm.expression -> Cmm.expression
+val instrument_initialiser : Cmm.expression -> Cmm.expression
diff --git a/asmcomp/amd64/CSE.ml b/asmcomp/amd64/CSE.ml
index 10066e4b..7e4193d7 100644
--- a/asmcomp/amd64/CSE.ml
+++ b/asmcomp/amd64/CSE.ml
@@ -28,7 +28,7 @@ method! class_of_operation op =
   | Ispecific spec ->
     begin match spec with
     | Ilea _ -> Op_pure
-    | Istore_int(_, _, is_asg) | Istore_symbol(_, _, is_asg) -> Op_store is_asg
+    | Istore_int(_, _, is_asg) -> Op_store is_asg
     | Ioffset_loc(_, _) -> Op_store true
     | Ifloatarithmem _ | Ifloatsqrtf _ -> Op_load
     | Ibswap _ | Isqrtf -> super#class_of_operation op
diff --git a/asmcomp/amd64/arch.ml b/asmcomp/amd64/arch.ml
index 451b431d..38fc2fb2 100644
--- a/asmcomp/amd64/arch.ml
+++ b/asmcomp/amd64/arch.ml
@@ -36,7 +36,6 @@ type specific_operation =
     Ilea of addressing_mode             (* "lea" gives scaled adds *)
   | Istore_int of nativeint * addressing_mode * bool
                                         (* Store an integer constant *)
-  | Istore_symbol of string * addressing_mode * bool (* Store a symbol *)
   | Ioffset_loc of int * addressing_mode (* Add a constant to a location *)
   | Ifloatarithmem of float_operation * addressing_mode
                                        (* Float arith operation with memory *)
@@ -109,10 +108,6 @@ let print_specific_operation printreg op ppf arg =
       fprintf ppf "[%a] := %nd %s"
          (print_addressing printreg addr) arg n
          (if is_assign then "(assign)" else "(init)")
-  | Istore_symbol(lbl, addr, is_assign) ->
-      fprintf ppf "[%a] := \"%s\" %s"
-         (print_addressing printreg addr) arg lbl
-         (if is_assign then "(assign)" else "(init)")
   | Ioffset_loc(n, addr) ->
       fprintf ppf "[%a] +:= %i" (print_addressing printreg addr) arg n
   | Isqrtf ->
@@ -131,3 +126,8 @@ let print_specific_operation printreg op ppf arg =
                    (Array.sub arg 1 (Array.length arg - 1))
   | Ibswap i ->
       fprintf ppf "bswap_%i %a" i printreg arg.(0)
+
+let win64 =
+  match Config.system with
+  | "win64" | "mingw64" | "cygwin" -> true
+  | _                   -> false
diff --git a/asmcomp/amd64/emit.mlp b/asmcomp/amd64/emit.mlp
index 85b4cee3..c3f8692a 100644
--- a/asmcomp/amd64/emit.mlp
+++ b/asmcomp/amd64/emit.mlp
@@ -256,12 +256,8 @@ let record_frame_label ?label live raise_ dbg =
       | _ -> ()
     )
     live;
-  frame_descriptors :=
-    { fd_lbl = lbl;
-      fd_frame_size = frame_size();
-      fd_live_offset = !live_offset;
-      fd_raise = raise_;
-      fd_debuginfo = dbg } :: !frame_descriptors;
+  record_frame_descr ~label:lbl ~frame_size:(frame_size())
+    ~live_offset:!live_offset ~raise_frame:raise_ dbg;
   lbl
 
 let record_frame ?label live raise_ dbg =
@@ -731,10 +727,6 @@ let emit_instr fallthrough i =
       I.lea (addressing addr NONE i 0) (res i 0)
   | Lop(Ispecific(Istore_int(n, addr, _))) ->
       I.mov (nat n) (addressing addr QWORD i 0)
-  | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
-      assert (not !Clflags.pic_code && not !Clflags.dlcode);
-      add_used_symbol s;
-      load_symbol_addr s (addressing addr QWORD i 0)
   | Lop(Ispecific(Ioffset_loc(n, addr))) ->
       I.add (int n) (addressing addr QWORD i 0)
   | Lop(Ispecific(Ifloatarithmem(op, addr))) ->
@@ -992,7 +984,7 @@ let begin_assembly() =
   end;
 
 
-  if !Clflags.dlcode then begin
+  if !Clflags.dlcode || Arch.win64 then begin
     (* from amd64.S; could emit these constants on demand *)
     begin match system with
     | S_macosx -> D.section ["__TEXT";"__literal16"] None ["16byte_literals"]
diff --git a/asmcomp/amd64/proc.ml b/asmcomp/amd64/proc.ml
index 92f68b50..0b2cc119 100644
--- a/asmcomp/amd64/proc.ml
+++ b/asmcomp/amd64/proc.ml
@@ -26,10 +26,7 @@ let fp = Config.with_frame_pointers
 
 (* Which ABI to use *)
 
-let win64 =
-  match Config.system with
-  | "win64" | "mingw64" | "cygwin" -> true
-  | _                   -> false
+let win64 = Arch.win64
 
 (* Registers available for register allocation *)
 
diff --git a/asmcomp/amd64/reload.ml b/asmcomp/amd64/reload.ml
index 2e29de4c..690e0165 100644
--- a/asmcomp/amd64/reload.ml
+++ b/asmcomp/amd64/reload.ml
@@ -94,7 +94,7 @@ method! reload_operation op arg res =
       then (arg, res)
       else super#reload_operation op arg res
   | Iconst_symbol _ ->
-      if !Clflags.pic_code || !Clflags.dlcode
+      if !Clflags.pic_code || !Clflags.dlcode || Arch.win64
       then super#reload_operation op arg res
       else (arg, res)
   | _ -> (* Other operations: all args and results in registers *)
diff --git a/asmcomp/amd64/selection.ml b/asmcomp/amd64/selection.ml
index fb50bc15..336120f4 100644
--- a/asmcomp/amd64/selection.ml
+++ b/asmcomp/amd64/selection.ml
@@ -33,28 +33,28 @@ let rec select_addr exp =
   match exp with
     Cconst_symbol s when not !Clflags.dlcode ->
       (Asymbol s, 0)
-  | Cop((Caddi | Caddv | Cadda), [arg; Cconst_int m]) ->
+  | Cop((Caddi | Caddv | Cadda), [arg; Cconst_int m], _) ->
       let (a, n) = select_addr arg in (a, n + m)
-  | Cop(Csubi, [arg; Cconst_int m]) ->
+  | Cop(Csubi, [arg; Cconst_int m], _) ->
       let (a, n) = select_addr arg in (a, n - m)
-  | Cop((Caddi | Caddv | Cadda), [Cconst_int m; arg]) ->
+  | Cop((Caddi | Caddv | Cadda), [Cconst_int m; arg], _) ->
       let (a, n) = select_addr arg in (a, n + m)
-  | Cop(Clsl, [arg; Cconst_int(1|2|3 as shift)]) ->
+  | Cop(Clsl, [arg; Cconst_int(1|2|3 as shift)], _) ->
       begin match select_addr arg with
         (Alinear e, n) -> (Ascale(e, 1 lsl shift), n lsl shift)
       | _ -> (Alinear exp, 0)
       end
-  | Cop(Cmuli, [arg; Cconst_int(2|4|8 as mult)]) ->
+  | Cop(Cmuli, [arg; Cconst_int(2|4|8 as mult)], _) ->
       begin match select_addr arg with
         (Alinear e, n) -> (Ascale(e, mult), n * mult)
       | _ -> (Alinear exp, 0)
       end
-  | Cop(Cmuli, [Cconst_int(2|4|8 as mult); arg]) ->
+  | Cop(Cmuli, [Cconst_int(2|4|8 as mult); arg], _) ->
       begin match select_addr arg with
         (Alinear e, n) -> (Ascale(e, mult), n * mult)
       | _ -> (Alinear exp, 0)
       end
-  | Cop((Caddi | Caddv | Cadda), [arg1; arg2]) ->
+  | Cop((Caddi | Caddv | Cadda), [arg1; arg2], _) ->
       begin match (select_addr arg1, select_addr arg2) with
           ((Alinear e1, n1), (Alinear e2, n2)) ->
               (Aadd(e1, e2), n1 + n2)
@@ -115,6 +115,8 @@ let pseudoregs_for_operation op arg res =
   (* Other instructions are regular *)
   | _ -> raise Use_default
 
+(* If you update [inline_ops], you may need to update [is_simple_expr] and/or
+   [effects_of], below. *)
 let inline_ops =
   [ "sqrt"; "caml_bswap16_direct"; "caml_int32_direct_bswap";
     "caml_int64_direct_bswap"; "caml_nativeint_direct_bswap" ]
@@ -133,13 +135,21 @@ method is_immediate_natint n = n <= 0x7FFFFFFFn && n >= -0x80000000n
 
 method! is_simple_expr e =
   match e with
-  | Cop(Cextcall (fn, _, _, _, _), args)
+  | Cop(Cextcall (fn, _, _, _), args, _)
     when List.mem fn inline_ops ->
       (* inlined ops are simple if their arguments are *)
       List.for_all self#is_simple_expr args
   | _ ->
       super#is_simple_expr e
 
+method! effects_of e =
+  match e with
+  | Cop(Cextcall(fn, _, _, _), args, _)
+    when List.mem fn inline_ops ->
+      Selectgen.Effect_and_coeffect.join_list_map args self#effects_of
+  | _ ->
+      super#effects_of e
+
 method select_addressing _chunk exp =
   let (a, d) = select_addr exp in
   (* PR#4625: displacement must be a signed 32-bit immediate *)
@@ -170,18 +180,16 @@ method! select_store is_assign addr exp =
       (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
   | Cconst_natpointer n when self#is_immediate_natint n ->
       (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
-  | Cconst_symbol s when not (!Clflags.pic_code || !Clflags.dlcode) ->
-      (Ispecific(Istore_symbol(s, addr, is_assign)), Ctuple [])
   | _ ->
       super#select_store is_assign addr exp
 
-method! select_operation op args =
+method! select_operation op args dbg =
   match op with
   (* Recognize the LEA instruction *)
     Caddi | Caddv | Cadda | Csubi ->
-      begin match self#select_addressing Word_int (Cop(op, args)) with
+      begin match self#select_addressing Word_int (Cop(op, args, dbg)) with
         (Iindexed _, _)
-      | (Iindexed2 0, _) -> super#select_operation op args
+      | (Iindexed2 0, _) -> super#select_operation op args dbg
       | (addr, arg) -> (Ispecific(Ilea addr), [arg])
       end
   (* Recognize float arithmetic with memory. *)
@@ -193,9 +201,9 @@ method! select_operation op args =
       self#select_floatarith true Imulf Ifloatmul args
   | Cdivf ->
       self#select_floatarith false Idivf Ifloatdiv args
-  | Cextcall("sqrt", _, false, _, _) ->
+  | Cextcall("sqrt", _, false, _) ->
      begin match args with
-       [Cop(Cload (Double|Double_u as chunk), [loc])] ->
+       [Cop(Cload ((Double|Double_u as chunk), _), [loc], _dbg)] ->
          let (addr, arg) = self#select_addressing chunk loc in
          (Ispecific(Ifloatsqrtf addr), [arg])
      | [arg] ->
@@ -206,34 +214,35 @@ method! select_operation op args =
   (* Recognize store instructions *)
   | Cstore ((Word_int|Word_val as chunk), _init) ->
       begin match args with
-        [loc; Cop(Caddi, [Cop(Cload _, [loc']); Cconst_int n])]
+        [loc; Cop(Caddi, [Cop(Cload _, [loc'], _); Cconst_int n], _)]
         when loc = loc' && self#is_immediate n ->
           let (addr, arg) = self#select_addressing chunk loc in
           (Ispecific(Ioffset_loc(n, addr)), [arg])
       | _ ->
-          super#select_operation op args
+          super#select_operation op args dbg
       end
-  | Cextcall("caml_bswap16_direct", _, _, _, _) ->
+  | Cextcall("caml_bswap16_direct", _, _, _) ->
       (Ispecific (Ibswap 16), args)
-  | Cextcall("caml_int32_direct_bswap", _, _, _, _) ->
+  | Cextcall("caml_int32_direct_bswap", _, _, _) ->
       (Ispecific (Ibswap 32), args)
-  | Cextcall("caml_int64_direct_bswap", _, _, _, _)
-  | Cextcall("caml_nativeint_direct_bswap", _, _, _, _) ->
+  | Cextcall("caml_int64_direct_bswap", _, _, _)
+  | Cextcall("caml_nativeint_direct_bswap", _, _, _) ->
       (Ispecific (Ibswap 64), args)
   (* AMD64 does not support immediate operands for multiply high signed *)
   | Cmulhi ->
       (Iintop Imulh, args)
-  | _ -> super#select_operation op args
+  | _ -> super#select_operation op args dbg
 
 (* Recognize float arithmetic with mem *)
 
 method select_floatarith commutative regular_op mem_op args =
   match args with
-    [arg1; Cop(Cload (Double|Double_u as chunk), [loc2])] ->
+    [arg1; Cop(Cload ((Double|Double_u as chunk), _), [loc2], _)] ->
       let (addr, arg2) = self#select_addressing chunk loc2 in
       (Ispecific(Ifloatarithmem(mem_op, addr)),
                  [arg1; arg2])
-  | [Cop(Cload (Double|Double_u as chunk), [loc1]); arg2] when commutative ->
+  | [Cop(Cload ((Double|Double_u as chunk), _), [loc1], _); arg2]
+        when commutative ->
       let (addr, arg1) = self#select_addressing chunk loc1 in
       (Ispecific(Ifloatarithmem(mem_op, addr)),
                  [arg2; arg1])
diff --git a/asmcomp/arm/emit.mlp b/asmcomp/arm/emit.mlp
index de61da57..0563828e 100644
--- a/asmcomp/arm/emit.mlp
+++ b/asmcomp/arm/emit.mlp
@@ -116,12 +116,8 @@ let record_frame_label ?label live raise_ dbg =
           Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
-  frame_descriptors :=
-    { fd_lbl = lbl;
-      fd_frame_size = frame_size();
-      fd_live_offset = !live_offset;
-      fd_raise = raise_;
-      fd_debuginfo = dbg } :: !frame_descriptors;
+  record_frame_descr ~label:lbl ~frame_size:(frame_size())
+    ~live_offset:!live_offset ~raise_frame:raise_ dbg;
   lbl
 
 let record_frame ?label live raise_ dbg =
diff --git a/asmcomp/arm/selection.ml b/asmcomp/arm/selection.ml
index 2063e606..3a3a5c61 100644
--- a/asmcomp/arm/selection.ml
+++ b/asmcomp/arm/selection.ml
@@ -107,58 +107,70 @@ method is_immediate n =
 
 method! is_simple_expr = function
   (* inlined floating-point ops are simple if their arguments are *)
-  | Cop(Cextcall("sqrt", _, _, _, _), args) when !fpu >= VFPv2 ->
+  | Cop(Cextcall("sqrt", _, _, _), args, _) when !fpu >= VFPv2 ->
       List.for_all self#is_simple_expr args
   (* inlined byte-swap ops are simple if their arguments are *)
-  | Cop(Cextcall("caml_bswap16_direct", _, _, _, _), args)
+  | Cop(Cextcall("caml_bswap16_direct", _, _, _), args, _)
     when !arch >= ARMv6T2 ->
       List.for_all self#is_simple_expr args
-  | Cop(Cextcall("caml_int32_direct_bswap", _,_,_,_), args)
+  | Cop(Cextcall("caml_int32_direct_bswap",_,_,_), args, _)
     when !arch >= ARMv6 ->
       List.for_all self#is_simple_expr args
   | e -> super#is_simple_expr e
 
+method! effects_of e =
+  match e with
+  | Cop(Cextcall("sqrt", _, _, _), args, _) when !fpu >= VFPv2 ->
+      Selectgen.Effect_and_coeffect.join_list_map args self#effects_of
+  | Cop(Cextcall("caml_bswap16_direct", _, _, _), args, _)
+    when !arch >= ARMv6T2 ->
+      Selectgen.Effect_and_coeffect.join_list_map args self#effects_of
+  | Cop(Cextcall("caml_int32_direct_bswap",_,_,_), args, _)
+    when !arch >= ARMv6 ->
+      Selectgen.Effect_and_coeffect.join_list_map args self#effects_of
+  | e -> super#effects_of e
+
 method select_addressing chunk = function
-  | Cop((Cadda | Caddv), [arg; Cconst_int n])
+  | Cop((Cadda | Caddv), [arg; Cconst_int n], _)
     when is_offset chunk n ->
       (Iindexed n, arg)
-  | Cop((Cadda | Caddv as op), [arg1; Cop(Caddi, [arg2; Cconst_int n])])
+  | Cop((Cadda | Caddv as op), [arg1; Cop(Caddi, [arg2; Cconst_int n], _)], dbg)
     when is_offset chunk n ->
-      (Iindexed n, Cop(op, [arg1; arg2]))
+      (Iindexed n, Cop(op, [arg1; arg2], dbg))
   | arg ->
       (Iindexed 0, arg)
 
-method select_shift_arith op arithop arithrevop args =
+method select_shift_arith op dbg arithop arithrevop args =
   match args with
-    [arg1; Cop(Clsl | Clsr | Casr as op, [arg2; Cconst_int n])]
+    [arg1; Cop(Clsl | Clsr | Casr as op, [arg2; Cconst_int n], _)]
     when n > 0 && n < 32 ->
       (Ispecific(Ishiftarith(arithop, select_shiftop op, n)), [arg1; arg2])
-  | [Cop(Clsl | Clsr | Casr as op, [arg1; Cconst_int n]); arg2]
+  | [Cop(Clsl | Clsr | Casr as op, [arg1; Cconst_int n], _); arg2]
     when n > 0 && n < 32 ->
       (Ispecific(Ishiftarith(arithrevop, select_shiftop op, n)), [arg2; arg1])
   | args ->
-      begin match super#select_operation op args with
+      begin match super#select_operation op args dbg with
       (* Recognize multiply high and add *)
-        (Iintop Iadd, [Cop(Cmulhi, args); arg3])
-      | (Iintop Iadd, [arg3; Cop(Cmulhi, args)]) as op_args
+        (Iintop Iadd, [Cop(Cmulhi, args, _); arg3])
+      | (Iintop Iadd, [arg3; Cop(Cmulhi, args, _)]) as op_args
         when !arch >= ARMv6 ->
-          begin match self#select_operation Cmulhi args with
+          begin match self#select_operation Cmulhi args dbg with
             (Iintop Imulh, [arg1; arg2]) ->
               (Ispecific Imulhadd, [arg1; arg2; arg3])
           | _ -> op_args
           end
       (* Recognize multiply and add *)
-      | (Iintop Iadd, [Cop(Cmuli, args); arg3])
-      | (Iintop Iadd, [arg3; Cop(Cmuli, args)]) as op_args ->
-          begin match self#select_operation Cmuli args with
+      | (Iintop Iadd, [Cop(Cmuli, args, _); arg3])
+      | (Iintop Iadd, [arg3; Cop(Cmuli, args, _)]) as op_args ->
+          begin match self#select_operation Cmuli args dbg with
             (Iintop Imul, [arg1; arg2]) ->
               (Ispecific Imuladd, [arg1; arg2; arg3])
           | _ -> op_args
           end
       (* Recognize multiply and subtract *)
-      | (Iintop Isub, [arg3; Cop(Cmuli, args)]) as op_args
+      | (Iintop Isub, [arg3; Cop(Cmuli, args, _)]) as op_args
         when !arch > ARMv6 ->
-          begin match self#select_operation Cmuli args with
+          begin match self#select_operation Cmuli args dbg with
             (Iintop Imul, [arg1; arg2]) ->
               (Ispecific Imulsub, [arg1; arg2; arg3])
           | _ -> op_args
@@ -169,14 +181,14 @@ method select_shift_arith op arithop arithrevop args =
 method private iextcall (func, alloc) =
   Iextcall { func; alloc; label_after = Cmm.new_label (); }
 
-method! select_operation op args =
+method! select_operation op args dbg =
   match (op, args) with
   (* Recognize special shift arithmetic *)
     ((Caddv | Cadda | Caddi), [arg; Cconst_int n])
     when n < 0 && self#is_immediate (-n) ->
       (Iintop_imm(Isub, -n), [arg])
   | ((Caddv | Cadda | Caddi as op), args) ->
-      self#select_shift_arith op Ishiftadd Ishiftadd args
+      self#select_shift_arith op dbg Ishiftadd Ishiftadd args
   | (Csubi, [arg; Cconst_int n])
     when n < 0 && self#is_immediate (-n) ->
       (Iintop_imm(Iadd, -n), [arg])
@@ -184,14 +196,15 @@ method! select_operation op args =
     when self#is_immediate n ->
       (Ispecific(Irevsubimm n), [arg])
   | (Csubi as op, args) ->
-      self#select_shift_arith op Ishiftsub Ishiftsubrev args
+      self#select_shift_arith op dbg Ishiftsub Ishiftsubrev args
   | (Cand as op, args) ->
-      self#select_shift_arith op Ishiftand Ishiftand args
+      self#select_shift_arith op dbg Ishiftand Ishiftand args
   | (Cor as op, args) ->
-      self#select_shift_arith op Ishiftor Ishiftor args
+      self#select_shift_arith op dbg Ishiftor Ishiftor args
   | (Cxor as op, args) ->
-      self#select_shift_arith op Ishiftxor Ishiftxor args
-  | (Ccheckbound _, [Cop(Clsl | Clsr | Casr as op, [arg1; Cconst_int n]); arg2])
+      self#select_shift_arith op dbg Ishiftxor Ishiftxor args
+  | (Ccheckbound,
+      [Cop(Clsl | Clsr | Casr as op, [arg1; Cconst_int n], _); arg2])
     when n > 0 && n < 32 ->
       (Ispecific(Ishiftcheckbound(select_shiftop op, n)), [arg1; arg2])
   (* ARM does not support immediate operands for multiplication *)
@@ -206,18 +219,18 @@ method! select_operation op args =
       (* See above for fix up of return register *)
       (self#iextcall("__aeabi_idivmod", false), args)
   (* Recognize 16-bit bswap instruction (ARMv6T2 because we need movt) *)
-  | (Cextcall("caml_bswap16_direct", _, _, _, _), args) when !arch >= ARMv6T2 ->
+  | (Cextcall("caml_bswap16_direct", _, _, _), args) when !arch >= ARMv6T2 ->
       (Ispecific(Ibswap 16), args)
   (* Recognize 32-bit bswap instructions (ARMv6 and above) *)
-  | (Cextcall("caml_int32_direct_bswap", _, _, _, _), args)
+  | (Cextcall("caml_int32_direct_bswap", _, _, _), args)
     when !arch >= ARMv6 ->
       (Ispecific(Ibswap 32), args)
   (* Turn floating-point operations into runtime ABI calls for softfp *)
-  | (op, args) when !fpu = Soft -> self#select_operation_softfp op args
+  | (op, args) when !fpu = Soft -> self#select_operation_softfp op args dbg
   (* Select operations for VFPv{2,3} *)
-  | (op, args) -> self#select_operation_vfpv3 op args
+  | (op, args) -> self#select_operation_vfpv3 op args dbg
 
-method private select_operation_softfp op args =
+method private select_operation_softfp op args dbg =
   match (op, args) with
   (* Turn floating-point operations into runtime ABI calls *)
   | (Caddf, args) -> (self#iextcall("__aeabi_dadd", false), args)
@@ -238,47 +251,47 @@ method private select_operation_softfp op args =
                     Cne -> Ceq (* eq 0 => false *)
                   | _   -> Cne (* ne 0 => true *)) in
       (Iintop_imm(Icomp(Iunsigned comp), 0),
-       [Cop(Cextcall(func, typ_int, false, Debuginfo.none, None), args)])
+       [Cop(Cextcall(func, typ_int, false, None), args, dbg)])
   (* Add coercions around loads and stores of 32-bit floats *)
-  | (Cload Single, args) ->
-      (self#iextcall("__aeabi_f2d", false), [Cop(Cload Word_int, args)])
+  | (Cload (Single, mut), args) ->
+      (self#iextcall("__aeabi_f2d", false),
+        [Cop(Cload (Word_int, mut), args, dbg)])
   | (Cstore (Single, init), [arg1; arg2]) ->
       let arg2' =
-        Cop(Cextcall("__aeabi_d2f", typ_int, false, Debuginfo.none, None),
-            [arg2]) in
-      self#select_operation (Cstore (Word_int, init)) [arg1; arg2']
+        Cop(Cextcall("__aeabi_d2f", typ_int, false, None), [arg2], dbg) in
+      self#select_operation (Cstore (Word_int, init)) [arg1; arg2'] dbg
   (* Other operations are regular *)
-  | (op, args) -> super#select_operation op args
+  | (op, args) -> super#select_operation op args dbg
 
-method private select_operation_vfpv3 op args =
+method private select_operation_vfpv3 op args dbg =
   match (op, args) with
   (* Recognize floating-point negate and multiply *)
-    (Cnegf, [Cop(Cmulf, args)]) ->
+    (Cnegf, [Cop(Cmulf, args, _)]) ->
       (Ispecific Inegmulf, args)
   (* Recognize floating-point multiply and add *)
-  | (Caddf, [arg; Cop(Cmulf, args)])
-  | (Caddf, [Cop(Cmulf, args); arg]) ->
+  | (Caddf, [arg; Cop(Cmulf, args, _)])
+  | (Caddf, [Cop(Cmulf, args, _); arg]) ->
       (Ispecific Imuladdf, arg :: args)
   (* Recognize floating-point negate, multiply and subtract *)
-  | (Csubf, [Cop(Cnegf, [arg]); Cop(Cmulf, args)])
-  | (Csubf, [Cop(Cnegf, [Cop(Cmulf, args)]); arg]) ->
+  | (Csubf, [Cop(Cnegf, [arg], _); Cop(Cmulf, args, _)])
+  | (Csubf, [Cop(Cnegf, [Cop(Cmulf, args, _)], _); arg]) ->
       (Ispecific Inegmulsubf, arg :: args)
   (* Recognize floating-point negate, multiply and add *)
-  | (Csubf, [arg; Cop(Cmulf, args)]) ->
+  | (Csubf, [arg; Cop(Cmulf, args, _)]) ->
       (Ispecific Inegmuladdf, arg :: args)
   (* Recognize multiply and subtract *)
-  | (Csubf, [Cop(Cmulf, args); arg]) ->
+  | (Csubf, [Cop(Cmulf, args, _); arg]) ->
       (Ispecific Imulsubf, arg :: args)
   (* Recognize floating-point square root *)
-  | (Cextcall("sqrt", _, false, _, _), args) ->
+  | (Cextcall("sqrt", _, false, _), args) ->
       (Ispecific Isqrtf, args)
   (* Other operations are regular *)
-  | (op, args) -> super#select_operation op args
+  | (op, args) -> super#select_operation op args dbg
 
 method! select_condition = function
   (* Turn floating-point comparisons into runtime ABI calls *)
-    Cop(Ccmpf _ as op, args) when !fpu = Soft ->
-      begin match self#select_operation_softfp op args with
+    Cop(Ccmpf _ as op, args, dbg) when !fpu = Soft ->
+      begin match self#select_operation_softfp op args dbg with
         (Iintop_imm(Icomp(Iunsigned Ceq), 0), [arg]) -> (Ifalsetest, arg)
       | (Iintop_imm(Icomp(Iunsigned Cne), 0), [arg]) -> (Itruetest, arg)
       | _ -> assert false
diff --git a/asmcomp/arm64/emit.mlp b/asmcomp/arm64/emit.mlp
index b67723a8..f75646e1 100644
--- a/asmcomp/arm64/emit.mlp
+++ b/asmcomp/arm64/emit.mlp
@@ -135,12 +135,8 @@ let record_frame_label ?label live raise_ dbg =
           Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
-  frame_descriptors :=
-    { fd_lbl = lbl;
-      fd_frame_size = frame_size();
-      fd_live_offset = !live_offset;
-      fd_raise = raise_;
-      fd_debuginfo = dbg } :: !frame_descriptors;
+  record_frame_descr ~label:lbl ~frame_size:(frame_size())
+    ~live_offset:!live_offset ~raise_frame:raise_ dbg;
   lbl
 
 let record_frame ?label live raise_ dbg =
diff --git a/asmcomp/arm64/selection.ml b/asmcomp/arm64/selection.ml
index 719c5ec2..d8ea7f83 100644
--- a/asmcomp/arm64/selection.ml
+++ b/asmcomp/arm64/selection.ml
@@ -76,6 +76,8 @@ let rec run_automata nbits state input =
 let is_logical_immediate n =
   n <> 0 && n <> -1 && run_automata 64 0 n
 
+(* If you update [inline_ops], you may need to update [is_simple_expr] and/or
+   [effects_of], below. *)
 let inline_ops =
   [ "sqrt"; "caml_bswap16_direct"; "caml_int32_direct_bswap";
     "caml_int64_direct_bswap"; "caml_nativeint_direct_bswap" ]
@@ -96,27 +98,33 @@ method is_immediate n =
 
 method! is_simple_expr = function
   (* inlined floating-point ops are simple if their arguments are *)
-  | Cop(Cextcall (fn, _, _, _, _), args) when List.mem fn inline_ops ->
+  | Cop(Cextcall (fn, _, _, _), args, _) when List.mem fn inline_ops ->
       List.for_all self#is_simple_expr args
   | e -> super#is_simple_expr e
 
+method! effects_of e =
+  match e with
+  | Cop(Cextcall (fn, _, _, _), args, _) when List.mem fn inline_ops ->
+      Selectgen.Effect_and_coeffect.join_list_map args self#effects_of
+  | e -> super#effects_of e
+
 method select_addressing chunk = function
-  | Cop((Caddv | Cadda), [Cconst_symbol s; Cconst_int n])
+  | Cop((Caddv | Cadda), [Cconst_symbol s; Cconst_int n], _)
     when use_direct_addressing s ->
       (Ibased(s, n), Ctuple [])
-  | Cop((Caddv | Cadda), [arg; Cconst_int n])
+  | Cop((Caddv | Cadda), [arg; Cconst_int n], _)
     when is_offset chunk n ->
       (Iindexed n, arg)
-  | Cop((Caddv | Cadda as op), [arg1; Cop(Caddi, [arg2; Cconst_int n])])
+  | Cop((Caddv | Cadda as op), [arg1; Cop(Caddi, [arg2; Cconst_int n], _)], dbg)
     when is_offset chunk n ->
-      (Iindexed n, Cop(op, [arg1; arg2]))
+      (Iindexed n, Cop(op, [arg1; arg2], dbg))
   | Cconst_symbol s
     when use_direct_addressing s ->
       (Ibased(s, 0), Ctuple [])
   | arg ->
       (Iindexed 0, arg)
 
-method! select_operation op args =
+method! select_operation op args dbg =
   match op with
   (* Integer addition *)
   | Caddi | Caddv | Cadda ->
@@ -129,26 +137,26 @@ method! select_operation op args =
           ((if n >= 0 then Iintop_imm(Iadd, n) else Iintop_imm(Isub, -n)),
            [arg])
       (* Shift-add *)
-      | [arg1; Cop(Clsl, [arg2; Cconst_int n])] when n > 0 && n < 64 ->
+      | [arg1; Cop(Clsl, [arg2; Cconst_int n], _)] when n > 0 && n < 64 ->
           (Ispecific(Ishiftarith(Ishiftadd, n)), [arg1; arg2])
-      | [arg1; Cop(Casr, [arg2; Cconst_int n])] when n > 0 && n < 64 ->
+      | [arg1; Cop(Casr, [arg2; Cconst_int n], _)] when n > 0 && n < 64 ->
           (Ispecific(Ishiftarith(Ishiftadd, -n)), [arg1; arg2])
-      | [Cop(Clsl, [arg1; Cconst_int n]); arg2] when n > 0 && n < 64 ->
+      | [Cop(Clsl, [arg1; Cconst_int n], _); arg2] when n > 0 && n < 64 ->
           (Ispecific(Ishiftarith(Ishiftadd, n)), [arg2; arg1])
-      | [Cop(Casr, [arg1; Cconst_int n]); arg2] when n > 0 && n < 64 ->
+      | [Cop(Casr, [arg1; Cconst_int n], _); arg2] when n > 0 && n < 64 ->
           (Ispecific(Ishiftarith(Ishiftadd, -n)), [arg2; arg1])
       (* Multiply-add *)
-      | [arg1; Cop(Cmuli, args2)] | [Cop(Cmuli, args2); arg1] ->
-          begin match self#select_operation Cmuli args2 with
+      | [arg1; Cop(Cmuli, args2, dbg)] | [Cop(Cmuli, args2, dbg); arg1] ->
+          begin match self#select_operation Cmuli args2 dbg with
           | (Iintop_imm(Ilsl, l), [arg3]) ->
               (Ispecific(Ishiftarith(Ishiftadd, l)), [arg1; arg3])
           | (Iintop Imul, [arg3; arg4]) ->
               (Ispecific Imuladd, [arg3; arg4; arg1])
           | _ ->
-              super#select_operation op args
+              super#select_operation op args dbg
           end
       | _ ->
-          super#select_operation op args
+          super#select_operation op args dbg
       end
   (* Integer subtraction *)
   | Csubi ->
@@ -158,31 +166,31 @@ method! select_operation op args =
           ((if n >= 0 then Iintop_imm(Isub, n) else Iintop_imm(Iadd, -n)),
            [arg])
       (* Shift-sub *)
-      | [arg1; Cop(Clsl, [arg2; Cconst_int n])] when n > 0 && n < 64 ->
+      | [arg1; Cop(Clsl, [arg2; Cconst_int n], _)] when n > 0 && n < 64 ->
           (Ispecific(Ishiftarith(Ishiftsub, n)), [arg1; arg2])
-      | [arg1; Cop(Casr, [arg2; Cconst_int n])] when n > 0 && n < 64 ->
+      | [arg1; Cop(Casr, [arg2; Cconst_int n], _)] when n > 0 && n < 64 ->
           (Ispecific(Ishiftarith(Ishiftsub, -n)), [arg1; arg2])
       (* Multiply-sub *)
-      | [arg1; Cop(Cmuli, args2)] ->
-          begin match self#select_operation Cmuli args2 with
+      | [arg1; Cop(Cmuli, args2, dbg)] ->
+          begin match self#select_operation Cmuli args2 dbg with
           | (Iintop_imm(Ilsl, l), [arg3]) ->
               (Ispecific(Ishiftarith(Ishiftsub, l)), [arg1; arg3])
           | (Iintop Imul, [arg3; arg4]) ->
               (Ispecific Imulsub, [arg3; arg4; arg1])
           | _ ->
-              super#select_operation op args
+              super#select_operation op args dbg
           end
       | _ ->
-          super#select_operation op args
+          super#select_operation op args dbg
       end
   (* Checkbounds *)
-  | Ccheckbound _ ->
+  | Ccheckbound ->
       begin match args with
-      | [Cop(Clsr, [arg1; Cconst_int n]); arg2] when n > 0 && n < 64 ->
+      | [Cop(Clsr, [arg1; Cconst_int n], _); arg2] when n > 0 && n < 64 ->
           (Ispecific(Ishiftcheckbound { shift = n; label_after_error = None; }),
             [arg1; arg2])
       | _ ->
-          super#select_operation op args
+          super#select_operation op args dbg
       end
   (* Integer multiplication *)
   (* ARM does not support immediate operands for multiplication *)
@@ -198,40 +206,40 @@ method! select_operation op args =
   (* Recognize floating-point negate and multiply *)
   | Cnegf ->
       begin match args with
-      | [Cop(Cmulf, args)] -> (Ispecific Inegmulf, args)
-      | _ -> super#select_operation op args
+      | [Cop(Cmulf, args, _)] -> (Ispecific Inegmulf, args)
+      | _ -> super#select_operation op args dbg
       end
   (* Recognize floating-point multiply and add/sub *)
   | Caddf ->
       begin match args with
-      | [arg; Cop(Cmulf, args)] | [Cop(Cmulf, args); arg] ->
+      | [arg; Cop(Cmulf, args, _)] | [Cop(Cmulf, args, _); arg] ->
           (Ispecific Imuladdf, arg :: args)
       | _ ->
-          super#select_operation op args
+          super#select_operation op args dbg
       end
   | Csubf ->
       begin match args with
-      | [arg; Cop(Cmulf, args)] ->
+      | [arg; Cop(Cmulf, args, _)] ->
           (Ispecific Imulsubf, arg :: args)
-      | [Cop(Cmulf, args); arg] ->
+      | [Cop(Cmulf, args, _); arg] ->
           (Ispecific Inegmulsubf, arg :: args)
       | _ ->
-          super#select_operation op args
+          super#select_operation op args dbg
       end
   (* Recognize floating-point square root *)
-  | Cextcall("sqrt", _, _, _, _) ->
+  | Cextcall("sqrt", _, _, _) ->
       (Ispecific Isqrtf, args)
   (* Recognize bswap instructions *)
-  | Cextcall("caml_bswap16_direct", _, _, _, _) ->
+  | Cextcall("caml_bswap16_direct", _, _, _) ->
       (Ispecific(Ibswap 16), args)
-  | Cextcall("caml_int32_direct_bswap", _, _, _, _) ->
+  | Cextcall("caml_int32_direct_bswap", _, _, _) ->
       (Ispecific(Ibswap 32), args)
   | Cextcall(("caml_int64_direct_bswap"|"caml_nativeint_direct_bswap"),
-              _, _, _, _) ->
+              _, _, _) ->
       (Ispecific (Ibswap 64), args)
   (* Other operations are regular *)
   | _ ->
-      super#select_operation op args
+      super#select_operation op args dbg
 
 method select_logical op = function
   | [arg; Cconst_int n] when is_logical_immediate n ->
diff --git a/asmcomp/asmlibrarian.ml b/asmcomp/asmlibrarian.ml
index ca3f5740..6545a9f5 100644
--- a/asmcomp/asmlibrarian.ml
+++ b/asmcomp/asmlibrarian.ml
@@ -38,7 +38,7 @@ let read_info name =
     with Not_found ->
       raise(Error(File_not_found name)) in
   let (info, crc) = Compilenv.read_unit_info filename in
-  info.ui_force_link <- !Clflags.link_everything;
+  info.ui_force_link <- info.ui_force_link || !Clflags.link_everything;
   (* There is no need to keep the approximation in the .cmxa file,
      since the compiler will go looking directly for .cmx files.
      The linker, which is the only one that reads .cmxa files, does not
diff --git a/asmcomp/asmpackager.ml b/asmcomp/asmpackager.ml
index 6f0db063..09db234b 100644
--- a/asmcomp/asmpackager.ml
+++ b/asmcomp/asmpackager.ml
@@ -43,7 +43,9 @@ let read_member_info pack_path file = (
   let name =
     String.capitalize_ascii(Filename.basename(chop_extensions file)) in
   let kind =
-    if Filename.check_suffix file ".cmx" then begin
+    if Filename.check_suffix file ".cmi" then
+      PM_intf
+    else begin
       let (info, crc) = Compilenv.read_unit_info file in
       if info.ui_name <> name
       then raise(Error(Illegal_renaming(name, file, info.ui_name)));
@@ -53,8 +55,7 @@ let read_member_info pack_path file = (
       Asmlink.check_consistency file info crc;
       Compilenv.cache_unit_info info;
       PM_impl info
-    end else
-      PM_intf in
+    end in
   { pm_file = file; pm_name = name; pm_kind = kind }
 )
 
diff --git a/asmcomp/clambda.ml b/asmcomp/clambda.ml
index df4cfc94..7d21fcd8 100644
--- a/asmcomp/clambda.ml
+++ b/asmcomp/clambda.ml
@@ -64,7 +64,8 @@ and ufunction = {
   arity  : int;
   params : Ident.t list;
   body   : ulambda;
-  dbg    : Debuginfo.t
+  dbg    : Debuginfo.t;
+  env    : Ident.t option;
 }
 
 and ulambda_switch =
diff --git a/asmcomp/clambda.mli b/asmcomp/clambda.mli
index dd989cd9..6a6bc1b2 100644
--- a/asmcomp/clambda.mli
+++ b/asmcomp/clambda.mli
@@ -65,6 +65,7 @@ and ufunction = {
   params : Ident.t list;
   body   : ulambda;
   dbg    : Debuginfo.t;
+  env    : Ident.t option;
 }
 
 and ulambda_switch =
diff --git a/asmcomp/closure.ml b/asmcomp/closure.ml
index 78b7fc3e..1bdc4392 100644
--- a/asmcomp/closure.ml
+++ b/asmcomp/closure.ml
@@ -109,8 +109,8 @@ let prim_size prim args =
   | Pfield _ -> 1
   | Psetfield(_f, isptr, init) ->
     begin match init with
-    | Initialization -> 1  (* never causes a write barrier hit *)
-    | Assignment ->
+    | Root_initialization -> 1  (* never causes a write barrier hit *)
+    | Assignment | Heap_initialization ->
       match isptr with
       | Pointer -> 4
       | Immediate -> 1
@@ -201,16 +201,19 @@ let lambda_smaller lam threshold =
   with Exit ->
     false
 
+let is_pure_prim p =
+  let open Semantics_of_primitives in
+  match Semantics_of_primitives.for_primitive p with
+  | (No_effects | Only_generative_effects), _ -> true
+  | Arbitrary_effects, _ -> false
+
 (* Check if a clambda term is ``pure'',
    that is without side-effects *and* not containing function definitions *)
 
 let rec is_pure_clambda = function
     Uvar _ -> true
   | Uconst _ -> true
-  | Uprim((Psetglobal _ | Psetfield _ | Psetfloatfield _ | Pduprecord _ |
-           Pccall _ | Praise _ | Poffsetref _ |  Pbytessetu | Pbytessets |
-           Parraysetu _ | Parraysets _ | Pbigarrayset _), _, _) -> false
-  | Uprim(_, args, _) -> List.for_all is_pure_clambda args
+  | Uprim(p, args, _) -> is_pure_prim p && List.for_all is_pure_clambda args
   | _ -> false
 
 (* Simplify primitive operations on known arguments *)
@@ -653,7 +656,7 @@ let is_simple_argument = function
 
 let no_effects = function
   | Uclosure _ -> true
-  | u -> is_simple_argument u
+  | u -> is_pure_clambda u
 
 let rec bind_params_rec loc fpc subst params args body =
   match (params, args) with
@@ -689,10 +692,7 @@ let bind_params loc fpc params args body =
 let rec is_pure = function
     Lvar _ -> true
   | Lconst _ -> true
-  | Lprim((Psetglobal _ | Psetfield _ | Psetfloatfield _ | Pduprecord _ |
-           Pccall _ | Praise _ | Poffsetref _  | Pbytessetu | Pbytessets |
-           Parraysetu _ | Parraysets _ | Pbigarrayset _), _,_) -> false
-  | Lprim(_, args,_) -> List.for_all is_pure args
+  | Lprim(p, args,_) -> is_pure_prim p && List.for_all is_pure args
   | Levent(lam, _ev) -> is_pure lam
   | _ -> false
 
@@ -824,7 +824,7 @@ let rec close fenv cenv = function
   | Lfunction _ as funct ->
       close_one_function fenv cenv (Ident.create "fun") funct
 
-    (* We convert [f a] to [let a' = a in fun b c -> f a' b c]
+    (* We convert [f a] to [let a' = a in let f' = f in fun b c -> f' a' b c]
        when fun_arity > nargs *)
   | Lapply{ap_func = funct; ap_args = args; ap_loc = loc;
         ap_inlined = attribute} ->
@@ -842,7 +842,7 @@ let rec close fenv cenv = function
             direct_apply ~loc ~attribute fundesc funct ufunct uargs in
           (app, strengthen_approx app approx_res)
 
-      | ((_ufunct, Value_closure(fundesc, _approx_res)), uargs)
+      | ((ufunct, (Value_closure(fundesc, _) as fapprox)), uargs)
           when nargs < fundesc.fun_arity ->
         let first_args = List.map (fun arg ->
           (Ident.create "arg", arg) ) uargs in
@@ -860,32 +860,48 @@ let rec close fenv cenv = function
           (List.map (fun (arg1, _arg2) -> Lvar arg1) first_args)
           @ (List.map (fun arg -> Lvar arg ) final_args)
         in
+        let funct_var = Ident.create "funct" in
+        let fenv = Tbl.add funct_var fapprox fenv in
         let (new_fun, approx) = close fenv cenv
           (Lfunction{
                kind = Curried;
                params = final_args;
                body = Lapply{ap_should_be_tailcall=false;
                              ap_loc=loc;
-                             ap_func=funct;
+                             ap_func=(Lvar funct_var);
                              ap_args=internal_args;
                              ap_inlined=Default_inline;
                              ap_specialised=Default_specialise};
                loc;
                attr = default_function_attribute})
         in
-        let new_fun = iter first_args new_fun in
+        let new_fun =
+          iter first_args
+            (Ulet (Immutable, Pgenval, funct_var, ufunct, new_fun))
+        in
         warning_if_forced_inline ~loc ~attribute "Partial application";
         (new_fun, approx)
 
       | ((ufunct, Value_closure(fundesc, _approx_res)), uargs)
         when fundesc.fun_arity > 0 && nargs > fundesc.fun_arity ->
-          let (first_args, rem_args) = split_list fundesc.fun_arity uargs in
+          let args = List.map (fun arg -> Ident.create "arg", arg) uargs in
+          let (first_args, rem_args) = split_list fundesc.fun_arity args in
+          let first_args = List.map (fun (id, _) -> Uvar id) first_args in
+          let rem_args = List.map (fun (id, _) -> Uvar id) rem_args in
           let dbg = Debuginfo.from_location loc in
           warning_if_forced_inline ~loc ~attribute "Over-application";
-          (Ugeneric_apply(direct_apply ~loc ~attribute
-                            fundesc funct ufunct first_args,
-                          rem_args, dbg),
-           Value_unknown)
+          let body =
+            Ugeneric_apply(direct_apply ~loc ~attribute
+                              fundesc funct ufunct first_args,
+                           rem_args, dbg)
+          in
+          let result =
+            List.fold_left (fun body (id, defining_expr) ->
+                Ulet (Immutable, Pgenval, id, defining_expr, body))
+              body
+              args
+          in
+          result, Value_unknown
       | ((ufunct, _), uargs) ->
           let dbg = Debuginfo.from_location loc in
           warning_if_forced_inline ~loc ~attribute "Unknown function";
@@ -1090,16 +1106,15 @@ and close_functions fenv cenv fun_defs =
          (function
            | (id, Lfunction{kind; params; body; attr; loc}) ->
                Simplif.split_default_wrapper ~id ~kind ~params
-                 ~body ~attr ~wrapper_attr:attr ~loc ()
+                 ~body ~attr ~loc
            | _ -> assert false
          )
          fun_defs)
   in
   let inline_attribute = match fun_defs with
-    | [_, Lfunction{attr = { inline }}] -> inline
+    | [_, Lfunction{attr = { inline; }}] -> inline
     | _ -> Default_inline (* recursive functions can't be inlined *)
   in
-
   (* Update and check nesting depth *)
   incr function_nesting_depth;
   let initially_closed =
@@ -1165,6 +1180,7 @@ and close_functions fenv cenv fun_defs =
         params = fun_params;
         body   = ubody;
         dbg;
+        env = Some env_param;
       }
     in
     (* give more chance of function with default parameters (i.e.
diff --git a/asmcomp/cmm.ml b/asmcomp/cmm.ml
index eb920b28..5b2fd6b8 100644
--- a/asmcomp/cmm.ml
+++ b/asmcomp/cmm.ml
@@ -117,6 +117,8 @@ type raise_kind =
   | Raise_withtrace
   | Raise_notrace
 
+type rec_flag = Nonrecursive | Recursive
+
 type memory_chunk =
     Byte_unsigned
   | Byte_signed
@@ -131,12 +133,12 @@ type memory_chunk =
   | Double_u
 
 and operation =
-    Capply of machtype * Debuginfo.t
-  | Cextcall of string * machtype * bool * Debuginfo.t * label option
+    Capply of machtype
+  | Cextcall of string * machtype * bool * label option
     (** If specified, the given label will be placed immediately after the
         call (at the same place as any frame descriptor would reference). *)
-  | Cload of memory_chunk
-  | Calloc of Debuginfo.t
+  | Cload of memory_chunk * Asttypes.mutable_flag
+  | Calloc
   | Cstore of memory_chunk * Lambda.initialization_or_assignment
   | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi
   | Cand | Cor | Cxor | Clsl | Clsr | Casr
@@ -147,8 +149,8 @@ and operation =
   | Caddf | Csubf | Cmulf | Cdivf
   | Cfloatofint | Cintoffloat
   | Ccmpf of comparison
-  | Craise of raise_kind * Debuginfo.t
-  | Ccheckbound of Debuginfo.t
+  | Craise of raise_kind
+  | Ccheckbound
 
 type expression =
     Cconst_int of int
@@ -162,12 +164,12 @@ type expression =
   | Clet of Ident.t * expression * expression
   | Cassign of Ident.t * expression
   | Ctuple of expression list
-  | Cop of operation * expression list
+  | Cop of operation * expression list * Debuginfo.t
   | Csequence of expression * expression
   | Cifthenelse of expression * expression * expression
-  | Cswitch of expression * int array * expression array
+  | Cswitch of expression * int array * expression array * Debuginfo.t
   | Cloop of expression
-  | Ccatch of int * Ident.t list * expression * expression
+  | Ccatch of rec_flag * (int * Ident.t list * expression) list * expression
   | Cexit of int * expression list
   | Ctrywith of expression * Ident.t * expression
 
@@ -197,5 +199,8 @@ type phrase =
     Cfunction of fundecl
   | Cdata of data_item list
 
+let ccatch (i, ids, e1, e2)=
+  Ccatch(Nonrecursive, [i, ids, e2], e1)
+
 let reset () =
   label_counter := 99
diff --git a/asmcomp/cmm.mli b/asmcomp/cmm.mli
index 0b1a781e..a62578f6 100644
--- a/asmcomp/cmm.mli
+++ b/asmcomp/cmm.mli
@@ -90,6 +90,8 @@ type raise_kind =
   | Raise_withtrace
   | Raise_notrace
 
+type rec_flag = Nonrecursive | Recursive
+
 type memory_chunk =
     Byte_unsigned
   | Byte_signed
@@ -104,10 +106,10 @@ type memory_chunk =
   | Double_u                           (* word-aligned 64-bit float *)
 
 and operation =
-    Capply of machtype * Debuginfo.t
-  | Cextcall of string * machtype * bool * Debuginfo.t * label option
-  | Cload of memory_chunk
-  | Calloc of Debuginfo.t
+    Capply of machtype
+  | Cextcall of string * machtype * bool * label option
+  | Cload of memory_chunk * Asttypes.mutable_flag
+  | Calloc
   | Cstore of memory_chunk * Lambda.initialization_or_assignment
   | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi
   | Cand | Cor | Cxor | Clsl | Clsr | Casr
@@ -119,9 +121,13 @@ and operation =
   | Caddf | Csubf | Cmulf | Cdivf
   | Cfloatofint | Cintoffloat
   | Ccmpf of comparison
-  | Craise of raise_kind * Debuginfo.t
-  | Ccheckbound of Debuginfo.t
+  | Craise of raise_kind
+  | Ccheckbound
 
+(** Not all cmm expressions currently have [Debuginfo.t] values attached to
+    them.  The ones that do are those that are likely to generate code that
+    can fairly robustly be mapped back to a source location.  In the future
+    it might be the case that more [Debuginfo.t] annotations are desirable. *)
 and expression =
     Cconst_int of int
   | Cconst_natint of nativeint
@@ -134,12 +140,12 @@ and expression =
   | Clet of Ident.t * expression * expression
   | Cassign of Ident.t * expression
   | Ctuple of expression list
-  | Cop of operation * expression list
+  | Cop of operation * expression list * Debuginfo.t
   | Csequence of expression * expression
   | Cifthenelse of expression * expression * expression
-  | Cswitch of expression * int array * expression array
+  | Cswitch of expression * int array * expression array * Debuginfo.t
   | Cloop of expression
-  | Ccatch of int * Ident.t list * expression * expression
+  | Ccatch of rec_flag * (int * Ident.t list * expression) list * expression
   | Cexit of int * expression list
   | Ctrywith of expression * Ident.t * expression
 
@@ -169,4 +175,6 @@ type phrase =
     Cfunction of fundecl
   | Cdata of data_item list
 
+val ccatch : int * Ident.t list * expression * expression -> expression
+
 val reset : unit -> unit
diff --git a/asmcomp/cmmgen.ml b/asmcomp/cmmgen.ml
index fd21651f..4ac4b40c 100644
--- a/asmcomp/cmmgen.ml
+++ b/asmcomp/cmmgen.ml
@@ -25,6 +25,37 @@ open Clambda
 open Cmm
 open Cmx_format
 
+(* Environments used for translation to Cmm. *)
+
+type boxed_number =
+  | Boxed_float of Debuginfo.t
+  | Boxed_integer of boxed_integer * Debuginfo.t
+
+type env = {
+  unboxed_ids : (Ident.t * boxed_number) Ident.tbl;
+  environment_param : Ident.t option;
+}
+
+let empty_env =
+  {
+    unboxed_ids =Ident.empty;
+    environment_param = None;
+  }
+
+let create_env ~environment_param =
+  { unboxed_ids = Ident.empty;
+    environment_param;
+  }
+
+let is_unboxed_id id env =
+  try Some (Ident.find_same id env.unboxed_ids)
+  with Not_found -> None
+
+let add_unboxed_id id unboxed_id bn env =
+  { env with
+    unboxed_ids = Ident.add id (unboxed_id, bn) env.unboxed_ids;
+  }
+
 (* Local binding of complex expressions *)
 
 let bind name arg fn =
@@ -36,7 +67,7 @@ let bind name arg fn =
 
 let bind_load name arg fn =
   match arg with
-  | Cop(Cload _, [Cvar _]) -> fn arg
+  | Cop(Cload _, [Cvar _], _) -> fn arg
   | _ -> bind name arg fn
 
 let bind_nonvar name arg fn =
@@ -65,20 +96,24 @@ let black_closure_header sz = black_block_header Obj.closure_tag sz
 let infix_header ofs = block_header Obj.infix_tag ofs
 let float_header = block_header Obj.double_tag (size_float / size_addr)
 let floatarray_header len =
-      block_header Obj.double_array_tag (len * size_float / size_addr)
+  (* Zero-sized float arrays have tag zero for consistency with
+     [caml_alloc_float_array]. *)
+  assert (len >= 0);
+  if len = 0 then block_header 0 0
+  else block_header Obj.double_array_tag (len * size_float / size_addr)
 let string_header len =
       block_header Obj.string_tag ((len + size_addr) / size_addr)
 let boxedint32_header = block_header Obj.custom_tag 2
 let boxedint64_header = block_header Obj.custom_tag (1 + 8 / size_addr)
 let boxedintnat_header = block_header Obj.custom_tag 2
 
-let alloc_float_header dbg = Cblockheader(float_header, dbg)
-let alloc_floatarray_header len dbg = Cblockheader(floatarray_header len, dbg)
-let alloc_closure_header sz dbg = Cblockheader(white_closure_header sz, dbg)
-let alloc_infix_header ofs dbg = Cblockheader(infix_header ofs, dbg)
-let alloc_boxedint32_header dbg = Cblockheader(boxedint32_header, dbg)
-let alloc_boxedint64_header dbg = Cblockheader(boxedint64_header, dbg)
-let alloc_boxedintnat_header dbg = Cblockheader(boxedintnat_header, dbg)
+let alloc_float_header dbg = Cblockheader (float_header, dbg)
+let alloc_floatarray_header len dbg = Cblockheader (floatarray_header len, dbg)
+let alloc_closure_header sz dbg = Cblockheader (white_closure_header sz, dbg)
+let alloc_infix_header ofs dbg = Cblockheader (infix_header ofs, dbg)
+let alloc_boxedint32_header dbg = Cblockheader (boxedint32_header, dbg)
+let alloc_boxedint64_header dbg = Cblockheader (boxedint64_header, dbg)
+let alloc_boxedintnat_header dbg = Cblockheader (boxedintnat_header, dbg)
 
 (* Integers *)
 
@@ -94,135 +129,138 @@ let int_const n =
 let cint_const n =
   Cint(Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n)
 
-let add_no_overflow n x c =
+let add_no_overflow n x c dbg =
   let d = n + x in
-  if d = 0 then c else Cop(Caddi, [c; Cconst_int d])
+  if d = 0 then c else Cop(Caddi, [c; Cconst_int d], dbg)
 
-let rec add_const c n =
+let rec add_const c n dbg =
   if n = 0 then c
   else match c with
   | Cconst_int x when no_overflow_add x n -> Cconst_int (x + n)
-  | Cop(Caddi, [Cconst_int x; c])
+  | Cop(Caddi, [Cconst_int x; c], _)
     when no_overflow_add n x ->
-      add_no_overflow n x c
-  | Cop(Caddi, [c; Cconst_int x])
+      add_no_overflow n x c dbg
+  | Cop(Caddi, [c; Cconst_int x], _)
     when no_overflow_add n x ->
-      add_no_overflow n x c
-  | Cop(Csubi, [Cconst_int x; c]) when no_overflow_add n x ->
-      Cop(Csubi, [Cconst_int (n + x); c])
-  | Cop(Csubi, [c; Cconst_int x]) when no_overflow_sub n x ->
-      add_const c (n - x)
-  | c -> Cop(Caddi, [c; Cconst_int n])
+      add_no_overflow n x c dbg
+  | Cop(Csubi, [Cconst_int x; c], _) when no_overflow_add n x ->
+      Cop(Csubi, [Cconst_int (n + x); c], dbg)
+  | Cop(Csubi, [c; Cconst_int x], _) when no_overflow_sub n x ->
+      add_const c (n - x) dbg
+  | c -> Cop(Caddi, [c; Cconst_int n], dbg)
 
-let incr_int c = add_const c 1
-let decr_int c = add_const c (-1)
+let incr_int c dbg = add_const c 1 dbg
+let decr_int c dbg = add_const c (-1) dbg
 
-let rec add_int c1 c2 =
+let rec add_int c1 c2 dbg =
   match (c1, c2) with
   | (Cconst_int n, c) | (c, Cconst_int n) ->
-      add_const c n
-  | (Cop(Caddi, [c1; Cconst_int n1]), c2) ->
-      add_const (add_int c1 c2) n1
-  | (c1, Cop(Caddi, [c2; Cconst_int n2])) ->
-      add_const (add_int c1 c2) n2
+      add_const c n dbg
+  | (Cop(Caddi, [c1; Cconst_int n1], _), c2) ->
+      add_const (add_int c1 c2 dbg) n1 dbg
+  | (c1, Cop(Caddi, [c2; Cconst_int n2], _)) ->
+      add_const (add_int c1 c2 dbg) n2 dbg
   | (_, _) ->
-      Cop(Caddi, [c1; c2])
+      Cop(Caddi, [c1; c2], dbg)
 
-let rec sub_int c1 c2 =
+let rec sub_int c1 c2 dbg =
   match (c1, c2) with
   | (c1, Cconst_int n2) when n2 <> min_int ->
-      add_const c1 (-n2)
-  | (c1, Cop(Caddi, [c2; Cconst_int n2])) when n2 <> min_int ->
-      add_const (sub_int c1 c2) (-n2)
-  | (Cop(Caddi, [c1; Cconst_int n1]), c2) ->
-      add_const (sub_int c1 c2) n1
+      add_const c1 (-n2) dbg
+  | (c1, Cop(Caddi, [c2; Cconst_int n2], _)) when n2 <> min_int ->
+      add_const (sub_int c1 c2 dbg) (-n2) dbg
+  | (Cop(Caddi, [c1; Cconst_int n1], _), c2) ->
+      add_const (sub_int c1 c2 dbg) n1 dbg
   | (c1, c2) ->
-      Cop(Csubi, [c1; c2])
+      Cop(Csubi, [c1; c2], dbg)
 
-let rec lsl_int c1 c2 =
+let rec lsl_int c1 c2 dbg =
   match (c1, c2) with
-  | (Cop(Clsl, [c; Cconst_int n1]), Cconst_int n2)
+  | (Cop(Clsl, [c; Cconst_int n1], _), Cconst_int n2)
     when n1 > 0 && n2 > 0 && n1 + n2 < size_int * 8 ->
-      Cop(Clsl, [c; Cconst_int (n1 + n2)])
-  | (Cop(Caddi, [c1; Cconst_int n1]), Cconst_int n2)
+      Cop(Clsl, [c; Cconst_int (n1 + n2)], dbg)
+  | (Cop(Caddi, [c1; Cconst_int n1], _), Cconst_int n2)
     when no_overflow_lsl n1 n2 ->
-      add_const (lsl_int c1 c2) (n1 lsl n2)
+      add_const (lsl_int c1 c2 dbg) (n1 lsl n2) dbg
   | (_, _) ->
-      Cop(Clsl, [c1; c2])
+      Cop(Clsl, [c1; c2], dbg)
 
 let is_power2 n = n = 1 lsl Misc.log2 n
 
-and mult_power2 c n = lsl_int c (Cconst_int (Misc.log2 n))
+and mult_power2 c n dbg = lsl_int c (Cconst_int (Misc.log2 n)) dbg
 
-let rec mul_int c1 c2 =
+let rec mul_int c1 c2 dbg =
   match (c1, c2) with
-  | (_, Cconst_int 0) | (Cconst_int 0, _) ->
-      Cconst_int 0
+  | (c, Cconst_int 0) | (Cconst_int 0, c) -> Csequence (c, Cconst_int 0)
   | (c, Cconst_int 1) | (Cconst_int 1, c) ->
       c
   | (c, Cconst_int(-1)) | (Cconst_int(-1), c) ->
-      sub_int (Cconst_int 0) c
-  | (c, Cconst_int n) when is_power2 n -> mult_power2 c n
-  | (Cconst_int n, c) when is_power2 n -> mult_power2 c n
-  | (Cop(Caddi, [c; Cconst_int n]), Cconst_int k) |
-    (Cconst_int k, Cop(Caddi, [c; Cconst_int n]))
+      sub_int (Cconst_int 0) c dbg
+  | (c, Cconst_int n) when is_power2 n -> mult_power2 c n dbg
+  | (Cconst_int n, c) when is_power2 n -> mult_power2 c n dbg
+  | (Cop(Caddi, [c; Cconst_int n], _), Cconst_int k) |
+    (Cconst_int k, Cop(Caddi, [c; Cconst_int n], _))
     when no_overflow_mul n k ->
-      add_const (mul_int c (Cconst_int k)) (n * k)
+      add_const (mul_int c (Cconst_int k) dbg) (n * k) dbg
   | (c1, c2) ->
-      Cop(Cmuli, [c1; c2])
+      Cop(Cmuli, [c1; c2], dbg)
 
 
 let ignore_low_bit_int = function
-    Cop(Caddi, [(Cop(Clsl, [_; Cconst_int n]) as c); Cconst_int 1]) when n > 0
+    Cop(Caddi, [(Cop(Clsl, [_; Cconst_int n], _) as c); Cconst_int 1], _)
+      when n > 0
       -> c
-  | Cop(Cor, [c; Cconst_int 1]) -> c
+  | Cop(Cor, [c; Cconst_int 1], _) -> c
   | c -> c
 
-let lsr_int c1 c2 =
+let lsr_int c1 c2 dbg =
   match c2 with
     Cconst_int 0 ->
       c1
   | Cconst_int n when n > 0 ->
-      Cop(Clsr, [ignore_low_bit_int c1; c2])
+      Cop(Clsr, [ignore_low_bit_int c1; c2], dbg)
   | _ ->
-      Cop(Clsr, [c1; c2])
+      Cop(Clsr, [c1; c2], dbg)
 
-let asr_int c1 c2 =
+let asr_int c1 c2 dbg =
   match c2 with
     Cconst_int 0 ->
       c1
   | Cconst_int n when n > 0 ->
-      Cop(Casr, [ignore_low_bit_int c1; c2])
+      Cop(Casr, [ignore_low_bit_int c1; c2], dbg)
   | _ ->
-      Cop(Casr, [c1; c2])
+      Cop(Casr, [c1; c2], dbg)
 
-let tag_int = function
+let tag_int i dbg =
+  match i with
     Cconst_int n ->
       int_const n
-  | Cop(Casr, [c; Cconst_int n]) when n > 0 ->
-      Cop(Cor, [asr_int c (Cconst_int (n - 1)); Cconst_int 1])
+  | Cop(Casr, [c; Cconst_int n], _) when n > 0 ->
+      Cop(Cor, [asr_int c (Cconst_int (n - 1)) dbg; Cconst_int 1], dbg)
   | c ->
-      incr_int (lsl_int c (Cconst_int 1))
+      incr_int (lsl_int c (Cconst_int 1) dbg) dbg
 
-let force_tag_int = function
+let force_tag_int i dbg =
+  match i with
     Cconst_int n ->
       int_const n
-  | Cop(Casr, [c; Cconst_int n]) when n > 0 ->
-      Cop(Cor, [asr_int c (Cconst_int (n - 1)); Cconst_int 1])
+  | Cop(Casr, [c; Cconst_int n], dbg) when n > 0 ->
+      Cop(Cor, [asr_int c (Cconst_int (n - 1)) dbg; Cconst_int 1], dbg)
   | c ->
-      Cop(Cor, [lsl_int c (Cconst_int 1); Cconst_int 1])
+      Cop(Cor, [lsl_int c (Cconst_int 1) dbg; Cconst_int 1], dbg)
 
-let untag_int = function
+let untag_int i dbg =
+  match i with
     Cconst_int n -> Cconst_int(n asr 1)
-  | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1]) -> c
-  | Cop(Cor, [Cop(Casr, [c; Cconst_int n]); Cconst_int 1])
+  | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1], _); Cconst_int 1], _) -> c
+  | Cop(Cor, [Cop(Casr, [c; Cconst_int n], _); Cconst_int 1], _)
     when n > 0 && n < size_int * 8 ->
-      Cop(Casr, [c; Cconst_int (n+1)])
-  | Cop(Cor, [Cop(Clsr, [c; Cconst_int n]); Cconst_int 1])
+      Cop(Casr, [c; Cconst_int (n+1)], dbg)
+  | Cop(Cor, [Cop(Clsr, [c; Cconst_int n], _); Cconst_int 1], _)
     when n > 0 && n < size_int * 8 ->
-      Cop(Clsr, [c; Cconst_int (n+1)])
-  | Cop(Cor, [c; Cconst_int 1]) -> Cop(Casr, [c; Cconst_int 1])
-  | c -> Cop(Casr, [c; Cconst_int 1])
+      Cop(Clsr, [c; Cconst_int (n+1)], dbg)
+  | Cop(Cor, [c; Cconst_int 1], _) -> Cop(Casr, [c; Cconst_int 1], dbg)
+  | c -> Cop(Casr, [c; Cconst_int 1], dbg)
 
 let if_then_else (cond, ifso, ifnot) =
   match cond with
@@ -323,8 +361,8 @@ let validate d m p =
 let raise_regular dbg exc =
   Csequence(
     Cop(Cstore (Thirtytwo_signed, Assignment),
-        [(Cconst_symbol "caml_backtrace_pos"); Cconst_int 0]),
-      Cop(Craise (Raise_withtrace, dbg),[exc]))
+        [(Cconst_symbol "caml_backtrace_pos"); Cconst_int 0], dbg),
+      Cop(Craise Raise_withtrace,[exc], dbg))
 
 let raise_symbol dbg symb =
   raise_regular dbg (Cconst_symbol symb)
@@ -335,8 +373,6 @@ let rec div_int c1 c2 is_safe dbg =
       Csequence(c1, raise_symbol dbg "caml_exn_Division_by_zero")
   | (c1, Cconst_int 1) ->
       c1
-  | (Cconst_int 0 as c1, c2) ->
-      Csequence(c2, c1)
   | (Cconst_int n1, Cconst_int n2) ->
       Cconst_int (n1 / n2)
   | (c1, Cconst_int n) when n <> min_int ->
@@ -349,12 +385,12 @@ let rec div_int c1 c2 is_safe dbg =
               res = shift-right-signed(c1 + t, l)
         *)
         Cop(Casr, [bind "dividend" c1 (fun c1 ->
-                     let t = asr_int c1 (Cconst_int (l - 1)) in
-                     let t = lsr_int t (Cconst_int (Nativeint.size - l)) in
-                     add_int c1 t);
-                   Cconst_int l])
+                     let t = asr_int c1 (Cconst_int (l - 1)) dbg in
+                     let t = lsr_int t (Cconst_int (Nativeint.size - l)) dbg in
+                     add_int c1 t dbg);
+                   Cconst_int l], dbg)
       else if n < 0 then
-        sub_int (Cconst_int 0) (div_int c1 (Cconst_int (-n)) is_safe dbg)
+        sub_int (Cconst_int 0) (div_int c1 (Cconst_int (-n)) is_safe dbg) dbg
       else begin
         let (m, p) = divimm_parameters (Nativeint.of_int n) in
         (* Algorithm:
@@ -364,18 +400,19 @@ let rec div_int c1 c2 is_safe dbg =
               res = t + sign-bit(c1)
         *)
         bind "dividend" c1 (fun c1 ->
-          let t = Cop(Cmulhi, [c1; Cconst_natint m]) in
-          let t = if m < 0n then Cop(Caddi, [t; c1]) else t in
-          let t = if p > 0 then Cop(Casr, [t; Cconst_int p]) else t in
-          add_int t (lsr_int c1 (Cconst_int (Nativeint.size - 1))))
+          let t = Cop(Cmulhi, [c1; Cconst_natint m], dbg) in
+          let t = if m < 0n then Cop(Caddi, [t; c1], dbg) else t in
+          let t = if p > 0 then Cop(Casr, [t; Cconst_int p], dbg) else t in
+          add_int t (lsr_int c1 (Cconst_int (Nativeint.size - 1)) dbg) dbg)
       end
   | (c1, c2) when !Clflags.fast || is_safe = Lambda.Unsafe ->
-      Cop(Cdivi, [c1; c2])
+      Cop(Cdivi, [c1; c2], dbg)
   | (c1, c2) ->
       bind "divisor" c2 (fun c2 ->
-        Cifthenelse(c2,
-                    Cop(Cdivi, [c1; c2]),
-                    raise_symbol dbg "caml_exn_Division_by_zero"))
+        bind "dividend" c1 (fun c1 ->
+          Cifthenelse(c2,
+                      Cop(Cdivi, [c1; c2], dbg),
+                      raise_symbol dbg "caml_exn_Division_by_zero")))
 
 let mod_int c1 c2 is_safe dbg =
   match (c1, c2) with
@@ -383,8 +420,6 @@ let mod_int c1 c2 is_safe dbg =
       Csequence(c1, raise_symbol dbg "caml_exn_Division_by_zero")
   | (c1, Cconst_int (1 | (-1))) ->
       Csequence(c1, Cconst_int 0)
-  | (Cconst_int 0, c2) ->
-      Csequence(c2, Cconst_int 0)
   | (Cconst_int n1, Cconst_int n2) ->
       Cconst_int (n1 mod n2)
   | (c1, (Cconst_int n as c2)) when n <> min_int ->
@@ -398,22 +433,23 @@ let mod_int c1 c2 is_safe dbg =
               res = c1 - t
          *)
         bind "dividend" c1 (fun c1 ->
-          let t = asr_int c1 (Cconst_int (l - 1)) in
-          let t = lsr_int t (Cconst_int (Nativeint.size - l)) in
-          let t = add_int c1 t in
-          let t = Cop(Cand, [t; Cconst_int (-n)]) in
-          sub_int c1 t)
+          let t = asr_int c1 (Cconst_int (l - 1)) dbg in
+          let t = lsr_int t (Cconst_int (Nativeint.size - l)) dbg in
+          let t = add_int c1 t dbg in
+          let t = Cop(Cand, [t; Cconst_int (-n)], dbg) in
+          sub_int c1 t dbg)
       else
         bind "dividend" c1 (fun c1 ->
-          sub_int c1 (mul_int (div_int c1 c2 is_safe dbg) c2))
+          sub_int c1 (mul_int (div_int c1 c2 is_safe dbg) c2 dbg) dbg)
   | (c1, c2) when !Clflags.fast || is_safe = Lambda.Unsafe ->
       (* Flambda already generates that test *)
-      Cop(Cmodi, [c1; c2])
+      Cop(Cmodi, [c1; c2], dbg)
   | (c1, c2) ->
       bind "divisor" c2 (fun c2 ->
-        Cifthenelse(c2,
-                    Cop(Cmodi, [c1; c2]),
-                    raise_symbol dbg "caml_exn_Division_by_zero"))
+        bind "dividend" c1 (fun c1 ->
+          Cifthenelse(c2,
+                      Cop(Cmodi, [c1; c2], dbg),
+                      raise_symbol dbg "caml_exn_Division_by_zero")))
 
 (* Division or modulo on boxed integers.  The overflow case min_int / -1
    can occur, in which case we force x / -1 = -x and x mod -1 = 0. (PR#5513). *)
@@ -430,49 +466,60 @@ let safe_divmod_bi mkop is_safe mkm1 c1 c2 bi dbg =
     if Arch.division_crashes_on_overflow
     && (size_int = 4 || bi <> Pint32)
     && not (is_different_from (-1) c2)
-    then Cifthenelse(Cop(Ccmpi Cne, [c2; Cconst_int(-1)]), c, mkm1 c1)
+    then Cifthenelse(Cop(Ccmpi Cne, [c2; Cconst_int(-1)], dbg), c, mkm1 c1 dbg)
     else c))
 
 let safe_div_bi is_safe =
-  safe_divmod_bi div_int is_safe (fun c1 -> Cop(Csubi, [Cconst_int 0; c1]))
+  safe_divmod_bi div_int is_safe
+    (fun c1 dbg -> Cop(Csubi, [Cconst_int 0; c1], dbg))
 
 let safe_mod_bi is_safe =
-  safe_divmod_bi mod_int is_safe (fun _ -> Cconst_int 0)
+  safe_divmod_bi mod_int is_safe (fun _ _ -> Cconst_int 0)
 
 (* Bool *)
 
-let test_bool = function
-    Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1]) -> c
+let test_bool dbg cmm =
+  match cmm with
+  | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1], _); Cconst_int 1], _) -> c
   | Cconst_int n ->
       if n = 1 then
         Cconst_int 0
       else
         Cconst_int 1
-  | c -> Cop(Ccmpi Cne, [c; Cconst_int 1])
+  | c -> Cop(Ccmpi Cne, [c; Cconst_int 1], dbg)
 
 (* Float *)
 
-let box_float dbg c = Cop(Calloc dbg, [alloc_float_header dbg; c])
+let box_float dbg c = Cop(Calloc, [alloc_float_header dbg; c], dbg)
 
-let rec unbox_float = function
-    Cop(Calloc _, [_header; c]) -> c
-  | Clet(id, exp, body) -> Clet(id, exp, unbox_float body)
+let map_ccatch f rec_flag handlers body =
+  let handlers = List.map
+      (fun (n, ids, handler) -> (n, ids, f handler))
+      handlers in
+  Ccatch(rec_flag, handlers, f body)
+
+let rec unbox_float dbg cmm =
+  match cmm with
+  | Cop(Calloc, [_header; c], _) -> c
+  | Clet(id, exp, body) -> Clet(id, exp, unbox_float dbg body)
   | Cifthenelse(cond, e1, e2) ->
-      Cifthenelse(cond, unbox_float e1, unbox_float e2)
-  | Csequence(e1, e2) -> Csequence(e1, unbox_float e2)
-  | Cswitch(e, tbl, el) -> Cswitch(e, tbl, Array.map unbox_float el)
-  | Ccatch(n, ids, e1, e2) -> Ccatch(n, ids, unbox_float e1, unbox_float e2)
-  | Ctrywith(e1, id, e2) -> Ctrywith(unbox_float e1, id, unbox_float e2)
-  | c -> Cop(Cload Double_u, [c])
+      Cifthenelse(cond, unbox_float dbg e1, unbox_float dbg e2)
+  | Csequence(e1, e2) -> Csequence(e1, unbox_float dbg e2)
+  | Cswitch(e, tbl, el, dbg) ->
+    Cswitch(e, tbl, Array.map (unbox_float dbg) el, dbg)
+  | Ccatch(rec_flag, handlers, body) ->
+    map_ccatch (unbox_float dbg) rec_flag handlers body
+  | Ctrywith(e1, id, e2) -> Ctrywith(unbox_float dbg e1, id, unbox_float dbg e2)
+  | c -> Cop(Cload (Double_u, Immutable), [c], dbg)
 
 (* Complex *)
 
 let box_complex dbg c_re c_im =
-  Cop(Calloc dbg, [alloc_floatarray_header 2 dbg; c_re; c_im])
+  Cop(Calloc, [alloc_floatarray_header 2 dbg; c_re; c_im], dbg)
 
-let complex_re c = Cop(Cload Double_u, [c])
-let complex_im c = Cop(Cload Double_u,
-                       [Cop(Cadda, [c; Cconst_int size_float])])
+let complex_re c dbg = Cop(Cload (Double_u, Immutable), [c], dbg)
+let complex_im c dbg = Cop(Cload (Double_u, Immutable),
+                        [Cop(Cadda, [c; Cconst_int size_float], dbg)], dbg)
 
 (* Unit *)
 
@@ -485,58 +532,72 @@ let rec remove_unit = function
       Csequence(c1, remove_unit c2)
   | Cifthenelse(cond, ifso, ifnot) ->
       Cifthenelse(cond, remove_unit ifso, remove_unit ifnot)
-  | Cswitch(sel, index, cases) ->
-      Cswitch(sel, index, Array.map remove_unit cases)
-  | Ccatch(io, ids, body, handler) ->
-      Ccatch(io, ids, remove_unit body, remove_unit handler)
+  | Cswitch(sel, index, cases, dbg) ->
+      Cswitch(sel, index, Array.map remove_unit cases, dbg)
+  | Ccatch(rec_flag, handlers, body) ->
+      map_ccatch remove_unit rec_flag handlers body
   | Ctrywith(body, exn, handler) ->
       Ctrywith(remove_unit body, exn, remove_unit handler)
   | Clet(id, c1, c2) ->
       Clet(id, c1, remove_unit c2)
-  | Cop(Capply (_mty, dbg), args) ->
-      Cop(Capply (typ_void, dbg), args)
-  | Cop(Cextcall(proc, _mty, alloc, dbg, label_after), args) ->
-      Cop(Cextcall(proc, typ_void, alloc, dbg, label_after), args)
+  | Cop(Capply _mty, args, dbg) ->
+      Cop(Capply typ_void, args, dbg)
+  | Cop(Cextcall(proc, _mty, alloc, label_after), args, dbg) ->
+      Cop(Cextcall(proc, typ_void, alloc, label_after), args, dbg)
   | Cexit (_,_) as c -> c
   | Ctuple [] as c -> c
   | c -> Csequence(c, Ctuple [])
 
 (* Access to block fields *)
 
-let field_address ptr n =
+let field_address ptr n dbg =
   if n = 0
   then ptr
-  else Cop(Cadda, [ptr; Cconst_int(n * size_addr)])
+  else Cop(Cadda, [ptr; Cconst_int(n * size_addr)], dbg)
+
+let get_field env ptr n dbg =
+  let mut =
+    match env.environment_param with
+    | None -> Mutable
+    | Some environment_param ->
+      match ptr with
+      | Cvar ptr ->
+        (* Loads from the current function's closure are immutable. *)
+        if Ident.same environment_param ptr then Immutable
+        else Mutable
+      | _ -> Mutable
+  in
+  Cop(Cload (Word_val, mut), [field_address ptr n dbg], dbg)
 
+let set_field ptr n newval init dbg =
+  Cop(Cstore (Word_val, init), [field_address ptr n dbg; newval], dbg)
 
-let get_field ptr n =
-  Cop(Cload Word_val, [field_address ptr n])
+let non_profinfo_mask = (1 lsl (64 - Config.profinfo_width)) - 1
 
-let set_field ptr n newval init =
-  Cop(Cstore (Word_val, init), [field_address ptr n; newval])
+let get_header ptr dbg =
+  (* We cannot deem this as [Immutable] due to the presence of [Obj.truncate]
+     and [Obj.set_tag]. *)
+  Cop(Cload (Word_int, Mutable),
+    [Cop(Cadda, [ptr; Cconst_int(-size_int)], dbg)], dbg)
 
-let header ptr =
-  if Config.spacetime then
-    let non_profinfo_mask = (1 lsl (64 - Config.profinfo_width)) - 1 in
-    Cop(Cand, [Cop (Cload Word_int,
-        [Cop(Cadda, [ptr; Cconst_int(-size_int)])]);
-      Cconst_int non_profinfo_mask;
-    ])
+let get_header_without_profinfo ptr dbg =
+  if Config.profinfo then
+    Cop(Cand, [get_header ptr dbg; Cconst_int non_profinfo_mask], dbg)
   else
-    Cop(Cload Word_int, [Cop(Cadda, [ptr; Cconst_int(-size_int)])])
+    get_header ptr dbg
 
 let tag_offset =
   if big_endian then -1 else -size_int
 
-let get_tag ptr =
+let get_tag ptr dbg =
   if Proc.word_addressed then           (* If byte loads are slow *)
-    Cop(Cand, [header ptr; Cconst_int 255])
+    Cop(Cand, [get_header ptr dbg; Cconst_int 255], dbg)
   else                                  (* If byte loads are efficient *)
-    Cop(Cload Byte_unsigned,
-        [Cop(Cadda, [ptr; Cconst_int(tag_offset)])])
+    Cop(Cload (Byte_unsigned, Mutable), (* Same comment as [get_header] above *)
+        [Cop(Cadda, [ptr; Cconst_int(tag_offset)], dbg)], dbg)
 
-let get_size ptr =
-  Cop(Clsr, [header ptr; Cconst_int 10])
+let get_size ptr dbg =
+  Cop(Clsr, [get_header_without_profinfo ptr dbg; Cconst_int 10], dbg)
 
 (* Array indexing *)
 
@@ -546,18 +607,20 @@ let log2_size_float = Misc.log2 size_float
 let wordsize_shift = 9
 let numfloat_shift = 9 + log2_size_float - log2_size_addr
 
-let is_addr_array_hdr hdr =
-  Cop(Ccmpi Cne, [Cop(Cand, [hdr; Cconst_int 255]); floatarray_tag])
+let is_addr_array_hdr hdr dbg =
+  Cop(Ccmpi Cne, [Cop(Cand, [hdr; Cconst_int 255], dbg); floatarray_tag], dbg)
 
-let is_addr_array_ptr ptr =
-  Cop(Ccmpi Cne, [get_tag ptr; floatarray_tag])
+let is_addr_array_ptr ptr dbg =
+  Cop(Ccmpi Cne, [get_tag ptr dbg; floatarray_tag], dbg)
 
-let addr_array_length hdr = Cop(Clsr, [hdr; Cconst_int wordsize_shift])
-let float_array_length hdr = Cop(Clsr, [hdr; Cconst_int numfloat_shift])
+let addr_array_length hdr dbg =
+  Cop(Clsr, [hdr; Cconst_int wordsize_shift], dbg)
+let float_array_length hdr dbg =
+  Cop(Clsr, [hdr; Cconst_int numfloat_shift], dbg)
 
-let lsl_const c n =
+let lsl_const c n dbg =
   if n = 0 then c
-  else Cop(Clsl, [c; Cconst_int n])
+  else Cop(Clsl, [c; Cconst_int n], dbg)
 
 (* Produces a pointer to the element of the array [ptr] on the position [ofs]
    with the given element [log2size] log2 element size. [ofs] is given as a
@@ -567,106 +630,121 @@ let lsl_const c n =
    into the heap.  If we know the pointer is outside the heap
    (this is the case for bigarray indexing), we give type Int instead. *)
 
-let array_indexing ?typ log2size ptr ofs =
+let array_indexing ?typ log2size ptr ofs dbg =
   let add =
     match typ with
     | None | Some Addr -> Cadda
     | Some Int -> Caddi
     | _ -> assert false in
   match ofs with
-    Cconst_int n ->
+  | Cconst_int n ->
       let i = n asr 1 in
-      if i = 0 then ptr else Cop(add, [ptr; Cconst_int(i lsl log2size)])
-  | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1]) ->
-      Cop(add, [ptr; lsl_const c log2size])
-  | Cop(Caddi, [c; Cconst_int n]) when log2size = 0 ->
-      Cop(add, [Cop(add, [ptr; untag_int c]); Cconst_int (n asr 1)])
-  | Cop(Caddi, [c; Cconst_int n]) ->
-      Cop(add, [Cop(add, [ptr; lsl_const c (log2size - 1)]);
-                   Cconst_int((n-1) lsl (log2size - 1))])
+      if i = 0 then ptr else Cop(add, [ptr; Cconst_int(i lsl log2size)], dbg)
+  | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1], _); Cconst_int 1], _) ->
+      Cop(add, [ptr; lsl_const c log2size dbg], dbg)
+  | Cop(Caddi, [c; Cconst_int n], _) when log2size = 0 ->
+      Cop(add, [Cop(add, [ptr; untag_int c dbg], dbg); Cconst_int (n asr 1)],
+        dbg)
+  | Cop(Caddi, [c; Cconst_int n], _) ->
+      Cop(add, [Cop(add, [ptr; lsl_const c (log2size - 1) dbg], dbg);
+                    Cconst_int((n-1) lsl (log2size - 1))], dbg)
   | _ when log2size = 0 ->
-      Cop(add, [ptr; untag_int ofs])
+      Cop(add, [ptr; untag_int ofs dbg], dbg)
   | _ ->
-      Cop(add, [Cop(add, [ptr; lsl_const ofs (log2size - 1)]);
-                   Cconst_int((-1) lsl (log2size - 1))])
-
-let addr_array_ref arr ofs =
-  Cop(Cload Word_val, [array_indexing log2_size_addr arr ofs])
-let int_array_ref arr ofs =
-  Cop(Cload Word_int, [array_indexing log2_size_addr arr ofs])
-let unboxed_float_array_ref arr ofs =
-  Cop(Cload Double_u, [array_indexing log2_size_float arr ofs])
+      Cop(add, [Cop(add, [ptr; lsl_const ofs (log2size - 1) dbg], dbg);
+                    Cconst_int((-1) lsl (log2size - 1))], dbg)
+
+let addr_array_ref arr ofs dbg =
+  Cop(Cload (Word_val, Mutable),
+    [array_indexing log2_size_addr arr ofs dbg], dbg)
+let int_array_ref arr ofs dbg =
+  Cop(Cload (Word_int, Mutable),
+    [array_indexing log2_size_addr arr ofs dbg], dbg)
+let unboxed_float_array_ref arr ofs dbg =
+  Cop(Cload (Double_u, Mutable),
+    [array_indexing log2_size_float arr ofs dbg], dbg)
 let float_array_ref dbg arr ofs =
-  box_float dbg (unboxed_float_array_ref arr ofs)
-
-let addr_array_set arr ofs newval =
-  Cop(Cextcall("caml_modify", typ_void, false, Debuginfo.none, None),
-      [array_indexing log2_size_addr arr ofs; newval])
-let int_array_set arr ofs newval =
+  box_float dbg (unboxed_float_array_ref arr ofs dbg)
+
+let addr_array_set arr ofs newval dbg =
+  Cop(Cextcall("caml_modify", typ_void, false, None),
+      [array_indexing log2_size_addr arr ofs dbg; newval], dbg)
+let addr_array_initialize arr ofs newval dbg =
+  Cop(Cextcall("caml_initialize", typ_void, false, None),
+      [array_indexing log2_size_addr arr ofs dbg; newval], dbg)
+let int_array_set arr ofs newval dbg =
   Cop(Cstore (Word_int, Assignment),
-    [array_indexing log2_size_addr arr ofs; newval])
-let float_array_set arr ofs newval =
+    [array_indexing log2_size_addr arr ofs dbg; newval], dbg)
+let float_array_set arr ofs newval dbg =
   Cop(Cstore (Double_u, Assignment),
-    [array_indexing log2_size_float arr ofs; newval])
+    [array_indexing log2_size_float arr ofs dbg; newval], dbg)
 
 (* String length *)
 
 (* Length of string block *)
 
-let string_length exp =
+let string_length exp dbg =
   bind "str" exp (fun str ->
     let tmp_var = Ident.create "tmp" in
     Clet(tmp_var,
          Cop(Csubi,
              [Cop(Clsl,
-                   [get_size str;
-                     Cconst_int log2_size_addr]);
-              Cconst_int 1]),
+                   [get_size str dbg;
+                     Cconst_int log2_size_addr],
+                   dbg);
+              Cconst_int 1],
+             dbg),
          Cop(Csubi,
              [Cvar tmp_var;
-               Cop(Cload Byte_unsigned,
-                     [Cop(Cadda, [str; Cvar tmp_var])])])))
+               Cop(Cload (Byte_unsigned, Mutable),
+                     [Cop(Cadda, [str; Cvar tmp_var], dbg)], dbg)], dbg)))
 
 (* Message sending *)
 
-let lookup_tag obj tag =
+let lookup_tag obj tag dbg =
   bind "tag" tag (fun tag ->
-    Cop(Cextcall("caml_get_public_method", typ_val, false, Debuginfo.none,
-          None),
-        [obj; tag]))
+    Cop(Cextcall("caml_get_public_method", typ_val, false, None),
+        [obj; tag],
+        dbg))
 
-let lookup_label obj lab =
+let lookup_label obj lab dbg =
   bind "lab" lab (fun lab ->
-    let table = Cop (Cload Word_val, [obj]) in
-    addr_array_ref table lab)
+    let table = Cop (Cload (Word_val, Mutable), [obj], dbg) in
+    addr_array_ref table lab dbg)
 
 let call_cached_method obj tag cache pos args dbg =
   let arity = List.length args in
-  let cache = array_indexing log2_size_addr cache pos in
+  let cache = array_indexing log2_size_addr cache pos dbg in
   Compilenv.need_send_fun arity;
-  Cop(Capply (typ_val, dbg),
+  Cop(Capply typ_val,
       Cconst_symbol("caml_send" ^ string_of_int arity) ::
-      obj :: tag :: cache :: args)
+        obj :: tag :: cache :: args,
+      dbg)
 
 (* Allocation *)
 
 let make_alloc_generic set_fn dbg tag wordsize args =
   if wordsize <= Config.max_young_wosize then
-    Cop(Calloc dbg, Cblockheader(block_header tag wordsize, dbg) :: args)
+    Cop(Calloc, Cblockheader(block_header tag wordsize, dbg) :: args, dbg)
   else begin
     let id = Ident.create "alloc" in
     let rec fill_fields idx = function
       [] -> Cvar id
-    | e1::el -> Csequence(set_fn (Cvar id) (Cconst_int idx) e1,
+    | e1::el -> Csequence(set_fn (Cvar id) (Cconst_int idx) e1 dbg,
                           fill_fields (idx + 2) el) in
     Clet(id,
-         Cop(Cextcall("caml_alloc", typ_val, true, Debuginfo.none, None),
-                 [Cconst_int wordsize; Cconst_int tag]),
+         Cop(Cextcall("caml_alloc", typ_val, true, None),
+                 [Cconst_int wordsize; Cconst_int tag], dbg),
          fill_fields 1 args)
   end
 
 let make_alloc dbg tag args =
-  make_alloc_generic addr_array_set dbg tag (List.length args) args
+  let addr_array_init arr ofs newval dbg =
+    Cop(Cextcall("caml_initialize", typ_void, false, None),
+        [array_indexing log2_size_addr arr ofs dbg; newval], dbg)
+  in
+  make_alloc_generic addr_array_init dbg tag (List.length args) args
+
 let make_float_alloc dbg tag args =
   make_alloc_generic float_array_set dbg tag
                      (List.length args * size_float / size_addr) args
@@ -674,10 +752,10 @@ let make_float_alloc dbg tag args =
 (* Bounds checking *)
 
 let make_checkbound dbg = function
-  | [Cop(Clsr, [a1; Cconst_int n]); Cconst_int m] when (m lsl n) > n ->
-      Cop(Ccheckbound dbg, [a1; Cconst_int(m lsl n + 1 lsl n - 1)])
+  | [Cop(Clsr, [a1; Cconst_int n], _); Cconst_int m] when (m lsl n) > n ->
+      Cop(Ccheckbound, [a1; Cconst_int(m lsl n + 1 lsl n - 1)], dbg)
   | args ->
-      Cop(Ccheckbound dbg, args)
+      Cop(Ccheckbound, args, dbg)
 
 (* To compile "let rec" over values *)
 
@@ -776,8 +854,17 @@ let transl_structured_constant cst =
 
 type is_global = Global | Not_global
 
-let constant_closures =
-  ref ([] : ((string * is_global) * ufunction list * uconstant list) list)
+type symbol_defn = string * is_global
+
+type cmm_constant =
+  | Const_closure of symbol_defn * ufunction list * uconstant list
+  | Const_table of symbol_defn * data_item list
+
+let cmm_constants =
+  ref ([] : cmm_constant list)
+
+let add_cmm_constant c =
+  cmm_constants := c :: !cmm_constants
 
 (* Boxed integers *)
 
@@ -808,56 +895,57 @@ let box_int dbg bi arg =
   | _ ->
       let arg' =
         if bi = Pint32 && size_int = 8 && big_endian
-        then Cop(Clsl, [arg; Cconst_int 32])
+        then Cop(Clsl, [arg; Cconst_int 32], dbg)
         else arg in
-      Cop(Calloc dbg, [alloc_header_boxed_int bi dbg;
+      Cop(Calloc, [alloc_header_boxed_int bi dbg;
                    Cconst_symbol(operations_boxed_int bi);
-                   arg'])
+                   arg'], dbg)
 
-let split_int64_for_32bit_target arg =
+let split_int64_for_32bit_target arg dbg =
   bind "split_int64" arg (fun arg ->
-    let first = Cop (Cadda, [Cconst_int size_int; arg]) in
-    let second = Cop (Cadda, [Cconst_int (2 * size_int); arg]) in
-    Ctuple [Cop (Cload Thirtytwo_unsigned, [first]);
-            Cop (Cload Thirtytwo_unsigned, [second])])
+    let first = Cop (Cadda, [Cconst_int size_int; arg], dbg) in
+    let second = Cop (Cadda, [Cconst_int (2 * size_int); arg], dbg) in
+    Ctuple [Cop (Cload (Thirtytwo_unsigned, Mutable), [first], dbg);
+            Cop (Cload (Thirtytwo_unsigned, Mutable), [second], dbg)])
 
-let rec unbox_int bi arg =
+let rec unbox_int bi arg dbg =
   match arg with
-    Cop(Calloc _, [_hdr; _ops; Cop(Clsl, [contents; Cconst_int 32])])
+    Cop(Calloc, [_hdr; _ops; Cop(Clsl, [contents; Cconst_int 32], dbg')], dbg)
     when bi = Pint32 && size_int = 8 && big_endian ->
       (* Force sign-extension of low 32 bits *)
-      Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32]); Cconst_int 32])
-  | Cop(Calloc _, [_hdr; _ops; contents])
+      Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32], dbg'); Cconst_int 32],
+        dbg)
+  | Cop(Calloc, [_hdr; _ops; contents], dbg)
     when bi = Pint32 && size_int = 8 && not big_endian ->
       (* Force sign-extension of low 32 bits *)
-      Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32]); Cconst_int 32])
-  | Cop(Calloc _, [_hdr; _ops; contents]) ->
+      Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32], dbg); Cconst_int 32], dbg)
+  | Cop(Calloc, [_hdr; _ops; contents], _dbg) ->
       contents
-  | Clet(id, exp, body) -> Clet(id, exp, unbox_int bi body)
+  | Clet(id, exp, body) -> Clet(id, exp, unbox_int bi body dbg)
   | Cifthenelse(cond, e1, e2) ->
-      Cifthenelse(cond, unbox_int bi e1, unbox_int bi e2)
-  | Csequence(e1, e2) -> Csequence(e1, unbox_int bi e2)
-  | Cswitch(e, tbl, el) -> Cswitch(e, tbl, Array.map (unbox_int bi) el)
-  | Ccatch(n, ids, e1, e2) -> Ccatch(n, ids, unbox_int bi e1, unbox_int bi e2)
-  | Ctrywith(e1, id, e2) -> Ctrywith(unbox_int bi e1, id, unbox_int bi e2)
+      Cifthenelse(cond, unbox_int bi e1 dbg, unbox_int bi e2 dbg)
+  | Csequence(e1, e2) -> Csequence(e1, unbox_int bi e2 dbg)
+  | Cswitch(e, tbl, el, dbg) ->
+      Cswitch(e, tbl, Array.map (fun e -> unbox_int bi e dbg) el, dbg)
+  | Ccatch(rec_flag, handlers, body) ->
+      map_ccatch (fun e -> unbox_int bi e dbg) rec_flag handlers body
+  | Ctrywith(e1, id, e2) ->
+      Ctrywith(unbox_int bi e1 dbg, id, unbox_int bi e2 dbg)
   | _ ->
       if size_int = 4 && bi = Pint64 then
-        split_int64_for_32bit_target arg
+        split_int64_for_32bit_target arg dbg
       else
-        Cop(Cload(if bi = Pint32 then Thirtytwo_signed else Word_int),
-            [Cop(Cadda, [arg; Cconst_int size_addr])])
+        Cop(
+          Cload((if bi = Pint32 then Thirtytwo_signed else Word_int), Mutable),
+          [Cop(Cadda, [arg; Cconst_int size_addr], dbg)], dbg)
 
-let make_unsigned_int bi arg =
+let make_unsigned_int bi arg dbg =
   if bi = Pint32 && size_int = 8
-  then Cop(Cand, [arg; Cconst_natint 0xFFFFFFFFn])
+  then Cop(Cand, [arg; Cconst_natint 0xFFFFFFFFn], dbg)
   else arg
 
 (* Boxed numbers *)
 
-type boxed_number =
-  | Boxed_float of Debuginfo.t
-  | Boxed_integer of boxed_integer * Debuginfo.t
-
 let equal_unboxed_integer ui1 ui2 =
   match ui1, ui2 with
   | Pnativeint, Pnativeint -> true
@@ -877,25 +965,6 @@ let box_number bn arg =
   | Boxed_float dbg -> box_float dbg arg
   | Boxed_integer (bi, dbg) -> box_int dbg bi arg
 
-type env = {
-  unboxed_ids : (Ident.t * boxed_number) Ident.tbl;
-}
-
-let empty_env =
-  {
-    unboxed_ids =Ident.empty;
-  }
-
-let is_unboxed_id id env =
-  try Some (Ident.find_same id env.unboxed_ids)
-  with Not_found -> None
-
-let add_unboxed_id id unboxed_id bn env =
-  {
-    unboxed_ids = Ident.add id (unboxed_id, bn) env.unboxed_ids;
-  }
-
-
 (* Big arrays *)
 
 let bigarray_elt_size = function
@@ -929,22 +998,28 @@ let bigarray_indexing unsafe elt_kind layout b args dbg =
       else
         bind "idx" arg (fun idx ->
           (* Load the untagged int bound for the given dimension *)
-          let bound = Cop(Cload Word_int,[field_address b dim_ofs]) in
-          let idxn = untag_int idx in
+          let bound =
+            Cop(Cload (Word_int, Mutable),[field_address b dim_ofs dbg], dbg)
+          in
+          let idxn = untag_int idx dbg in
           check_ba_bound bound idxn idx)
   | arg1 :: argl ->
       (* The remainder of the list is transformed into a one dimensional offset
          *)
       let rem = ba_indexing (dim_ofs + delta_ofs) delta_ofs argl in
       (* Load the untagged int bound for the given dimension *)
-      let bound = Cop(Cload Word_int, [field_address b dim_ofs]) in
-      if unsafe then add_int (mul_int (decr_int rem) bound) arg1
+      let bound =
+        Cop(Cload (Word_int, Mutable), [field_address b dim_ofs dbg], dbg)
+      in
+      if unsafe then add_int (mul_int (decr_int rem dbg) bound dbg) arg1 dbg
       else
         bind "idx" arg1 (fun idx ->
           bind "bound" bound (fun bound ->
-            let idxn = untag_int idx in
+            let idxn = untag_int idx dbg in
             (* [offset = rem * (tag_int bound) + idx] *)
-            let offset = add_int (mul_int (decr_int rem) bound) idx in
+            let offset =
+              add_int (mul_int (decr_int rem dbg) bound dbg) idx dbg
+            in
             check_ba_bound bound idxn offset)) in
   (* The offset as an expression evaluating to int *)
   let offset =
@@ -954,12 +1029,14 @@ let bigarray_indexing unsafe elt_kind layout b args dbg =
     | Pbigarray_c_layout ->
         ba_indexing (4 + List.length args) (-1) (List.rev args)
     | Pbigarray_fortran_layout ->
-        ba_indexing 5 1 (List.map (fun idx -> sub_int idx (Cconst_int 2)) args)
+        ba_indexing 5 1
+          (List.map (fun idx -> sub_int idx (Cconst_int 2) dbg) args)
   and elt_size =
     bigarray_elt_size elt_kind in
   (* [array_indexing] can simplify the given expressions *)
   array_indexing ~typ:Int (log2 elt_size)
-                 (Cop(Cload Word_int, [field_address b 1])) offset
+                 (Cop(Cload (Word_int, Mutable),
+                    [field_address b 1 dbg], dbg)) offset dbg
 
 let bigarray_word_kind = function
     Pbigarray_unknown -> assert false
@@ -985,11 +1062,13 @@ let bigarray_get unsafe elt_kind layout b args dbg =
         bind "addr" (bigarray_indexing unsafe elt_kind layout b args dbg)
           (fun addr ->
           box_complex dbg
-            (Cop(Cload kind, [addr]))
-            (Cop(Cload kind, [Cop(Cadda, [addr; Cconst_int sz])])))
+            (Cop(Cload (kind, Mutable), [addr], dbg))
+            (Cop(Cload (kind, Mutable),
+              [Cop(Cadda, [addr; Cconst_int sz], dbg)], dbg)))
     | _ ->
-        Cop(Cload (bigarray_word_kind elt_kind),
-            [bigarray_indexing unsafe elt_kind layout b args dbg]))
+        Cop(Cload (bigarray_word_kind elt_kind, Mutable),
+            [bigarray_indexing unsafe elt_kind layout b args dbg],
+            dbg))
 
 let bigarray_set unsafe elt_kind layout b args newval dbg =
   bind "ba" b (fun b ->
@@ -1001,135 +1080,166 @@ let bigarray_set unsafe elt_kind layout b args newval dbg =
         bind "addr" (bigarray_indexing unsafe elt_kind layout b args dbg)
           (fun addr ->
           Csequence(
-            Cop(Cstore (kind, Assignment), [addr; complex_re newv]),
+            Cop(Cstore (kind, Assignment), [addr; complex_re newv dbg], dbg),
             Cop(Cstore (kind, Assignment),
-                [Cop(Cadda, [addr; Cconst_int sz]); complex_im newv]))))
+                [Cop(Cadda, [addr; Cconst_int sz], dbg); complex_im newv dbg],
+                dbg))))
     | _ ->
         Cop(Cstore (bigarray_word_kind elt_kind, Assignment),
-            [bigarray_indexing unsafe elt_kind layout b args dbg; newval]))
+            [bigarray_indexing unsafe elt_kind layout b args dbg; newval],
+            dbg))
 
-let unaligned_load_16 ptr idx =
+let unaligned_load_16 ptr idx dbg =
   if Arch.allow_unaligned_access
-  then Cop(Cload Sixteen_unsigned, [add_int ptr idx])
+  then Cop(Cload (Sixteen_unsigned, Mutable), [add_int ptr idx dbg], dbg)
   else
-    let v1 = Cop(Cload Byte_unsigned, [add_int ptr idx]) in
-    let v2 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 1)]) in
+    let v1 = Cop(Cload (Byte_unsigned, Mutable), [add_int ptr idx dbg], dbg) in
+    let v2 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 1) dbg], dbg) in
     let b1, b2 = if Arch.big_endian then v1, v2 else v2, v1 in
-    Cop(Cor, [lsl_int b1 (Cconst_int 8); b2])
+    Cop(Cor, [lsl_int b1 (Cconst_int 8) dbg; b2], dbg)
 
-let unaligned_set_16 ptr idx newval =
+let unaligned_set_16 ptr idx newval dbg =
   if Arch.allow_unaligned_access
-  then Cop(Cstore (Sixteen_unsigned, Assignment), [add_int ptr idx; newval])
+  then
+    Cop(Cstore (Sixteen_unsigned, Assignment),
+      [add_int ptr idx dbg; newval], dbg)
   else
-    let v1 = Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8]); Cconst_int 0xFF]) in
-    let v2 = Cop(Cand, [newval; Cconst_int 0xFF]) in
+    let v1 =
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8], dbg); Cconst_int 0xFF], dbg)
+    in
+    let v2 = Cop(Cand, [newval; Cconst_int 0xFF], dbg) in
     let b1, b2 = if Arch.big_endian then v1, v2 else v2, v1 in
     Csequence(
-        Cop(Cstore (Byte_unsigned, Assignment), [add_int ptr idx; b1]),
+        Cop(Cstore (Byte_unsigned, Assignment), [add_int ptr idx dbg; b1], dbg),
         Cop(Cstore (Byte_unsigned, Assignment),
-            [add_int (add_int ptr idx) (Cconst_int 1); b2]))
+            [add_int (add_int ptr idx dbg) (Cconst_int 1) dbg; b2], dbg))
 
-let unaligned_load_32 ptr idx =
+let unaligned_load_32 ptr idx dbg =
   if Arch.allow_unaligned_access
-  then Cop(Cload Thirtytwo_unsigned, [add_int ptr idx])
+  then Cop(Cload (Thirtytwo_unsigned, Mutable), [add_int ptr idx dbg], dbg)
   else
-    let v1 = Cop(Cload Byte_unsigned, [add_int ptr idx]) in
-    let v2 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 1)]) in
-    let v3 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 2)]) in
-    let v4 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 3)]) in
+    let v1 = Cop(Cload (Byte_unsigned, Mutable), [add_int ptr idx dbg], dbg) in
+    let v2 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 1) dbg], dbg) in
+    let v3 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 2) dbg], dbg) in
+    let v4 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 3) dbg], dbg) in
     let b1, b2, b3, b4 =
       if Arch.big_endian
       then v1, v2, v3, v4
       else v4, v3, v2, v1 in
     Cop(Cor,
-        [Cop(Cor, [lsl_int b1 (Cconst_int 24); lsl_int b2 (Cconst_int 16)]);
-         Cop(Cor, [lsl_int b3 (Cconst_int 8); b4])])
+      [Cop(Cor, [lsl_int b1 (Cconst_int 24) dbg;
+         lsl_int b2 (Cconst_int 16) dbg], dbg);
+       Cop(Cor, [lsl_int b3 (Cconst_int 8) dbg; b4], dbg)],
+      dbg)
 
-let unaligned_set_32 ptr idx newval =
+let unaligned_set_32 ptr idx newval dbg =
   if Arch.allow_unaligned_access
-  then Cop(Cstore (Thirtytwo_unsigned, Assignment), [add_int ptr idx; newval])
+  then
+    Cop(Cstore (Thirtytwo_unsigned, Assignment), [add_int ptr idx dbg; newval],
+      dbg)
   else
     let v1 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int 24]); Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int 24], dbg); Cconst_int 0xFF], dbg)
+    in
     let v2 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int 16]); Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int 16], dbg); Cconst_int 0xFF], dbg)
+    in
     let v3 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8]); Cconst_int 0xFF]) in
-    let v4 = Cop(Cand, [newval; Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8], dbg); Cconst_int 0xFF], dbg)
+    in
+    let v4 = Cop(Cand, [newval; Cconst_int 0xFF], dbg) in
     let b1, b2, b3, b4 =
       if Arch.big_endian
       then v1, v2, v3, v4
       else v4, v3, v2, v1 in
     Csequence(
         Csequence(
-            Cop(Cstore (Byte_unsigned, Assignment), [add_int ptr idx; b1]),
             Cop(Cstore (Byte_unsigned, Assignment),
-                [add_int (add_int ptr idx) (Cconst_int 1); b2])),
+                [add_int ptr idx dbg; b1], dbg),
+            Cop(Cstore (Byte_unsigned, Assignment),
+                [add_int (add_int ptr idx dbg) (Cconst_int 1) dbg; b2], dbg)),
         Csequence(
             Cop(Cstore (Byte_unsigned, Assignment),
-                [add_int (add_int ptr idx) (Cconst_int 2); b3]),
+                [add_int (add_int ptr idx dbg) (Cconst_int 2) dbg; b3], dbg),
             Cop(Cstore (Byte_unsigned, Assignment),
-                [add_int (add_int ptr idx) (Cconst_int 3); b4])))
+                [add_int (add_int ptr idx dbg) (Cconst_int 3) dbg; b4], dbg)))
 
-let unaligned_load_64 ptr idx =
+let unaligned_load_64 ptr idx dbg =
   assert(size_int = 8);
   if Arch.allow_unaligned_access
-  then Cop(Cload Word_int, [add_int ptr idx])
+  then Cop(Cload (Word_int, Mutable), [add_int ptr idx dbg], dbg)
   else
-    let v1 = Cop(Cload Byte_unsigned, [add_int ptr idx]) in
-    let v2 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 1)]) in
-    let v3 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 2)]) in
-    let v4 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 3)]) in
-    let v5 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 4)]) in
-    let v6 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 5)]) in
-    let v7 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 6)]) in
-    let v8 = Cop(Cload Byte_unsigned,
-                 [add_int (add_int ptr idx) (Cconst_int 7)]) in
+    let v1 = Cop(Cload (Byte_unsigned, Mutable), [add_int ptr idx dbg], dbg) in
+    let v2 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 1) dbg], dbg) in
+    let v3 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 2) dbg], dbg) in
+    let v4 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 3) dbg], dbg) in
+    let v5 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 4) dbg], dbg) in
+    let v6 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 5) dbg], dbg) in
+    let v7 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 6) dbg], dbg) in
+    let v8 = Cop(Cload (Byte_unsigned, Mutable),
+                 [add_int (add_int ptr idx dbg) (Cconst_int 7) dbg], dbg) in
     let b1, b2, b3, b4, b5, b6, b7, b8 =
       if Arch.big_endian
       then v1, v2, v3, v4, v5, v6, v7, v8
       else v8, v7, v6, v5, v4, v3, v2, v1 in
     Cop(Cor,
         [Cop(Cor,
-             [Cop(Cor, [lsl_int b1 (Cconst_int (8*7));
-                        lsl_int b2 (Cconst_int (8*6))]);
-              Cop(Cor, [lsl_int b3 (Cconst_int (8*5));
-                        lsl_int b4 (Cconst_int (8*4))])]);
+             [Cop(Cor, [lsl_int b1 (Cconst_int (8*7)) dbg;
+                        lsl_int b2 (Cconst_int (8*6)) dbg], dbg);
+              Cop(Cor, [lsl_int b3 (Cconst_int (8*5)) dbg;
+                        lsl_int b4 (Cconst_int (8*4)) dbg], dbg)],
+             dbg);
          Cop(Cor,
-             [Cop(Cor, [lsl_int b5 (Cconst_int (8*3));
-                        lsl_int b6 (Cconst_int (8*2))]);
-              Cop(Cor, [lsl_int b7 (Cconst_int 8);
-                        b8])])])
+             [Cop(Cor, [lsl_int b5 (Cconst_int (8*3)) dbg;
+                        lsl_int b6 (Cconst_int (8*2)) dbg], dbg);
+              Cop(Cor, [lsl_int b7 (Cconst_int 8) dbg;
+                        b8], dbg)],
+             dbg)], dbg)
 
-let unaligned_set_64 ptr idx newval =
+let unaligned_set_64 ptr idx newval dbg =
   assert(size_int = 8);
   if Arch.allow_unaligned_access
-  then Cop(Cstore (Word_int, Assignment), [add_int ptr idx; newval])
+  then Cop(Cstore (Word_int, Assignment), [add_int ptr idx dbg; newval], dbg)
   else
     let v1 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*7)]); Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*7)], dbg); Cconst_int 0xFF],
+        dbg)
+    in
     let v2 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*6)]); Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*6)], dbg); Cconst_int 0xFF],
+        dbg)
+    in
     let v3 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*5)]); Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*5)], dbg); Cconst_int 0xFF],
+        dbg)
+    in
     let v4 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*4)]); Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*4)], dbg); Cconst_int 0xFF],
+        dbg)
+    in
     let v5 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*3)]); Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*3)], dbg); Cconst_int 0xFF],
+        dbg)
+    in
     let v6 =
-      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*2)]); Cconst_int 0xFF]) in
-    let v7 = Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8]); Cconst_int 0xFF]) in
-    let v8 = Cop(Cand, [newval; Cconst_int 0xFF]) in
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*2)], dbg); Cconst_int 0xFF],
+        dbg)
+    in
+    let v7 =
+      Cop(Cand, [Cop(Clsr, [newval; Cconst_int 8], dbg); Cconst_int 0xFF],
+        dbg)
+    in
+    let v8 = Cop(Cand, [newval; Cconst_int 0xFF], dbg) in
     let b1, b2, b3, b4, b5, b6, b7, b8 =
       if Arch.big_endian
       then v1, v2, v3, v4, v5, v6, v7, v8
@@ -1137,27 +1247,36 @@ let unaligned_set_64 ptr idx newval =
     Csequence(
         Csequence(
             Csequence(
-                Cop(Cstore (Byte_unsigned, Assignment), [add_int ptr idx; b1]),
                 Cop(Cstore (Byte_unsigned, Assignment),
-                    [add_int (add_int ptr idx) (Cconst_int 1); b2])),
+                    [add_int ptr idx dbg; b1],
+                    dbg),
+                Cop(Cstore (Byte_unsigned, Assignment),
+                    [add_int (add_int ptr idx dbg) (Cconst_int 1) dbg; b2],
+                    dbg)),
             Csequence(
                 Cop(Cstore (Byte_unsigned, Assignment),
-                    [add_int (add_int ptr idx) (Cconst_int 2); b3]),
+                    [add_int (add_int ptr idx dbg) (Cconst_int 2) dbg; b3],
+                    dbg),
                 Cop(Cstore (Byte_unsigned, Assignment),
-                    [add_int (add_int ptr idx) (Cconst_int 3); b4]))),
+                    [add_int (add_int ptr idx dbg) (Cconst_int 3) dbg; b4],
+                    dbg))),
         Csequence(
             Csequence(
                 Cop(Cstore (Byte_unsigned, Assignment),
-                    [add_int (add_int ptr idx) (Cconst_int 4); b5]),
+                    [add_int (add_int ptr idx dbg) (Cconst_int 4) dbg; b5],
+                    dbg),
                 Cop(Cstore (Byte_unsigned, Assignment),
-                    [add_int (add_int ptr idx) (Cconst_int 5); b6])),
+                    [add_int (add_int ptr idx dbg) (Cconst_int 5) dbg; b6],
+                    dbg)),
             Csequence(
                 Cop(Cstore (Byte_unsigned, Assignment),
-                    [add_int (add_int ptr idx) (Cconst_int 6); b7]),
+                    [add_int (add_int ptr idx dbg) (Cconst_int 6) dbg; b7],
+                    dbg),
                 Cop(Cstore (Byte_unsigned, Assignment),
-                    [add_int (add_int ptr idx) (Cconst_int 7); b8]))))
+                    [add_int (add_int ptr idx dbg) (Cconst_int 7) dbg; b8],
+                    dbg))))
 
-let max_or_zero a =
+let max_or_zero a dbg =
   bind "size" a (fun a ->
     (* equivalent to
        Cifthenelse(Cop(Ccmpi Cle, [a; Cconst_int 0]), Cconst_int 0, a)
@@ -1166,13 +1285,13 @@ let max_or_zero a =
                          so sign_negation&a = a
        if a is negative, sign is full of 1 hence sign_negation is 0
                          so sign_negation&a = 0 *)
-    let sign = Cop(Casr, [a; Cconst_int (size_int * 8 - 1)]) in
-    let sign_negation = Cop(Cxor, [sign; Cconst_int (-1)]) in
-    Cop(Cand, [sign_negation; a]))
+    let sign = Cop(Casr, [a; Cconst_int (size_int * 8 - 1)], dbg) in
+    let sign_negation = Cop(Cxor, [sign; Cconst_int (-1)], dbg) in
+    Cop(Cand, [sign_negation; a], dbg))
 
 let check_bound unsafe dbg a1 a2 k =
   if unsafe then k
-  else Csequence(make_checkbound dbg [max_or_zero a1;a2], k)
+  else Csequence(make_checkbound dbg [max_or_zero a1 dbg; a2], k)
 
 (* Simplification of some primitives into C calls *)
 
@@ -1234,10 +1353,37 @@ let simplif_primitive p =
 
 (* Build switchers both for constants and blocks *)
 
-let transl_isout h arg = tag_int (Cop(Ccmpa Clt, [h ; arg]))
+let transl_isout h arg dbg = tag_int (Cop(Ccmpa Clt, [h ; arg], dbg)) dbg
 
 (* Build an actual switch (ie jump table) *)
 
+let make_switch arg cases actions dbg =
+  let is_const = function
+    (* Constant integers loaded from a table should end in 1,
+       so that Cload never produces untagged integers *)
+    | Cconst_int n
+    | Cconst_pointer n -> (n land 1) = 1
+    | Cconst_natint n
+    | Cconst_natpointer n -> (Nativeint.(to_int (logand n one) = 1))
+    | Cconst_symbol _ -> true
+    | _ -> false in
+  if Array.for_all is_const actions then
+    let to_data_item = function
+      | Cconst_int n
+      | Cconst_pointer n -> Cint (Nativeint.of_int n)
+      | Cconst_natint n
+      | Cconst_natpointer n -> Cint n
+      | Cconst_symbol s -> Csymbol_address s
+      | _ -> assert false in
+    let const_actions = Array.map to_data_item actions in
+    let table = Compilenv.new_const_symbol () in
+    add_cmm_constant (Const_table ((table, Not_global),
+        Array.to_list (Array.map (fun act ->
+          const_actions.(act)) cases)));
+    addr_array_ref (Cconst_symbol table) (tag_int arg dbg) dbg
+  else
+    Cswitch (arg,cases,actions,dbg)
+
 module SArgBlocks =
 struct
   type primitive = operation
@@ -1252,12 +1398,14 @@ struct
   type act = expression
 
   let make_const i =  Cconst_int i
-  let make_prim p args = Cop (p,args)
-  let make_offset arg n = add_const arg n
-  let make_isout h arg =  Cop (Ccmpa Clt, [h ; arg])
-  let make_isin h arg =  Cop (Ccmpa Cge, [h ; arg])
+  (* CR mshinwell: fix debuginfo *)
+  let make_prim p args = Cop (p,args, Debuginfo.none)
+  let make_offset arg n = add_const arg n Debuginfo.none
+  let make_isout h arg = Cop (Ccmpa Clt, [h ; arg], Debuginfo.none)
+  let make_isin h arg = Cop (Ccmpa Cge, [h ; arg], Debuginfo.none)
   let make_if cond ifso ifnot = Cifthenelse (cond, ifso, ifnot)
-  let make_switch arg cases actions = Cswitch (arg,cases,actions)
+  let make_switch arg cases actions =
+    make_switch arg cases actions Debuginfo.none
   let bind arg body = bind "switcher" arg body
 
   let make_catch handler = match handler with
@@ -1274,7 +1422,7 @@ struct
       | Cexit (j,_) ->
           if i=j then handler
           else body
-      | _ ->  Ccatch (i,[],body,handler))
+      | _ ->  ccatch (i,[],body,handler))
 
   let make_exit i = Cexit (i,[])
 
@@ -1452,6 +1600,18 @@ let rec is_unboxed_number ~strict env e =
       join (is_unboxed_number ~strict env e1) e2
   | _ -> No_unboxing
 
+(* Helper for compilation of initialization and assignment operations *)
+
+type assignment_kind = Caml_modify | Caml_initialize | Simple
+
+let assignment_kind ptr init =
+  match init, ptr with
+  | Assignment, Pointer -> Caml_modify
+  | Heap_initialization, Pointer -> Caml_initialize
+  | Assignment, Immediate
+  | Heap_initialization, Immediate
+  | Root_initialization, (Immediate | Pointer) -> Simple
+
 (* Translate an expression *)
 
 let functions = (Queue.create() : ufunction Queue.t)
@@ -1460,7 +1620,7 @@ let strmatch_compile =
   let module S =
     Strmatch.Make
       (struct
-        let string_block_length = get_size
+        let string_block_length ptr = get_size ptr Debuginfo.none
         let transl_switch = transl_int_switch
       end) in
   S.compile
@@ -1476,8 +1636,8 @@ let rec transl env e =
       transl_constant sc
   | Uclosure(fundecls, []) ->
       let lbl = Compilenv.new_const_symbol() in
-      constant_closures :=
-        ((lbl, Not_global), fundecls, []) :: !constant_closures;
+      add_cmm_constant (
+        Const_closure ((lbl, Not_global), fundecls, []));
       List.iter (fun f -> Queue.add f functions) fundecls;
       Cconst_symbol lbl
   | Uclosure(fundecls, clos_vars) ->
@@ -1503,43 +1663,46 @@ let rec transl env e =
               int_const f.arity ::
               Cconst_symbol f.label ::
               transl_fundecls (pos + 4) rem in
-      Cop(Calloc Debuginfo.none, transl_fundecls 0 fundecls)
+      Cop(Calloc, transl_fundecls 0 fundecls, Debuginfo.none)
   | Uoffset(arg, offset) ->
       (* produces a valid Caml value, pointing just after an infix header *)
       let ptr = transl env arg in
       if offset = 0
       then ptr
-      else Cop(Caddv, [ptr; Cconst_int(offset * size_addr)])
+      else Cop(Caddv, [ptr; Cconst_int(offset * size_addr)], Debuginfo.none)
   | Udirect_apply(lbl, args, dbg) ->
-      Cop(Capply(typ_val, dbg), Cconst_symbol lbl :: List.map (transl env) args)
+      Cop(Capply typ_val, Cconst_symbol lbl :: List.map (transl env) args, dbg)
   | Ugeneric_apply(clos, [arg], dbg) ->
       bind "fun" (transl env clos) (fun clos ->
-        Cop(Capply(typ_val, dbg), [get_field clos 0; transl env arg; clos]))
+        Cop(Capply typ_val, [get_field env clos 0 dbg; transl env arg; clos],
+          dbg))
   | Ugeneric_apply(clos, args, dbg) ->
       let arity = List.length args in
       let cargs = Cconst_symbol(apply_function arity) ::
         List.map (transl env) (args @ [clos]) in
-      Cop(Capply(typ_val, dbg), cargs)
+      Cop(Capply typ_val, cargs, dbg)
   | Usend(kind, met, obj, args, dbg) ->
       let call_met obj args clos =
         if args = [] then
-          Cop(Capply(typ_val, dbg), [get_field clos 0;obj;clos])
+          Cop(Capply typ_val, [get_field env clos 0 dbg; obj; clos], dbg)
         else
           let arity = List.length args + 1 in
           let cargs = Cconst_symbol(apply_function arity) :: obj ::
             (List.map (transl env) args) @ [clos] in
-          Cop(Capply(typ_val, dbg), cargs)
+          Cop(Capply typ_val, cargs, dbg)
       in
       bind "obj" (transl env obj) (fun obj ->
         match kind, args with
           Self, _ ->
-            bind "met" (lookup_label obj (transl env met)) (call_met obj args)
+            bind "met" (lookup_label obj (transl env met) dbg)
+              (call_met obj args)
         | Cached, cache :: pos :: args ->
             call_cached_method obj
               (transl env met) (transl env cache) (transl env pos)
               (List.map (transl env) args) dbg
         | _ ->
-            bind "met" (lookup_tag obj (transl env met)) (call_met obj args))
+            bind "met" (lookup_tag obj (transl env met) dbg)
+              (call_met obj args))
   | Ulet(str, kind, id, exp, body) ->
       transl_let env str kind id exp body
   | Uletrec(bindings, body) ->
@@ -1587,8 +1750,8 @@ let rec transl env e =
           | Pbigarray_int32 -> box_int dbg Pint32 elt
           | Pbigarray_int64 -> box_int dbg Pint64 elt
           | Pbigarray_native_int -> box_int dbg Pnativeint elt
-          | Pbigarray_caml_int -> force_tag_int elt
-          | _ -> tag_int elt
+          | Pbigarray_caml_int -> force_tag_int elt dbg
+          | _ -> tag_int elt dbg
           end
       | (Pbigarrayset(unsafe, _num_dims, elt_kind, layout), arg1 :: argl) ->
           let (argidx, argnewval) = split_last argl in
@@ -1597,16 +1760,19 @@ let rec transl env e =
             (List.map (transl env) argidx)
             (match elt_kind with
               Pbigarray_float32 | Pbigarray_float64 ->
-                transl_unbox_float env argnewval
+                transl_unbox_float dbg env argnewval
             | Pbigarray_complex32 | Pbigarray_complex64 -> transl env argnewval
-            | Pbigarray_int32 -> transl_unbox_int env Pint32 argnewval
-            | Pbigarray_int64 -> transl_unbox_int env Pint64 argnewval
-            | Pbigarray_native_int -> transl_unbox_int env Pnativeint argnewval
-            | _ -> untag_int (transl env argnewval))
+            | Pbigarray_int32 -> transl_unbox_int dbg env Pint32 argnewval
+            | Pbigarray_int64 -> transl_unbox_int dbg env Pint64 argnewval
+            | Pbigarray_native_int ->
+                transl_unbox_int dbg env Pnativeint argnewval
+            | _ -> untag_int (transl env argnewval) dbg)
             dbg)
       | (Pbigarraydim(n), [b]) ->
           let dim_ofs = 4 + n in
-          tag_int (Cop(Cload Word_int, [field_address (transl env b) dim_ofs]))
+          tag_int (Cop(Cload (Word_int, Mutable),
+            [field_address (transl env b) dim_ofs dbg],
+            dbg)) dbg
       | (p, [arg]) ->
           transl_prim_1 env p arg dbg
       | (p, [arg1; arg2]) ->
@@ -1619,81 +1785,90 @@ let rec transl env e =
 
   (* Control structures *)
   | Uswitch(arg, s) ->
+      let dbg = Debuginfo.none in
       (* As in the bytecode interpreter, only matching against constants
          can be checked *)
       if Array.length s.us_index_blocks = 0 then
-        Cswitch
-          (untag_int (transl env arg),
-           s.us_index_consts,
-           Array.map (transl env) s.us_actions_consts)
+        make_switch
+          (untag_int (transl env arg) dbg)
+          s.us_index_consts
+          (Array.map (transl env) s.us_actions_consts)
+          dbg
       else if Array.length s.us_index_consts = 0 then
-        transl_switch env (get_tag (transl env arg))
+        transl_switch dbg env (get_tag (transl env arg) dbg)
           s.us_index_blocks s.us_actions_blocks
       else
         bind "switch" (transl env arg) (fun arg ->
           Cifthenelse(
-          Cop(Cand, [arg; Cconst_int 1]),
-          transl_switch env
-            (untag_int arg) s.us_index_consts s.us_actions_consts,
-          transl_switch env
-            (get_tag arg) s.us_index_blocks s.us_actions_blocks))
+          Cop(Cand, [arg; Cconst_int 1], dbg),
+          transl_switch dbg env
+            (untag_int arg dbg) s.us_index_consts s.us_actions_consts,
+          transl_switch dbg env
+            (get_tag arg dbg) s.us_index_blocks s.us_actions_blocks))
   | Ustringswitch(arg,sw,d) ->
+      let dbg = Debuginfo.none in
       bind "switch" (transl env arg)
         (fun arg ->
-          strmatch_compile arg (Misc.may_map (transl env) d)
+          strmatch_compile dbg arg (Misc.may_map (transl env) d)
             (List.map (fun (s,act) -> s,transl env act) sw))
   | Ustaticfail (nfail, args) ->
       Cexit (nfail, List.map (transl env) args)
   | Ucatch(nfail, [], body, handler) ->
       make_catch nfail (transl env body) (transl env handler)
   | Ucatch(nfail, ids, body, handler) ->
-      Ccatch(nfail, ids, transl env body, transl env handler)
+      ccatch(nfail, ids, transl env body, transl env handler)
   | Utrywith(body, exn, handler) ->
       Ctrywith(transl env body, exn, transl env handler)
   | Uifthenelse(Uprim(Pnot, [arg], _), ifso, ifnot) ->
       transl env (Uifthenelse(arg, ifnot, ifso))
   | Uifthenelse(cond, ifso, Ustaticfail (nfail, [])) ->
-      exit_if_false env cond (transl env ifso) nfail
+      let dbg = Debuginfo.none in
+      exit_if_false dbg env cond (transl env ifso) nfail
   | Uifthenelse(cond, Ustaticfail (nfail, []), ifnot) ->
-      exit_if_true env cond nfail (transl env ifnot)
-  | Uifthenelse(Uprim(Psequand, _, _) as cond, ifso, ifnot) ->
+      let dbg = Debuginfo.none in
+      exit_if_true dbg env cond nfail (transl env ifnot)
+  | Uifthenelse(Uprim(Psequand, _, dbg) as cond, ifso, ifnot) ->
       let raise_num = next_raise_count () in
       make_catch
         raise_num
-        (exit_if_false env cond (transl env ifso) raise_num)
+        (exit_if_false dbg env cond (transl env ifso) raise_num)
         (transl env ifnot)
-  | Uifthenelse(Uprim(Psequor, _, _) as cond, ifso, ifnot) ->
+  | Uifthenelse(Uprim(Psequor, _, dbg) as cond, ifso, ifnot) ->
       let raise_num = next_raise_count () in
       make_catch
         raise_num
-        (exit_if_true env cond raise_num (transl env ifnot))
+        (exit_if_true dbg env cond raise_num (transl env ifnot))
         (transl env ifso)
   | Uifthenelse (Uifthenelse (cond, condso, condnot), ifso, ifnot) ->
+      let dbg = Debuginfo.none in
       let num_true = next_raise_count () in
       make_catch
         num_true
         (make_catch2
            (fun shared_false ->
              if_then_else
-               (test_bool (transl env cond),
-                exit_if_true env condso num_true shared_false,
-                exit_if_true env condnot num_true shared_false))
+               (test_bool dbg (transl env cond),
+                exit_if_true dbg env condso num_true shared_false,
+                exit_if_true dbg env condnot num_true shared_false))
            (transl env ifnot))
         (transl env ifso)
   | Uifthenelse(cond, ifso, ifnot) ->
-      if_then_else(test_bool(transl env cond), transl env ifso,
+      let dbg = Debuginfo.none in
+      if_then_else(test_bool dbg (transl env cond), transl env ifso,
         transl env ifnot)
   | Usequence(exp1, exp2) ->
       Csequence(remove_unit(transl env exp1), transl env exp2)
   | Uwhile(cond, body) ->
+      let dbg = Debuginfo.none in
       let raise_num = next_raise_count () in
       return_unit
-        (Ccatch
+        (ccatch
            (raise_num, [],
-            Cloop(exit_if_false env cond
+            Cloop(exit_if_false dbg env cond
                     (remove_unit(transl env body)) raise_num),
             Ctuple []))
   | Ufor(id, low, high, dir, body) ->
+      let dbg = Debuginfo.none in
       let tst = match dir with Upto -> Cgt   | Downto -> Clt in
       let inc = match dir with Upto -> Caddi | Downto -> Csubi in
       let raise_num = next_raise_count () in
@@ -1702,49 +1877,55 @@ let rec transl env e =
         (Clet
            (id, transl env low,
             bind_nonvar "bound" (transl env high) (fun high ->
-              Ccatch
+              ccatch
                 (raise_num, [],
                  Cifthenelse
-                   (Cop(Ccmpi tst, [Cvar id; high]), Cexit (raise_num, []),
+                   (Cop(Ccmpi tst, [Cvar id; high], dbg),
+                    Cexit (raise_num, []),
                     Cloop
                       (Csequence
                          (remove_unit(transl env body),
                          Clet(id_prev, Cvar id,
                           Csequence
                             (Cassign(id,
-                               Cop(inc, [Cvar id; Cconst_int 2])),
+                               Cop(inc, [Cvar id; Cconst_int 2],
+                                 dbg)),
                              Cifthenelse
-                               (Cop(Ccmpi Ceq, [Cvar id_prev; high]),
+                               (Cop(Ccmpi Ceq, [Cvar id_prev; high],
+                                  dbg),
                                 Cexit (raise_num,[]), Ctuple [])))))),
                  Ctuple []))))
   | Uassign(id, exp) ->
+      let dbg = Debuginfo.none in
       begin match is_unboxed_id id env with
       | None ->
           return_unit (Cassign(id, transl env exp))
       | Some (unboxed_id, bn) ->
-          return_unit(Cassign(unboxed_id, transl_unbox_number env bn exp))
+          return_unit(Cassign(unboxed_id,
+            transl_unbox_number dbg env bn exp))
       end
   | Uunreachable ->
-      Cop(Cload Word_int, [Cconst_int 0])
+      let dbg = Debuginfo.none in
+      Cop(Cload (Word_int, Mutable), [Cconst_int 0], dbg)
 
 and transl_make_array dbg env kind args =
   match kind with
   | Pgenarray ->
-      Cop(Cextcall("caml_make_array", typ_val, true, Debuginfo.none, None),
-          [make_alloc dbg 0 (List.map (transl env) args)])
+      Cop(Cextcall("caml_make_array", typ_val, true, None),
+          [make_alloc dbg 0 (List.map (transl env) args)], dbg)
   | Paddrarray | Pintarray ->
       make_alloc dbg 0 (List.map (transl env) args)
   | Pfloatarray ->
       make_float_alloc dbg Obj.double_array_tag
-                      (List.map (transl_unbox_float env) args)
+                      (List.map (transl_unbox_float dbg env) args)
 
 and transl_ccall env prim args dbg =
   let transl_arg native_repr arg =
     match native_repr with
     | Same_as_ocaml_repr -> transl env arg
-    | Unboxed_float -> transl_unbox_float env arg
-    | Unboxed_integer bi -> transl_unbox_int env bi arg
-    | Untagged_int -> untag_int (transl env arg)
+    | Unboxed_float -> transl_unbox_float dbg env arg
+    | Unboxed_integer bi -> transl_unbox_int dbg env bi arg
+    | Untagged_int -> untag_int (transl env arg) dbg
   in
   let rec transl_args native_repr_args args =
     match native_repr_args, args with
@@ -1763,12 +1944,12 @@ and transl_ccall env prim args dbg =
     | Unboxed_integer Pint64 when size_int = 4 ->
         ([|Int; Int|], box_int dbg Pint64)
     | Unboxed_integer bi -> (typ_int, box_int dbg bi)
-    | Untagged_int -> (typ_int, tag_int)
+    | Untagged_int -> (typ_int, (fun i -> tag_int i dbg))
   in
   let args = transl_args prim.prim_native_repr_args args in
   wrap_result
     (Cop(Cextcall(Primitive.native_name prim,
-                  typ_res, prim.prim_alloc, dbg, None), args))
+                  typ_res, prim.prim_alloc, None), args, dbg))
 
 and transl_prim_1 env p arg dbg =
   match p with
@@ -1779,46 +1960,47 @@ and transl_prim_1 env p arg dbg =
       return_unit(remove_unit (transl env arg))
   (* Heap operations *)
   | Pfield n ->
-      get_field (transl env arg) n
+      get_field env (transl env arg) n dbg
   | Pfloatfield n ->
       let ptr = transl env arg in
       box_float dbg (
-        Cop(Cload Double_u,
+        Cop(Cload (Double_u, Mutable),
             [if n = 0 then ptr
-                       else Cop(Cadda, [ptr; Cconst_int(n * size_float)])]))
+                       else Cop(Cadda, [ptr; Cconst_int(n * size_float)], dbg)],
+            dbg))
   | Pint_as_pointer ->
-     Cop(Caddi, [transl env arg; Cconst_int (-1)])
+     Cop(Caddi, [transl env arg; Cconst_int (-1)], dbg)
      (* always a pointer outside the heap *)
   (* Exceptions *)
   | Praise _ when not (!Clflags.debug) ->
-      Cop(Craise (Cmm.Raise_notrace, dbg), [transl env arg])
+      Cop(Craise Cmm.Raise_notrace, [transl env arg], dbg)
   | Praise Lambda.Raise_notrace ->
-      Cop(Craise (Cmm.Raise_notrace, dbg), [transl env arg])
+      Cop(Craise Cmm.Raise_notrace, [transl env arg], dbg)
   | Praise Lambda.Raise_reraise ->
-      Cop(Craise (Cmm.Raise_withtrace, dbg), [transl env arg])
+      Cop(Craise Cmm.Raise_withtrace, [transl env arg], dbg)
   | Praise Lambda.Raise_regular ->
       raise_regular dbg (transl env arg)
   (* Integer operations *)
   | Pnegint ->
-      Cop(Csubi, [Cconst_int 2; transl env arg])
+      Cop(Csubi, [Cconst_int 2; transl env arg], dbg)
   | Pctconst c ->
-      let const_of_bool b = tag_int (Cconst_int (if b then 1 else 0)) in
+      let const_of_bool b = tag_int (Cconst_int (if b then 1 else 0)) dbg in
       begin
         match c with
         | Big_endian -> const_of_bool Arch.big_endian
-        | Word_size -> tag_int (Cconst_int (8*Arch.size_int))
-        | Int_size -> tag_int (Cconst_int ((8*Arch.size_int) - 1))
+        | Word_size -> tag_int (Cconst_int (8*Arch.size_int)) dbg
+        | Int_size -> tag_int (Cconst_int ((8*Arch.size_int) - 1)) dbg
         | Max_wosize ->
-            tag_int (Cconst_int ((1 lsl ((8*Arch.size_int) - 10)) - 1 ))
+            tag_int (Cconst_int ((1 lsl ((8*Arch.size_int) - 10)) - 1 )) dbg
         | Ostype_unix -> const_of_bool (Sys.os_type = "Unix")
         | Ostype_win32 -> const_of_bool (Sys.os_type = "Win32")
         | Ostype_cygwin -> const_of_bool (Sys.os_type = "Cygwin")
         | Backend_type ->
-            tag_int (Cconst_int 0) (* tag 0 is the same as Native here *)
+            tag_int (Cconst_int 0) dbg (* tag 0 is the same as Native here *)
       end
   | Poffsetint n ->
       if no_overflow_lsl n 1 then
-        add_const (transl env arg) (n lsl 1)
+        add_const (transl env arg) (n lsl 1) dbg
       else
         transl_prim_2 env Paddint arg (Uconst (Uconst_int n))
                       Debuginfo.none
@@ -1826,102 +2008,118 @@ and transl_prim_1 env p arg dbg =
       return_unit
         (bind "ref" (transl env arg) (fun arg ->
           Cop(Cstore (Word_int, Assignment),
-              [arg; add_const (Cop(Cload Word_int, [arg])) (n lsl 1)])))
+              [arg;
+               add_const (Cop(Cload (Word_int, Mutable), [arg], dbg))
+                 (n lsl 1) dbg],
+              dbg)))
   (* Floating-point operations *)
   | Pfloatofint ->
-      box_float dbg (Cop(Cfloatofint, [untag_int(transl env arg)]))
+      box_float dbg (Cop(Cfloatofint, [untag_int(transl env arg) dbg], dbg))
   | Pintoffloat ->
-     tag_int(Cop(Cintoffloat, [transl_unbox_float env arg]))
+     tag_int(Cop(Cintoffloat, [transl_unbox_float dbg env arg], dbg)) dbg
   | Pnegfloat ->
-      box_float dbg (Cop(Cnegf, [transl_unbox_float env arg]))
+      box_float dbg (Cop(Cnegf, [transl_unbox_float dbg env arg], dbg))
   | Pabsfloat ->
-      box_float dbg (Cop(Cabsf, [transl_unbox_float env arg]))
+      box_float dbg (Cop(Cabsf, [transl_unbox_float dbg env arg], dbg))
   (* String operations *)
   | Pstringlength | Pbyteslength ->
-      tag_int(string_length (transl env arg))
+      tag_int(string_length (transl env arg) dbg) dbg
   (* Array operations *)
   | Parraylength kind ->
+      let hdr = get_header_without_profinfo (transl env arg) dbg in
       begin match kind with
         Pgenarray ->
           let len =
             if wordsize_shift = numfloat_shift then
-              Cop(Clsr, [header(transl env arg); Cconst_int wordsize_shift])
+              Cop(Clsr, [hdr; Cconst_int wordsize_shift], dbg)
             else
-              bind "header" (header(transl env arg)) (fun hdr ->
-                Cifthenelse(is_addr_array_hdr hdr,
-                            Cop(Clsr, [hdr; Cconst_int wordsize_shift]),
-                            Cop(Clsr, [hdr; Cconst_int numfloat_shift]))) in
-          Cop(Cor, [len; Cconst_int 1])
+              bind "header" hdr (fun hdr ->
+                Cifthenelse(is_addr_array_hdr hdr dbg,
+                            Cop(Clsr, [hdr; Cconst_int wordsize_shift], dbg),
+                            Cop(Clsr, [hdr; Cconst_int numfloat_shift], dbg))) in
+          Cop(Cor, [len; Cconst_int 1], dbg)
       | Paddrarray | Pintarray ->
-          Cop(Cor, [addr_array_length(header(transl env arg)); Cconst_int 1])
+          Cop(Cor, [addr_array_length hdr dbg; Cconst_int 1], dbg)
       | Pfloatarray ->
-          Cop(Cor, [float_array_length(header(transl env arg)); Cconst_int 1])
+          Cop(Cor, [float_array_length hdr dbg; Cconst_int 1], dbg)
       end
   (* Boolean operations *)
   | Pnot ->
-      Cop(Csubi, [Cconst_int 4; transl env arg]) (* 1 -> 3, 3 -> 1 *)
+      Cop(Csubi, [Cconst_int 4; transl env arg], dbg) (* 1 -> 3, 3 -> 1 *)
   (* Test integer/block *)
   | Pisint ->
-      tag_int(Cop(Cand, [transl env arg; Cconst_int 1]))
+      tag_int(Cop(Cand, [transl env arg; Cconst_int 1], dbg)) dbg
   (* Boxed integers *)
   | Pbintofint bi ->
-      box_int dbg bi (untag_int (transl env arg))
+      box_int dbg bi (untag_int (transl env arg) dbg)
   | Pintofbint bi ->
-      force_tag_int (transl_unbox_int env bi arg)
+      force_tag_int (transl_unbox_int dbg env bi arg) dbg
   | Pcvtbint(bi1, bi2) ->
-      box_int dbg bi2 (transl_unbox_int env bi1 arg)
+      box_int dbg bi2 (transl_unbox_int dbg env bi1 arg)
   | Pnegbint bi ->
-      box_int dbg bi (Cop(Csubi, [Cconst_int 0; transl_unbox_int env bi arg]))
+      box_int dbg bi
+        (Cop(Csubi, [Cconst_int 0; transl_unbox_int dbg env bi arg], dbg))
   | Pbbswap bi ->
       let prim = match bi with
         | Pnativeint -> "nativeint"
         | Pint32 -> "int32"
         | Pint64 -> "int64" in
       box_int dbg bi (Cop(Cextcall(Printf.sprintf "caml_%s_direct_bswap" prim,
-                               typ_int, false, Debuginfo.none, None),
-                      [transl_unbox_int env bi arg]))
+                               typ_int, false, None),
+                      [transl_unbox_int dbg env bi arg],
+                      dbg))
   | Pbswap16 ->
-      tag_int (Cop(Cextcall("caml_bswap16_direct", typ_int, false,
-                            Debuginfo.none, None),
-                   [untag_int (transl env arg)]))
+      tag_int (Cop(Cextcall("caml_bswap16_direct", typ_int, false, None),
+                   [untag_int (transl env arg) dbg],
+                   dbg))
+              dbg
   | prim ->
       fatal_errorf "Cmmgen.transl_prim_1: %a" Printlambda.primitive prim
 
 and transl_prim_2 env p arg1 arg2 dbg =
   match p with
   (* Heap operations *)
-    Psetfield(n, ptr, init) ->
-      begin match init, ptr with
-      | Assignment, Pointer ->
-        return_unit(Cop(Cextcall("caml_modify", typ_void, false,Debuginfo.none,
-                          None),
-                        [field_address (transl env arg1) n; transl env arg2]))
-      | Assignment, Immediate
-      | Initialization, (Immediate | Pointer) ->
-        return_unit(set_field (transl env arg1) n (transl env arg2) init)
+  | Pfield_computed ->
+      addr_array_ref (transl env arg1) (transl env arg2) dbg
+  | Psetfield(n, ptr, init) ->
+      begin match assignment_kind ptr init with
+      | Caml_modify ->
+        return_unit(Cop(Cextcall("caml_modify", typ_void, false, None),
+                        [field_address (transl env arg1) n dbg;
+                         transl env arg2],
+                        dbg))
+      | Caml_initialize ->
+        return_unit(Cop(Cextcall("caml_initialize", typ_void, false, None),
+                        [field_address (transl env arg1) n dbg;
+                         transl env arg2],
+                        dbg))
+      | Simple ->
+        return_unit(set_field (transl env arg1) n (transl env arg2) init dbg)
       end
   | Psetfloatfield (n, init) ->
       let ptr = transl env arg1 in
       return_unit(
         Cop(Cstore (Double_u, init),
             [if n = 0 then ptr
-                       else Cop(Cadda, [ptr; Cconst_int(n * size_float)]);
-                   transl_unbox_float env arg2]))
+                       else Cop(Cadda, [ptr; Cconst_int(n * size_float)], dbg);
+                   transl_unbox_float dbg env arg2], dbg))
 
   (* Boolean operations *)
   | Psequand ->
-      if_then_else(test_bool(transl env arg1), transl env arg2, Cconst_int 1)
+      if_then_else(test_bool dbg (transl env arg1),
+        transl env arg2, Cconst_int 1)
       (* let id = Ident.create "res1" in
       Clet(id, transl env arg1,
-           Cifthenelse(test_bool(Cvar id), transl env arg2, Cvar id)) *)
+           Cifthenelse(test_bool dbg (Cvar id), transl env arg2, Cvar id)) *)
   | Psequor ->
-      if_then_else(test_bool(transl env arg1), Cconst_int 3, transl env arg2)
+      if_then_else(test_bool dbg (transl env arg1),
+        Cconst_int 3, transl env arg2)
 
   (* Integer operations *)
   | Paddint ->
-      decr_int(add_int (transl env arg1) (transl env arg2))
+      decr_int(add_int (transl env arg1) (transl env arg2) dbg) dbg
   | Psubint ->
-      incr_int(sub_int (transl env arg1) (transl env arg2))
+      incr_int(sub_int (transl env arg1) (transl env arg2) dbg) dbg
   | Pmulint ->
      begin
        (* decrementing the non-constant part helps when the multiplication is
@@ -1933,118 +2131,134 @@ and transl_prim_2 env p arg1 arg2 dbg =
         *)
        match transl env arg1, transl env arg2 with
          | Cconst_int _ as c1, c2 ->
-             incr_int (mul_int (untag_int c1) (decr_int c2))
-         | c1, c2 -> incr_int (mul_int (decr_int c1) (untag_int c2))
+             incr_int (mul_int (untag_int c1 dbg) (decr_int c2 dbg) dbg) dbg
+         | c1, c2 ->
+             incr_int (mul_int (decr_int c1 dbg) (untag_int c2 dbg) dbg) dbg
      end
   | Pdivint is_safe ->
-      tag_int(div_int (untag_int(transl env arg1))
-        (untag_int(transl env arg2)) is_safe dbg)
+      tag_int(div_int (untag_int(transl env arg1) dbg)
+        (untag_int(transl env arg2) dbg) is_safe dbg) dbg
   | Pmodint is_safe ->
-      tag_int(mod_int (untag_int(transl env arg1))
-        (untag_int(transl env arg2)) is_safe dbg)
+      tag_int(mod_int (untag_int(transl env arg1) dbg)
+        (untag_int(transl env arg2) dbg) is_safe dbg) dbg
   | Pandint ->
-      Cop(Cand, [transl env arg1; transl env arg2])
+      Cop(Cand, [transl env arg1; transl env arg2], dbg)
   | Porint ->
-      Cop(Cor, [transl env arg1; transl env arg2])
+      Cop(Cor, [transl env arg1; transl env arg2], dbg)
   | Pxorint ->
       Cop(Cor, [Cop(Cxor, [ignore_low_bit_int(transl env arg1);
-                           ignore_low_bit_int(transl env arg2)]);
-                Cconst_int 1])
+                           ignore_low_bit_int(transl env arg2)], dbg);
+                Cconst_int 1], dbg)
   | Plslint ->
-      incr_int(lsl_int (decr_int(transl env arg1)) (untag_int(transl env arg2)))
+      incr_int(lsl_int (decr_int(transl env arg1) dbg)
+        (untag_int(transl env arg2) dbg) dbg) dbg
   | Plsrint ->
-      Cop(Cor, [lsr_int (transl env arg1) (untag_int(transl env arg2));
-                Cconst_int 1])
+      Cop(Cor, [lsr_int (transl env arg1) (untag_int(transl env arg2) dbg) dbg;
+                Cconst_int 1], dbg)
   | Pasrint ->
-      Cop(Cor, [asr_int (transl env arg1) (untag_int(transl env arg2));
-                Cconst_int 1])
+      Cop(Cor, [asr_int (transl env arg1) (untag_int(transl env arg2) dbg) dbg;
+                Cconst_int 1], dbg)
   | Pintcomp cmp ->
       tag_int(Cop(Ccmpi(transl_comparison cmp),
-                  [transl env arg1; transl env arg2]))
+                  [transl env arg1; transl env arg2], dbg)) dbg
   | Pisout ->
-      transl_isout (transl env arg1) (transl env arg2)
+      transl_isout (transl env arg1) (transl env arg2) dbg
   (* Float operations *)
   | Paddfloat ->
       box_float dbg (Cop(Caddf,
-                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
+                    [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                    dbg))
   | Psubfloat ->
       box_float dbg (Cop(Csubf,
-                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
+                    [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                    dbg))
   | Pmulfloat ->
       box_float dbg (Cop(Cmulf,
-                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
+                    [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                    dbg))
   | Pdivfloat ->
       box_float dbg (Cop(Cdivf,
-                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
+                    [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                    dbg))
   | Pfloatcomp cmp ->
       tag_int(Cop(Ccmpf(transl_comparison cmp),
-                  [transl_unbox_float env arg1; transl_unbox_float env arg2]))
+                  [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                  dbg)) dbg
 
   (* String operations *)
   | Pstringrefu | Pbytesrefu ->
-      tag_int(Cop(Cload Byte_unsigned,
-                  [add_int (transl env arg1) (untag_int(transl env arg2))]))
+      tag_int(Cop(Cload (Byte_unsigned, Mutable),
+                  [add_int (transl env arg1) (untag_int(transl env arg2) dbg)
+                    dbg],
+                  dbg)) dbg
   | Pstringrefs | Pbytesrefs ->
       tag_int
         (bind "str" (transl env arg1) (fun str ->
-          bind "index" (untag_int (transl env arg2)) (fun idx ->
+          bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
             Csequence(
-              make_checkbound dbg [string_length str; idx],
-              Cop(Cload Byte_unsigned, [add_int str idx])))))
+              make_checkbound dbg [string_length str dbg; idx],
+              Cop(Cload (Byte_unsigned, Mutable),
+                [add_int str idx dbg], dbg))))) dbg
 
   | Pstring_load_16(unsafe) ->
      tag_int
        (bind "str" (transl env arg1) (fun str ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-          check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 1))
-                      idx (unaligned_load_16 str idx))))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+          check_bound unsafe dbg
+             (sub_int (string_length str dbg) (Cconst_int 1) dbg)
+             idx (unaligned_load_16 str idx dbg)))) dbg
 
   | Pbigstring_load_16(unsafe) ->
      tag_int
        (bind "ba" (transl env arg1) (fun ba ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "ba_data" (Cop(Cload Word_int, [field_address ba 1]))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "ba_data"
+         (Cop(Cload (Word_int, Mutable), [field_address ba 1 dbg], dbg))
          (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word_int,
-                                               [field_address ba 5]))
-                                          (Cconst_int 1)) idx
-                      (unaligned_load_16 ba_data idx)))))
+          check_bound unsafe dbg (sub_int (Cop(Cload (Word_int, Mutable),
+                                               [field_address ba 5 dbg], dbg))
+                                          (Cconst_int 1) dbg) idx
+                      (unaligned_load_16 ba_data idx dbg))))) dbg
 
   | Pstring_load_32(unsafe) ->
      box_int dbg Pint32
        (bind "str" (transl env arg1) (fun str ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-          check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 3))
-                      idx (unaligned_load_32 str idx))))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+          check_bound unsafe dbg
+            (sub_int (string_length str dbg) (Cconst_int 3) dbg)
+            idx (unaligned_load_32 str idx dbg))))
 
   | Pbigstring_load_32(unsafe) ->
      box_int dbg Pint32
        (bind "ba" (transl env arg1) (fun ba ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "ba_data" (Cop(Cload Word_int, [field_address ba 1]))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "ba_data"
+         (Cop(Cload (Word_int, Mutable), [field_address ba 1 dbg], dbg))
          (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word_int,
-                                               [field_address ba 5]))
-                                          (Cconst_int 3)) idx
-                      (unaligned_load_32 ba_data idx)))))
+          check_bound unsafe dbg (sub_int (Cop(Cload (Word_int, Mutable),
+                                               [field_address ba 5 dbg], dbg))
+                                          (Cconst_int 3) dbg) idx
+                      (unaligned_load_32 ba_data idx dbg)))))
 
   | Pstring_load_64(unsafe) ->
      box_int dbg Pint64
        (bind "str" (transl env arg1) (fun str ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-          check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 7))
-                      idx (unaligned_load_64 str idx))))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+          check_bound unsafe dbg
+            (sub_int (string_length str dbg) (Cconst_int 7) dbg)
+            idx (unaligned_load_64 str idx dbg))))
 
   | Pbigstring_load_64(unsafe) ->
      box_int dbg Pint64
        (bind "ba" (transl env arg1) (fun ba ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "ba_data" (Cop(Cload Word_int, [field_address ba 1]))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "ba_data"
+         (Cop(Cload (Word_int, Mutable), [field_address ba 1 dbg], dbg))
          (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word_int,
-                                               [field_address ba 5]))
-                                          (Cconst_int 7)) idx
-                      (unaligned_load_64 ba_data idx)))))
+          check_bound unsafe dbg (sub_int (Cop(Cload (Word_int, Mutable),
+                                               [field_address ba 5 dbg], dbg))
+                                          (Cconst_int 7) dbg) idx
+                      (unaligned_load_64 ba_data idx dbg)))))
 
   (* Array operations *)
   | Parrayrefu kind ->
@@ -2052,13 +2266,14 @@ and transl_prim_2 env p arg1 arg2 dbg =
         Pgenarray ->
           bind "arr" (transl env arg1) (fun arr ->
             bind "index" (transl env arg2) (fun idx ->
-              Cifthenelse(is_addr_array_ptr arr,
-                          addr_array_ref arr idx,
+              Cifthenelse(is_addr_array_ptr arr dbg,
+                          addr_array_ref arr idx dbg,
                           float_array_ref dbg arr idx)))
       | Paddrarray ->
-          addr_array_ref (transl env arg1) (transl env arg2)
+          addr_array_ref (transl env arg1) (transl env arg2) dbg
       | Pintarray ->
-          int_array_ref (transl env arg1) (transl env arg2)
+          (* CR mshinwell: for int/addr_array_ref move "dbg" to first arg *)
+          int_array_ref (transl env arg1) (transl env arg2) dbg
       | Pfloatarray ->
           float_array_ref dbg (transl env arg1) (transl env arg2)
       end
@@ -2067,116 +2282,140 @@ and transl_prim_2 env p arg1 arg2 dbg =
       | Pgenarray ->
           bind "index" (transl env arg2) (fun idx ->
           bind "arr" (transl env arg1) (fun arr ->
-          bind "header" (header arr) (fun hdr ->
+          bind "header" (get_header_without_profinfo arr dbg) (fun hdr ->
             if wordsize_shift = numfloat_shift then
-              Csequence(make_checkbound dbg [addr_array_length hdr; idx],
-                        Cifthenelse(is_addr_array_hdr hdr,
-                                    addr_array_ref arr idx,
+              Csequence(make_checkbound dbg [addr_array_length hdr dbg; idx],
+                        Cifthenelse(is_addr_array_hdr hdr dbg,
+                                    addr_array_ref arr idx dbg,
                                     float_array_ref dbg arr idx))
             else
-              Cifthenelse(is_addr_array_hdr hdr,
-                Csequence(make_checkbound dbg [addr_array_length hdr; idx],
-                          addr_array_ref arr idx),
-                Csequence(make_checkbound dbg [float_array_length hdr; idx],
+              Cifthenelse(is_addr_array_hdr hdr dbg,
+                Csequence(make_checkbound dbg [addr_array_length hdr dbg; idx],
+                          addr_array_ref arr idx dbg),
+                Csequence(make_checkbound dbg [float_array_length hdr dbg; idx],
                           float_array_ref dbg arr idx)))))
       | Paddrarray ->
           bind "index" (transl env arg2) (fun idx ->
           bind "arr" (transl env arg1) (fun arr ->
-            Csequence(make_checkbound dbg [addr_array_length(header arr); idx],
-                      addr_array_ref arr idx)))
+            Csequence(make_checkbound dbg [
+              addr_array_length(get_header_without_profinfo arr dbg) dbg; idx],
+                      addr_array_ref arr idx dbg)))
       | Pintarray ->
           bind "index" (transl env arg2) (fun idx ->
           bind "arr" (transl env arg1) (fun arr ->
-            Csequence(make_checkbound dbg [addr_array_length(header arr); idx],
-                      int_array_ref arr idx)))
+            Csequence(make_checkbound dbg [
+              addr_array_length(get_header_without_profinfo arr dbg) dbg; idx],
+                      int_array_ref arr idx dbg)))
       | Pfloatarray ->
           box_float dbg (
             bind "index" (transl env arg2) (fun idx ->
             bind "arr" (transl env arg1) (fun arr ->
               Csequence(make_checkbound dbg
-                                        [float_array_length(header arr); idx],
-                        unboxed_float_array_ref arr idx))))
+                [float_array_length(get_header_without_profinfo arr dbg) dbg;
+                  idx],
+                unboxed_float_array_ref arr idx dbg))))
       end
 
   (* Operations on bitvects *)
   | Pbittest ->
-      bind "index" (untag_int(transl env arg2)) (fun idx ->
+      bind "index" (untag_int(transl env arg2) dbg) (fun idx ->
         tag_int(
-          Cop(Cand, [Cop(Clsr, [Cop(Cload Byte_unsigned,
+          Cop(Cand, [Cop(Clsr, [Cop(Cload (Byte_unsigned, Mutable),
                                     [add_int (transl env arg1)
-                                      (Cop(Clsr, [idx; Cconst_int 3]))]);
-                                Cop(Cand, [idx; Cconst_int 7])]);
-                     Cconst_int 1])))
+                                      (Cop(Clsr, [idx; Cconst_int 3], dbg))
+                                      dbg],
+                                    dbg);
+                                Cop(Cand, [idx; Cconst_int 7], dbg)], dbg);
+                     Cconst_int 1], dbg)) dbg)
 
   (* Boxed integers *)
   | Paddbint bi ->
       box_int dbg bi (Cop(Caddi,
-                      [transl_unbox_int env bi arg1;
-                       transl_unbox_int env bi arg2]))
+                      [transl_unbox_int dbg env bi arg1;
+                       transl_unbox_int dbg env bi arg2], dbg))
   | Psubbint bi ->
       box_int dbg bi (Cop(Csubi,
-                      [transl_unbox_int env bi arg1;
-                       transl_unbox_int env bi arg2]))
+                      [transl_unbox_int dbg env bi arg1;
+                       transl_unbox_int dbg env bi arg2], dbg))
   | Pmulbint bi ->
       box_int dbg bi (Cop(Cmuli,
-                      [transl_unbox_int env bi arg1;
-                       transl_unbox_int env bi arg2]))
+                      [transl_unbox_int dbg env bi arg1;
+                       transl_unbox_int dbg env bi arg2], dbg))
   | Pdivbint { size = bi; is_safe } ->
       box_int dbg bi (safe_div_bi is_safe
-                      (transl_unbox_int env bi arg1)
-                      (transl_unbox_int env bi arg2)
+                      (transl_unbox_int dbg env bi arg1)
+                      (transl_unbox_int dbg env bi arg2)
                       bi dbg)
   | Pmodbint { size = bi; is_safe } ->
       box_int dbg bi (safe_mod_bi is_safe
-                      (transl_unbox_int env bi arg1)
-                      (transl_unbox_int env bi arg2)
+                      (transl_unbox_int dbg env bi arg1)
+                      (transl_unbox_int dbg env bi arg2)
                       bi dbg)
   | Pandbint bi ->
       box_int dbg bi (Cop(Cand,
-                     [transl_unbox_int env bi arg1;
-                      transl_unbox_int env bi arg2]))
+                     [transl_unbox_int dbg env bi arg1;
+                      transl_unbox_int dbg env bi arg2], dbg))
   | Porbint bi ->
       box_int dbg bi (Cop(Cor,
-                     [transl_unbox_int env bi arg1;
-                      transl_unbox_int env bi arg2]))
+                     [transl_unbox_int dbg env bi arg1;
+                      transl_unbox_int dbg env bi arg2], dbg))
   | Pxorbint bi ->
       box_int dbg bi (Cop(Cxor,
-                     [transl_unbox_int env bi arg1;
-                      transl_unbox_int env bi arg2]))
+                     [transl_unbox_int dbg env bi arg1;
+                      transl_unbox_int dbg env bi arg2], dbg))
   | Plslbint bi ->
       box_int dbg bi (Cop(Clsl,
-                     [transl_unbox_int env bi arg1;
-                      untag_int(transl env arg2)]))
+                     [transl_unbox_int dbg env bi arg1;
+                      untag_int(transl env arg2) dbg], dbg))
   | Plsrbint bi ->
       box_int dbg bi (Cop(Clsr,
-                     [make_unsigned_int bi (transl_unbox_int env bi arg1);
-                      untag_int(transl env arg2)]))
+                     [make_unsigned_int bi (transl_unbox_int dbg env bi arg1) dbg;
+                      untag_int(transl env arg2) dbg], dbg))
   | Pasrbint bi ->
       box_int dbg bi (Cop(Casr,
-                     [transl_unbox_int env bi arg1;
-                      untag_int(transl env arg2)]))
+                     [transl_unbox_int dbg env bi arg1;
+                      untag_int(transl env arg2) dbg], dbg))
   | Pbintcomp(bi, cmp) ->
       tag_int (Cop(Ccmpi(transl_comparison cmp),
-                     [transl_unbox_int env bi arg1;
-                      transl_unbox_int env bi arg2]))
+                     [transl_unbox_int dbg env bi arg1;
+                      transl_unbox_int dbg env bi arg2], dbg)) dbg
   | prim ->
       fatal_errorf "Cmmgen.transl_prim_2: %a" Printlambda.primitive prim
 
 and transl_prim_3 env p arg1 arg2 arg3 dbg =
   match p with
+  (* Heap operations *)
+  | Psetfield_computed(ptr, init) ->
+      begin match assignment_kind ptr init with
+      | Caml_modify ->
+        return_unit (
+          addr_array_set (transl env arg1) (transl env arg2) (transl env arg3)
+            dbg)
+      | Caml_initialize ->
+        return_unit (
+          addr_array_initialize (transl env arg1) (transl env arg2)
+            (transl env arg3) dbg)
+      | Simple ->
+        return_unit (
+          int_array_set (transl env arg1) (transl env arg2) (transl env arg3)
+            dbg)
+      end
   (* String operations *)
   | Pbytessetu ->
       return_unit(Cop(Cstore (Byte_unsigned, Assignment),
-                      [add_int (transl env arg1) (untag_int(transl env arg2));
-                        untag_int(transl env arg3)]))
+                      [add_int (transl env arg1)
+                          (untag_int(transl env arg2) dbg)
+                          dbg;
+                        untag_int(transl env arg3) dbg], dbg))
   | Pbytessets ->
       return_unit
         (bind "str" (transl env arg1) (fun str ->
-          bind "index" (untag_int (transl env arg2)) (fun idx ->
+          bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
             Csequence(
-              make_checkbound dbg [string_length str; idx],
+              make_checkbound dbg [string_length str dbg; idx],
               Cop(Cstore (Byte_unsigned, Assignment),
-                  [add_int str idx; untag_int(transl env arg3)])))))
+                  [add_int str idx dbg; untag_int(transl env arg3) dbg],
+                  dbg)))))
 
   (* Array operations *)
   | Parraysetu kind ->
@@ -2185,16 +2424,20 @@ and transl_prim_3 env p arg1 arg2 arg3 dbg =
           bind "newval" (transl env arg3) (fun newval ->
             bind "index" (transl env arg2) (fun index ->
               bind "arr" (transl env arg1) (fun arr ->
-                Cifthenelse(is_addr_array_ptr arr,
-                            addr_array_set arr index newval,
-                            float_array_set arr index (unbox_float newval)))))
+                Cifthenelse(is_addr_array_ptr arr dbg,
+                            addr_array_set arr index newval dbg,
+                            float_array_set arr index (unbox_float dbg newval)
+                              dbg))))
       | Paddrarray ->
           addr_array_set (transl env arg1) (transl env arg2) (transl env arg3)
+            dbg
       | Pintarray ->
           int_array_set (transl env arg1) (transl env arg2) (transl env arg3)
+            dbg
       | Pfloatarray ->
           float_array_set (transl env arg1) (transl env arg2)
-            (transl_unbox_float env arg3)
+            (transl_unbox_float dbg env arg3)
+            dbg
       end)
   | Parraysets kind ->
       return_unit(begin match kind with
@@ -2202,108 +2445,121 @@ and transl_prim_3 env p arg1 arg2 arg3 dbg =
           bind "newval" (transl env arg3) (fun newval ->
           bind "index" (transl env arg2) (fun idx ->
           bind "arr" (transl env arg1) (fun arr ->
-          bind "header" (header arr) (fun hdr ->
+          bind "header" (get_header_without_profinfo arr dbg) (fun hdr ->
             if wordsize_shift = numfloat_shift then
-              Csequence(make_checkbound dbg [addr_array_length hdr; idx],
-                        Cifthenelse(is_addr_array_hdr hdr,
-                                    addr_array_set arr idx newval,
+              Csequence(make_checkbound dbg [addr_array_length hdr dbg; idx],
+                        Cifthenelse(is_addr_array_hdr hdr dbg,
+                                    addr_array_set arr idx newval dbg,
                                     float_array_set arr idx
-                                                    (unbox_float newval)))
+                                                    (unbox_float dbg newval)
+                                                    dbg))
             else
-              Cifthenelse(is_addr_array_hdr hdr,
-                Csequence(make_checkbound dbg [addr_array_length hdr; idx],
-                          addr_array_set arr idx newval),
-                Csequence(make_checkbound dbg [float_array_length hdr; idx],
+              Cifthenelse(is_addr_array_hdr hdr dbg,
+                Csequence(make_checkbound dbg [addr_array_length hdr dbg; idx],
+                          addr_array_set arr idx newval dbg),
+                Csequence(make_checkbound dbg [float_array_length hdr dbg; idx],
                           float_array_set arr idx
-                                          (unbox_float newval)))))))
+                                          (unbox_float dbg newval) dbg))))))
       | Paddrarray ->
           bind "newval" (transl env arg3) (fun newval ->
           bind "index" (transl env arg2) (fun idx ->
           bind "arr" (transl env arg1) (fun arr ->
-            Csequence(make_checkbound dbg [addr_array_length(header arr); idx],
-                      addr_array_set arr idx newval))))
+            Csequence(make_checkbound dbg [
+              addr_array_length(get_header_without_profinfo arr dbg) dbg; idx],
+                      addr_array_set arr idx newval dbg))))
       | Pintarray ->
           bind "newval" (transl env arg3) (fun newval ->
           bind "index" (transl env arg2) (fun idx ->
           bind "arr" (transl env arg1) (fun arr ->
-            Csequence(make_checkbound dbg [addr_array_length(header arr); idx],
-                      int_array_set arr idx newval))))
+            Csequence(make_checkbound dbg [
+              addr_array_length(get_header_without_profinfo arr dbg) dbg; idx],
+                      int_array_set arr idx newval dbg))))
       | Pfloatarray ->
-          bind_load "newval" (transl_unbox_float env arg3) (fun newval ->
+          bind_load "newval" (transl_unbox_float dbg env arg3) (fun newval ->
           bind "index" (transl env arg2) (fun idx ->
           bind "arr" (transl env arg1) (fun arr ->
-            Csequence(make_checkbound dbg [float_array_length(header arr);idx],
-                      float_array_set arr idx newval))))
+            Csequence(make_checkbound dbg [
+              float_array_length (get_header_without_profinfo arr dbg) dbg;idx],
+                      float_array_set arr idx newval dbg))))
       end)
 
   | Pstring_set_16(unsafe) ->
      return_unit
        (bind "str" (transl env arg1) (fun str ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "newval" (untag_int (transl env arg3)) (fun newval ->
-          check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 1))
-                      idx (unaligned_set_16 str idx newval)))))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "newval" (untag_int (transl env arg3) dbg) (fun newval ->
+          check_bound unsafe dbg
+                      (sub_int (string_length str dbg) (Cconst_int 1) dbg)
+                      idx (unaligned_set_16 str idx newval dbg)))))
 
   | Pbigstring_set_16(unsafe) ->
      return_unit
        (bind "ba" (transl env arg1) (fun ba ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "newval" (untag_int (transl env arg3)) (fun newval ->
-        bind "ba_data" (Cop(Cload Word_int, [field_address ba 1]))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "newval" (untag_int (transl env arg3) dbg) (fun newval ->
+        bind "ba_data"
+             (Cop(Cload (Word_int, Mutable), [field_address ba 1 dbg], dbg))
              (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word_int,
-                                               [field_address ba 5]))
-                                          (Cconst_int 1))
-                      idx (unaligned_set_16 ba_data idx newval))))))
+          check_bound unsafe dbg (sub_int (Cop(Cload (Word_int, Mutable),
+                                               [field_address ba 5 dbg], dbg))
+                                          (Cconst_int 1)
+                                          dbg)
+                      idx (unaligned_set_16 ba_data idx newval dbg))))))
 
   | Pstring_set_32(unsafe) ->
      return_unit
        (bind "str" (transl env arg1) (fun str ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "newval" (transl_unbox_int env Pint32 arg3) (fun newval ->
-          check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 3))
-                      idx (unaligned_set_32 str idx newval)))))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "newval" (transl_unbox_int dbg env Pint32 arg3) (fun newval ->
+          check_bound unsafe dbg
+                      (sub_int (string_length str dbg) (Cconst_int 3) dbg)
+                      idx (unaligned_set_32 str idx newval dbg)))))
 
   | Pbigstring_set_32(unsafe) ->
      return_unit
        (bind "ba" (transl env arg1) (fun ba ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "newval" (transl_unbox_int env Pint32 arg3) (fun newval ->
-        bind "ba_data" (Cop(Cload Word_int, [field_address ba 1]))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "newval" (transl_unbox_int dbg env Pint32 arg3) (fun newval ->
+        bind "ba_data"
+             (Cop(Cload (Word_int, Mutable), [field_address ba 1 dbg], dbg))
              (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word_int,
-                                               [field_address ba 5]))
-                                          (Cconst_int 3))
-                      idx (unaligned_set_32 ba_data idx newval))))))
+          check_bound unsafe dbg (sub_int (Cop(Cload (Word_int, Mutable),
+                                               [field_address ba 5 dbg], dbg))
+                                          (Cconst_int 3)
+                                          dbg)
+                      idx (unaligned_set_32 ba_data idx newval dbg))))))
 
   | Pstring_set_64(unsafe) ->
      return_unit
        (bind "str" (transl env arg1) (fun str ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "newval" (transl_unbox_int env Pint64 arg3) (fun newval ->
-          check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 7))
-                      idx (unaligned_set_64 str idx newval)))))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "newval" (transl_unbox_int dbg env Pint64 arg3) (fun newval ->
+          check_bound unsafe dbg
+                      (sub_int (string_length str dbg) (Cconst_int 7) dbg)
+                      idx (unaligned_set_64 str idx newval dbg)))))
 
   | Pbigstring_set_64(unsafe) ->
      return_unit
        (bind "ba" (transl env arg1) (fun ba ->
-        bind "index" (untag_int (transl env arg2)) (fun idx ->
-        bind "newval" (transl_unbox_int env Pint64 arg3) (fun newval ->
-        bind "ba_data" (Cop(Cload Word_int, [field_address ba 1]))
+        bind "index" (untag_int (transl env arg2) dbg) (fun idx ->
+        bind "newval" (transl_unbox_int dbg env Pint64 arg3) (fun newval ->
+        bind "ba_data"
+             (Cop(Cload (Word_int, Mutable), [field_address ba 1 dbg], dbg))
              (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word_int,
-                                               [field_address ba 5]))
-                                          (Cconst_int 7)) idx
-                      (unaligned_set_64 ba_data idx newval))))))
+          check_bound unsafe dbg (sub_int (Cop(Cload (Word_int, Mutable),
+                                               [field_address ba 5 dbg], dbg))
+                                          (Cconst_int 7)
+                                          dbg) idx
+                      (unaligned_set_64 ba_data idx newval dbg))))))
 
   | prim ->
       fatal_errorf "Cmmgen.transl_prim_3: %a" Printlambda.primitive prim
 
-and transl_unbox_float env = function
+and transl_unbox_float dbg env = function
     Uconst(Uconst_ref(_, Some (Uconst_float f))) -> Cconst_float f
-  | exp -> unbox_float(transl env exp)
+  | exp -> unbox_float dbg (transl env exp)
 
-and transl_unbox_int env bi = function
+and transl_unbox_int dbg env bi = function
     Uconst(Uconst_ref(_, Some (Uconst_int32 n))) ->
       Cconst_natint (Nativeint.of_int32 n)
   | Uconst(Uconst_ref(_, Some (Uconst_nativeint n))) ->
@@ -2319,14 +2575,15 @@ and transl_unbox_int env bi = function
       end
   | Uprim(Pbintofint bi',[Uconst(Uconst_int i)],_) when bi = bi' ->
       Cconst_int i
-  | exp -> unbox_int bi (transl env exp)
+  | exp -> unbox_int bi (transl env exp) dbg
 
-and transl_unbox_number env bn arg =
+and transl_unbox_number dbg env bn arg =
   match bn with
-  | Boxed_float _ -> transl_unbox_float env arg
-  | Boxed_integer (bi, _) -> transl_unbox_int env bi arg
+  | Boxed_float _ -> transl_unbox_float dbg env arg
+  | Boxed_integer (bi, _) -> transl_unbox_int dbg env bi arg
 
 and transl_let env str kind id exp body =
+  let dbg = Debuginfo.none in
   let unboxing =
     (* If [id] is a mutable variable (introduced to eliminate a local
        reference) and it contains a type of unboxable numbers, then
@@ -2335,9 +2592,9 @@ and transl_let env str kind id exp body =
        used in loops and we really want to avoid repeated boxing. *)
     match str, kind with
     | Mutable, Pfloatval ->
-        Boxed (Boxed_float Debuginfo.none, false)
+        Boxed (Boxed_float dbg, false)
     | Mutable, Pboxedintval bi ->
-        Boxed (Boxed_integer (bi, Debuginfo.none), false)
+        Boxed (Boxed_integer (bi, dbg), false)
     | _, (Pfloatval | Pboxedintval _) ->
         (* It would be safe to always unbox in this case, but
            we do it only if this indeed allows us to get rid of
@@ -2354,20 +2611,18 @@ and transl_let env str kind id exp body =
         No_unboxing
   in
   match unboxing with
-  | No_unboxing | Boxed (_, true) ->
+  | No_unboxing | Boxed (_, true) | No_result ->
+      (* N.B. [body] must still be traversed even if [exp] will never return:
+         there may be constant closures inside that need lifting out. *)
       Clet(id, transl env exp, transl env body)
-  | No_result ->
-      (* the let-bound expression never returns a value, we can ignore
-         the body *)
-      transl env exp
   | Boxed (boxed_number, _false) ->
       let unboxed_id = Ident.create (Ident.name id) in
-      Clet(unboxed_id, transl_unbox_number env boxed_number exp,
+      Clet(unboxed_id, transl_unbox_number dbg env boxed_number exp,
            transl (add_unboxed_id id unboxed_id boxed_number env) body)
 
 and make_catch ncatch body handler = match body with
 | Cexit (nexit,[]) when nexit=ncatch -> handler
-| _ ->  Ccatch (ncatch, [], body, handler)
+| _ ->  ccatch (ncatch, [], body, handler)
 
 and make_catch2 mk_body handler = match handler with
 | Cexit (_,[])|Ctuple []|Cconst_int _|Cconst_pointer _ ->
@@ -2379,71 +2634,75 @@ and make_catch2 mk_body handler = match handler with
       (mk_body (Cexit (nfail,[])))
       handler
 
-and exit_if_true env cond nfail otherwise =
+and exit_if_true dbg env cond nfail otherwise =
   match cond with
   | Uconst (Uconst_ptr 0) -> otherwise
   | Uconst (Uconst_ptr 1) -> Cexit (nfail,[])
   | Uifthenelse (arg1, Uconst (Uconst_ptr 1), arg2)
   | Uprim(Psequor, [arg1; arg2], _) ->
-      exit_if_true env arg1 nfail (exit_if_true env arg2 nfail otherwise)
+      exit_if_true dbg env arg1 nfail
+        (exit_if_true dbg env arg2 nfail otherwise)
   | Uifthenelse (_, _, Uconst (Uconst_ptr 0))
   | Uprim(Psequand, _, _) ->
       begin match otherwise with
       | Cexit (raise_num,[]) ->
-          exit_if_false env cond (Cexit (nfail,[])) raise_num
+          exit_if_false dbg env cond (Cexit (nfail,[])) raise_num
       | _ ->
           let raise_num = next_raise_count () in
           make_catch
             raise_num
-            (exit_if_false env cond (Cexit (nfail,[])) raise_num)
+            (exit_if_false dbg env cond (Cexit (nfail,[])) raise_num)
             otherwise
       end
   | Uprim(Pnot, [arg], _) ->
-      exit_if_false env arg otherwise nfail
+      exit_if_false dbg env arg otherwise nfail
   | Uifthenelse (cond, ifso, ifnot) ->
       make_catch2
         (fun shared ->
           if_then_else
-            (test_bool (transl env cond),
-             exit_if_true env ifso nfail shared,
-             exit_if_true env ifnot nfail shared))
+            (test_bool dbg (transl env cond),
+             exit_if_true dbg env ifso nfail shared,
+             exit_if_true dbg env ifnot nfail shared))
         otherwise
   | _ ->
-      if_then_else(test_bool(transl env cond), Cexit (nfail, []), otherwise)
+      if_then_else(test_bool dbg (transl env cond),
+        Cexit (nfail, []), otherwise)
 
-and exit_if_false env cond otherwise nfail =
+and exit_if_false dbg env cond otherwise nfail =
   match cond with
   | Uconst (Uconst_ptr 0) -> Cexit (nfail,[])
   | Uconst (Uconst_ptr 1) -> otherwise
   | Uifthenelse (arg1, arg2, Uconst (Uconst_ptr 0))
   | Uprim(Psequand, [arg1; arg2], _) ->
-      exit_if_false env arg1 (exit_if_false env arg2 otherwise nfail) nfail
+      exit_if_false dbg env arg1
+        (exit_if_false dbg env arg2 otherwise nfail) nfail
   | Uifthenelse (_, Uconst (Uconst_ptr 1), _)
   | Uprim(Psequor, _, _) ->
       begin match otherwise with
       | Cexit (raise_num,[]) ->
-          exit_if_true env cond raise_num (Cexit (nfail,[]))
+          exit_if_true dbg env cond raise_num (Cexit (nfail,[]))
       | _ ->
           let raise_num = next_raise_count () in
           make_catch
             raise_num
-            (exit_if_true env cond raise_num (Cexit (nfail,[])))
+            (exit_if_true dbg env cond raise_num (Cexit (nfail,[])))
             otherwise
       end
   | Uprim(Pnot, [arg], _) ->
-      exit_if_true env arg nfail otherwise
+      exit_if_true dbg env arg nfail otherwise
   | Uifthenelse (cond, ifso, ifnot) ->
       make_catch2
         (fun shared ->
           if_then_else
-            (test_bool (transl env cond),
-             exit_if_false env ifso shared nfail,
-             exit_if_false env ifnot shared nfail))
+            (test_bool dbg (transl env cond),
+             exit_if_false dbg env ifso shared nfail,
+             exit_if_false dbg env ifnot shared nfail))
         otherwise
   | _ ->
-      if_then_else(test_bool(transl env cond), otherwise, Cexit (nfail, []))
+      if_then_else (test_bool dbg (transl env cond), otherwise,
+        Cexit (nfail, []))
 
-and transl_switch env arg index cases = match Array.length cases with
+and transl_switch _dbg env arg index cases = match Array.length cases with
 | 0 -> fatal_error "Cmmgen.transl_switch"
 | 1 -> transl env cases.(0)
 | _ ->
@@ -2481,16 +2740,21 @@ and transl_switch env arg index cases = match Array.length cases with
               (Array.of_list inters) store)
 
 and transl_letrec env bindings cont =
+  let dbg = Debuginfo.none in
   let bsz =
-    List.map (fun (id, exp) -> (id, exp, expr_size Ident.empty exp)) bindings in
+    List.map (fun (id, exp) -> (id, exp, expr_size Ident.empty exp))
+      bindings
+  in
   let op_alloc prim sz =
-    Cop(Cextcall(prim, typ_val, true, Debuginfo.none, None), [int_const sz]) in
+    Cop(Cextcall(prim, typ_val, true, None), [int_const sz], dbg) in
   let rec init_blocks = function
     | [] -> fill_nonrec bsz
     | (id, _exp, RHS_block sz) :: rem ->
-        Clet(id, op_alloc "caml_alloc_dummy" sz, init_blocks rem)
+        Clet(id, op_alloc "caml_alloc_dummy" sz,
+          init_blocks rem)
     | (id, _exp, RHS_floatblock sz) :: rem ->
-        Clet(id, op_alloc "caml_alloc_dummy_float" sz, init_blocks rem)
+        Clet(id, op_alloc "caml_alloc_dummy_float" sz,
+          init_blocks rem)
     | (id, _exp, RHS_nonrec) :: rem ->
         Clet (id, Cconst_int 0, init_blocks rem)
   and fill_nonrec = function
@@ -2503,9 +2767,8 @@ and transl_letrec env bindings cont =
     | [] -> cont
     | (id, exp, (RHS_block _ | RHS_floatblock _)) :: rem ->
         let op =
-          Cop(Cextcall("caml_update_dummy", typ_void, false, Debuginfo.none,
-                None),
-              [Cvar id; transl env exp]) in
+          Cop(Cextcall("caml_update_dummy", typ_void, false, None),
+              [Cvar id; transl env exp], dbg) in
         Csequence(op, fill_blocks rem)
     | (_id, _exp, RHS_nonrec) :: rem ->
         fill_blocks rem
@@ -2520,11 +2783,17 @@ let transl_function f =
     else
       f.body
   in
+  let cmm_body =
+    let env = create_env ~environment_param:f.env in
+    if !Clflags.afl_instrument then
+      Afl_instrument.instrument_function (transl env body)
+    else
+      transl env body in
   Cfunction {fun_name = f.label;
              fun_args = List.map (fun id -> (id, typ_val)) f.params;
-             fun_body = transl empty_env body;
+             fun_body = cmm_body;
              fun_fast = !Clflags.optimize_for_speed;
-             fun_dbg  = f.dbg; }
+             fun_dbg  = f.dbg}
 
 (* Translate all function definitions *)
 
@@ -2584,7 +2853,7 @@ let rec emit_structured_constant symb cst cont =
         (Misc.map_end (fun f -> Cdouble f) fields cont)
   | Uconst_closure(fundecls, lbl, fv) ->
       assert(lbl = fst symb);
-      constant_closures := (symb, fundecls, fv) :: !constant_closures;
+      add_cmm_constant (Const_closure (symb, fundecls, fv));
       List.iter (fun f -> Queue.add f functions) fundecls;
       cont
 
@@ -2671,6 +2940,12 @@ let emit_constant_closure ((_, global_symb) as symb) fundecls clos_vars cont =
         Csymbol_address f1.label ::
         emit_others 4 remainder
 
+(* Emit constant blocks *)
+
+let emit_constant_table symb elems =
+  cdefine_symbol symb @
+  elems
+
 (* Emit all structured constants *)
 
 let emit_constants cont (constants:Clambda.preallocated_constant list) =
@@ -2682,10 +2957,13 @@ let emit_constants cont (constants:Clambda.preallocated_constant list) =
          c:= Cdata(cst):: !c)
     constants;
   List.iter
-    (fun (symb, fundecls, clos_vars) ->
-        c := Cdata(emit_constant_closure symb fundecls clos_vars []) :: !c)
-    !constant_closures;
-  constant_closures := [];
+    (function
+    | Const_closure (symb, fundecls, clos_vars) ->
+        c := Cdata(emit_constant_closure symb fundecls clos_vars []) :: !c
+    | Const_table (symb, elems) ->
+        c := Cdata(emit_constant_table symb elems) :: !c)
+    !cmm_constants;
+  cmm_constants := [];
   !c
 
 let emit_all_constants cont =
@@ -2760,7 +3038,11 @@ let emit_preallocated_blocks preallocated_blocks cont =
 (* Translate a compilation unit *)
 
 let compunit (ulam, preallocated_blocks, constants) =
-  let init_code = transl empty_env ulam in
+  let init_code =
+    if !Clflags.afl_instrument then
+      Afl_instrument.instrument_initialiser (transl empty_env ulam)
+    else
+      transl empty_env ulam in
   let c1 = [Cfunction {fun_name = Compilenv.make_symbol (Some "entry");
                        fun_args = [];
                        fun_body = init_code; fun_fast = false;
@@ -2783,41 +3065,46 @@ CAMLprim value caml_cache_public_method (value meths, value tag, value *cache)
 }
 *)
 
-let cache_public_method meths tag cache =
+let cache_public_method meths tag cache dbg =
   let raise_num = next_raise_count () in
   let li = Ident.create "li" and hi = Ident.create "hi"
   and mi = Ident.create "mi" and tagged = Ident.create "tagged" in
   Clet (
   li, Cconst_int 3,
   Clet (
-  hi, Cop(Cload Word_int, [meths]),
+  hi, Cop(Cload (Word_int, Mutable), [meths], dbg),
   Csequence(
-  Ccatch
+  ccatch
     (raise_num, [],
      Cloop
        (Clet(
         mi,
         Cop(Cor,
-            [Cop(Clsr, [Cop(Caddi, [Cvar li; Cvar hi]); Cconst_int 1]);
-             Cconst_int 1]),
+            [Cop(Clsr, [Cop(Caddi, [Cvar li; Cvar hi], dbg); Cconst_int 1],
+               dbg);
+             Cconst_int 1],
+            dbg),
         Csequence(
         Cifthenelse
           (Cop (Ccmpi Clt,
                 [tag;
-                 Cop(Cload Word_int,
+                 Cop(Cload (Word_int, Mutable),
                      [Cop(Cadda,
-                          [meths; lsl_const (Cvar mi) log2_size_addr])])]),
-           Cassign(hi, Cop(Csubi, [Cvar mi; Cconst_int 2])),
+                          [meths; lsl_const (Cvar mi) log2_size_addr dbg],
+                          dbg)],
+                     dbg)], dbg),
+           Cassign(hi, Cop(Csubi, [Cvar mi; Cconst_int 2], dbg)),
            Cassign(li, Cvar mi)),
         Cifthenelse
-          (Cop(Ccmpi Cge, [Cvar li; Cvar hi]), Cexit (raise_num, []),
+          (Cop(Ccmpi Cge, [Cvar li; Cvar hi], dbg), Cexit (raise_num, []),
            Ctuple [])))),
      Ctuple []),
   Clet (
-  tagged, Cop(Cadda, [lsl_const (Cvar li) log2_size_addr;
-                      Cconst_int(1 - 3 * size_addr)]),
-  Csequence(Cop (Cstore (Word_int, Assignment), [cache; Cvar tagged]),
-            Cvar tagged)))))
+    tagged,
+      Cop(Cadda, [lsl_const (Cvar li) log2_size_addr dbg;
+        Cconst_int(1 - 3 * size_addr)], dbg),
+    Csequence(Cop (Cstore (Word_int, Assignment), [cache; Cvar tagged], dbg),
+              Cvar tagged)))))
 
 (* Generate an application function:
      (defun caml_applyN (a1 ... aN clos)
@@ -2831,18 +3118,20 @@ let cache_public_method meths tag cache =
 *)
 
 let apply_function_body arity =
+  let dbg = Debuginfo.none in
   let arg = Array.make arity (Ident.create "arg") in
   for i = 1 to arity - 1 do arg.(i) <- Ident.create "arg" done;
   let clos = Ident.create "clos" in
+  let env = empty_env in
   let rec app_fun clos n =
     if n = arity-1 then
-      Cop(Capply(typ_val, Debuginfo.none),
-          [get_field (Cvar clos) 0; Cvar arg.(n); Cvar clos])
+      Cop(Capply typ_val,
+          [get_field env (Cvar clos) 0 dbg; Cvar arg.(n); Cvar clos], dbg)
     else begin
       let newclos = Ident.create "clos" in
       Clet(newclos,
-           Cop(Capply(typ_val, Debuginfo.none),
-               [get_field (Cvar clos) 0; Cvar arg.(n); Cvar clos]),
+           Cop(Capply typ_val,
+               [get_field env (Cvar clos) 0 dbg; Cvar arg.(n); Cvar clos], dbg),
            app_fun newclos (n+1))
     end in
   let args = Array.to_list arg in
@@ -2850,44 +3139,51 @@ let apply_function_body arity =
   (args, clos,
    if arity = 1 then app_fun clos 0 else
    Cifthenelse(
-   Cop(Ccmpi Ceq, [get_field (Cvar clos) 1; int_const arity]),
-   Cop(Capply(typ_val, Debuginfo.none),
-       get_field (Cvar clos) 2 :: List.map (fun s -> Cvar s) all_args),
+   Cop(Ccmpi Ceq, [get_field env (Cvar clos) 1 dbg; int_const arity], dbg),
+   Cop(Capply typ_val,
+       get_field env (Cvar clos) 2 dbg :: List.map (fun s -> Cvar s) all_args,
+       dbg),
    app_fun clos 0))
 
 let send_function arity =
+  let dbg = Debuginfo.none in
   let (args, clos', body) = apply_function_body (1+arity) in
   let cache = Ident.create "cache"
   and obj = List.hd args
   and tag = Ident.create "tag" in
+  let env = empty_env in
   let clos =
     let cache = Cvar cache and obj = Cvar obj and tag = Cvar tag in
     let meths = Ident.create "meths" and cached = Ident.create "cached" in
     let real = Ident.create "real" in
-    let mask = get_field (Cvar meths) 1 in
+    let mask = get_field env (Cvar meths) 1 dbg in
     let cached_pos = Cvar cached in
-    let tag_pos = Cop(Cadda, [Cop (Cadda, [cached_pos; Cvar meths]);
-                              Cconst_int(3*size_addr-1)]) in
-    let tag' = Cop(Cload Word_int, [tag_pos]) in
+    let tag_pos = Cop(Cadda, [Cop (Cadda, [cached_pos; Cvar meths], dbg);
+                              Cconst_int(3*size_addr-1)], dbg) in
+    let tag' = Cop(Cload (Word_int, Mutable), [tag_pos], dbg) in
     Clet (
-    meths, Cop(Cload Word_val, [obj]),
+    meths, Cop(Cload (Word_val, Mutable), [obj], dbg),
     Clet (
-    cached, Cop(Cand, [Cop(Cload Word_int, [cache]); mask]),
+    cached,
+      Cop(Cand, [Cop(Cload (Word_int, Mutable), [cache], dbg); mask], dbg),
     Clet (
     real,
-    Cifthenelse(Cop(Ccmpa Cne, [tag'; tag]),
-                cache_public_method (Cvar meths) tag cache,
+    Cifthenelse(Cop(Ccmpa Cne, [tag'; tag], dbg),
+                cache_public_method (Cvar meths) tag cache dbg,
                 cached_pos),
-    Cop(Cload Word_val, [Cop(Cadda, [Cop (Cadda, [Cvar real; Cvar meths]);
-                                     Cconst_int(2*size_addr-1)])]))))
+    Cop(Cload (Word_val, Mutable),
+      [Cop(Cadda, [Cop (Cadda, [Cvar real; Cvar meths], dbg);
+       Cconst_int(2*size_addr-1)], dbg)], dbg))))
 
   in
   let body = Clet(clos', clos, body) in
+  let cache = cache in
   let fun_args =
     [obj, typ_val; tag, typ_int; cache, typ_val]
     @ List.map (fun id -> (id, typ_val)) (List.tl args) in
+  let fun_name = "caml_send" ^ string_of_int arity in
   Cfunction
-   {fun_name = "caml_send" ^ string_of_int arity;
+   {fun_name;
     fun_args = fun_args;
     fun_body = body;
     fun_fast = true;
@@ -2896,32 +3192,39 @@ let send_function arity =
 let apply_function arity =
   let (args, clos, body) = apply_function_body arity in
   let all_args = args @ [clos] in
+  let fun_name = "caml_apply" ^ string_of_int arity in
   Cfunction
-   {fun_name = "caml_apply" ^ string_of_int arity;
+   {fun_name;
     fun_args = List.map (fun id -> (id, typ_val)) all_args;
     fun_body = body;
     fun_fast = true;
-    fun_dbg  = Debuginfo.none }
+    fun_dbg  = Debuginfo.none;
+   }
 
 (* Generate tuplifying functions:
       (defun caml_tuplifyN (arg clos)
         (app clos.direct #0(arg) ... #N-1(arg) clos)) *)
 
 let tuplify_function arity =
+  let dbg = Debuginfo.none in
   let arg = Ident.create "arg" in
   let clos = Ident.create "clos" in
+  let env = empty_env in
   let rec access_components i =
     if i >= arity
     then []
-    else get_field (Cvar arg) i :: access_components(i+1) in
+    else get_field env (Cvar arg) i dbg :: access_components(i+1) in
+  let fun_name = "caml_tuplify" ^ string_of_int arity in
   Cfunction
-   {fun_name = "caml_tuplify" ^ string_of_int arity;
+   {fun_name;
     fun_args = [arg, typ_val; clos, typ_val];
     fun_body =
-      Cop(Capply(typ_val, Debuginfo.none),
-          get_field (Cvar clos) 2 :: access_components 0 @ [Cvar clos]);
+      Cop(Capply typ_val,
+          get_field env (Cvar clos) 2 dbg :: access_components 0 @ [Cvar clos],
+          dbg);
     fun_fast = true;
-    fun_dbg  = Debuginfo.none }
+    fun_dbg  = Debuginfo.none;
+   }
 
 (* Generate currying functions:
       (defun caml_curryN (arg clos)
@@ -2953,26 +3256,29 @@ let tuplify_function arity =
 
 let max_arity_optimized = 15
 let final_curry_function arity =
+  let dbg = Debuginfo.none in
   let last_arg = Ident.create "arg" in
   let last_clos = Ident.create "clos" in
+  let env = empty_env in
   let rec curry_fun args clos n =
     if n = 0 then
-      Cop(Capply(typ_val, Debuginfo.none),
-          get_field (Cvar clos) 2 ::
-          args @ [Cvar last_arg; Cvar clos])
+      Cop(Capply typ_val,
+          get_field env (Cvar clos) 2 dbg ::
+            args @ [Cvar last_arg; Cvar clos],
+          dbg)
     else
       if n = arity - 1 || arity > max_arity_optimized then
         begin
       let newclos = Ident.create "clos" in
       Clet(newclos,
-           get_field (Cvar clos) 3,
-           curry_fun (get_field (Cvar clos) 2 :: args) newclos (n-1))
+           get_field env (Cvar clos) 3 dbg,
+           curry_fun (get_field env (Cvar clos) 2 dbg :: args) newclos (n-1))
         end else
         begin
           let newclos = Ident.create "clos" in
           Clet(newclos,
-               get_field (Cvar clos) 4,
-               curry_fun (get_field (Cvar clos) 3 :: args) newclos (n-1))
+               get_field env (Cvar clos) 4 dbg,
+               curry_fun (get_field env (Cvar clos) 3 dbg :: args) newclos (n-1))
     end in
   Cfunction
    {fun_name = "caml_curry" ^ string_of_int arity ^
@@ -2983,6 +3289,8 @@ let final_curry_function arity =
     fun_dbg  = Debuginfo.none }
 
 let rec intermediate_curry_functions arity num =
+  let dbg = Debuginfo.none in
+  let env = empty_env in
   if num = arity - 1 then
     [final_curry_function arity]
   else begin
@@ -2994,17 +3302,19 @@ let rec intermediate_curry_functions arity num =
       fun_args = [arg, typ_val; clos, typ_val];
       fun_body =
          if arity - num > 2 && arity <= max_arity_optimized then
-           Cop(Calloc Debuginfo.none,
+           Cop(Calloc,
                [alloc_closure_header 5 Debuginfo.none;
                 Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1));
                 int_const (arity - num - 1);
                 Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1) ^ "_app");
-                Cvar arg; Cvar clos])
+                Cvar arg; Cvar clos],
+               dbg)
          else
-           Cop(Calloc Debuginfo.none,
-                     [alloc_closure_header 4 Debuginfo.none;
-                      Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1));
-                      int_const 1; Cvar arg; Cvar clos]);
+           Cop(Calloc,
+                [alloc_closure_header 4 Debuginfo.none;
+                 Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1));
+                 int_const 1; Cvar arg; Cvar clos],
+                dbg);
       fun_fast = true;
       fun_dbg  = Debuginfo.none }
     ::
@@ -3018,13 +3328,14 @@ let rec intermediate_curry_functions arity num =
           let direct_args = iter (num+2) in
           let rec iter i args clos =
             if i = 0 then
-              Cop(Capply(typ_val, Debuginfo.none),
-                  (get_field (Cvar clos) 2) :: args @ [Cvar clos])
+              Cop(Capply typ_val,
+                  (get_field env (Cvar clos) 2 dbg) :: args @ [Cvar clos],
+                  dbg)
             else
               let newclos = Ident.create "clos" in
               Clet(newclos,
-                   get_field (Cvar clos) 4,
-                   iter (i-1) (get_field (Cvar clos) 3 :: args) newclos)
+                   get_field env (Cvar clos) 4 dbg,
+                   iter (i-1) (get_field env (Cvar clos) 3 dbg :: args) newclos)
           in
           let cf =
             Cfunction
@@ -3075,17 +3386,21 @@ let generic_functions shared units =
 (* Generate the entry point *)
 
 let entry_point namelist =
+  (* CR mshinwell: review all of these "None"s.  We should be able to at
+     least have filenames for these. *)
+  let dbg = Debuginfo.none in
   let incr_global_inited =
     Cop(Cstore (Word_int, Assignment),
         [Cconst_symbol "caml_globals_inited";
-         Cop(Caddi, [Cop(Cload Word_int, [Cconst_symbol "caml_globals_inited"]);
-                     Cconst_int 1])]) in
+         Cop(Caddi, [Cop(Cload (Word_int, Mutable),
+                       [Cconst_symbol "caml_globals_inited"], dbg);
+                     Cconst_int 1], dbg)], dbg) in
   let body =
     List.fold_right
       (fun name next ->
         let entry_sym = Compilenv.make_symbol ~unitname:name (Some "entry") in
-        Csequence(Cop(Capply(typ_void, Debuginfo.none),
-                         [Cconst_symbol entry_sym]),
+        Csequence(Cop(Capply typ_void,
+                         [Cconst_symbol entry_sym], dbg),
                   Csequence(incr_global_inited, next)))
       namelist (Cconst_int 1) in
   Cfunction {fun_name = "caml_program";
diff --git a/asmcomp/comballoc.ml b/asmcomp/comballoc.ml
index e33acd06..b4e1b1ef 100644
--- a/asmcomp/comballoc.ml
+++ b/asmcomp/comballoc.ml
@@ -77,11 +77,13 @@ let rec combine i allocstate =
       let newbody = combine_restart body in
       (instr_cons (Iloop(newbody)) i.arg i.res i.next,
        allocated_size allocstate)
-  | Icatch(io, body, handler) ->
+  | Icatch(rec_flag, handlers, body) ->
       let (newbody, sz) = combine body allocstate in
-      let newhandler = combine_restart handler in
+      let newhandlers =
+        List.map (fun (io, handler) -> io, combine_restart handler) handlers in
       let newnext = combine_restart i.next in
-      (instr_cons (Icatch(io, newbody, newhandler)) i.arg i.res newnext, sz)
+      (instr_cons (Icatch(rec_flag, newhandlers, newbody))
+         i.arg i.res newnext, sz)
   | Itrywith(body, handler) ->
       let (newbody, sz) = combine body allocstate in
       let newhandler = combine_restart handler in
diff --git a/asmcomp/compilenv.ml b/asmcomp/compilenv.ml
index 9847cb93..a50c57f4 100644
--- a/asmcomp/compilenv.ml
+++ b/asmcomp/compilenv.ml
@@ -39,7 +39,7 @@ let export_infos_table =
 
 let imported_sets_of_closures_table =
   (Set_of_closures_id.Tbl.create 10
-   : Flambda.function_declarations Set_of_closures_id.Tbl.t)
+   : Flambda.function_declarations option Set_of_closures_id.Tbl.t)
 
 let sourcefile = ref None
 
@@ -129,7 +129,7 @@ let reset ?packname ~source_provenance:file name =
   current_unit.ui_curry_fun <- [];
   current_unit.ui_apply_fun <- [];
   current_unit.ui_send_fun <- [];
-  current_unit.ui_force_link <- false;
+  current_unit.ui_force_link <- !Clflags.link_everything;
   Hashtbl.clear exported_constants;
   structured_constants := structured_constants_empty;
   current_unit.ui_export_info <- default_ui_export_info;
diff --git a/asmcomp/compilenv.mli b/asmcomp/compilenv.mli
index 32813bdb..fa3cfc34 100644
--- a/asmcomp/compilenv.mli
+++ b/asmcomp/compilenv.mli
@@ -26,7 +26,7 @@ open Cmx_format
    improvement feature.
 *)
 val imported_sets_of_closures_table
-  : Flambda.function_declarations Set_of_closures_id.Tbl.t
+  : Flambda.function_declarations option Set_of_closures_id.Tbl.t
         (* flambda-only *)
 
 val reset: ?packname:string -> source_provenance:Timings.source_provenance ->
diff --git a/asmcomp/deadcode.ml b/asmcomp/deadcode.ml
index 42981ded..c713b64b 100644
--- a/asmcomp/deadcode.ml
+++ b/asmcomp/deadcode.ml
@@ -58,12 +58,17 @@ let rec deadcode i =
       let (body', _) = deadcode body in
       let (s, _) = deadcode i.next in
       ({i with desc = Iloop body'; next = s}, i.live)
-  | Icatch(nfail, body, handler) ->
+  | Icatch(rec_flag, handlers, body) ->
       let (body', _) = deadcode body in
-      let (handler', _) = deadcode handler in
+      let handlers' =
+        List.map (fun (nfail, handler) ->
+            let (handler', _) = deadcode handler in
+            nfail, handler')
+          handlers
+      in
       let (s, _) = deadcode i.next in
-      ({i with desc = Icatch(nfail, body', handler'); next = s}, i.live)
-  | Iexit _ ->
+      ({i with desc = Icatch(rec_flag, handlers', body'); next = s}, i.live)
+  | Iexit _nfail ->
       (i, i.live)
   | Itrywith(body, handler) ->
       let (body', _) = deadcode body in
diff --git a/asmcomp/emitaux.ml b/asmcomp/emitaux.ml
index 1149814a..22173f4d 100644
--- a/asmcomp/emitaux.ml
+++ b/asmcomp/emitaux.ml
@@ -114,6 +114,14 @@ type frame_descr =
 
 let frame_descriptors = ref([] : frame_descr list)
 
+let record_frame_descr ~label ~frame_size ~live_offset ~raise_frame debuginfo =
+  frame_descriptors :=
+    { fd_lbl = label;
+      fd_frame_size = frame_size;
+      fd_live_offset = List.sort_uniq (-) live_offset;
+      fd_raise = raise_frame;
+      fd_debuginfo = debuginfo } :: !frame_descriptors
+
 type emit_frame_actions =
   { efa_code_label: int -> unit;
     efa_data_label: int -> unit;
@@ -135,10 +143,21 @@ let emit_frames a =
       Hashtbl.add filenames name lbl;
       lbl
   in
-  let debuginfos = Hashtbl.create 7 in
+  let module Label_table =
+    Hashtbl.Make (struct
+      type t = bool * Debuginfo.t
+
+      let equal ((rs1 : bool), dbg1) (rs2, dbg2) =
+        rs1 = rs2 && Debuginfo.compare dbg1 dbg2 = 0
+
+      let hash (rs, dbg) =
+        Hashtbl.hash (rs, Debuginfo.hash dbg)
+    end)
+  in
+  let debuginfos = Label_table.create 7 in
   let rec label_debuginfos rs rdbg =
     let key = (rs, rdbg) in
-    try fst (Hashtbl.find debuginfos key)
+    try fst (Label_table.find debuginfos key)
     with Not_found ->
       let lbl = Cmm.new_label () in
       let next =
@@ -147,7 +166,7 @@ let emit_frames a =
         | _ :: [] -> None
         | _ :: ((_ :: _) as rdbg') -> Some (label_debuginfos false rdbg')
       in
-      Hashtbl.add debuginfos key (lbl, next);
+      Label_table.add debuginfos key (lbl, next);
       lbl
   in
   let emit_debuginfo_label rs rdbg =
@@ -196,7 +215,7 @@ let emit_frames a =
   in
   a.efa_word (List.length !frame_descriptors);
   List.iter emit_frame !frame_descriptors;
-  Hashtbl.iter emit_debuginfo debuginfos;
+  Label_table.iter emit_debuginfo debuginfos;
   Hashtbl.iter emit_filename filenames;
   frame_descriptors := []
 
diff --git a/asmcomp/emitaux.mli b/asmcomp/emitaux.mli
index 1e4addd3..b2b2141c 100644
--- a/asmcomp/emitaux.mli
+++ b/asmcomp/emitaux.mli
@@ -38,14 +38,13 @@ val emit_debug_info_gen :
   (file_num:int -> file_name:string -> unit) ->
   (file_num:int -> line:int -> col:int -> unit) -> unit
 
-type frame_descr =
-  { fd_lbl: int;                        (* Return address *)
-    fd_frame_size: int;                 (* Size of stack frame *)
-    fd_live_offset: int list;           (* Offsets/regs of live addresses *)
-    fd_raise: bool;                     (* Is frame for a raise? *)
-    fd_debuginfo: Debuginfo.t }         (* Location, if any *)
-
-val frame_descriptors : frame_descr list ref
+val record_frame_descr :
+  label:int ->              (* Return address *)
+  frame_size:int ->         (* Size of stack frame *)
+  live_offset:int list ->   (* Offsets/regs of live addresses *)
+  raise_frame:bool ->       (* Is frame for a raise? *)
+  Debuginfo.t ->            (* Location, if any *)
+  unit
 
 type emit_frame_actions =
   { efa_code_label: int -> unit;
diff --git a/asmcomp/export_info.ml b/asmcomp/export_info.ml
index b67998bb..82123a92 100644
--- a/asmcomp/export_info.ml
+++ b/asmcomp/export_info.ml
@@ -190,7 +190,7 @@ let merge (t1 : t) (t2 : t) : t =
       Set_of_closures_id.Map.disjoint_union t1.sets_of_closures
         t2.sets_of_closures;
     closures = Closure_id.Map.disjoint_union t1.closures t2.closures;
-    symbol_id = Symbol.Map.disjoint_union t1.symbol_id t2.symbol_id;
+    symbol_id = Symbol.Map.disjoint_union ~print:Export_id.print t1.symbol_id t2.symbol_id;
     offset_fun = Closure_id.Map.disjoint_union
         ~eq:int_eq t1.offset_fun t2.offset_fun;
     offset_fv = Var_within_closure.Map.disjoint_union
@@ -200,6 +200,7 @@ let merge (t1 : t) (t2 : t) : t =
         t2.constant_sets_of_closures;
     invariant_params =
       Set_of_closures_id.Map.disjoint_union
+        ~print:(Variable.Map.print Variable.Set.print)
         ~eq:(Variable.Map.equal Variable.Set.equal)
         t1.invariant_params t2.invariant_params;
   }
@@ -224,7 +225,7 @@ let nest_eid_map map =
   in
   Export_id.Map.fold add_map map Compilation_unit.Map.empty
 
-let print_approx ppf (t : t) =
+let print_approx ppf ((t,root_symbols) : t * Symbol.t list) =
   let values = t.values in
   let fprintf = Format.fprintf in
   let printed = ref Export_id.Set.empty in
@@ -293,7 +294,7 @@ let print_approx ppf (t : t) =
   and print_fields ppf fields =
     Array.iter (fun approx -> fprintf ppf "%a@ " print_approx approx) fields
   and print_set_of_closures ppf
-      { set_of_closures_id; bound_vars; aliased_symbol } =
+      { set_of_closures_id; bound_vars; aliased_symbol; results } =
     if Set_of_closures_id.Set.mem set_of_closures_id !printed_set_of_closures
     then fprintf ppf "%a" Set_of_closures_id.print set_of_closures_id
     else begin
@@ -304,10 +305,11 @@ let print_approx ppf (t : t) =
         | Some symbol ->
           Format.fprintf ppf "@ (alias: %a)" Symbol.print symbol
       in
-      fprintf ppf "{%a: %a%a}"
+      fprintf ppf "{%a: %a%a => %a}"
         Set_of_closures_id.print set_of_closures_id
         print_binding bound_vars
         print_alias aliased_symbol
+        (Closure_id.Map.print print_approx) results
     end
   and print_binding ppf bound_vars =
     Var_within_closure.Map.iter (fun clos_id approx ->
@@ -329,6 +331,7 @@ let print_approx ppf (t : t) =
       print_recorded_symbols ();
     end
   in
+  List.iter (fun s -> Queue.push s symbols_to_print) root_symbols;
   fprintf ppf "@[Globals:@ ";
   fprintf ppf "@]@ @[Symbols:@ ";
   print_recorded_symbols ();
@@ -345,10 +348,13 @@ let print_offsets ppf (t : t) =
         Var_within_closure.print vid off) t.offset_fv;
   Format.fprintf ppf "@]@ "
 
-let print_all ppf (t : t) =
+let print_functions ppf (t : t) =
+  Set_of_closures_id.Map.print Flambda.print_function_declarations ppf
+    t.sets_of_closures
+
+let print_all ppf ((t, root_symbols) : t * Symbol.t list) =
   let fprintf = Format.fprintf in
   fprintf ppf "approxs@ %a@.@."
-    print_approx t;
+    print_approx (t, root_symbols);
   fprintf ppf "functions@ %a@.@."
-    (Set_of_closures_id.Map.print Flambda.print_function_declarations)
-    t.sets_of_closures
+    print_functions t
diff --git a/asmcomp/export_info.mli b/asmcomp/export_info.mli
index 9d6bc0f6..d6fbd7ae 100644
--- a/asmcomp/export_info.mli
+++ b/asmcomp/export_info.mli
@@ -143,6 +143,7 @@ val nest_eid_map
 
 (**/**)
 (* Debug printing functions. *)
-val print_approx : Format.formatter -> t -> unit
+val print_approx : Format.formatter -> t * Symbol.t list -> unit
+val print_functions : Format.formatter -> t -> unit
 val print_offsets : Format.formatter -> t -> unit
-val print_all : Format.formatter -> t -> unit
+val print_all : Format.formatter -> t * Symbol.t list -> unit
diff --git a/asmcomp/export_info_for_pack.ml b/asmcomp/export_info_for_pack.ml
index 25ef70c6..da413408 100644
--- a/asmcomp/export_info_for_pack.ml
+++ b/asmcomp/export_info_for_pack.ml
@@ -17,6 +17,10 @@
 [@@@ocaml.warning "+a-4-9-30-40-41-42"]
 
 let rename_id_state = Export_id.Tbl.create 100
+let rename_set_of_closures_id_state = Set_of_closures_id.Tbl.create 10
+let imported_function_declarations_table =
+  (Set_of_closures_id.Tbl.create 10
+   : Flambda.function_declarations Set_of_closures_id.Tbl.t)
 
 (* Rename export identifiers' compilation units to denote that they now
    live within a pack. *)
@@ -46,10 +50,35 @@ let import_approx_for_pack units pack (approx : Export_info.approx)
   | Value_id eid -> Value_id (import_eid_for_pack units pack eid)
   | Value_unknown -> Value_unknown
 
+let import_set_of_closures_id_for_pack units pack
+    (set_of_closures_id : Set_of_closures_id.t)
+      : Set_of_closures_id.t =
+  let compilation_unit =
+    Set_of_closures_id.get_compilation_unit set_of_closures_id
+  in
+  if Compilation_unit.Set.mem compilation_unit units then
+    Set_of_closures_id.Tbl.memoize
+      rename_set_of_closures_id_state
+      (fun _ ->
+         Set_of_closures_id.create
+           ?name:(Set_of_closures_id.name set_of_closures_id)
+           pack)
+      set_of_closures_id
+  else set_of_closures_id
+
+let import_set_of_closures_origin_for_pack units pack
+    (set_of_closures_origin : Set_of_closures_origin.t)
+    : Set_of_closures_origin.t =
+  Set_of_closures_origin.rename
+    (import_set_of_closures_id_for_pack units pack)
+    set_of_closures_origin
+
 let import_set_of_closures units pack
       (set_of_closures : Export_info.value_set_of_closures)
       : Export_info.value_set_of_closures =
-  { set_of_closures_id = set_of_closures.set_of_closures_id;
+  { set_of_closures_id =
+      import_set_of_closures_id_for_pack units pack
+        set_of_closures.set_of_closures_id;
     bound_vars =
       Var_within_closure.Map.map (import_approx_for_pack units pack)
         set_of_closures.bound_vars;
@@ -83,15 +112,26 @@ let import_descr_for_pack units pack (descr : Export_info.descr)
   | Value_set_of_closures set_of_closures ->
     Value_set_of_closures (import_set_of_closures units pack set_of_closures)
 
-let import_code_for_pack units pack expr =
+let rec import_code_for_pack units pack expr =
   Flambda_iterators.map_named (function
       | Symbol sym -> Symbol (import_symbol_for_pack units pack sym)
       | Read_symbol_field (sym, field) ->
         Read_symbol_field (import_symbol_for_pack units pack sym, field)
+      | Set_of_closures set_of_closures ->
+        let set_of_closures =
+          Flambda.create_set_of_closures
+            ~free_vars:set_of_closures.free_vars
+            ~specialised_args:set_of_closures.specialised_args
+            ~direct_call_surrogates:set_of_closures.direct_call_surrogates
+            ~function_decls:
+              (import_function_declarations_for_pack units pack
+                 set_of_closures.function_decls)
+        in
+        Set_of_closures set_of_closures
       | e -> e)
     expr
 
-let import_function_declarations_for_pack units pack
+and import_function_declarations_for_pack_aux units pack
       (function_decls : Flambda.function_declarations) =
   let funs =
     Variable.Map.map (fun (function_decl : Flambda.function_declaration) ->
@@ -103,7 +143,26 @@ let import_function_declarations_for_pack units pack
           ~is_a_functor:function_decl.is_a_functor)
       function_decls.funs
   in
-  Flambda.update_function_declarations function_decls ~funs
+  Flambda.import_function_declarations_for_pack
+    (Flambda.update_function_declarations function_decls ~funs)
+    (import_set_of_closures_id_for_pack units pack)
+    (import_set_of_closures_origin_for_pack units pack)
+
+and import_function_declarations_for_pack units pack
+    (function_decls:Flambda.function_declarations) =
+  let original_set_of_closures_id = function_decls.set_of_closures_id in
+  try
+    Set_of_closures_id.Tbl.find imported_function_declarations_table
+      original_set_of_closures_id
+  with Not_found ->
+    let function_decls =
+      import_function_declarations_for_pack_aux units pack function_decls
+    in
+    Set_of_closures_id.Tbl.add
+      imported_function_declarations_table
+      original_set_of_closures_id
+      function_decls;
+    function_decls
 
 let import_eidmap_for_pack units pack f map =
   Export_info.nest_eid_map
@@ -120,10 +179,17 @@ let import_for_pack ~pack_units ~pack (exp : Export_info.t) =
   let import_descr = import_descr_for_pack pack_units pack in
   let import_eid = import_eid_for_pack pack_units pack in
   let import_eidmap f map = import_eidmap_for_pack pack_units pack f map in
+  let import_set_of_closures_id =
+    import_set_of_closures_id_for_pack pack_units pack
+  in
+  let import_function_declarations =
+    import_function_declarations_for_pack pack_units pack
+  in
   let sets_of_closures =
-    Set_of_closures_id.Map.map
-      (import_function_declarations_for_pack pack_units pack)
-      exp.sets_of_closures
+    Set_of_closures_id.Map.map_keys import_set_of_closures_id
+      (Set_of_closures_id.Map.map
+         import_function_declarations
+         exp.sets_of_closures)
   in
   Export_info.create ~sets_of_closures
     ~closures:(Flambda_utils.make_closure_map' sets_of_closures)
@@ -132,7 +198,14 @@ let import_for_pack ~pack_units ~pack (exp : Export_info.t) =
     ~values:(import_eidmap import_descr exp.values)
     ~symbol_id:(Symbol.Map.map_keys import_sym
       (Symbol.Map.map import_eid exp.symbol_id))
-    ~constant_sets_of_closures:exp.constant_sets_of_closures
-    ~invariant_params:exp.invariant_params
+    ~constant_sets_of_closures:
+      (Set_of_closures_id.Set.map import_set_of_closures_id
+         exp.constant_sets_of_closures)
+    ~invariant_params:
+      (Set_of_closures_id.Map.map_keys import_set_of_closures_id
+         exp.invariant_params)
 
-let clear_import_state () = Export_id.Tbl.clear rename_id_state
+let clear_import_state () =
+  Set_of_closures_id.Tbl.clear imported_function_declarations_table;
+  Set_of_closures_id.Tbl.clear rename_set_of_closures_id_state;
+  Export_id.Tbl.clear rename_id_state
diff --git a/asmcomp/flambda_to_clambda.ml b/asmcomp/flambda_to_clambda.ml
index 9ae0ecf9..01a6be7d 100644
--- a/asmcomp/flambda_to_clambda.ml
+++ b/asmcomp/flambda_to_clambda.ml
@@ -519,6 +519,7 @@ and to_clambda_set_of_closures t env
       params = params @ [env_var];
       body = to_clambda t env_body function_decl.body;
       dbg = function_decl.dbg;
+      env = Some env_var;
     }
   in
   let funs = List.map to_clambda_function all_functions in
@@ -558,6 +559,7 @@ and to_clambda_closed_set_of_closures t env symbol
       params;
       body = to_clambda t env_body function_decl.body;
       dbg = function_decl.dbg;
+      env = None;
     }
   in
   let ufunct = List.map to_clambda_function functions in
@@ -571,7 +573,7 @@ let to_clambda_initialize_symbol t env symbol fields : Clambda.ulambda =
   let build_setfield (index, field) : Clambda.ulambda =
     (* Note that this will never cause a write barrier hit, owing to
        the [Initialization]. *)
-    Uprim (Psetfield (index, Pointer, Initialization),
+    Uprim (Psetfield (index, Pointer, Root_initialization),
       [to_clambda_symbol env symbol; field],
       Debuginfo.none)
   in
diff --git a/asmcomp/i386/emit.mlp b/asmcomp/i386/emit.mlp
index d3325e1d..94c3d035 100644
--- a/asmcomp/i386/emit.mlp
+++ b/asmcomp/i386/emit.mlp
@@ -207,12 +207,8 @@ let record_frame_label ?label live raise_ dbg =
           Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
-  frame_descriptors :=
-    { fd_lbl = lbl;
-      fd_frame_size = frame_size();
-      fd_live_offset = !live_offset;
-      fd_raise = raise_;
-      fd_debuginfo = dbg } :: !frame_descriptors;
+  record_frame_descr ~label:lbl ~frame_size:(frame_size())
+    ~live_offset:!live_offset ~raise_frame:raise_ dbg;
   lbl
 
 let record_frame ?label live raise_ dbg =
diff --git a/asmcomp/i386/selection.ml b/asmcomp/i386/selection.ml
index 16199ca6..efde628d 100644
--- a/asmcomp/i386/selection.ml
+++ b/asmcomp/i386/selection.ml
@@ -34,28 +34,28 @@ let rec select_addr exp =
   match exp with
     Cconst_symbol s ->
       (Asymbol s, 0)
-  | Cop((Caddi | Caddv | Cadda), [arg; Cconst_int m]) ->
+  | Cop((Caddi | Caddv | Cadda), [arg; Cconst_int m], _) ->
       let (a, n) = select_addr arg in (a, n + m)
-  | Cop(Csubi, [arg; Cconst_int m]) ->
+  | Cop(Csubi, [arg; Cconst_int m], _) ->
       let (a, n) = select_addr arg in (a, n - m)
-  | Cop((Caddi | Caddv | Cadda), [Cconst_int m; arg]) ->
+  | Cop((Caddi | Caddv | Cadda), [Cconst_int m; arg], _) ->
       let (a, n) = select_addr arg in (a, n + m)
-  | Cop(Clsl, [arg; Cconst_int(1|2|3 as shift)]) ->
+  | Cop(Clsl, [arg; Cconst_int(1|2|3 as shift)], _) ->
       begin match select_addr arg with
         (Alinear e, n) -> (Ascale(e, 1 lsl shift), n lsl shift)
       | _ -> (Alinear exp, 0)
       end
-  | Cop(Cmuli, [arg; Cconst_int(2|4|8 as mult)]) ->
+  | Cop(Cmuli, [arg; Cconst_int(2|4|8 as mult)], _) ->
       begin match select_addr arg with
         (Alinear e, n) -> (Ascale(e, mult), n * mult)
       | _ -> (Alinear exp, 0)
       end
-  | Cop(Cmuli, [Cconst_int(2|4|8 as mult); arg]) ->
+  | Cop(Cmuli, [Cconst_int(2|4|8 as mult); arg], _) ->
       begin match select_addr arg with
         (Alinear e, n) -> (Ascale(e, mult), n * mult)
       | _ -> (Alinear exp, 0)
       end
-  | Cop((Caddi | Cadda | Caddv), [arg1; arg2]) ->
+  | Cop((Caddi | Cadda | Caddv), [arg1; arg2], _) ->
       begin match (select_addr arg1, select_addr arg2) with
           ((Alinear e1, n1), (Alinear e2, n2)) ->
               (Aadd(e1, e2), n1 + n2)
@@ -73,8 +73,9 @@ let rec select_addr exp =
   | arg ->
       (Alinear arg, 0)
 
-(* C functions to be turned into Ifloatspecial instructions if -ffast-math *)
-
+(* C functions to be turned into Ifloatspecial instructions if -ffast-math.
+   If you update this list, you may need to update [is_simple_expr] and/or
+   [effects_of], below. *)
 let inline_float_ops =
   ["atan"; "atan2"; "cos"; "log"; "log10"; "sin"; "sqrt"; "tan"]
 
@@ -82,13 +83,13 @@ let inline_float_ops =
    (Ershov's algorithm) *)
 
 let rec float_needs = function
-    Cop((Cnegf | Cabsf), [arg]) ->
+    Cop((Cnegf | Cabsf), [arg], _) ->
       float_needs arg
-  | Cop((Caddf | Csubf | Cmulf | Cdivf), [arg1; arg2]) ->
+  | Cop((Caddf | Csubf | Cmulf | Cdivf), [arg1; arg2], _) ->
       let n1 = float_needs arg1 in
       let n2 = float_needs arg2 in
       if n1 = n2 then 1 + n1 else if n1 > n2 then n1 else n2
-  | Cop(Cextcall(fn, _ty_res, _alloc, _dbg, _label), args)
+  | Cop(Cextcall(fn, _ty_res, _alloc, _label), args, _dbg)
     when !fast_math && List.mem fn inline_float_ops ->
       begin match args with
         [arg] -> float_needs arg
@@ -161,13 +162,21 @@ method is_immediate (_n : int) = true
 
 method! is_simple_expr e =
   match e with
-  | Cop(Cextcall(fn, _, _, _, _), args)
+  | Cop(Cextcall(fn, _, _alloc, _), args, _)
     when !fast_math && List.mem fn inline_float_ops ->
       (* inlined float ops are simple if their arguments are *)
       List.for_all self#is_simple_expr args
   | _ ->
       super#is_simple_expr e
 
+method! effects_of e =
+  match e with
+  | Cop(Cextcall(fn, _, _, _), args, _)
+    when !fast_math && List.mem fn inline_float_ops ->
+      Selectgen.Effect_and_coeffect.join_list_map args self#effects_of
+  | _ ->
+      super#effects_of e
+
 method select_addressing _chunk exp =
   match select_addr exp with
     (Asymbol s, d) ->
@@ -196,13 +205,13 @@ method! select_store is_assign addr exp =
   | _ ->
       super#select_store is_assign addr exp
 
-method! select_operation op args =
+method! select_operation op args dbg =
   match op with
   (* Recognize the LEA instruction *)
     Caddi | Caddv | Cadda | Csubi ->
-      begin match self#select_addressing Word_int (Cop(op, args)) with
+      begin match self#select_addressing Word_int (Cop(op, args, dbg)) with
         (Iindexed _, _)
-      | (Iindexed2 0, _) -> super#select_operation op args
+      | (Iindexed2 0, _) -> super#select_operation op args dbg
       | (addr, arg) -> (Ispecific(Ilea addr), [arg])
       end
   (* Recognize float arithmetic with memory.
@@ -220,32 +229,32 @@ method! select_operation op args =
   (* Recognize store instructions *)
   | Cstore ((Word_int | Word_val) as chunk, _) ->
       begin match args with
-        [loc; Cop(Caddi, [Cop(Cload _, [loc']); Cconst_int n])]
+        [loc; Cop(Caddi, [Cop(Cload _, [loc'], _); Cconst_int n], _)]
         when loc = loc' ->
           let (addr, arg) = self#select_addressing chunk loc in
           (Ispecific(Ioffset_loc(n, addr)), [arg])
       | _ ->
-          super#select_operation op args
+          super#select_operation op args dbg
       end
   (* Recognize inlined floating point operations *)
-  | Cextcall(fn, _ty_res, false, _dbg, _label)
+  | Cextcall(fn, _ty_res, false, _label)
     when !fast_math && List.mem fn inline_float_ops ->
       (Ispecific(Ifloatspecial fn), args)
   (* i386 does not support immediate operands for multiply high signed *)
   | Cmulhi ->
       (Iintop Imulh, args)
   (* Default *)
-  | _ -> super#select_operation op args
+  | _ -> super#select_operation op args dbg
 
 (* Recognize float arithmetic with mem *)
 
 method select_floatarith regular_op reversed_op mem_op mem_rev_op args =
   match args with
-    [arg1; Cop(Cload chunk, [loc2])] ->
+    [arg1; Cop(Cload (chunk, _), [loc2], _)] ->
       let (addr, arg2) = self#select_addressing chunk loc2 in
       (Ispecific(Ifloatarithmem(chunk_double chunk, mem_op, addr)),
                  [arg1; arg2])
-  | [Cop(Cload chunk, [loc1]); arg2] ->
+  | [Cop(Cload (chunk, _), [loc1], _); arg2] ->
       let (addr, arg1) = self#select_addressing chunk loc1 in
       (Ispecific(Ifloatarithmem(chunk_double chunk, mem_rev_op, addr)),
                  [arg2; arg1])
@@ -283,10 +292,10 @@ method select_push exp =
   | Cconst_pointer n -> (Ispecific(Ipush_int(Nativeint.of_int n)), Ctuple [])
   | Cconst_natpointer n -> (Ispecific(Ipush_int n), Ctuple [])
   | Cconst_symbol s -> (Ispecific(Ipush_symbol s), Ctuple [])
-  | Cop(Cload (Word_int | Word_val as chunk), [loc]) ->
+  | Cop(Cload ((Word_int | Word_val as chunk), _), [loc], _) ->
       let (addr, arg) = self#select_addressing chunk loc in
       (Ispecific(Ipush_load addr), arg)
-  | Cop(Cload Double_u, [loc]) ->
+  | Cop(Cload (Double_u, _), [loc], _) ->
       let (addr, arg) = self#select_addressing Double_u loc in
       (Ispecific(Ipush_load_float addr), arg)
   | _ -> (Ispecific(Ipush), exp)
diff --git a/asmcomp/import_approx.ml b/asmcomp/import_approx.ml
index 7b4fef9c..0ab09ca0 100644
--- a/asmcomp/import_approx.ml
+++ b/asmcomp/import_approx.ml
@@ -54,18 +54,20 @@ let import_set_of_closures =
     Flambda.update_function_declarations clos ~funs
   in
   let aux set_of_closures_id =
+    ignore (Compilenv.approx_for_global
+      (Set_of_closures_id.get_compilation_unit set_of_closures_id));
     let ex_info = Compilenv.approx_env () in
     let function_declarations =
       try
-        Set_of_closures_id.Map.find set_of_closures_id
-          ex_info.sets_of_closures
+        Some (Set_of_closures_id.Map.find set_of_closures_id
+          ex_info.sets_of_closures)
       with Not_found ->
-        Misc.fatal_errorf "[functions] does not map set of closures ID %a. \
-            ex_info = %a"
-          Set_of_closures_id.print set_of_closures_id
-          Export_info.print_all ex_info
+        None
     in
-    import_function_declarations function_declarations
+    match function_declarations with
+    | None -> None
+    | Some function_declarations ->
+      Some (import_function_declarations function_declarations)
   in
   Set_of_closures_id.Tbl.memoize Compilenv.imported_sets_of_closures_table aux
 
@@ -73,7 +75,7 @@ let rec import_ex ex =
   ignore (Compilenv.approx_for_global (Export_id.get_compilation_unit ex));
   let ex_info = Compilenv.approx_env () in
   let import_value_set_of_closures ~set_of_closures_id ~bound_vars
-        ~(ex_info : Export_info.t) ~what : A.value_set_of_closures =
+        ~(ex_info : Export_info.t) ~what : A.value_set_of_closures option =
     let bound_vars = Var_within_closure.Map.map import_approx bound_vars in
     match
       Set_of_closures_id.Map.find set_of_closures_id ex_info.invariant_params
@@ -85,13 +87,16 @@ let rec import_ex ex =
         Export_id.print ex
         what
     | invariant_params ->
-      A.create_value_set_of_closures
-        ~function_decls:(import_set_of_closures set_of_closures_id)
-        ~bound_vars
-        ~invariant_params:(lazy invariant_params)
-        ~specialised_args:Variable.Map.empty
-        ~freshening:Freshening.Project_var.empty
-        ~direct_call_surrogates:Closure_id.Map.empty
+      match import_set_of_closures set_of_closures_id with
+      | None -> None
+      | Some function_decls ->
+        Some (A.create_value_set_of_closures
+          ~function_decls
+          ~bound_vars
+          ~invariant_params:(lazy invariant_params)
+          ~specialised_args:Variable.Map.empty
+          ~freshening:Freshening.Project_var.empty
+          ~direct_call_surrogates:Closure_id.Map.empty)
   in
   match Export_info.find_description ex_info ex with
   | exception Not_found -> A.value_unknown Other
@@ -128,17 +133,25 @@ let rec import_ex ex =
       import_value_set_of_closures ~set_of_closures_id ~bound_vars ~ex_info
         ~what:(Format.asprintf "Value_closure %a" Closure_id.print closure_id)
     in
-    A.value_closure ?set_of_closures_symbol:aliased_symbol
-      value_set_of_closures closure_id
+    begin match value_set_of_closures with
+    | None -> A.value_unresolved (Set_of_closures_id set_of_closures_id)
+    | Some value_set_of_closures ->
+      A.value_closure ?set_of_closures_symbol:aliased_symbol
+        value_set_of_closures closure_id
+    end
   | Value_set_of_closures { set_of_closures_id; bound_vars; aliased_symbol } ->
     let value_set_of_closures =
       import_value_set_of_closures ~set_of_closures_id ~bound_vars ~ex_info
         ~what:"Value_set_of_closures"
     in
-    let approx = A.value_set_of_closures value_set_of_closures in
-    match aliased_symbol with
-    | None -> approx
-    | Some symbol -> A.augment_with_symbol approx symbol
+    match value_set_of_closures with
+    | None ->
+      A.value_unresolved (Set_of_closures_id set_of_closures_id)
+    | Some value_set_of_closures ->
+      let approx = A.value_set_of_closures value_set_of_closures in
+      match aliased_symbol with
+      | None -> approx
+      | Some symbol -> A.augment_with_symbol approx symbol
 
 and import_approx (ap : Export_info.approx) =
   match ap with
@@ -157,7 +170,7 @@ let import_symbol sym =
     match Symbol.Map.find sym symbol_id_map with
     | approx -> A.augment_with_symbol (import_ex approx) sym
     | exception Not_found ->
-      A.value_unresolved sym
+      A.value_unresolved (Symbol sym)
 
 (* Note for code reviewers: Observe that [really_import] iterates until
    the approximation description is fully resolved (or a necessary .cmx
diff --git a/asmcomp/interf.ml b/asmcomp/interf.ml
index 28f00c11..7d569c5b 100644
--- a/asmcomp/interf.ml
+++ b/asmcomp/interf.ml
@@ -107,8 +107,10 @@ let build_graph fundecl =
         interf i.next
     | Iloop body ->
         interf body; interf i.next
-    | Icatch(_, body, handler) ->
-        interf body; interf handler; interf i.next
+    | Icatch(_rec_flag, handlers, body) ->
+        interf body;
+        List.iter (fun (_, handler) -> interf handler) handlers;
+        interf i.next
     | Iexit _ ->
         ()
     | Itrywith(body, handler) ->
@@ -179,8 +181,18 @@ let build_graph fundecl =
         (* Avoid overflow of weight and spill_cost *)
         prefer (if weight < 1000 then 8 * weight else weight) body;
         prefer weight i.next
-    | Icatch(_, body, handler) ->
-        prefer weight body; prefer weight handler; prefer weight i.next
+    | Icatch(rec_flag, handlers, body) ->
+        prefer weight body;
+        List.iter (fun (_nfail, handler) ->
+            let weight =
+              match rec_flag with
+              | Cmm.Recursive ->
+                  (* Avoid overflow of weight and spill_cost *)
+                  if weight < 1000 then 8 * weight else weight
+              | Cmm.Nonrecursive ->
+                  weight in
+            prefer weight handler) handlers;
+        prefer weight i.next
     | Iexit _ ->
         ()
     | Itrywith(body, handler) ->
diff --git a/asmcomp/linearize.ml b/asmcomp/linearize.ml
index 44df185c..1aa5d90f 100644
--- a/asmcomp/linearize.ml
+++ b/asmcomp/linearize.ml
@@ -253,12 +253,29 @@ let rec linear i n =
       let n1 = linear i.Mach.next n in
       let n2 = linear body (cons_instr (Lbranch lbl_head) n1) in
       cons_instr (Llabel lbl_head) n2
-  | Icatch(io, body, handler) ->
+  | Icatch(_rec_flag, handlers, body) ->
       let (lbl_end, n1) = get_label(linear i.Mach.next n) in
-      let (lbl_handler, n2) = get_label(linear handler n1) in
-      exit_label := (io, (lbl_handler, !try_depth)) :: !exit_label ;
+      (* CR mshinwell for pchambart:
+         1. rename "io"
+         2. Make sure the test cases cover the "Iend" cases too *)
+      let labels_at_entry_to_handlers = List.map (fun (_nfail, handler) ->
+          match handler.Mach.desc with
+          | Iend -> lbl_end
+          | _ -> Cmm.new_label ())
+          handlers in
+      let exit_label_add = List.map2
+          (fun (nfail, _) lbl -> (nfail, (lbl, !try_depth)))
+          handlers labels_at_entry_to_handlers in
+      let previous_exit_label = !exit_label in
+      exit_label := exit_label_add @ !exit_label;
+      let n2 = List.fold_left2 (fun n (_nfail, handler) lbl_handler ->
+          match handler.Mach.desc with
+          | Iend -> n
+          | _ -> cons_instr (Llabel lbl_handler) (linear handler n))
+          n1 handlers labels_at_entry_to_handlers
+      in
       let n3 = linear body (add_branch lbl_end n2) in
-      exit_label := List.tl !exit_label;
+      exit_label := previous_exit_label;
       n3
   | Iexit nfail ->
       let lbl, t = find_exit_label_try_depth nfail in
diff --git a/asmcomp/liveness.ml b/asmcomp/liveness.ml
index c3d2f878..e289b464 100644
--- a/asmcomp/liveness.ml
+++ b/asmcomp/liveness.ml
@@ -101,14 +101,46 @@ let rec live i finally =
       end;
       i.live <- !at_top;
       !at_top
-  | Icatch(nfail, body, handler) ->
+  | Icatch(rec_flag, handlers, body) ->
       let at_join = live i.next finally in
-      let before_handler = live handler at_join in
-      let before_body =
-          live_at_exit := (nfail,before_handler) :: !live_at_exit ;
-          let before_body = live body at_join in
-          live_at_exit := List.tl !live_at_exit ;
-          before_body in
+      let aux (nfail,handler) (nfail', before_handler) =
+        assert(nfail = nfail');
+        let before_handler' = live handler at_join in
+        nfail, Reg.Set.union before_handler before_handler'
+      in
+      let aux_equal (nfail, before_handler) (nfail', before_handler') =
+        assert(nfail = nfail');
+        Reg.Set.equal before_handler before_handler'
+      in
+      let live_at_exit_before = !live_at_exit in
+      let live_at_exit_add before_handlers =
+        List.map (fun (nfail, before_handler) ->
+            (nfail, before_handler))
+          before_handlers
+      in
+      let rec fixpoint before_handlers =
+        let live_at_exit_add = live_at_exit_add before_handlers in
+        live_at_exit := live_at_exit_add @ !live_at_exit;
+        let before_handlers' = List.map2 aux handlers before_handlers in
+        live_at_exit := live_at_exit_before;
+        match rec_flag with
+        | Cmm.Nonrecursive ->
+            before_handlers'
+        | Cmm.Recursive ->
+            if List.for_all2 aux_equal before_handlers before_handlers'
+            then before_handlers'
+            else fixpoint before_handlers'
+      in
+      let init_state =
+        List.map (fun (nfail, _handler) -> nfail, Reg.Set.empty) handlers
+      in
+      let before_handler = fixpoint init_state in
+      (* We could use handler.live instead of Reg.Set.empty as the initial
+         value but we would need to clean the live field before doing the
+         analysis (to remove remnants of previous passes). *)
+      live_at_exit := (live_at_exit_add before_handler) @ !live_at_exit;
+      let before_body = live body at_join in
+      live_at_exit := live_at_exit_before;
       i.live <- before_body;
       before_body
   | Iexit nfail ->
diff --git a/asmcomp/mach.ml b/asmcomp/mach.ml
index d1e0b3bd..2808448b 100644
--- a/asmcomp/mach.ml
+++ b/asmcomp/mach.ml
@@ -75,7 +75,7 @@ and instruction_desc =
   | Iifthenelse of test * instruction * instruction
   | Iswitch of int array * instruction array
   | Iloop of instruction
-  | Icatch of int * instruction * instruction
+  | Icatch of Cmm.rec_flag * (int * instruction) list * instruction
   | Iexit of int
   | Itrywith of instruction * instruction
   | Iraise of Cmm.raise_kind
@@ -136,8 +136,10 @@ let rec instr_iter f i =
           instr_iter f i.next
       | Iloop(body) ->
           instr_iter f body; instr_iter f i.next
-      | Icatch(_, body, handler) ->
-          instr_iter f body; instr_iter f handler; instr_iter f i.next
+      | Icatch(_, handlers, body) ->
+          instr_iter f body;
+          List.iter (fun (_n, handler) -> instr_iter f handler) handlers;
+          instr_iter f i.next
       | Iexit _ -> ()
       | Itrywith(body, handler) ->
           instr_iter f body; instr_iter f handler; instr_iter f i.next
diff --git a/asmcomp/mach.mli b/asmcomp/mach.mli
index 798e314f..f97834d7 100644
--- a/asmcomp/mach.mli
+++ b/asmcomp/mach.mli
@@ -85,7 +85,7 @@ and instruction_desc =
   | Iifthenelse of test * instruction * instruction
   | Iswitch of int array * instruction array
   | Iloop of instruction
-  | Icatch of int * instruction * instruction
+  | Icatch of Cmm.rec_flag * (int * instruction) list * instruction
   | Iexit of int
   | Itrywith of instruction * instruction
   | Iraise of Cmm.raise_kind
diff --git a/asmcomp/power/emit.mlp b/asmcomp/power/emit.mlp
index d8bc1bf0..5abc5f85 100644
--- a/asmcomp/power/emit.mlp
+++ b/asmcomp/power/emit.mlp
@@ -317,12 +317,8 @@ let record_frame ?label live raise_ dbg =
           Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
-  frame_descriptors :=
-    { fd_lbl = lbl;
-      fd_frame_size = frame_size();
-      fd_live_offset = !live_offset;
-      fd_raise = raise_;
-      fd_debuginfo = dbg } :: !frame_descriptors;
+  record_frame_descr ~label:lbl ~frame_size:(frame_size())
+    ~live_offset:!live_offset ~raise_frame:raise_ dbg;
   `{emit_label lbl}:\n`
 
 (* Record floating-point literals (for PPC32) *)
diff --git a/asmcomp/power/selection.ml b/asmcomp/power/selection.ml
index 71c47490..e62b0b89 100644
--- a/asmcomp/power/selection.ml
+++ b/asmcomp/power/selection.ml
@@ -28,20 +28,20 @@ type addressing_expr =
 
 let rec select_addr = function
     Cconst_symbol s ->
-      (Asymbol s, 0)
-  | Cop((Caddi | Caddv | Cadda), [arg; Cconst_int m]) ->
-      let (a, n) = select_addr arg in (a, n + m)
-  | Cop((Caddi | Caddv | Cadda), [Cconst_int m; arg]) ->
-      let (a, n) = select_addr arg in (a, n + m)
-  | Cop((Caddi | Caddv | Cadda), [arg1; arg2]) ->
+      (Asymbol s, 0, Debuginfo.none)
+  | Cop((Caddi | Caddv | Cadda), [arg; Cconst_int m], dbg) ->
+      let (a, n, _) = select_addr arg in (a, n + m, dbg)
+  | Cop((Caddi | Caddv | Cadda), [Cconst_int m; arg], dbg) ->
+      let (a, n, _) = select_addr arg in (a, n + m, dbg)
+  | Cop((Caddi | Caddv | Cadda), [arg1; arg2], dbg) ->
       begin match (select_addr arg1, select_addr arg2) with
-          ((Alinear e1, n1), (Alinear e2, n2)) ->
-              (Aadd(e1, e2), n1 + n2)
+          ((Alinear e1, n1, _), (Alinear e2, n2, _)) ->
+              (Aadd(e1, e2), n1 + n2, dbg)
         | _ ->
-              (Aadd(arg1, arg2), 0)
+              (Aadd(arg1, arg2), 0, dbg)
       end
   | exp ->
-      (Alinear exp, 0)
+      (Alinear exp, 0, Debuginfo.none)
 
 (* Instruction selection *)
 
@@ -53,16 +53,16 @@ method is_immediate n = (n <= 32767) && (n >= -32768)
 
 method select_addressing _chunk exp =
   match select_addr exp with
-    (Asymbol s, d) ->
+    (Asymbol s, d, _dbg) ->
       (Ibased(s, d), Ctuple [])
-  | (Alinear e, d) ->
+  | (Alinear e, d, _dbg) ->
       (Iindexed d, e)
-  | (Aadd(e1, e2), d) ->
+  | (Aadd(e1, e2), d, dbg) ->
       if d = 0
       then (Iindexed2, Ctuple[e1; e2])
-      else (Iindexed d, Cop(Cadda, [e1; e2]))
+      else (Iindexed d, Cop(Cadda, [e1; e2], dbg))
 
-method! select_operation op args =
+method! select_operation op args dbg =
   match (op, args) with
   (* PowerPC does not support immediate operands for multiply high *)
     (Cmulhi, _) -> (Iintop Imulh, args)
@@ -72,14 +72,14 @@ method! select_operation op args =
   | (Cor, _) -> self#select_logical Ior args
   | (Cxor, _) -> self#select_logical Ixor args
   (* Recognize mult-add and mult-sub instructions *)
-  | (Caddf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
+  | (Caddf, [Cop(Cmulf, [arg1; arg2], _); arg3]) ->
       (Ispecific Imultaddf, [arg1; arg2; arg3])
-  | (Caddf, [arg3; Cop(Cmulf, [arg1; arg2])]) ->
+  | (Caddf, [arg3; Cop(Cmulf, [arg1; arg2], _)]) ->
       (Ispecific Imultaddf, [arg1; arg2; arg3])
-  | (Csubf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
+  | (Csubf, [Cop(Cmulf, [arg1; arg2], _); arg3]) ->
       (Ispecific Imultsubf, [arg1; arg2; arg3])
   | _ ->
-      super#select_operation op args
+      super#select_operation op args dbg
 
 method select_logical op = function
     [arg; Cconst_int n] when n >= 0 && n <= 0xFFFF ->
diff --git a/asmcomp/printcmm.ml b/asmcomp/printcmm.ml
index 21823e31..697ebca8 100644
--- a/asmcomp/printcmm.ml
+++ b/asmcomp/printcmm.ml
@@ -18,6 +18,10 @@
 open Format
 open Cmm
 
+let rec_flag ppf = function
+  | Nonrecursive -> ()
+  | Recursive -> fprintf ppf " rec"
+
 let machtype_component ppf = function
   | Val -> fprintf ppf "val"
   | Addr -> fprintf ppf "addr"
@@ -57,16 +61,18 @@ let raise_kind fmt = function
   | Raise_withtrace -> Format.fprintf fmt "raise_withtrace"
   | Raise_notrace -> Format.fprintf fmt "raise_notrace"
 
-let operation = function
-  | Capply(_ty, d) -> "app" ^ Debuginfo.to_string d
-  | Cextcall(lbl, _ty, _alloc, d, _) ->
+let operation d = function
+  | Capply _ty -> "app" ^ Debuginfo.to_string d
+  | Cextcall(lbl, _ty, _alloc, _) ->
       Printf.sprintf "extcall \"%s\"%s" lbl (Debuginfo.to_string d)
-  | Cload c -> Printf.sprintf "load %s" (chunk c)
-  | Calloc d -> "alloc" ^ Debuginfo.to_string d
+  | Cload (c, Asttypes.Immutable) -> Printf.sprintf "load %s" (chunk c)
+  | Cload (c, Asttypes.Mutable) -> Printf.sprintf "load_mut %s" (chunk c)
+  | Calloc -> "alloc" ^ Debuginfo.to_string d
   | Cstore (c, init) ->
     let init =
       match init with
-      | Lambda.Initialization -> "(init)"
+      | Lambda.Heap_initialization -> "(heap-init)"
+      | Lambda.Root_initialization -> "(root-init)"
       | Lambda.Assignment -> ""
     in
     Printf.sprintf "store %s%s" (chunk c) init
@@ -95,8 +101,8 @@ let operation = function
   | Cfloatofint -> "floatofint"
   | Cintoffloat -> "intoffloat"
   | Ccmpf c -> Printf.sprintf "%sf" (comparison c)
-  | Craise (k, d) -> Format.asprintf "%a%s" raise_kind k (Debuginfo.to_string d)
-  | Ccheckbound d -> "checkbound" ^ Debuginfo.to_string d
+  | Craise k -> Format.asprintf "%a%s" raise_kind k (Debuginfo.to_string d)
+  | Ccheckbound -> "checkbound" ^ Debuginfo.to_string d
 
 let rec expr ppf = function
   | Cconst_int n -> fprintf ppf "%i" n
@@ -136,12 +142,12 @@ let rec expr ppf = function
           expr ppf e)
         el in
       fprintf ppf "@[<1>[%a]@]" tuple el
-  | Cop(op, el) ->
-      fprintf ppf "@[<2>(%s" (operation op);
+  | Cop(op, el, dbg) ->
+      fprintf ppf "@[<2>(%s" (operation dbg op);
       List.iter (fun e -> fprintf ppf "@ %a" expr e) el;
       begin match op with
-      | Capply (mty, _) -> fprintf ppf "@ %a" machtype mty
-      | Cextcall(_, mty, _, _, _) -> fprintf ppf "@ %a" machtype mty
+      | Capply mty -> fprintf ppf "@ %a" machtype mty
+      | Cextcall(_, mty, _, _) -> fprintf ppf "@ %a" machtype mty
       | _ -> ()
       end;
       fprintf ppf ")@]"
@@ -149,7 +155,7 @@ let rec expr ppf = function
       fprintf ppf "@[<2>(seq@ %a@ %a)@]" sequence e1 sequence e2
   | Cifthenelse(e1, e2, e3) ->
       fprintf ppf "@[<2>(if@ %a@ %a@ %a)@]" expr e1 expr e2 expr e3
-  | Cswitch(e1, index, cases) ->
+  | Cswitch(e1, index, cases, _dbg) ->
       let print_case i ppf =
         for j = 0 to Array.length index - 1 do
           if index.(j) = i then fprintf ppf "case %i:" j
@@ -161,17 +167,26 @@ let rec expr ppf = function
       fprintf ppf "@[@[<2>(switch@ %a@ @]%t)@]" expr e1 print_cases
   | Cloop e ->
       fprintf ppf "@[<2>(loop@ %a)@]" sequence e
-  | Ccatch(i, ids, e1, e2) ->
+  | Ccatch(flag, handlers, e1) ->
+      let print_handler ppf (i, ids, e2) =
+        fprintf ppf "(%d%a)@ %a"
+          i
+          (fun ppf ids ->
+             List.iter
+               (fun id -> fprintf ppf " %a" Ident.print id)
+               ids) ids
+          sequence e2
+      in
+      let print_handlers ppf l =
+        List.iter (print_handler ppf) l
+      in
       fprintf ppf
-        "@[<2>(catch@ %a@;<1 -2>with(%d%a)@ %a)@]"
-        sequence e1 i
-        (fun ppf ids ->
-          List.iter
-            (fun id -> fprintf ppf " %a" Ident.print id)
-            ids) ids
-        sequence e2
+        "@[<2>(catch%a@ %a@;<1 -2>with%a)@]"
+        rec_flag flag
+        sequence e1
+        print_handlers handlers
   | Cexit (i, el) ->
-      fprintf ppf "@[<2>(exit %d" i ;
+      fprintf ppf "@[<2>(exit %d" i;
       List.iter (fun e -> fprintf ppf "@ %a" expr e) el;
       fprintf ppf ")@]"
   | Ctrywith(e1, id, e2) ->
diff --git a/asmcomp/printcmm.mli b/asmcomp/printcmm.mli
index 86ec11fe..bd4739b2 100644
--- a/asmcomp/printcmm.mli
+++ b/asmcomp/printcmm.mli
@@ -17,11 +17,12 @@
 
 open Format
 
+val rec_flag : formatter -> Cmm.rec_flag -> unit
 val machtype_component : formatter -> Cmm.machtype_component -> unit
 val machtype : formatter -> Cmm.machtype_component array -> unit
 val comparison : Cmm.comparison -> string
 val chunk : Cmm.memory_chunk -> string
-val operation : Cmm.operation -> string
+val operation : Debuginfo.t -> Cmm.operation -> string
 val expression : formatter -> Cmm.expression -> unit
 val fundecl : formatter -> Cmm.fundecl -> unit
 val data : formatter -> Cmm.data_item list -> unit
diff --git a/asmcomp/printmach.ml b/asmcomp/printmach.ml
index e9e4937d..f45dbb8f 100644
--- a/asmcomp/printmach.ml
+++ b/asmcomp/printmach.ml
@@ -190,10 +190,20 @@ let rec instr ppf i =
       fprintf ppf "@,endswitch"
   | Iloop(body) ->
       fprintf ppf "@[loop@,%a@;<0 -2>endloop@]" instr body
-  | Icatch(i, body, handler) ->
-      fprintf
-        ppf "@[catch@,%a@;<0 -2>with(%d)@,%a@;<0 -2>endcatch@]"
-        instr body i instr handler
+  | Icatch(flag, handlers, body) ->
+      fprintf ppf "@[catch%a@,%a@;<0 -2>with"
+        Printcmm.rec_flag flag instr body;
+      let h (nfail, handler) =
+        fprintf ppf "(%d)@,%a@;" nfail instr handler in
+      let rec aux = function
+        | [] -> ()
+        | [v] -> h v
+        | v :: t ->
+            h v;
+            fprintf ppf "@ and";
+            aux t
+      in
+      aux handlers
   | Iexit i ->
       fprintf ppf "exit(%d)" i
   | Itrywith(body, handler) ->
diff --git a/asmcomp/reloadgen.ml b/asmcomp/reloadgen.ml
index f40cf02d..3c0b9873 100644
--- a/asmcomp/reloadgen.ml
+++ b/asmcomp/reloadgen.ml
@@ -112,9 +112,12 @@ method private reload i =
           (self#reload i.next))
   | Iloop body ->
       instr_cons (Iloop(self#reload body)) [||] [||] (self#reload i.next)
-  | Icatch(nfail, body, handler) ->
+  | Icatch(rec_flag, handlers, body) ->
+      let new_handlers = List.map
+          (fun (nfail, handler) -> nfail, self#reload handler)
+          handlers in
       instr_cons
-        (Icatch(nfail, self#reload body, self#reload handler)) [||] [||]
+        (Icatch(rec_flag, new_handlers, self#reload body)) [||] [||]
         (self#reload i.next)
   | Iexit i ->
       instr_cons (Iexit i) [||] [||] dummy_instr
diff --git a/asmcomp/s390x/emit.mlp b/asmcomp/s390x/emit.mlp
index 5d233a36..0579bfd4 100644
--- a/asmcomp/s390x/emit.mlp
+++ b/asmcomp/s390x/emit.mlp
@@ -53,10 +53,10 @@ let emit_symbol s = Emitaux.emit_symbol '.' s
 (* Output function call *)
 
 let emit_call s =
-   if !pic_code then
-    `brasl	%r14, {emit_symbol s}@PLT`
-   else
-    `brasl	%r14, {emit_symbol s}`
+  if !pic_code then
+   `	brasl	%r14, {emit_symbol s}@PLT\n`
+  else
+   `	brasl	%r14, {emit_symbol s}\n`
 
 (* Output a label *)
 
@@ -83,7 +83,13 @@ let emit_reg r =
 
 (* Special registers *)
 
-let reg_f15 = phys_reg 115
+let check_phys_reg reg_idx name =
+  let reg = phys_reg reg_idx in
+  assert (register_name reg_idx = name);
+  reg
+
+let reg_f15 = check_phys_reg 115 "%f15"
+let reg_r7 = check_phys_reg 5 "%r7"
 
 (* Output a stack reference *)
 
@@ -94,6 +100,14 @@ let emit_stack r =
   | _ -> fatal_error "Emit.emit_stack"
 
 
+(* Output a load of the address of a global symbol *)
+
+let emit_load_symbol_addr reg s =
+  if !pic_code then
+  `	lgrl	{emit_reg reg}, {emit_symbol s}@GOTENT\n`
+  else
+  `	larl	{emit_reg reg}, {emit_symbol s}\n`
+
 (* Output a load or store operation *)
 
 let emit_load_store instr addressing_mode addr n arg =
@@ -148,7 +162,7 @@ let emit_set_comp cmp res =
 
 (* Record live pointers at call points *)
 
-let record_frame ?label live raise_ dbg =
+let record_frame_label ?label live raise_ dbg =
   let lbl =
     match label with
     | None -> new_label()
@@ -165,14 +179,14 @@ let record_frame ?label live raise_ dbg =
           Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
-  frame_descriptors :=
-    { fd_lbl = lbl;
-      fd_frame_size = frame_size();
-      fd_live_offset = !live_offset;
-      fd_raise = raise_;
-      fd_debuginfo = dbg } :: !frame_descriptors;
+  record_frame_descr ~label:lbl ~frame_size:(frame_size())
+    ~live_offset:!live_offset ~raise_frame:raise_ dbg;
   lbl
 
+let record_frame ?label live raise_ dbg =
+  let lbl = record_frame_label ?label live raise_ dbg in
+  `{emit_label lbl}:`
+
 (* Record calls to caml_call_gc, emitted out of line. *)
 
 type gc_call =
@@ -183,7 +197,7 @@ type gc_call =
 let call_gc_sites = ref ([] : gc_call list)
 
 let emit_call_gc gc =
-  `{emit_label gc.gc_lbl}:	{emit_call "caml_call_gc"}\n`;
+  `{emit_label gc.gc_lbl}:`; emit_call "caml_call_gc";
   `{emit_label gc.gc_frame_lbl}:	brcl	15, {emit_label gc.gc_return_lbl}\n`
 
 (* Record calls to caml_ml_array_bound_error, emitted out of line. *)
@@ -198,7 +212,7 @@ let bound_error_call = ref 0
 let bound_error_label ?label dbg =
   if !Clflags.debug then begin
     let lbl_bound_error = new_label() in
-    let lbl_frame = record_frame ?label Reg.Set.empty false dbg in
+    let lbl_frame = record_frame_label ?label Reg.Set.empty false dbg in
     bound_error_sites :=
      { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
    lbl_bound_error
@@ -208,13 +222,14 @@ let bound_error_label ?label dbg =
  end
 
 let emit_call_bound_error bd =
-  `{emit_label bd.bd_lbl}:	{emit_call "caml_ml_array_bound_error"}\n`;
+  `{emit_label bd.bd_lbl}:`; emit_call "caml_ml_array_bound_error";
   `{emit_label bd.bd_frame}:\n`
 
 let emit_call_bound_errors () =
   List.iter emit_call_bound_error !bound_error_sites;
-  if !bound_error_call > 0 then
-    `{emit_label !bound_error_call}:	{emit_call "caml_ml_array_bound_error"}\n`
+  if !bound_error_call > 0 then begin
+    `{emit_label !bound_error_call}:`; emit_call "caml_ml_array_bound_error";
+  end
 
 (* Record floating-point and large integer literals *)
 
@@ -319,22 +334,14 @@ let emit_instr i =
         `	larl	%r1, {emit_label lbl}\n`;
         `	ld	{emit_reg i.res.(0)}, 0(%r1)\n`
      | Lop(Iconst_symbol s) ->
-        if !pic_code then
-        `	lgrl	{emit_reg i.res.(0)}, {emit_symbol s}@GOTENT\n`
-        else
-        `	larl	{emit_reg i.res.(0)}, {emit_symbol s}\n`;
+        emit_load_symbol_addr i.res.(0) s
     | Lop(Icall_ind { label_after; }) ->
         `	basr	%r14, {emit_reg i.arg.(0)}\n`;
-        let lbl = record_frame i.live false i.dbg ~label:label_after in
-         `{emit_label lbl}:\n`
+        `{record_frame i.live false i.dbg ~label:label_after}\n`
 
     | Lop(Icall_imm { func; label_after; }) ->
-        if !pic_code then
-        `	brasl	%r14, {emit_symbol func}@PLT\n`
-        else
-        `	brasl	%r14, {emit_symbol func}\n`;
-        let lbl = record_frame i.live false i.dbg ~label:label_after in
-         `{emit_label lbl}:\n`;
+        emit_call func;
+        `{record_frame i.live false i.dbg ~label:label_after}\n`
     | Lop(Itailcall_ind { label_after = _; }) ->
         let n = frame_size() in
         if !contains_calls then
@@ -356,22 +363,12 @@ let emit_instr i =
         end
 
      | Lop(Iextcall { func; alloc; label_after; }) ->
-        if alloc then begin
-          if !pic_code then begin
-          `	lgrl	%r7, {emit_symbol func}@GOTENT\n`;
-          `	brasl	%r14, {emit_symbol "caml_c_call"}@PLT\n`
-          end else begin
-          `	larl	%r7, {emit_symbol func}\n`;
-          `	brasl	%r14, {emit_symbol "caml_c_call"}\n`
-          end;
-          let lbl = record_frame i.live false i.dbg ~label:label_after in
-           `{emit_label lbl}:\n`;
-        end else begin
-          if !pic_code then
-          `	brasl	%r14, {emit_symbol func}@PLT\n`
-          else
-          `	brasl	%r14, {emit_symbol func}\n`
-       end
+        if not alloc then emit_call func
+        else begin
+          emit_load_symbol_addr reg_r7 func;
+          emit_call "caml_c_call";
+          `{record_frame i.live false i.dbg ~label:label_after}\n`
+        end
 
      | Lop(Istackoffset n) ->
         emit_stack_adjust n;
@@ -411,7 +408,7 @@ let emit_instr i =
         let lbl_redo = new_label() in
         let lbl_call_gc = new_label() in
         let lbl_frame =
-          record_frame i.live false i.dbg ?label:label_after_call_gc
+          record_frame_label i.live false i.dbg ?label:label_after_call_gc
         in
         call_gc_sites :=
           { gc_lbl = lbl_call_gc;
@@ -611,9 +608,8 @@ let emit_instr i =
     | Lraise k ->
         begin match k with
         | Cmm.Raise_withtrace ->
-          `	brasl	%r14, {emit_symbol "caml_raise_exn"}\n`;
-          let lbl = record_frame Reg.Set.empty true i.dbg in
-          `{emit_label lbl}:\n`
+          emit_call "caml_raise_exn";
+          `{record_frame Reg.Set.empty true i.dbg}\n`
         | Cmm.Raise_notrace ->
           `	lg	%r1, 0(%r13)\n`;
           `	lgr	%r15, %r13\n`;
diff --git a/asmcomp/s390x/selection.ml b/asmcomp/s390x/selection.ml
index 9a00108d..44ab1f9d 100644
--- a/asmcomp/s390x/selection.ml
+++ b/asmcomp/s390x/selection.ml
@@ -30,11 +30,11 @@ type addressing_expr =
   | Aadd of expression * expression
 
 let rec select_addr = function
-  | Cop((Caddi | Cadda | Caddv), [arg; Cconst_int m]) ->
+  | Cop((Caddi | Cadda | Caddv), [arg; Cconst_int m], _) ->
       let (a, n) = select_addr arg in (a, n + m)
-  | Cop((Caddi | Cadda | Caddv), [Cconst_int m; arg]) ->
+  | Cop((Caddi | Cadda | Caddv), [Cconst_int m; arg], _) ->
       let (a, n) = select_addr arg in (a, n + m)
-  | Cop((Caddi | Cadda | Caddv), [arg1; arg2]) ->
+  | Cop((Caddi | Cadda | Caddv), [arg1; arg2], _) ->
       begin match (select_addr arg1, select_addr arg2) with
           ((Alinear e1, n1), (Alinear e2, n2)) ->
               (Aadd(e1, e2), n1 + n2)
@@ -76,7 +76,7 @@ method select_addressing _chunk exp =
   end else
     (Iindexed 0, exp)
 
-method! select_operation op args =
+method! select_operation op args dbg =
   match (op, args) with
   (* Z does not support immediate operands for multiply high *)
     (Cmulhi, _) -> (Iintop Imulh, args)
@@ -87,14 +87,14 @@ method! select_operation op args =
   | (Cor, _) -> self#select_logical Ior 0 (1 lsl 32 - 1 (*0xFFFF_FFFF*)) args
   | (Cxor, _) -> self#select_logical Ixor  0 (1 lsl 32 - 1 (*0xFFFF_FFFF*)) args
   (* Recognize mult-add and mult-sub instructions *)
-  | (Caddf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
+  | (Caddf, [Cop(Cmulf, [arg1; arg2], _); arg3]) ->
       (Ispecific Imultaddf, [arg1; arg2; arg3])
-  | (Caddf, [arg3; Cop(Cmulf, [arg1; arg2])]) ->
+  | (Caddf, [arg3; Cop(Cmulf, [arg1; arg2], _)]) ->
       (Ispecific Imultaddf, [arg1; arg2; arg3])
-  | (Csubf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
+  | (Csubf, [Cop(Cmulf, [arg1; arg2], _); arg3]) ->
       (Ispecific Imultsubf, [arg1; arg2; arg3])
   | _ ->
-      super#select_operation op args
+      super#select_operation op args dbg
 
 method select_logical op lo hi = function
     [arg; Cconst_int n] when n >= lo && n <= hi ->
diff --git a/asmcomp/selectgen.ml b/asmcomp/selectgen.ml
index f7e1c0d8..7cd8cd5c 100644
--- a/asmcomp/selectgen.ml
+++ b/asmcomp/selectgen.ml
@@ -21,20 +21,42 @@ open Cmm
 open Reg
 open Mach
 
-type environment = (Ident.t, Reg.t array) Tbl.t
+type environment =
+  { vars : (Ident.t, Reg.t array) Tbl.t;
+    static_exceptions : (int, Reg.t array list) Tbl.t;
+    (** Which registers must be populated when jumping to the given
+        handler. *)
+  }
+
+let env_add id v env =
+  { env with vars = Tbl.add id v env.vars }
+
+let env_add_static_exception id v env =
+  { env with static_exceptions = Tbl.add id v env.static_exceptions }
+
+let env_find id env =
+  Tbl.find id env.vars
+
+let env_find_static_exception id env =
+  Tbl.find id env.static_exceptions
+
+let env_empty = {
+  vars = Tbl.empty;
+  static_exceptions = Tbl.empty;
+}
 
 (* Infer the type of the result of an operation *)
 
 let oper_result_type = function
-    Capply(ty, _) -> ty
-  | Cextcall(_s, ty, _alloc, _, _) -> ty
-  | Cload c ->
+    Capply ty -> ty
+  | Cextcall(_s, ty, _alloc, _) -> ty
+  | Cload (c, _) ->
       begin match c with
       | Word_val -> typ_val
       | Single | Double | Double_u -> typ_float
       | _ -> typ_int
       end
-  | Calloc _ -> typ_val
+  | Calloc -> typ_val
   | Cstore (_c, _) -> typ_void
   | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi |
     Cand | Cor | Cxor | Clsl | Clsr | Casr |
@@ -45,11 +67,12 @@ let oper_result_type = function
   | Cfloatofint -> typ_float
   | Cintoffloat -> typ_int
   | Craise _ -> typ_void
-  | Ccheckbound _ -> typ_void
+  | Ccheckbound -> typ_void
 
-(* Infer the size in bytes of the result of a simple expression *)
+(* Infer the size in bytes of the result of an expression whose evaluation
+   may be deferred (cf. [emit_parts]). *)
 
-let size_expr env exp =
+let size_expr (env:environment) exp =
   let rec size localenv = function
       Cconst_int _ | Cconst_natint _ -> Arch.size_int
     | Cconst_symbol _ | Cconst_pointer _ | Cconst_natpointer _ ->
@@ -61,7 +84,7 @@ let size_expr env exp =
           Tbl.find id localenv
         with Not_found ->
         try
-          let regs = Tbl.find id env in
+          let regs = env_find id env in
           size_machtype (Array.map (fun r -> r.typ) regs)
         with Not_found ->
           fatal_error("Selection.size_expr: unbound var " ^
@@ -69,7 +92,7 @@ let size_expr env exp =
         end
     | Ctuple el ->
         List.fold_right (fun e sz -> size localenv e + sz) el 0
-    | Cop(op, _) ->
+    | Cop(op, _, _) ->
         size_machtype(oper_result_type op)
     | Clet(id, arg, body) ->
         size (Tbl.add id (size localenv arg) localenv) body
@@ -169,32 +192,93 @@ let join_array rs =
       done;
       Some res
 
-(* Extract debug info contained in a C-- operation *)
-let debuginfo_op = function
-  | Capply(_, dbg) -> dbg
-  | Cextcall(_, _, _, dbg, _) -> dbg
-  | Craise (_, dbg) -> dbg
-  | Ccheckbound dbg -> dbg
-  | Calloc dbg -> dbg
-  | _ -> Debuginfo.none
-
-(* Registers for catch constructs *)
-let catch_regs = ref []
-
 (* Name of function being compiled *)
 let current_function_name = ref ""
 
+module Effect = struct
+  type t =
+    | None
+    | Raise
+    | Arbitrary
+
+  let join t1 t2 =
+    match t1, t2 with
+    | None, t2 -> t2
+    | t1, None -> t1
+    | Raise, Raise -> Raise
+    | Arbitrary, _ | _, Arbitrary -> Arbitrary
+
+  let pure = function
+    | None -> true
+    | Raise | Arbitrary -> false
+end
+
+module Coeffect = struct
+  type t =
+    | None
+    | Read_mutable
+    | Arbitrary
+
+  let join t1 t2 =
+    match t1, t2 with
+    | None, t2 -> t2
+    | t1, None -> t1
+    | Read_mutable, Read_mutable -> Read_mutable
+    | Arbitrary, _ | _, Arbitrary -> Arbitrary
+
+  let copure = function
+    | None -> true
+    | Read_mutable | Arbitrary -> false
+end
+
+module Effect_and_coeffect : sig
+  type t
+
+  val none : t
+  val arbitrary : t
+
+  val effect : t -> Effect.t
+  val coeffect : t -> Coeffect.t
+
+  val pure_and_copure : t -> bool
+
+  val effect_only : Effect.t -> t
+  val coeffect_only : Coeffect.t -> t
+
+  val join : t -> t -> t
+  val join_list_map : 'a list -> ('a -> t) -> t
+end = struct
+  type t = Effect.t * Coeffect.t
+
+  let none = Effect.None, Coeffect.None
+  let arbitrary = Effect.Arbitrary, Coeffect.Arbitrary
+
+  let effect (e, _ce) = e
+  let coeffect (_e, ce) = ce
+
+  let pure_and_copure (e, ce) = Effect.pure e && Coeffect.copure ce
+
+  let effect_only e = e, Coeffect.None
+  let coeffect_only ce = Effect.None, ce
+
+  let join (e1, ce1) (e2, ce2) =
+    Effect.join e1 e2, Coeffect.join ce1 ce2
+
+  let join_list_map xs f =
+    match xs with
+    | [] -> none
+    | x::xs -> List.fold_left (fun acc x -> join acc (f x)) (f x) xs
+end
+
 (* The default instruction selection class *)
 
 class virtual selector_generic = object (self)
 
-(* Says if an expression is "simple". A "simple" expression has no
-   side-effects and its execution can be delayed until its value
-   is really needed. In the case of e.g. an [alloc] instruction,
-   the non-simple arguments are computed in right-to-left order
-   first, then the block is allocated, then the simple arguments are
-   evaluated and stored. *)
-
+(* A syntactic criterion used in addition to judgements about (co)effects as
+   to whether the evaluation of a given expression may be deferred by
+   [emit_parts].  This criterion is a property of the instruction selection
+   algorithm in this file rather than a property of the Cmm language.
+*)
 method is_simple_expr = function
     Cconst_int _ -> true
   | Cconst_natint _ -> true
@@ -207,15 +291,62 @@ method is_simple_expr = function
   | Ctuple el -> List.for_all self#is_simple_expr el
   | Clet(_id, arg, body) -> self#is_simple_expr arg && self#is_simple_expr body
   | Csequence(e1, e2) -> self#is_simple_expr e1 && self#is_simple_expr e2
-  | Cop(op, args) ->
+  | Cop(op, args, _) ->
       begin match op with
         (* The following may have side effects *)
-      | Capply _ | Cextcall _ | Calloc _ | Cstore _ | Craise _ -> false
+      | Capply _ | Cextcall _ | Calloc | Cstore _ | Craise _ -> false
         (* The remaining operations are simple if their args are *)
-      | _ ->
-          List.for_all self#is_simple_expr args
+      | Cload _ | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi | Cand | Cor
+      | Cxor | Clsl | Clsr | Casr | Ccmpi _ | Caddv | Cadda | Ccmpa _ | Cnegf
+      | Cabsf | Caddf | Csubf | Cmulf | Cdivf | Cfloatofint | Cintoffloat
+      | Ccmpf _ | Ccheckbound -> List.for_all self#is_simple_expr args
       end
-  | _ -> false
+  | Cassign _ | Cifthenelse _ | Cswitch _ | Cloop _ | Ccatch _ | Cexit _
+  | Ctrywith _ -> false
+
+(* Analyses the effects and coeffects of an expression.  This is used across
+   a whole list of expressions with a view to determining which expressions
+   may have their evaluation deferred.  The result of this function, modulo
+   target-specific judgements if the [effects_of] method is overridden, is a
+   property of the Cmm language rather than anything particular about the
+   instruction selection algorithm in this file.
+
+   In the case of e.g. an OCaml function call, the arguments whose evaluation
+   cannot be deferred (cf. [emit_parts], below) are computed in right-to-left
+   order first with their results going into temporaries, then the block is
+   allocated, then the remaining arguments are evaluated before being
+   combined with the temporaries. *)
+method effects_of exp =
+  let module EC = Effect_and_coeffect in
+  match exp with
+  | Cconst_int _ | Cconst_natint _ | Cconst_float _ | Cconst_symbol _
+  | Cconst_pointer _ | Cconst_natpointer _ | Cblockheader _
+  | Cvar _ -> EC.none
+  | Ctuple el -> EC.join_list_map el self#effects_of
+  | Clet (_id, arg, body) ->
+    EC.join (self#effects_of arg) (self#effects_of body)
+  | Csequence (e1, e2) ->
+    EC.join (self#effects_of e1) (self#effects_of e2)
+  | Cifthenelse (cond, ifso, ifnot) ->
+    EC.join (self#effects_of cond)
+      (EC.join (self#effects_of ifso) (self#effects_of ifnot))
+  | Cop (op, args, _) ->
+    let from_op =
+      match op with
+      | Capply _ | Cextcall _ -> EC.arbitrary
+      | Calloc -> EC.none
+      | Cstore _ -> EC.effect_only Effect.Arbitrary
+      | Craise _ | Ccheckbound -> EC.effect_only Effect.Raise
+      | Cload (_, Asttypes.Immutable) -> EC.none
+      | Cload (_, Asttypes.Mutable) -> EC.coeffect_only Coeffect.Read_mutable
+      | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi | Cand | Cor | Cxor
+      | Clsl | Clsr | Casr | Ccmpi _ | Caddv | Cadda | Ccmpa _ | Cnegf | Cabsf
+      | Caddf | Csubf | Cmulf | Cdivf | Cfloatofint | Cintoffloat | Ccmpf _ ->
+        EC.none
+    in
+    EC.join from_op (EC.join_list_map args self#effects_of)
+  | Cassign _ | Cswitch _ | Cloop _ | Ccatch _ | Cexit _ | Ctrywith _ ->
+    EC.arbitrary
 
 (* Says whether an integer constant is a suitable immediate argument *)
 
@@ -272,7 +403,7 @@ method select_checkbound () =
   Icheckbound { spacetime_index = 0; label_after_error = None; }
 method select_checkbound_extra_args () = []
 
-method select_operation op args =
+method select_operation op args _dbg =
   match (op, args) with
   | (Capply _, Cconst_symbol func :: rem) ->
     let label_after = Cmm.new_label () in
@@ -280,21 +411,22 @@ method select_operation op args =
   | (Capply _, _) ->
     let label_after = Cmm.new_label () in
     (Icall_ind { label_after; }, args)
-  | (Cextcall(func, _ty, alloc, _dbg, label_after), _) ->
+  | (Cextcall(func, _ty, alloc, label_after), _) ->
     let label_after =
       match label_after with
       | None -> Cmm.new_label ()
       | Some label_after -> label_after
     in
     Iextcall { func; alloc; label_after; }, args
-  | (Cload chunk, [arg]) ->
+  | (Cload (chunk, _mut), [arg]) ->
       let (addr, eloc) = self#select_addressing chunk arg in
       (Iload(chunk, addr), [eloc])
   | (Cstore (chunk, init), [arg1; arg2]) ->
       let (addr, eloc) = self#select_addressing chunk arg1 in
       let is_assign =
         match init with
-        | Lambda.Initialization -> false
+        | Lambda.Root_initialization -> false
+        | Lambda.Heap_initialization -> false
         | Lambda.Assignment -> true
       in
       if chunk = Word_int || chunk = Word_val then begin
@@ -304,7 +436,7 @@ method select_operation op args =
         (Istore(chunk, addr, is_assign), [arg2; eloc])
         (* Inversion addr/datum in Istore *)
       end
-  | (Calloc _dbg, _) -> (self#select_allocation 0), args
+  | (Calloc, _) -> (self#select_allocation 0), args
   | (Caddi, _) -> self#select_arith_comm Iadd args
   | (Csubi, _) -> self#select_arith Isub args
   | (Cmuli, _) -> self#select_arith_comm Imul args
@@ -329,7 +461,7 @@ method select_operation op args =
   | (Cdivf, _) -> (Idivf, args)
   | (Cfloatofint, _) -> (Ifloatofint, args)
   | (Cintoffloat, _) -> (Iintoffloat, args)
-  | (Ccheckbound _, _) ->
+  | (Ccheckbound, _) ->
     let extra_args = self#select_checkbound_extra_args () in
     let op = self#select_checkbound () in
     self#select_arith op (args @ extra_args)
@@ -376,29 +508,29 @@ method private select_arith_comp cmp = function
 (* Instruction selection for conditionals *)
 
 method select_condition = function
-    Cop(Ccmpi cmp, [arg1; Cconst_int n]) when self#is_immediate n ->
+    Cop(Ccmpi cmp, [arg1; Cconst_int n], _) when self#is_immediate n ->
       (Iinttest_imm(Isigned cmp, n), arg1)
-  | Cop(Ccmpi cmp, [Cconst_int n; arg2]) when self#is_immediate n ->
+  | Cop(Ccmpi cmp, [Cconst_int n; arg2], _) when self#is_immediate n ->
       (Iinttest_imm(Isigned(swap_comparison cmp), n), arg2)
-  | Cop(Ccmpi cmp, [arg1; Cconst_pointer n]) when self#is_immediate n ->
+  | Cop(Ccmpi cmp, [arg1; Cconst_pointer n], _) when self#is_immediate n ->
       (Iinttest_imm(Isigned cmp, n), arg1)
-  | Cop(Ccmpi cmp, [Cconst_pointer n; arg2]) when self#is_immediate n ->
+  | Cop(Ccmpi cmp, [Cconst_pointer n; arg2], _) when self#is_immediate n ->
       (Iinttest_imm(Isigned(swap_comparison cmp), n), arg2)
-  | Cop(Ccmpi cmp, args) ->
+  | Cop(Ccmpi cmp, args, _) ->
       (Iinttest(Isigned cmp), Ctuple args)
-  | Cop(Ccmpa cmp, [arg1; Cconst_pointer n]) when self#is_immediate n ->
+  | Cop(Ccmpa cmp, [arg1; Cconst_pointer n], _) when self#is_immediate n ->
       (Iinttest_imm(Iunsigned cmp, n), arg1)
-  | Cop(Ccmpa cmp, [arg1; Cconst_int n]) when self#is_immediate n ->
+  | Cop(Ccmpa cmp, [arg1; Cconst_int n], _) when self#is_immediate n ->
       (Iinttest_imm(Iunsigned cmp, n), arg1)
-  | Cop(Ccmpa cmp, [Cconst_pointer n; arg2]) when self#is_immediate n ->
+  | Cop(Ccmpa cmp, [Cconst_pointer n; arg2], _) when self#is_immediate n ->
       (Iinttest_imm(Iunsigned(swap_comparison cmp), n), arg2)
-  | Cop(Ccmpa cmp, [Cconst_int n; arg2]) when self#is_immediate n ->
+  | Cop(Ccmpa cmp, [Cconst_int n; arg2], _) when self#is_immediate n ->
       (Iinttest_imm(Iunsigned(swap_comparison cmp), n), arg2)
-  | Cop(Ccmpa cmp, args) ->
+  | Cop(Ccmpa cmp, args, _) ->
       (Iinttest(Iunsigned cmp), Ctuple args)
-  | Cop(Ccmpf cmp, args) ->
+  | Cop(Ccmpf cmp, args, _) ->
       (Ifloattest(cmp, false), Ctuple args)
-  | Cop(Cand, [arg; Cconst_int 1]) ->
+  | Cop(Cand, [arg; Cconst_int 1], _) ->
       (Ioddtest, arg)
   | arg ->
       (Itruetest, arg)
@@ -497,7 +629,7 @@ method private maybe_emit_spacetime_move ~spacetime_reg =
 (* Add the instructions for the given expression
    at the end of the self sequence *)
 
-method emit_expr env exp =
+method emit_expr (env:environment) exp =
   match exp with
     Cconst_int n ->
       let r = self#regs_for typ_int in
@@ -521,7 +653,7 @@ method emit_expr env exp =
       self#emit_blockheader env n dbg
   | Cvar v ->
       begin try
-        Some(Tbl.find v env)
+        Some(env_find v env)
       with Not_found ->
         fatal_error("Selection.emit_expr: unbound var " ^ Ident.unique_name v)
       end
@@ -533,7 +665,7 @@ method emit_expr env exp =
   | Cassign(v, e1) ->
       let rv =
         try
-          Tbl.find v env
+          env_find v env
         with Not_found ->
           fatal_error ("Selection.emit_expr: unbound var " ^ Ident.name v) in
       begin match self#emit_expr env e1 with
@@ -548,7 +680,7 @@ method emit_expr env exp =
       | Some(simple_list, ext_env) ->
           Some(self#emit_tuple ext_env simple_list)
       end
-  | Cop(Craise (k, dbg), [arg]) ->
+  | Cop(Craise k, [arg], dbg) ->
       begin match self#emit_expr env arg with
         None -> None
       | Some r1 ->
@@ -557,15 +689,14 @@ method emit_expr env exp =
           self#insert_debug (Iraise k) dbg rd [||];
           None
       end
-  | Cop(Ccmpf _, _) ->
+  | Cop(Ccmpf _, _, _) ->
       self#emit_expr env (Cifthenelse(exp, Cconst_int 1, Cconst_int 0))
-  | Cop(op, args) ->
+  | Cop(op, args, dbg) ->
       begin match self#emit_parts_list env args with
         None -> None
       | Some(simple_args, env) ->
           let ty = oper_result_type op in
-          let (new_op, new_args) = self#select_operation op simple_args in
-          let dbg = debuginfo_op op in
+          let (new_op, new_args) = self#select_operation op simple_args dbg in
           match new_op with
             Icall_ind _ ->
               let r1 = self#emit_tuple env new_args in
@@ -639,7 +770,7 @@ method emit_expr env exp =
                       rarg [||];
           r
       end
-  | Cswitch(esel, index, ecases) ->
+  | Cswitch(esel, index, ecases, _dbg) ->
       begin match self#emit_expr env esel with
         None -> None
       | Some rsel ->
@@ -654,41 +785,70 @@ method emit_expr env exp =
       let (_rarg, sbody) = self#emit_sequence env ebody in
       self#insert (Iloop(sbody#extract)) [||] [||];
       Some [||]
-  | Ccatch(nfail, ids, e1, e2) ->
-      let rs =
-        List.map
-          (fun id ->
-            let r = self#regs_for typ_val in name_regs id r; r)
-          ids in
-      catch_regs := (nfail, Array.concat rs) :: !catch_regs ;
-      let (r1, s1) = self#emit_sequence env e1 in
-      catch_regs := List.tl !catch_regs ;
-      let new_env =
-        List.fold_left
-        (fun env (id,r) -> Tbl.add id r env)
-        env (List.combine ids rs) in
-      let (r2, s2) = self#emit_sequence new_env e2 in
-      let r = join r1 s1 r2 s2 in
-      self#insert (Icatch(nfail, s1#extract, s2#extract)) [||] [||];
+  | Ccatch(_, [], e1) ->
+      self#emit_expr env e1
+  | Ccatch(rec_flag, handlers, body) ->
+      let handlers =
+        List.map (fun (nfail, ids, e2) ->
+            let rs =
+              List.map
+                (* CR-someday mshinwell: consider how we can do better than
+                   [typ_val] when appropriate. *)
+                (fun id -> let r = self#regs_for typ_val in name_regs id r; r)
+                ids in
+            (nfail, ids, rs, e2))
+          handlers
+      in
+      let env =
+        (* Since the handlers may be recursive, and called from the body,
+           the same environment is used for translating both the handlers and
+           the body. *)
+        List.fold_left (fun env (nfail, _ids, rs, _e2) ->
+            env_add_static_exception nfail rs env)
+          env handlers
+      in
+      let (r_body, s_body) = self#emit_sequence env body in
+      let translate_one_handler (nfail, ids, rs, e2) =
+        assert(List.length ids = List.length rs);
+        let new_env =
+          List.fold_left (fun env (id, r) -> env_add id r env)
+            env (List.combine ids rs)
+        in
+        let (r, s) = self#emit_sequence new_env e2 in
+        (nfail, (r, s))
+      in
+      let l = List.map translate_one_handler handlers in
+      let a = Array.of_list ((r_body, s_body) :: List.map snd l) in
+      let r = join_array a in
+      let aux (nfail, (_r, s)) = (nfail, s#extract) in
+      self#insert (Icatch (rec_flag, List.map aux l, s_body#extract)) [||] [||];
       r
   | Cexit (nfail,args) ->
       begin match self#emit_parts_list env args with
         None -> None
       | Some (simple_list, ext_env) ->
           let src = self#emit_tuple ext_env simple_list in
-          let dest =
-            try List.assoc nfail !catch_regs
+          let dest_args =
+            try env_find_static_exception nfail env
             with Not_found ->
-              Misc.fatal_error
-                ("Selectgen.emit_expr, on exit("^string_of_int nfail^")") in
-          self#insert_moves src dest ;
+              fatal_error ("Selection.emit_expr: unboun label "^
+                           string_of_int nfail)
+          in
+          (* Intermediate registers to handle cases where some
+             registers from src are present in dest *)
+          let tmp_regs = Reg.createv_like src in
+          (* Ccatch registers are created with type Val. They must not
+             contain out of heap pointers *)
+          Array.iter (fun reg -> assert(reg.typ <> Addr)) src;
+          self#insert_moves src tmp_regs ;
+          self#insert_moves tmp_regs (Array.concat dest_args) ;
           self#insert (Iexit nfail) [||] [||];
           None
       end
   | Ctrywith(e1, v, e2) ->
       let (r1, s1) = self#emit_sequence env e1 in
       let rv = self#regs_for typ_val in
-      let (r2, s2) = self#emit_sequence (Tbl.add v rv env) e2 in
+      let (r2, s2) = self#emit_sequence (env_add v rv env) e2 in
       let r = join r1 s1 r2 s2 in
       self#insert
         (Itrywith(s1#extract,
@@ -697,24 +857,67 @@ method emit_expr env exp =
         [||] [||];
       r
 
-method private emit_sequence env exp =
+method private emit_sequence (env:environment) exp =
   let s = {< instr_seq = dummy_instr >} in
   let r = s#emit_expr env exp in
   (r, s)
 
-method private bind_let env v r1 =
+method private bind_let (env:environment) v r1 =
   if all_regs_anonymous r1 then begin
     name_regs v r1;
-    Tbl.add v r1 env
+    env_add v r1 env
   end else begin
     let rv = Reg.createv_like r1 in
     name_regs v rv;
     self#insert_moves r1 rv;
-    Tbl.add v rv env
+    env_add v rv env
   end
 
-method private emit_parts env exp =
-  if self#is_simple_expr exp then
+(* The following two functions, [emit_parts] and [emit_parts_list], force
+   right-to-left evaluation order as required by the Flambda [Un_anf] pass
+   (and to be consistent with the bytecode compiler). *)
+
+method private emit_parts (env:environment) ~effects_after exp =
+  let module EC = Effect_and_coeffect in
+  let may_defer_evaluation =
+    let ec = self#effects_of exp in
+    match EC.effect ec with
+    | Effect.Arbitrary | Effect.Raise ->
+      (* Preserve the ordering of effectful expressions by evaluating them
+         early (in the correct order) and assigning their results to
+         temporaries.  We can avoid this in just one case: if we know that
+         every [exp'] in the original expression list (cf. [emit_parts_list])
+         to be evaluated after [exp] cannot possibly affect the result of
+         [exp] or depend on the result of [exp], then [exp] may be deferred.
+         (Checking purity here is not enough: we need to check copurity too
+         to avoid e.g. moving mutable reads earlier than the raising of
+         an exception.) *)
+      EC.pure_and_copure effects_after
+    | Effect.None ->
+      match EC.coeffect ec with
+      | Coeffect.None ->
+        (* Pure expressions may be moved. *)
+        true
+      | Coeffect.Read_mutable -> begin
+        (* Read-mutable expressions may only be deferred if evaluation of
+           every [exp'] (for [exp'] as in the comment above) has no effects
+           "worse" (in the sense of the ordering in [Effect.t]) than raising
+           an exception. *)
+        match EC.effect effects_after with
+        | Effect.None | Effect.Raise -> true
+        | Effect.Arbitrary -> false
+      end
+      | Coeffect.Arbitrary -> begin
+        (* Arbitrary expressions may only be deferred if evaluation of
+           every [exp'] (for [exp'] as in the comment above) has no effects. *)
+        match EC.effect effects_after with
+        | Effect.None -> true
+        | Effect.Arbitrary | Effect.Raise -> false
+      end
+  in
+  (* Even though some expressions may look like they can be deferred from
+     the (co)effect analysis, it may be forbidden to move them. *)
+  if may_defer_evaluation && self#is_simple_expr exp then
     Some (exp, env)
   else begin
     match self#emit_expr env exp with
@@ -727,28 +930,37 @@ method private emit_parts env exp =
           let id = Ident.create "bind" in
           if all_regs_anonymous r then
             (* r is an anonymous, unshared register; use it directly *)
-            Some (Cvar id, Tbl.add id r env)
+            Some (Cvar id, env_add id r env)
           else begin
             (* Introduce a fresh temp to hold the result *)
             let tmp = Reg.createv_like r in
             self#insert_moves r tmp;
-            Some (Cvar id, Tbl.add id tmp env)
+            Some (Cvar id, env_add id tmp env)
           end
         end
   end
 
-method private emit_parts_list env exp_list =
-  match exp_list with
-    [] -> Some ([], env)
-  | exp :: rem ->
-      (* This ensures right-to-left evaluation, consistent with the
-         bytecode compiler *)
-      match self#emit_parts_list env rem with
-        None -> None
-      | Some(new_rem, new_env) ->
-          match self#emit_parts new_env exp with
-            None -> None
-          | Some(new_exp, fin_env) -> Some(new_exp :: new_rem, fin_env)
+method private emit_parts_list (env:environment) exp_list =
+  let module EC = Effect_and_coeffect in
+  let exp_list_right_to_left, _effect =
+    (* Annotate each expression with the (co)effects that happen after it
+       when the original expression list is evaluated from right to left.
+       The resulting expression list has the rightmost expression first. *)
+    List.fold_left (fun (exp_list, effects_after) exp ->
+        let exp_effect = self#effects_of exp in
+        (exp, effects_after)::exp_list, EC.join exp_effect effects_after)
+      ([], EC.none)
+      exp_list
+  in
+  List.fold_left (fun results_and_env (exp, effects_after) ->
+      match results_and_env with
+      | None -> None
+      | Some (result, env) ->
+          match self#emit_parts env exp ~effects_after with
+          | None -> None
+          | Some (exp_result, env) -> Some (exp_result :: result, env))
+    (Some ([], env))
+    exp_list_right_to_left
 
 method private emit_tuple_not_flattened env exp_list =
   let rec emit_list = function
@@ -804,7 +1016,7 @@ method emit_stores env data regs_addr =
 
 (* Same, but in tail position *)
 
-method private emit_return env exp =
+method private emit_return (env:environment) exp =
   match self#emit_expr env exp with
     None -> ()
   | Some r ->
@@ -812,18 +1024,18 @@ method private emit_return env exp =
       self#insert_moves r loc;
       self#insert Ireturn loc [||]
 
-method emit_tail env exp =
+method emit_tail (env:environment) exp =
   match exp with
     Clet(v, e1, e2) ->
       begin match self#emit_expr env e1 with
         None -> ()
       | Some r1 -> self#emit_tail (self#bind_let env v r1) e2
       end
-  | Cop(Capply(ty, dbg) as op, args) ->
+  | Cop((Capply ty) as op, args, dbg) ->
       begin match self#emit_parts_list env args with
         None -> ()
       | Some(simple_args, env) ->
-          let (new_op, new_args) = self#select_operation op simple_args in
+          let (new_op, new_args) = self#select_operation op simple_args dbg in
           match new_op with
             Icall_ind { label_after; } ->
               let r1 = self#emit_tuple env new_args in
@@ -899,7 +1111,7 @@ method emit_tail env exp =
                                          self#emit_tail_sequence env eelse))
                       rarg [||]
       end
-  | Cswitch(esel, index, ecases) ->
+  | Cswitch(esel, index, ecases, _dbg) ->
       begin match self#emit_expr env esel with
         None -> ()
       | Some rsel ->
@@ -907,27 +1119,35 @@ method emit_tail env exp =
             (Iswitch(index, Array.map (self#emit_tail_sequence env) ecases))
             rsel [||]
       end
-  | Ccatch(nfail, ids, e1, e2) ->
-       let rs =
-        List.map
-          (fun id ->
-            let r = self#regs_for typ_val in
-            name_regs id r  ;
-            r)
-          ids in
-      catch_regs := (nfail, Array.concat rs) :: !catch_regs ;
-      let s1 = self#emit_tail_sequence env e1 in
-      catch_regs := List.tl !catch_regs ;
-      let new_env =
-        List.fold_left
-        (fun env (id,r) -> Tbl.add id r env)
-        env (List.combine ids rs) in
-      let s2 = self#emit_tail_sequence new_env e2 in
-      self#insert (Icatch(nfail, s1, s2)) [||] [||]
+  | Ccatch(_, [], e1) ->
+      self#emit_tail env e1
+  | Ccatch(rec_flag, handlers, e1) ->
+      let handlers =
+        List.map (fun (nfail, ids, e2) ->
+            let rs =
+              List.map
+                (fun id -> let r = self#regs_for typ_val in name_regs id r; r)
+                ids in
+            (nfail, ids, rs, e2))
+          handlers in
+      let env =
+        List.fold_left (fun env (nfail, _ids, rs, _e2) ->
+            env_add_static_exception nfail rs env)
+          env handlers in
+      let s_body = self#emit_tail_sequence env e1 in
+      let aux (nfail, ids, rs, e2) =
+        assert(List.length ids = List.length rs);
+        let new_env =
+          List.fold_left
+            (fun env (id,r) -> env_add id r env)
+            env (List.combine ids rs) in
+        nfail, self#emit_tail_sequence new_env e2
+      in
+      self#insert (Icatch(rec_flag, List.map aux handlers, s_body)) [||] [||]
   | Ctrywith(e1, v, e2) ->
       let (opt_r1, s1) = self#emit_sequence env e1 in
       let rv = self#regs_for typ_val in
-      let s2 = self#emit_tail_sequence (Tbl.add v rv env) e2 in
+      let s2 = self#emit_tail_sequence (env_add v rv env) e2 in
       self#insert
         (Itrywith(s1#extract,
                   instr_cons (Iop Imove) [|Proc.loc_exn_bucket|] rv s2))
@@ -955,7 +1175,7 @@ method insert_prologue _f ~loc_arg ~rarg ~spacetime_node_hole:_ ~env:_ =
 
 (* Sequentialization of a function definition *)
 
-method initial_env () = Tbl.empty
+method initial_env () = env_empty
 
 method emit_fundecl f =
   Proc.contains_calls := false;
@@ -973,14 +1193,14 @@ method emit_fundecl f =
      together is then simply prepended to the body. *)
   let env =
     List.fold_right2
-      (fun (id, _ty) r env -> Tbl.add id r env)
+      (fun (id, _ty) r env -> env_add id r env)
       f.Cmm.fun_args rargs (self#initial_env ()) in
   let spacetime_node_hole, env =
     if not Config.spacetime then None, env
     else begin
       let reg = self#regs_for typ_int in
       let node_hole = Ident.create "spacetime_node_hole" in
-      Some (node_hole, reg), Tbl.add node_hole reg env
+      Some (node_hole, reg), env_add node_hole reg env
     end
   in
   self#emit_tail env f.Cmm.fun_body;
@@ -1016,5 +1236,4 @@ let _ =
   Simplif.is_tail_native_heuristic := is_tail_call
 
 let reset () =
-  catch_regs := [];
   current_function_name := ""
diff --git a/asmcomp/selectgen.mli b/asmcomp/selectgen.mli
index 5df80ad3..6ab3c215 100644
--- a/asmcomp/selectgen.mli
+++ b/asmcomp/selectgen.mli
@@ -16,10 +16,44 @@
 (* Selection of pseudo-instructions, assignment of pseudo-registers,
    sequentialization. *)
 
-type environment = (Ident.t, Reg.t array) Tbl.t
+type environment
+
+val env_add : Ident.t -> Reg.t array -> environment -> environment
+
+val env_find : Ident.t -> environment -> Reg.t array
 
 val size_expr : environment -> Cmm.expression -> int
 
+module Effect : sig
+  type t =
+    | None
+    | Raise
+    | Arbitrary
+end
+
+module Coeffect : sig
+  type t =
+    | None
+    | Read_mutable
+    | Arbitrary
+end
+
+module Effect_and_coeffect : sig
+  type t
+
+  val none : t
+  val arbitrary : t
+
+  val effect : t -> Effect.t
+  val coeffect : t -> Coeffect.t
+
+  val effect_only : Effect.t -> t
+  val coeffect_only : Coeffect.t -> t
+
+  val join : t -> t -> t
+  val join_list_map : 'a list -> ('a -> t) -> t
+end
+
 class virtual selector_generic : object
   (* The following methods must or can be overridden by the processor
      description *)
@@ -30,10 +64,13 @@ class virtual selector_generic : object
     Cmm.memory_chunk -> Cmm.expression -> Arch.addressing_mode * Cmm.expression
     (* Must be defined to select addressing modes *)
   method is_simple_expr: Cmm.expression -> bool
+  method effects_of : Cmm.expression -> Effect_and_coeffect.t
     (* Can be overridden to reflect special extcalls known to be pure *)
   method select_operation :
     Cmm.operation ->
-    Cmm.expression list -> Mach.operation * Cmm.expression list
+    Cmm.expression list ->
+    Debuginfo.t ->
+    Mach.operation * Cmm.expression list
     (* Can be overridden to deal with special arithmetic instructions *)
   method select_condition : Cmm.expression -> Mach.test * Cmm.expression
     (* Can be overridden to deal with special test instructions *)
@@ -105,34 +142,35 @@ class virtual selector_generic : object
   method adjust_type : Reg.t -> Reg.t -> unit
   method adjust_types : Reg.t array -> Reg.t array -> unit
   method emit_expr :
-    (Ident.t, Reg.t array) Tbl.t -> Cmm.expression -> Reg.t array option
-  method emit_tail : (Ident.t, Reg.t array) Tbl.t -> Cmm.expression -> unit
+    environment -> Cmm.expression -> Reg.t array option
+  method emit_tail : environment -> Cmm.expression -> unit
 
   (* Only for the use of [Spacetime_profiling]. *)
   method select_allocation : int -> Mach.operation
-  method select_allocation_args : (Ident.t, Reg.t array) Tbl.t -> Reg.t array
+  method select_allocation_args : environment -> Reg.t array
   method select_checkbound : unit -> Mach.integer_operation
   method select_checkbound_extra_args : unit -> Cmm.expression list
   method emit_blockheader
-     : (Ident.t, Reg.t array) Tbl.t
+     : environment
     -> nativeint
     -> Debuginfo.t
     -> Reg.t array option
   method about_to_emit_call
-     : (Ident.t, Reg.t array) Tbl.t
+     : environment
     -> Mach.instruction_desc
     -> Reg.t array
     -> Reg.t array option
-  method initial_env : unit -> (Ident.t, Reg.t array) Tbl.t
+  method initial_env : unit -> environment
   method insert_prologue
      : Cmm.fundecl
     -> loc_arg:Reg.t array
     -> rarg:Reg.t array
     -> spacetime_node_hole:(Ident.t * Reg.t array) option
-    -> env:(Ident.t, Reg.t array) Tbl.t
+    -> env:environment
     -> Mach.spacetime_shape option
 
   val mutable instr_seq : Mach.instruction
+
 end
 
 val reset : unit -> unit
diff --git a/asmcomp/spacetime_profiling.ml b/asmcomp/spacetime_profiling.ml
index 32037c55..b6786c1d 100644
--- a/asmcomp/spacetime_profiling.ml
+++ b/asmcomp/spacetime_profiling.ml
@@ -55,6 +55,7 @@ let code_for_function_prologue ~function_name ~node_hole =
   let must_allocate_node = Ident.create "must_allocate_node" in
   let is_new_node = Ident.create "is_new_node" in
   let no_tail_calls = List.length !direct_tail_call_point_indexes < 1 in
+  let dbg = Debuginfo.none in
   let open Cmm in
   let initialize_direct_tail_call_points_and_return_node =
     let new_node_encoded = Ident.create "new_node_encoded" in
@@ -68,8 +69,8 @@ let code_for_function_prologue ~function_name ~node_hole =
           let offset_in_bytes = index * Arch.size_addr in
           Csequence (
             Cop (Cstore (Word_int, Lambda.Assignment),
-              [Cop (Caddi, [Cvar new_node; Cconst_int offset_in_bytes]);
-               Cvar new_node_encoded]),
+              [Cop (Caddi, [Cvar new_node; Cconst_int offset_in_bytes], dbg);
+               Cvar new_node_encoded], dbg),
             init_code))
         (Cvar new_node)
         indexes
@@ -79,27 +80,31 @@ let code_for_function_prologue ~function_name ~node_hole =
     | _ ->
       Clet (new_node_encoded,
         (* Cf. [Encode_tail_caller_node] in the runtime. *)
-        Cop (Cor, [Cvar new_node; Cconst_int 1]),
+        Cop (Cor, [Cvar new_node; Cconst_int 1], dbg),
         body)
   in
   let pc = Ident.create "pc" in
-  Clet (node, Cop (Cload Word_int, [Cvar node_hole]),
-    Clet (must_allocate_node, Cop (Cand, [Cvar node; Cconst_int 1]),
-      Cifthenelse (Cop (Ccmpi Cne, [Cvar must_allocate_node; Cconst_int 1]),
+  Clet (node, Cop (Cload (Word_int, Asttypes.Mutable), [Cvar node_hole], dbg),
+    Clet (must_allocate_node,
+      Cop (Cand, [Cvar node; Cconst_int 1], dbg),
+      Cifthenelse (
+        Cop (Ccmpi Cne, [Cvar must_allocate_node; Cconst_int 1], dbg),
         Cvar node,
         Clet (is_new_node,
           Clet (pc, Cconst_symbol function_name,
             Cop (Cextcall ("caml_spacetime_allocate_node",
-              [| Int |], false, Debuginfo.none, None),
+                [| Int |], false, None),
               [Cconst_int (1 (* header *) + !index_within_node);
                Cvar pc;
                Cvar node_hole;
-              ])),
-            Clet (new_node, Cop (Cload Word_int, [Cvar node_hole]),
+              ],
+              dbg)),
+            Clet (new_node,
+              Cop (Cload (Word_int, Asttypes.Mutable), [Cvar node_hole], dbg),
               if no_tail_calls then Cvar new_node
               else
                 Cifthenelse (
-                  Cop (Ccmpi Ceq, [Cvar is_new_node; Cconst_int 0]),
+                  Cop (Ccmpi Ceq, [Cvar is_new_node; Cconst_int 0], dbg),
                   Cvar new_node,
                   initialize_direct_tail_call_points_and_return_node))))))
 
@@ -125,9 +130,10 @@ let code_for_blockheader ~value's_header ~node ~dbg =
        a point to a location.
     *)
     Cop (Cextcall ("caml_spacetime_generate_profinfo", [| Int |],
-        false, dbg, Some label),
+        false, Some label),
       [Cvar address_of_profinfo;
-       Cconst_int (index_within_node + 1)])
+       Cconst_int (index_within_node + 1)],
+      dbg)
   in
   (* Check if we have already allocated a profinfo value for this allocation
      point with the current backtrace.  If so, use that value; if not,
@@ -136,29 +142,31 @@ let code_for_blockheader ~value's_header ~node ~dbg =
     Cop (Caddi, [
       Cvar node;
       Cconst_int offset_into_node;
-    ]),
-    Clet (existing_profinfo, Cop (Cload Word_int, [Cvar address_of_profinfo]),
+    ], dbg),
+    Clet (existing_profinfo,
+        Cop (Cload (Word_int, Asttypes.Mutable), [Cvar address_of_profinfo],
+          dbg),
       Clet (profinfo,
         Cifthenelse (
-          Cop (Ccmpi Cne, [Cvar existing_profinfo; Cconst_int 1 (* () *)]),
+          Cop (Ccmpi Cne, [Cvar existing_profinfo; Cconst_int 1 (* () *)], dbg),
           Cvar existing_profinfo,
           generate_new_profinfo),
         Clet (existing_count,
-          Cop (Cload Word_int, [
+          Cop (Cload (Word_int, Asttypes.Mutable), [
             Cop (Caddi,
-              [Cvar address_of_profinfo; Cconst_int Arch.size_addr])
-          ]),
+              [Cvar address_of_profinfo; Cconst_int Arch.size_addr], dbg)
+          ], dbg),
           Csequence (
             Cop (Cstore (Word_int, Lambda.Assignment),
               [Cop (Caddi,
-                [Cvar address_of_profinfo; Cconst_int Arch.size_addr]);
+                [Cvar address_of_profinfo; Cconst_int Arch.size_addr], dbg);
                 Cop (Caddi, [
                   Cvar existing_count;
                   (* N.B. "*2" since the count is an OCaml integer.
                      The "1 +" is to count the value's header. *)
                   Cconst_int (2 * (1 + Nativeint.to_int num_words));
-                ]);
-              ]),
+                ], dbg);
+              ], dbg),
             (* [profinfo] looks like a black [Infix_tag] header.  Instead of
                having to mask [profinfo] before ORing it with the desired
                header, we can use an XOR trick, to keep code size down. *)
@@ -171,7 +179,7 @@ let code_for_blockheader ~value's_header ~node ~dbg =
                     (* The following is the [Infix_offset_val], in words. *)
                     (Nativeint.of_int (index_within_node + 1)) 10))
             in
-            Cop (Cxor, [Cvar profinfo; Cconst_natint value's_header]))))))
+            Cop (Cxor, [Cvar profinfo; Cconst_natint value's_header], dbg))))))
 
 type callee =
   | Direct of string
@@ -204,9 +212,10 @@ let code_for_call ~node ~callee ~is_tail ~label =
     | Direct _ | Indirect _ -> ()
   end;
   let place_within_node = Ident.create "place_within_node" in
+  let dbg = Debuginfo.none in
   let open Cmm in
   Clet (place_within_node,
-    Cop (Caddi, [node; Cconst_int (index_within_node * Arch.size_addr)]),
+    Cop (Caddi, [node; Cconst_int (index_within_node * Arch.size_addr)], dbg),
     (* The following code returns the address that is to be moved into the
        (hard) node hole pointer register immediately before the call.
        (That move is inserted in [Selectgen].) *)
@@ -218,8 +227,9 @@ let code_for_call ~node ~callee ~is_tail ~label =
         else Cconst_int 1  (* [Val_unit] *)
       in
       Cop (Cextcall ("caml_spacetime_indirect_node_hole_ptr",
-          [| Int |], false, Debuginfo.none, None),
-        [callee; Cvar place_within_node; caller_node]))
+          [| Int |], false, None),
+        [callee; Cvar place_within_node; caller_node],
+        dbg))
 
 class virtual instruction_selection = object (self)
   inherit Selectgen.selector_generic as super
@@ -241,11 +251,11 @@ class virtual instruction_selection = object (self)
     | Some reg -> Some reg
 
   method private instrument_indirect_call ~env ~callee ~is_tail
-        ~label_after =
+      ~label_after =
     (* [callee] is a pseudoregister, so we have to bind it in the environment
        and reference the variable to which it is bound. *)
     let callee_ident = Ident.create "callee" in
-    let env = Tbl.add callee_ident [| callee |] env in
+    let env = Selectgen.env_add callee_ident [| callee |] env in
     let instrumentation =
       code_for_call
         ~node:(Lazy.force !spacetime_node)
@@ -311,7 +321,7 @@ class virtual instruction_selection = object (self)
       in
       disable_instrumentation <- false;
       let node = Lazy.force !spacetime_node_ident in
-      let node_reg = Tbl.find node env in
+      let node_reg = Selectgen.env_find node env in
       self#insert_moves node_temp_reg node_reg
     end
 
@@ -347,7 +357,7 @@ class virtual instruction_selection = object (self)
 
   method! select_allocation_args env =
     if self#can_instrument () then begin
-      let regs = Tbl.find (Lazy.force !spacetime_node_ident) env in
+      let regs = Selectgen.env_find (Lazy.force !spacetime_node_ident) env in
       match regs with
       | [| reg |] -> [| reg |]
       | _ -> failwith "Expected one register only for spacetime_node_ident"
@@ -384,7 +394,7 @@ class virtual instruction_selection = object (self)
   method! initial_env () =
     let env = super#initial_env () in
     if Config.spacetime then
-      Tbl.add (Lazy.force !spacetime_node_ident)
+      Selectgen.env_add (Lazy.force !spacetime_node_ident)
         (self#regs_for Cmm.typ_int) env
     else
       env
diff --git a/asmcomp/sparc/emit.mlp b/asmcomp/sparc/emit.mlp
index 78d0098d..a4a50f94 100644
--- a/asmcomp/sparc/emit.mlp
+++ b/asmcomp/sparc/emit.mlp
@@ -178,6 +178,7 @@ let record_frame ?label live =
           Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
+  live_offset := List.sort_uniq (-) !live_offset;
   frame_descriptors :=
     { fd_lbl = lbl;
       fd_frame_size = frame_size();
diff --git a/asmcomp/sparc/selection.ml b/asmcomp/sparc/selection.ml
index c78a5f65..1083aa38 100644
--- a/asmcomp/sparc/selection.ml
+++ b/asmcomp/sparc/selection.ml
@@ -29,19 +29,20 @@ method is_immediate n = (n <= 4095) && (n >= -4096)
 method select_addressing _chunk = function
     Cconst_symbol s ->
       (Ibased(s, 0), Ctuple [])
-  | Cop((Caddv | Cadda), [Cconst_symbol s; Cconst_int n]) ->
+  | Cop((Caddv | Cadda), [Cconst_symbol s; Cconst_int n], _) ->
       (Ibased(s, n), Ctuple [])
-  | Cop((Caddv | Cadda), [arg; Cconst_int n]) ->
+  | Cop((Caddv | Cadda), [arg; Cconst_int n], _) ->
       (Iindexed n, arg)
-  | Cop((Caddv | Cadda as op), [arg1; Cop(Caddi, [arg2; Cconst_int n])]) ->
-      (Iindexed n, Cop(op, [arg1; arg2]))
+  | Cop((Caddv | Cadda as op),
+        [arg1; Cop(Caddi, [arg2; Cconst_int n], _)], dbg) ->
+      (Iindexed n, Cop(op, [arg1; arg2], dbg))
   | arg ->
       (Iindexed 0, arg)
 
 method private iextcall (func, alloc) =
   Iextcall { func; alloc; label_after = Cmm.new_label (); }
 
-method! select_operation op args =
+method! select_operation op args dbg =
   match (op, args) with
   (* For SPARC V7 multiplication, division and modulus are turned into
      calls to C library routines.
@@ -54,7 +55,7 @@ method! select_operation op args =
   | (Cmodi, _) ->
       (self#iextcall(".rem", false), args)
   | _ ->
-      super#select_operation op args
+      super#select_operation op args dbg
 
 (* Override insert_move_args to deal correctly with floating-point
    arguments being passed into pairs of integer registers. *)
diff --git a/asmcomp/spill.ml b/asmcomp/spill.ml
index d7a05697..cefef95e 100644
--- a/asmcomp/spill.ml
+++ b/asmcomp/spill.ml
@@ -219,16 +219,41 @@ let rec reload i before =
       let (new_next, finally) = reload i.next Reg.Set.empty in
       (instr_cons (Iloop(!final_body)) i.arg i.res new_next,
        finally)
-  | Icatch(nfail, body, handler) ->
-      let new_set = ref Reg.Set.empty in
-      reload_at_exit := (nfail, new_set) :: !reload_at_exit ;
+  | Icatch(rec_flag, handlers, body) ->
+      let new_sets = List.map
+          (fun (nfail, _) -> nfail, ref Reg.Set.empty) handlers in
+      let previous_reload_at_exit = !reload_at_exit in
+      reload_at_exit := new_sets @ !reload_at_exit ;
       let (new_body, after_body) = reload body before in
-      let at_exit = !new_set in
-      reload_at_exit := List.tl !reload_at_exit ;
-      let (new_handler, after_handler) = reload handler at_exit in
-      let (new_next, finally) =
-        reload i.next (Reg.Set.union after_body after_handler) in
-      (instr_cons (Icatch(nfail, new_body, new_handler)) i.arg i.res new_next,
+      let rec fixpoint () =
+        let at_exits = List.map (fun (nfail, set) -> (nfail, !set)) new_sets in
+        let res =
+          List.map2 (fun (nfail', handler) (nfail, at_exit) ->
+              assert(nfail = nfail');
+              reload handler at_exit) handlers at_exits in
+        match rec_flag with
+        | Cmm.Nonrecursive ->
+            res
+        | Cmm.Recursive ->
+            let equal = List.for_all2 (fun (nfail', at_exit) (nfail, new_set) ->
+                assert(nfail = nfail');
+                Reg.Set.equal at_exit !new_set)
+                at_exits new_sets in
+            if equal
+            then res
+            else fixpoint ()
+      in
+      let res = fixpoint () in
+      reload_at_exit := previous_reload_at_exit;
+      let union = List.fold_left
+          (fun acc (_, after_handler) -> Reg.Set.union acc after_handler)
+          after_body res in
+      let (new_next, finally) = reload i.next union in
+      let new_handlers = List.map2
+          (fun (nfail, _) (new_handler, _) -> nfail, new_handler)
+          handlers res in
+      (instr_cons
+         (Icatch(rec_flag, new_handlers, new_body)) i.arg i.res new_next,
        finally)
   | Iexit nfail ->
       let set = find_reload_at_exit nfail in
@@ -264,11 +289,15 @@ let rec reload i before =
    NB ter: is it the same thing for catch bodies ?
 *)
 
+(* CR mshinwell for pchambart: Try to test the new algorithms for dealing
+   with Icatch. *)
 
 let spill_at_exit = ref []
 let find_spill_at_exit k =
   try
-    List.assoc k !spill_at_exit
+    let used, set = List.assoc k !spill_at_exit in
+    used := true;
+    set
   with
   | Not_found -> Misc.fatal_error "Spill.find_spill_at_exit"
 
@@ -311,7 +340,7 @@ let rec spill i finally =
       let (new_ifso, before_ifso) = spill ifso at_join in
       let (new_ifnot, before_ifnot) = spill ifnot at_join in
       if
-        !inside_loop || !inside_arm
+        !inside_loop || !inside_arm || !inside_catch
       then
         (instr_cons (Iifthenelse(test, new_ifso, new_ifnot))
                      i.arg i.res new_next,
@@ -365,16 +394,46 @@ let rec spill i finally =
       inside_loop := saved_inside_loop;
       (instr_cons (Iloop(!final_body)) i.arg i.res new_next,
        !at_head)
-  | Icatch(nfail, body, handler) ->
+  | Icatch(rec_flag, handlers, body) ->
       let (new_next, at_join) = spill i.next finally in
-      let (new_handler, at_exit) = spill handler at_join in
       let saved_inside_catch = !inside_catch in
       inside_catch := true ;
-      spill_at_exit := (nfail, at_exit) :: !spill_at_exit ;
-      let (new_body, before) = spill body at_join in
-      spill_at_exit := List.tl !spill_at_exit;
+      let previous_spill_at_exit = !spill_at_exit in
+      let spill_at_exit_add at_exits = List.map2
+          (fun (nfail,_) at_exit -> nfail, (ref false, at_exit))
+          handlers at_exits
+      in
+      let rec fixpoint at_exits =
+        let spill_at_exit_add = spill_at_exit_add at_exits in
+        spill_at_exit := spill_at_exit_add @ !spill_at_exit;
+        let res =
+          List.map (fun (_, handler) -> spill handler at_join) handlers
+        in
+        spill_at_exit := previous_spill_at_exit;
+        match rec_flag with
+        | Cmm.Nonrecursive ->
+            res
+        | Cmm.Recursive ->
+            let equal =
+              List.for_all2
+                (fun (_new_handler, new_at_exit) (_, (used, at_exit)) ->
+                   Reg.Set.equal at_exit new_at_exit || not !used)
+                res spill_at_exit_add in
+            if equal
+            then res
+            else fixpoint (List.map snd res)
+      in
+      let res = fixpoint (List.map (fun _ -> Reg.Set.empty) handlers) in
       inside_catch := saved_inside_catch ;
-      (instr_cons (Icatch(nfail, new_body, new_handler)) i.arg i.res new_next,
+      let spill_at_exit_add = spill_at_exit_add (List.map snd res) in
+      spill_at_exit := spill_at_exit_add @ !spill_at_exit;
+      let (new_body, before) = spill body at_join in
+      spill_at_exit := previous_spill_at_exit;
+      let new_handlers = List.map2
+          (fun (nfail, _) (handler, _) -> nfail, handler)
+          handlers res in
+      (instr_cons (Icatch(rec_flag, new_handlers, new_body))
+         i.arg i.res new_next,
        before)
   | Iexit nfail ->
       (i, find_spill_at_exit nfail)
diff --git a/asmcomp/split.ml b/asmcomp/split.ml
index 00b009ec..ec1a52de 100644
--- a/asmcomp/split.ml
+++ b/asmcomp/split.ml
@@ -165,16 +165,24 @@ let rec rename i sub =
       let (new_next, sub_next) = rename i.next (merge_substs sub sub_body i) in
       (instr_cons (Iloop(new_body)) [||] [||] new_next,
        sub_next)
-  | Icatch(nfail, body, handler) ->
-      let new_subst = ref None in
-      exit_subst := (nfail, new_subst) :: !exit_subst ;
+  | Icatch(rec_flag, handlers, body) ->
+      let new_subst = List.map (fun (nfail, _) -> nfail, ref None)
+          handlers in
+      let previous_exit_subst = !exit_subst in
+      exit_subst := new_subst @ !exit_subst;
       let (new_body, sub_body) = rename body sub in
-      let sub_entry_handler = !new_subst in
-      exit_subst := List.tl !exit_subst;
-      let (new_handler, sub_handler) = rename handler sub_entry_handler in
-      let (new_next, sub_next) =
-        rename i.next (merge_substs sub_body sub_handler i.next) in
-      (instr_cons (Icatch(nfail, new_body, new_handler)) [||] [||] new_next,
+      let res = List.map2 (fun (_, handler) (_, new_subst) -> rename handler !new_subst)
+          handlers new_subst in
+      exit_subst := previous_exit_subst;
+      let merged_subst =
+        List.fold_left (fun acc (_, sub_handler) ->
+            merge_substs acc sub_handler i.next)
+          sub_body res in
+      let (new_next, sub_next) = rename i.next merged_subst in
+      let new_handlers = List.map2 (fun (nfail, _) (handler, _) ->
+          (nfail, handler)) handlers res in
+      (instr_cons
+         (Icatch(rec_flag, new_handlers, new_body)) [||] [||] new_next,
        sub_next)
   | Iexit nfail ->
       let r = find_exit_subst nfail in
diff --git a/asmcomp/strmatch.ml b/asmcomp/strmatch.ml
index 720bd645..983f5340 100644
--- a/asmcomp/strmatch.ml
+++ b/asmcomp/strmatch.ml
@@ -71,8 +71,11 @@ module Make(I:I) = struct
   let gen_size_id () = Ident.create "size"
 
   let mk_let_cell id str ind body =
+    let dbg = Debuginfo.none in
     let cell =
-      Cop(Cload Word_int,[Cop(Cadda,[str;Cconst_int(Arch.size_int*ind)])]) in
+      Cop(Cload (Word_int, Asttypes.Mutable),
+        [Cop(Cadda,[str;Cconst_int(Arch.size_int*ind)], dbg)],
+        dbg) in
     Clet(id, cell, body)
 
   let mk_let_size id str body =
@@ -80,7 +83,10 @@ module Make(I:I) = struct
     Clet(id, size, body)
 
   let mk_cmp_gen cmp_op id nat ifso ifnot =
-    let test = Cop (Ccmpi cmp_op, [ Cvar id; Cconst_natpointer nat ]) in
+    let dbg = Debuginfo.none in
+    let test =
+      Cop (Ccmpi cmp_op, [ Cvar id; Cconst_natpointer nat ], dbg)
+    in
     Cifthenelse (test, ifso, ifnot)
 
   let mk_lt = mk_cmp_gen Clt
@@ -332,7 +338,7 @@ module Make(I:I) = struct
   In that latter case pattern len is string length-1 and is corrected.
  *)
 
-    let compile_by_size from_ind str default cases =
+    let compile_by_size dbg from_ind str default cases =
       let size_cases =
         List.map
           (fun (len,cases) ->
@@ -344,6 +350,7 @@ module Make(I:I) = struct
             (len,act))
           (by_size cases) in
       let id = gen_size_id () in
+      ignore dbg;
       let switch = I.transl_switch (Cvar id) 1 max_int size_cases default in
       mk_let_size id str switch
 
@@ -352,16 +359,16 @@ module Make(I:I) = struct
   either on size or on first cell, using the
   'least discriminant' heuristics.
  *)
-    let top_compile str default cases =
+    let top_compile debuginfo str default cases =
       let a_len = count_arities_length cases
       and a_fst = count_arities_first cases in
       if a_len <= a_fst then begin
         if dbg then pp_cases stderr "SIZE" cases ;
-        compile_by_size 0 str default cases
+        compile_by_size debuginfo 0 str default cases
       end else begin
         if dbg then pp_cases stderr "FIRST COL" cases ;
         let compile_size_rest str default cases =
-          compile_by_size 1 str default cases in
+          compile_by_size debuginfo 1 str default cases in
         match_oncell compile_size_rest str default 0 (by_cell cases)
       end
 
@@ -371,9 +378,9 @@ module Make(I:I) = struct
     | Cexit (_e,[]) ->  k arg
     | _ ->
         let e =  next_raise_count () in
-        Ccatch (e,[],k (Cexit (e,[])),arg)
+        ccatch (e,[],k (Cexit (e,[])),arg)
 
-    let compile str default cases =
+    let compile dbg str default cases =
 (* We do not attempt to really optimise default=None *)
       let cases,default = match cases,default with
       | (_,e)::cases,None
@@ -383,6 +390,6 @@ module Make(I:I) = struct
         List.rev_map
           (fun (s,act) -> pat_of_string s,act)
           cases in
-      catch default (fun default -> top_compile str default cases)
+      catch default (fun default -> top_compile dbg str default cases)
 
   end
diff --git a/asmcomp/strmatch.mli b/asmcomp/strmatch.mli
index 4371502c..35bfc535 100644
--- a/asmcomp/strmatch.mli
+++ b/asmcomp/strmatch.mli
@@ -26,6 +26,7 @@ end
 module Make(I:I) : sig
   (* Compile stringswitch (arg,cases,d)
      Note: cases should not contain string duplicates *)
-  val compile : Cmm.expression (* arg *) -> Cmm.expression option (* d *) ->
+  val compile : Debuginfo.t -> Cmm.expression (* arg *)
+    -> Cmm.expression option (* d *) ->
     (string * Cmm.expression) list (* cases *)-> Cmm.expression
 end
diff --git a/asmcomp/un_anf.ml b/asmcomp/un_anf.ml
index b87ac249..9d373cab 100644
--- a/asmcomp/un_anf.ml
+++ b/asmcomp/un_anf.ml
@@ -35,6 +35,7 @@ let ignore_function_label (_ : Clambda.function_label) = ()
 let ignore_debuginfo (_ : Debuginfo.t) = ()
 let ignore_int (_ : int) = ()
 let ignore_ident (_ : Ident.t) = ()
+let ignore_ident_option (_ : Ident.t option) = ()
 let ignore_primitive (_ : Lambda.primitive) = ()
 let ignore_string (_ : string) = ()
 let ignore_int_array (_ : int array) = ()
@@ -86,7 +87,8 @@ let make_ident_info (clam : Clambda.ulambda) : ident_info =
       ignore_debuginfo dbg
     | Uclosure (functions, captured_variables) ->
       List.iter loop captured_variables;
-      List.iter (fun ({ Clambda. label; arity; params; body; dbg } as clos) ->
+      List.iter (fun (
+        { Clambda. label; arity; params; body; dbg; env; } as clos) ->
           (match closure_environment_ident clos with
            | None -> ()
            | Some env_var ->
@@ -96,7 +98,8 @@ let make_ident_info (clam : Clambda.ulambda) : ident_info =
           ignore_int arity;
           ignore_ident_list params;
           loop body;
-          ignore_debuginfo dbg)
+          ignore_debuginfo dbg;
+          ignore_ident_option env)
         functions
     | Uoffset (expr, offset) ->
       loop expr;
@@ -253,14 +256,15 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
     | Uclosure (functions, captured_variables) ->
       ignore_ulambda_list captured_variables;
       (* Start a new let stack for speed. *)
-      List.iter (fun { Clambda. label; arity; params; body; dbg; } ->
+      List.iter (fun { Clambda. label; arity; params; body; dbg; env; } ->
           ignore_function_label label;
           ignore_int arity;
           ignore_ident_list params;
           let_stack := [];
           loop body;
           let_stack := [];
-          ignore_debuginfo dbg)
+          ignore_debuginfo dbg;
+          ignore_ident_option env)
         functions
     | Uoffset (expr, offset) ->
       (* [expr] should usually be a variable. *)
@@ -520,7 +524,7 @@ and substitute_let_moveable_array is_let_moveable env clams =
 (* We say that an expression is "moveable" iff it has neither effects nor
    coeffects.  (See semantics_of_primitives.mli.)
 *)
-type moveable = Fixed | Constant | Moveable | Moveable_not_into_loops
+type moveable = Fixed | Constant | Moveable
 
 let both_moveable a b =
   match a, b with
@@ -528,17 +532,10 @@ let both_moveable a b =
   | Constant, Moveable
   | Moveable, Constant
   | Moveable, Moveable -> Moveable
-  | Moveable_not_into_loops, Constant
-  | Moveable_not_into_loops, Moveable
-  | Constant, Moveable_not_into_loops
-  | Moveable, Moveable_not_into_loops
-  | Moveable_not_into_loops, Moveable_not_into_loops -> Moveable_not_into_loops
   | Constant, Fixed
   | Moveable, Fixed
-  | Moveable_not_into_loops, Fixed
   | Fixed, Constant
   | Fixed, Moveable
-  | Fixed, Moveable_not_into_loops
   | Fixed, Fixed -> Fixed
 
 let primitive_moveable (prim : Lambda.primitive)
@@ -566,17 +563,7 @@ let primitive_moveable (prim : Lambda.primitive)
     | Arbitrary_effects, No_coeffects
     | Arbitrary_effects, Has_coeffects -> Fixed
 
-type moveable_for_env = Constant | Moveable | Moveable_not_into_loops
-
-(** Called when we are entering a loop or body of a function (which may be
-    called multiple times).  The environment is rewritten such that
-    identifiers previously moveable, but not into loops, are now fixed. *)
-let going_into_loop env =
-  Ident.Map.filter_map env ~f:(fun _var ((moveable : moveable_for_env), def) ->
-    match moveable with
-    | Constant -> Some (Constant, def)
-    | Moveable -> Some (Moveable, def)
-    | Moveable_not_into_loops -> None)
+type moveable_for_env = Constant | Moveable
 
 (** Eliminate, through substitution, [let]-bindings of linear variables with
     moveable defining expressions. *)
@@ -587,7 +574,6 @@ let rec un_anf_and_moveable ident_info env (clam : Clambda.ulambda)
     begin match Ident.Map.find id env with
     | Constant, def -> def, Constant
     | Moveable, def -> def, Moveable
-    | Moveable_not_into_loops, def -> def, Moveable_not_into_loops
     | exception Not_found ->
       let moveable : moveable =
         if Ident.Set.mem id ident_info.assigned then
@@ -611,15 +597,14 @@ let rec un_anf_and_moveable ident_info env (clam : Clambda.ulambda)
     let functions =
       List.map (fun (ufunction : Clambda.ufunction) ->
           { ufunction with
-            body = un_anf ident_info (going_into_loop env) ufunction.body;
+            body = un_anf ident_info env ufunction.body;
           })
         functions
     in
-    let variables_bound_by_the_closure, moveable =
-      un_anf_list_and_moveable ident_info env variables_bound_by_the_closure
+    let variables_bound_by_the_closure =
+      un_anf_list ident_info env variables_bound_by_the_closure
     in
-    Uclosure (functions, variables_bound_by_the_closure),
-      both_moveable moveable Moveable_not_into_loops
+    Uclosure (functions, variables_bound_by_the_closure), Fixed
   | Uoffset (clam, n) ->
     let clam, moveable = un_anf_and_moveable ident_info env clam in
     Uoffset (clam, n), both_moveable Moveable moveable
@@ -631,7 +616,7 @@ let rec un_anf_and_moveable ident_info env (clam : Clambda.ulambda)
     let is_used = Ident.Set.mem id ident_info.used in
     let is_assigned = Ident.Set.mem id ident_info.assigned in
     begin match def_moveable, is_linear, is_used, is_assigned with
-    | (Constant | Moveable | Moveable_not_into_loops), _, false, _ ->
+    | (Constant | Moveable), _, false, _ ->
       (* A moveable expression that is never used may be eliminated. *)
       un_anf_and_moveable ident_info env body
     | Constant, _, true, false
@@ -644,19 +629,13 @@ let rec un_anf_and_moveable ident_info env (clam : Clambda.ulambda)
         match def_moveable with
         | Moveable -> Moveable
         | Constant -> Constant
-        | Moveable_not_into_loops -> Moveable_not_into_loops
         | Fixed -> assert false
       in
       let env = Ident.Map.add id (def_moveable, def) env in
       un_anf_and_moveable ident_info env body
-    | Moveable_not_into_loops, true, true, false
-        (* We can't delete the [let] binding in this case because we don't
-           know whether the variable was substituted for its definition
-           (in the case of its linear use not being inside a loop) or not.
-           We could extend the code to cope with this case. *)
-    | (Constant | Moveable | Moveable_not_into_loops), _, _, true
+    | (Constant | Moveable), _, _, true
         (* Constant or Moveable but assigned. *)
-    | (Moveable | Moveable_not_into_loops), false, _, _
+    | Moveable, false, _, _
         (* Moveable but not used linearly. *)
     | Fixed, _, _, _ ->
       let body, body_moveable = un_anf_and_moveable ident_info env body in
@@ -717,14 +696,13 @@ let rec un_anf_and_moveable ident_info env (clam : Clambda.ulambda)
     let e2 = un_anf ident_info env e2 in
     Usequence (e1, e2), Fixed
   | Uwhile (cond, body) ->
-    let env = going_into_loop env in
     let cond = un_anf ident_info env cond in
     let body = un_anf ident_info env body in
     Uwhile (cond, body), Fixed
   | Ufor (id, low, high, direction, body) ->
     let low = un_anf ident_info env low in
     let high = un_anf ident_info env high in
-    let body = un_anf ident_info (going_into_loop env) body in
+    let body = un_anf ident_info env body in
     Ufor (id, low, high, direction, body), Fixed
   | Uassign (id, expr) ->
     let expr = un_anf ident_info env expr in
diff --git a/asmrun/.depend b/asmrun/.depend
index 276dd8b0..c2fa489b 100644
--- a/asmrun/.depend
+++ b/asmrun/.depend
@@ -1,3 +1,6 @@
+afl.o: afl.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h
 alloc.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -11,8 +14,8 @@ array.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h spacetime.h ../byterun/caml/io.h \
-  ../byterun/caml/stack.h
+  ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
+  ../byterun/caml/io.h ../byterun/caml/stack.h
 backtrace.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -64,7 +67,7 @@ custom.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
 debugger.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/debugger.h
+  ../byterun/caml/debugger.h ../byterun/caml/osdeps.h
 dynlink.o: dynlink.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/alloc.h ../byterun/caml/misc.h \
@@ -224,7 +227,8 @@ misc.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/version.h
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/version.h
 natdynlink.o: natdynlink.c ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -241,8 +245,9 @@ obj.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/prims.h spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
+  ../byterun/caml/address_class.h ../byterun/caml/prims.h \
+  ../byterun/caml/spacetime.h ../byterun/caml/io.h \
+  ../byterun/caml/stack.h
 parsing.o: parsing.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
@@ -281,7 +286,7 @@ signals_asm.o: signals_asm.c ../byterun/caml/fail.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
   ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
-  signals_osdep.h ../byterun/caml/stack.h spacetime.h \
+  signals_osdep.h ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
   ../byterun/caml/io.h
 spacetime.o: spacetime.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -292,8 +297,9 @@ spacetime.o: spacetime.c ../byterun/caml/config.h \
   ../byterun/caml/io.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/sys.h spacetime.h
+  ../byterun/caml/osdeps.h ../byterun/caml/roots.h \
+  ../byterun/caml/signals.h ../byterun/caml/stack.h \
+  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
 spacetime_offline.o: spacetime_offline.c ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -303,7 +309,7 @@ spacetime_offline.o: spacetime_offline.c ../byterun/caml/alloc.h \
   ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/roots.h \
   ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h spacetime.h ../config/s.h
+  ../byterun/caml/sys.h ../byterun/caml/spacetime.h ../config/s.h
 spacetime_snapshot.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -315,7 +321,8 @@ spacetime_snapshot.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
   ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/sys.h spacetime.h
+  ../byterun/caml/stack.h ../byterun/caml/sys.h \
+  ../byterun/caml/spacetime.h
 startup.o: startup.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -335,7 +342,8 @@ startup_aux.o: startup_aux.c ../byterun/caml/backtrace.h \
   ../byterun/caml/misc.h ../byterun/caml/exec.h ../byterun/caml/memory.h \
   ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/startup_aux.h
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/startup_aux.h
 str.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -370,6 +378,9 @@ weak.o: weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/weak.h
+afl.p.o: afl.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h
 alloc.p.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -383,8 +394,8 @@ array.p.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h spacetime.h ../byterun/caml/io.h \
-  ../byterun/caml/stack.h
+  ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
+  ../byterun/caml/io.h ../byterun/caml/stack.h
 backtrace.p.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -436,7 +447,7 @@ custom.p.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
 debugger.p.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/debugger.h
+  ../byterun/caml/debugger.h ../byterun/caml/osdeps.h
 dynlink.p.o: dynlink.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/alloc.h ../byterun/caml/misc.h \
@@ -596,7 +607,8 @@ misc.p.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/version.h
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/version.h
 natdynlink.p.o: natdynlink.c ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -613,8 +625,9 @@ obj.p.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/prims.h spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
+  ../byterun/caml/address_class.h ../byterun/caml/prims.h \
+  ../byterun/caml/spacetime.h ../byterun/caml/io.h \
+  ../byterun/caml/stack.h
 parsing.p.o: parsing.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
@@ -653,7 +666,7 @@ signals_asm.p.o: signals_asm.c ../byterun/caml/fail.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
   ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
-  signals_osdep.h ../byterun/caml/stack.h spacetime.h \
+  signals_osdep.h ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
   ../byterun/caml/io.h
 spacetime.p.o: spacetime.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -664,8 +677,9 @@ spacetime.p.o: spacetime.c ../byterun/caml/config.h \
   ../byterun/caml/io.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/sys.h spacetime.h
+  ../byterun/caml/osdeps.h ../byterun/caml/roots.h \
+  ../byterun/caml/signals.h ../byterun/caml/stack.h \
+  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
 spacetime_offline.p.o: spacetime_offline.c ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -675,7 +689,7 @@ spacetime_offline.p.o: spacetime_offline.c ../byterun/caml/alloc.h \
   ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/roots.h \
   ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h spacetime.h ../config/s.h
+  ../byterun/caml/sys.h ../byterun/caml/spacetime.h ../config/s.h
 spacetime_snapshot.p.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -687,7 +701,8 @@ spacetime_snapshot.p.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
   ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/sys.h spacetime.h
+  ../byterun/caml/stack.h ../byterun/caml/sys.h \
+  ../byterun/caml/spacetime.h
 startup.p.o: startup.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -707,7 +722,8 @@ startup_aux.p.o: startup_aux.c ../byterun/caml/backtrace.h \
   ../byterun/caml/misc.h ../byterun/caml/exec.h ../byterun/caml/memory.h \
   ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/startup_aux.h
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/startup_aux.h
 str.p.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -742,6 +758,9 @@ weak.p.o: weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/weak.h
+afl.d.o: afl.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h
 alloc.d.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -755,8 +774,8 @@ array.d.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h spacetime.h ../byterun/caml/io.h \
-  ../byterun/caml/stack.h
+  ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
+  ../byterun/caml/io.h ../byterun/caml/stack.h
 backtrace.d.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -808,7 +827,7 @@ custom.d.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
 debugger.d.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/debugger.h
+  ../byterun/caml/debugger.h ../byterun/caml/osdeps.h
 dynlink.d.o: dynlink.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/alloc.h ../byterun/caml/misc.h \
@@ -968,7 +987,8 @@ misc.d.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/version.h
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/version.h
 natdynlink.d.o: natdynlink.c ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -985,8 +1005,9 @@ obj.d.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/prims.h spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
+  ../byterun/caml/address_class.h ../byterun/caml/prims.h \
+  ../byterun/caml/spacetime.h ../byterun/caml/io.h \
+  ../byterun/caml/stack.h
 parsing.d.o: parsing.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
@@ -1025,7 +1046,7 @@ signals_asm.d.o: signals_asm.c ../byterun/caml/fail.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
   ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
-  signals_osdep.h ../byterun/caml/stack.h spacetime.h \
+  signals_osdep.h ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
   ../byterun/caml/io.h
 spacetime.d.o: spacetime.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -1036,8 +1057,9 @@ spacetime.d.o: spacetime.c ../byterun/caml/config.h \
   ../byterun/caml/io.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/sys.h spacetime.h
+  ../byterun/caml/osdeps.h ../byterun/caml/roots.h \
+  ../byterun/caml/signals.h ../byterun/caml/stack.h \
+  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
 spacetime_offline.d.o: spacetime_offline.c ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -1047,7 +1069,7 @@ spacetime_offline.d.o: spacetime_offline.c ../byterun/caml/alloc.h \
   ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/roots.h \
   ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h spacetime.h ../config/s.h
+  ../byterun/caml/sys.h ../byterun/caml/spacetime.h ../config/s.h
 spacetime_snapshot.d.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -1059,7 +1081,8 @@ spacetime_snapshot.d.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
   ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/sys.h spacetime.h
+  ../byterun/caml/stack.h ../byterun/caml/sys.h \
+  ../byterun/caml/spacetime.h
 startup.d.o: startup.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -1079,7 +1102,8 @@ startup_aux.d.o: startup_aux.c ../byterun/caml/backtrace.h \
   ../byterun/caml/misc.h ../byterun/caml/exec.h ../byterun/caml/memory.h \
   ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/startup_aux.h
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/startup_aux.h
 str.d.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -1114,6 +1138,9 @@ weak.d.o: weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/weak.h
+afl.i.o: afl.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h
 alloc.i.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -1127,8 +1154,8 @@ array.i.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h spacetime.h ../byterun/caml/io.h \
-  ../byterun/caml/stack.h
+  ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
+  ../byterun/caml/io.h ../byterun/caml/stack.h
 backtrace.i.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -1180,7 +1207,7 @@ custom.i.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
 debugger.i.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/debugger.h
+  ../byterun/caml/debugger.h ../byterun/caml/osdeps.h
 dynlink.i.o: dynlink.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/alloc.h ../byterun/caml/misc.h \
@@ -1340,7 +1367,8 @@ misc.i.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/version.h
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/version.h
 natdynlink.i.o: natdynlink.c ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
@@ -1357,8 +1385,9 @@ obj.i.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/prims.h spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
+  ../byterun/caml/address_class.h ../byterun/caml/prims.h \
+  ../byterun/caml/spacetime.h ../byterun/caml/io.h \
+  ../byterun/caml/stack.h
 parsing.i.o: parsing.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
@@ -1397,7 +1426,7 @@ signals_asm.i.o: signals_asm.c ../byterun/caml/fail.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
   ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
-  signals_osdep.h ../byterun/caml/stack.h spacetime.h \
+  signals_osdep.h ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
   ../byterun/caml/io.h
 spacetime.i.o: spacetime.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -1408,8 +1437,9 @@ spacetime.i.o: spacetime.c ../byterun/caml/config.h \
   ../byterun/caml/io.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/sys.h spacetime.h
+  ../byterun/caml/osdeps.h ../byterun/caml/roots.h \
+  ../byterun/caml/signals.h ../byterun/caml/stack.h \
+  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
 spacetime_offline.i.o: spacetime_offline.c ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -1419,7 +1449,7 @@ spacetime_offline.i.o: spacetime_offline.c ../byterun/caml/alloc.h \
   ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
   ../byterun/caml/address_class.h ../byterun/caml/roots.h \
   ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h spacetime.h ../config/s.h
+  ../byterun/caml/sys.h ../byterun/caml/spacetime.h ../config/s.h
 spacetime_snapshot.i.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -1431,7 +1461,8 @@ spacetime_snapshot.i.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
   ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/sys.h spacetime.h
+  ../byterun/caml/stack.h ../byterun/caml/sys.h \
+  ../byterun/caml/spacetime.h
 startup.i.o: startup.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -1451,7 +1482,8 @@ startup_aux.i.o: startup_aux.c ../byterun/caml/backtrace.h \
   ../byterun/caml/misc.h ../byterun/caml/exec.h ../byterun/caml/memory.h \
   ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/startup_aux.h
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/startup_aux.h
 str.i.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
diff --git a/asmrun/Makefile b/asmrun/Makefile
index 9588c163..aab82db0 100644
--- a/asmrun/Makefile
+++ b/asmrun/Makefile
@@ -15,244 +15,183 @@
 
 include ../config/Makefile
 
-CC=$(NATIVECC)
-FLAGS=-I../byterun -DCAML_NAME_SPACE -DNATIVE_CODE \
-      -DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) $(IFLEXDIR) \
-      $(LIBUNWIND_INCLUDE_FLAGS)
-#CFLAGS=$(FLAGS) -g -O0
-CFLAGS=$(FLAGS) -g -O0 $(NATIVECCCOMPOPTS)
-DFLAGS=$(FLAGS) -g -DDEBUG $(NATIVECCCOMPOPTS)
-IFLAGS=$(FLAGS) -DCAML_INSTR
-PFLAGS=$(FLAGS) -pg -DPROFILING $(NATIVECCPROFOPTS) $(NATIVECCCOMPOPTS)
-PICFLAGS=$(FLAGS) $(SHAREDCCCOMPOPTS) $(NATIVECCCOMPOPTS)
+LINKEDFILES=misc.c freelist.c major_gc.c minor_gc.c memory.c alloc.c array.c \
+  compare.c ints.c floats.c str.c io.c extern.c intern.c hash.c sys.c \
+  parsing.c gc_ctrl.c terminfo.c md5.c obj.c lexing.c printexc.c callback.c \
+  weak.c compact.c finalise.c meta.c custom.c main.c globroots.c \
+  $(UNIX_OR_WIN32).c dynlink.c signals.c debugger.c startup_aux.c \
+  backtrace.c afl.c
 
-COBJS=startup_aux.o startup.o \
-  main.o fail.o roots.o globroots.o signals.o signals_asm.o \
-  freelist.o misc.o major_gc.o minor_gc.o memory.o alloc.o compare.o ints.o \
-  floats.o str.o array.o io.o extern.o intern.o hash.o sys.o parsing.o \
-  gc_ctrl.o terminfo.o md5.o obj.o lexing.o printexc.o callback.o weak.o \
-  compact.o finalise.o custom.o $(UNIX_OR_WIN32).o backtrace_prim.o \
-  backtrace.o \
-  natdynlink.o debugger.o meta.o dynlink.o clambda_checks.o \
-  spacetime.o spacetime_snapshot.o spacetime_offline.o
+INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
 
-ASMOBJS=$(ARCH).o
+CC=$(NATIVECC)
 
-OBJS=$(COBJS) $(ASMOBJS)
-DOBJS=$(COBJS:.o=.d.o) $(ASMOBJS)
-IOBJS=$(COBJS:.o=.i.o) $(ASMOBJS)
-POBJS=$(COBJS:.o=.p.o) $(ASMOBJS:.o=.p.o)
-PICOBJS=$(COBJS:.o=.pic.o) $(ASMOBJS:.o=.pic.o)
+ifeq "$(UNIX_OR_WIN32)" "win32"
+LN = cp
+else
+LN = ln -s
+endif
 
-all: libasmrun.a all-$(RUNTIMED) all-$(PROFILING) all-$(SHARED)
+FLAGS=\
+  -I../byterun \
+  -DNATIVE_CODE -DTARGET_$(ARCH)
 
-ifeq "$(RUNTIMEI)" "true"
-all: libasmruni.a
+ifeq "$(UNIX_OR_WIN32)" "unix"
+FLAGS += -DMODEL_$(MODEL)
 endif
 
-libasmrun.a: $(OBJS)
-	rm -f libasmrun.a
-	$(ARCMD) rc libasmrun.a $(OBJS)
-	$(RANLIB) libasmrun.a
+FLAGS += -DSYS_$(SYSTEM) \
+  $(NATIVECCCOMPOPTS) $(IFLEXDIR) \
+  $(LIBUNWIND_INCLUDE_FLAGS)
 
-all-noruntimed:
-.PHONY: all-noruntimed
+ifeq "$(TOOLCHAIN)" "msvc"
+DFLAGS=$(FLAGS) -DDEBUG
+PFLAGS=$(FLAGS) -DPROFILING $(NATIVECCPROFOPTS)
+OUTPUTOBJ = -Fo
+ASMOBJS=$(ARCH)nt.$(O)
+else
+DFLAGS=$(FLAGS) -g -DDEBUG
+PFLAGS=$(FLAGS) -pg -DPROFILING $(NATIVECCPROFOPTS)
+OUTPUTOBJ = -o
+ASMOBJS=$(ARCH).$(O)
+endif
 
-all-runtimed: libasmrund.a
-.PHONY: all-runtimed
+IFLAGS=$(FLAGS) -DCAML_INSTR
+PICFLAGS=$(FLAGS) $(SHAREDCCCOMPOPTS)
 
-libasmrund.a: $(DOBJS)
-	rm -f libasmrund.a
-	$(ARCMD) rc libasmrund.a $(DOBJS)
-	$(RANLIB) libasmrund.a
+ASPPFLAGS = -DSYS_$(SYSTEM)
+ifeq "$(UNIX_OR_WIN32)" "unix"
+ASPPFLAGS += -DMODEL_$(MODEL)
+CFLAGS=$(FLAGS) -g
+else
+CFLAGS=$(FLAGS)
+endif
 
-libasmruni.a: $(IOBJS)
-	rm -f $@
-	$(ARCMD) rc $@ $^
-	$(RANLIB) $@
+COBJS=startup_aux.$(O) startup.$(O) main.$(O) fail.$(O)		\
+  roots.$(O) signals.$(O) signals_asm.$(O) misc.$(O) freelist.$(O)	\
+  major_gc.$(O) minor_gc.$(O) memory.$(O) alloc.$(O) compare.$(O)	\
+  ints.$(O) floats.$(O) str.$(O) array.$(O) io.$(O) extern.$(O)		\
+  intern.$(O) hash.$(O) sys.$(O) parsing.$(O) gc_ctrl.$(O)		\
+  terminfo.$(O) md5.$(O) obj.$(O) lexing.$(O) $(UNIX_OR_WIN32).$(O)	\
+  printexc.$(O) callback.$(O) weak.$(O) compact.$(O) finalise.$(O)	\
+  custom.$(O) globroots.$(O) backtrace_prim.$(O) backtrace.$(O)		\
+  natdynlink.$(O) debugger.$(O) meta.$(O) dynlink.$(O)			\
+  clambda_checks.$(O) spacetime.$(O) spacetime_snapshot.$(O)		\
+  spacetime_offline.$(O) afl.$(O)
 
-all-noprof:
+OBJS=$(COBJS) $(ASMOBJS)
 
-all-prof: libasmrunp.a
+DOBJS=$(COBJS:.$(O)=.d.$(O)) $(ASMOBJS)
+IOBJS=$(COBJS:.$(O)=.i.$(O)) $(ASMOBJS)
+POBJS=$(COBJS:.$(O)=.p.$(O)) $(ASMOBJS:.$(O)=.p.$(O))
+PICOBJS=$(COBJS:.$(O)=.pic.$(O)) $(ASMOBJS:.$(O)=.pic.$(O))
 
-libasmrunp.a: $(POBJS)
-	rm -f libasmrunp.a
-	$(ARCMD) rc libasmrunp.a $(POBJS)
-	$(RANLIB) libasmrunp.a
+TARGETS = libasmrun.$(A)
 
-all-noshared:
+ifeq "$(RUNTIMED)" "true"
+TARGETS += libasmrund.$(A)
+endif
 
-all-shared: libasmrun_pic.a libasmrun_shared.so
+ifeq "$(RUNTIMEI)" "true"
+TARGETS += libasmruni.$(A)
+endif
 
-libasmrun_pic.a: $(PICOBJS)
-	rm -f libasmrun_pic.a
-	$(ARCMD) rc libasmrun_pic.a $(PICOBJS)
-	$(RANLIB) libasmrun_pic.a
+ifeq "$(PROFILING)" "true"
+TARGETS += libasmrunp.$(A)
+endif
 
-libasmrun_shared.so: $(PICOBJS)
-	$(MKDLL) -o libasmrun_shared.so $(PICOBJS) $(NATIVECCLIBS)
+ifeq "$(UNIX_OR_WIN32)" "unix"
+ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"
+TARGETS += libasmrun_pic.$(A) libasmrun_shared.$(SO)
+endif
+endif
 
-INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
+.PHONY: all
+all: $(TARGETS)
 
-install::
-	cp libasmrun.a $(INSTALL_LIBDIR)/libasmrun.a
-	cd $(INSTALL_LIBDIR); $(RANLIB) libasmrun.a
-.PHONY: install-default
+libasmrun.$(A): $(OBJS)
+	$(call MKLIB,$@, $^)
 
-ifeq "$(RUNTIMED)" "runtimed"
-install::
-	cp libasmrund.a $(INSTALL_LIBDIR)/libasmrund.a
-	cd $(INSTALL_LIBDIR); $(RANLIB) libasmrund.a
-endif
+libasmrund.$(A): $(DOBJS)
+	$(call MKLIB,$@, $^)
 
-ifeq "$(RUNTIMEI)" "true"
-install::
-	cp libasmruni.a $(INSTALL_LIBDIR)/libasmruni.a
-	cd $(INSTALL_LIBDIR); $(RANLIB) libasmruni.a
-endif
+libasmruni.$(A): $(IOBJS)
+	$(call MKLIB,$@, $^)
 
-ifeq "$(PROFILING)" "prof"
-install::
-	cp libasmrunp.a $(INSTALL_LIBDIR)/libasmrunp.a
-	cd $(INSTALL_LIBDIR); $(RANLIB) libasmrunp.a
-else
-install::
-	rm -f $(INSTALL_LIBDIR)/libasmrunp.a
-	ln -s libasmrun.a $(INSTALL_LIBDIR)/libasmrunp.a
-endif
+libasmrunp.$(A): $(POBJS)
+	$(call MKLIB,$@, $^)
 
-ifeq "$(SHARED)" "shared"
-install::
-	cp libasmrun_pic.a $(INSTALL_LIBDIR)/libasmrun_pic.a
-	cd $(INSTALL_LIBDIR); $(RANLIB) libasmrunp.a
-	cp libasmrun_shared.so $(INSTALL_LIBDIR)/libasmrun_shared.so
-endif
+libasmrun_pic.$(A): $(PICOBJS)
+	$(call MKLIB,$@, $^)
 
-main.c: ../byterun/main.c
-	ln -s ../byterun/main.c main.c
-startup_aux.c: ../byterun/startup_aux.c
-	ln -s ../byterun/startup_aux.c startup_aux.c
-backtrace.c: ../byterun/backtrace.c
-	ln -s ../byterun/backtrace.c backtrace.c
-misc.c: ../byterun/misc.c
-	ln -s ../byterun/misc.c misc.c
-freelist.c: ../byterun/freelist.c
-	ln -s ../byterun/freelist.c freelist.c
-major_gc.c: ../byterun/major_gc.c
-	ln -s ../byterun/major_gc.c major_gc.c
-minor_gc.c: ../byterun/minor_gc.c
-	ln -s ../byterun/minor_gc.c minor_gc.c
-memory.c: ../byterun/memory.c
-	ln -s ../byterun/memory.c memory.c
-alloc.c: ../byterun/alloc.c
-	ln -s ../byterun/alloc.c alloc.c
-array.c: ../byterun/array.c
-	ln -s ../byterun/array.c array.c
-compare.c: ../byterun/compare.c
-	ln -s ../byterun/compare.c compare.c
-ints.c: ../byterun/ints.c
-	ln -s ../byterun/ints.c ints.c
-floats.c: ../byterun/floats.c
-	ln -s ../byterun/floats.c floats.c
-str.c: ../byterun/str.c
-	ln -s ../byterun/str.c str.c
-io.c: ../byterun/io.c
-	ln -s ../byterun/io.c io.c
-extern.c: ../byterun/extern.c
-	ln -s ../byterun/extern.c extern.c
-intern.c: ../byterun/intern.c
-	ln -s ../byterun/intern.c intern.c
-hash.c: ../byterun/hash.c
-	ln -s ../byterun/hash.c hash.c
-sys.c: ../byterun/sys.c
-	ln -s ../byterun/sys.c sys.c
-parsing.c: ../byterun/parsing.c
-	ln -s ../byterun/parsing.c parsing.c
-gc_ctrl.c: ../byterun/gc_ctrl.c
-	ln -s ../byterun/gc_ctrl.c gc_ctrl.c
-terminfo.c: ../byterun/terminfo.c
-	ln -s ../byterun/terminfo.c terminfo.c
-md5.c: ../byterun/md5.c
-	ln -s ../byterun/md5.c md5.c
-obj.c: ../byterun/obj.c
-	ln -s ../byterun/obj.c obj.c
-lexing.c: ../byterun/lexing.c
-	ln -s ../byterun/lexing.c lexing.c
-printexc.c: ../byterun/printexc.c
-	ln -s ../byterun/printexc.c printexc.c
-callback.c: ../byterun/callback.c
-	ln -s ../byterun/callback.c callback.c
-weak.c: ../byterun/weak.c
-	ln -s ../byterun/weak.c weak.c
-compact.c: ../byterun/compact.c
-	ln -s ../byterun/compact.c compact.c
-finalise.c: ../byterun/finalise.c
-	ln -s ../byterun/finalise.c finalise.c
-custom.c: ../byterun/custom.c
-	ln -s ../byterun/custom.c custom.c
-meta.c: ../byterun/meta.c
-	ln -s ../byterun/meta.c meta.c
-globroots.c: ../byterun/globroots.c
-	ln -s ../byterun/globroots.c globroots.c
-$(UNIX_OR_WIN32).c: ../byterun/$(UNIX_OR_WIN32).c
-	ln -s ../byterun/$(UNIX_OR_WIN32).c $(UNIX_OR_WIN32).c
-dynlink.c: ../byterun/dynlink.c
-	ln -s ../byterun/dynlink.c dynlink.c
-signals.c: ../byterun/signals.c
-	ln -s ../byterun/signals.c signals.c
-debugger.c: ../byterun/debugger.c
-	ln -s ../byterun/debugger.c debugger.c
+libasmrun_shared.$(SO): $(PICOBJS)
+	$(MKDLL) -o $@ $^ $(NATIVECCLIBS)
 
-LINKEDFILES=misc.c freelist.c major_gc.c minor_gc.c memory.c alloc.c array.c \
-  compare.c ints.c floats.c str.c io.c extern.c intern.c hash.c sys.c \
-  parsing.c gc_ctrl.c terminfo.c md5.c obj.c lexing.c printexc.c callback.c \
-  weak.c compact.c finalise.c meta.c custom.c main.c globroots.c \
-  $(UNIX_OR_WIN32).c dynlink.c signals.c debugger.c startup_aux.c backtrace.c
+.PHONY: install
+install:
+	cp $(TARGETS) "$(INSTALL_LIBDIR)"
 
-clean::
-	rm -f $(LINKEDFILES)
+$(LINKEDFILES): %.c: ../byterun/%.c
+	$(LN) $< $@
 
-%.d.o: %.c
-	$(CC) -c $(DFLAGS) -o $@ $<
+%.d.$(O): %.c
+	$(CC) -c $(DFLAGS) $(OUTPUTOBJ)$@ $<
 
-%.i.o : %.c
-	$(CC) -c $(IFLAGS) -o $@ $<
+%.i.$(O): %.c
+	$(CC) -c $(IFLAGS) $(OUTPUTOBJ)$@ $<
 
-%.p.o: %.c
-	$(CC) -c $(PFLAGS) -o $@ $<
+%.p.$(O): %.c
+	$(CC) -c $(PFLAGS) $(OUTPUTOBJ)$@ $<
 
-%.pic.o: %.c
-	$(CC) -c $(PICFLAGS) -o $@ $<
+%.pic.$(O): %.c
+	$(CC) -c $(PICFLAGS) $(OUTPUTOBJ)$@ $<
+
+%.$(O): %.c
+	$(CC) $(CFLAGS) -c $<
 
 %.o: %.S
-	$(ASPP) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) -o $@ $< || \
+	$(ASPP) $(ASPPFLAGS) -o $@ $< || \
 	{ echo "If your assembler produced syntax errors, it is probably";\
           echo "unhappy with the preprocessor. Check your assembler, or";\
           echo "try producing $*.o by hand.";\
           exit 2; }
 
 %.p.o: %.S
-	$(ASPP) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) $(ASPPPROFFLAGS) -o $@ $<
+	$(ASPP) $(ASPPFLAGS) $(ASPPPROFFLAGS) -o $@ $<
 
 %.pic.o: %.S
-	$(ASPP) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) $(SHAREDCCCOMPOPTS) -o $@ $<
+	$(ASPP) $(ASPPFLAGS) $(SHAREDCCCOMPOPTS) -o $@ $<
 
-%.o: %.s
-	$(ASPP) -DSYS_$(SYSTEM) -o $@ $<
+%.obj: %.asm
+	$(ASM)$@ $<
 
-%.p.o: %.s
-	$(ASPP) -DSYS_$(SYSTEM) $(ASPPPROFFLAGS) -o $@ $<
+%.pic.obj: %.asm
+	$(ASM)$@ $<
 
-%.pic.o: %.s
-	$(ASPP) -DSYS_$(SYSTEM) $(SHAREDCCCOMPOPTS) -o $@ $<
+.PHONY: clean
+clean:
+	rm -f $(LINKEDFILES)
+	rm -f *.$(O) *.$(A) *.$(SO)
 
-clean::
-	rm -f *.o *.a *.so *~
+.PHONY: distclean
+distclean: clean
+	rm -r *~
 
-depend: $(COBJS:.o=.c) ${LINKEDFILES}
+ifneq "$(TOOLCHAIN)" "msvc"
+.PHONY: depend
+depend: $(COBJS:.$(O)=.c) $(LINKEDFILES)
 	$(CC) -MM $(FLAGS) *.c > .depend
 	$(CC) -MM $(FLAGS) -DPROFILING *.c | sed -e 's/\.o/.p.o/' >> .depend
 	$(CC) -MM $(FLAGS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' >> .depend
 	$(CC) -MM $(FLAGS) -DCAML_INSTR *.c | sed -e 's/\.o/.i.o/' >> .depend
+endif
+
+ifeq "$(UNIX_OR_WIN32)" "win32"
+.depend.nt: .depend
+	sed -e 's/\.o/.$(O)/g' .depend > .depend.nt
+
+include .depend.nt
 
+else
 include .depend
+endif
diff --git a/asmrun/Makefile.nt b/asmrun/Makefile.nt
index b008fddc..ed9900bb 100644
--- a/asmrun/Makefile.nt
+++ b/asmrun/Makefile.nt
@@ -13,77 +13,4 @@
 #*                                                                        *
 #**************************************************************************
 
-include ../config/Makefile
-
-CC=$(NATIVECC)
-CFLAGS=-I../byterun -DNATIVE_CODE -DTARGET_$(ARCH) -DSYS_$(SYSTEM) \
-       $(NATIVECCCOMPOPTS)
-
-COBJS=startup_aux.$(O) startup.$(O) \
-  main.$(O) fail.$(O) roots.$(O) signals.$(O) signals_asm.$(O)\
-  misc.$(O) freelist.$(O) major_gc.$(O) minor_gc.$(O) memory.$(O) alloc.$(O) \
-  compare.$(O) ints.$(O) floats.$(O) str.$(O) array.$(O) io.$(O) extern.$(O) \
-  intern.$(O) hash.$(O) sys.$(O) parsing.$(O) gc_ctrl.$(O) terminfo.$(O) \
-  md5.$(O) obj.$(O) lexing.$(O) win32.$(O) printexc.$(O) callback.$(O) \
-  weak.$(O) compact.$(O) finalise.$(O) custom.$(O) globroots.$(O) \
-  backtrace_prim.$(O) backtrace.$(O) \
-  natdynlink.$(O) debugger.$(O) meta.$(O) dynlink.$(O) clambda_checks.$(O) \
-  spacetime.$(O) spacetime_snapshot.$(O) spacetime_offline.$(O)
-
-LINKEDFILES=misc.c freelist.c major_gc.c minor_gc.c memory.c alloc.c array.c \
-  compare.c ints.c floats.c str.c io.c extern.c intern.c hash.c sys.c \
-  parsing.c gc_ctrl.c terminfo.c md5.c obj.c lexing.c printexc.c callback.c \
-  weak.c compact.c meta.c finalise.c custom.c main.c globroots.c \
-  dynlink.c signals.c debugger.c startup_aux.c backtrace.c
-
-ifeq ($(TOOLCHAIN),mingw)
-ASMOBJS=$(ARCH).o
-else
-ASMOBJS=$(ARCH)nt.obj
-endif
-
-OBJS=$(COBJS) $(ASMOBJS)
-
-all: libasmrun.$(A)
-
-libasmrun.$(A): $(OBJS)
-	$(call MKLIB,libasmrun.$(A), $(OBJS))
-
-i386nt.obj: i386nt.asm
-	$(ASM)i386nt.obj i386nt.asm
-
-amd64nt.obj: amd64nt.asm
-	$(ASM)amd64nt.obj amd64nt.asm
-
-i386.o: i386.S
-	$(ASPP) -DSYS_$(SYSTEM) i386.S
-
-amd64.o: amd64.S
-	$(ASPP) -DSYS_$(SYSTEM) amd64.S
-
-INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
-
-install:
-	cp libasmrun.$(A) "$(INSTALL_LIBDIR)"
-
-$(LINKEDFILES): %.c: ../byterun/%.c
-	cp ../byterun/$*.c $*.c
-
-# Need special compilation rule so as not to do -I../byterun
-win32.$(O): ../byterun/win32.c
-	$(CC) -c $(NATIVECCCOMPOPTS) -DNATIVE_CODE $(IFLEXDIR) \
-	      ../byterun/win32.c
-
-%.$(O): %.c
-	$(CC) $(CFLAGS) -c $<
-
-clean::
-	rm -f $(LINKEDFILES)
-
-clean::
-	rm -f *.$(O) *.$(A) *~
-
-.depend.nt: .depend
-	sed -e 's/\.o/.$(O)/g' .depend > .depend.nt
-
-include .depend.nt
+include Makefile
diff --git a/asmrun/amd64.S b/asmrun/amd64.S
index 2d77e0f4..efb8fd9b 100644
--- a/asmrun/amd64.S
+++ b/asmrun/amd64.S
@@ -438,12 +438,15 @@ LBL(103):
         CFI_ADJUST(8)
         RECORD_STACK_FRAME(8)
 #ifdef WITH_FRAME_POINTERS
-        /* Do we need 16-byte alignment here ? */
+        /* ensure 16 byte alignment by subq + enter using 16-bytes, PR#7417 */
+        subq    $8, %rsp; CFI_ADJUST (8)
         ENTER_FUNCTION
 #endif
         call    LBL(caml_call_gc)
 #ifdef WITH_FRAME_POINTERS
+        /* ensure 16 byte alignment by leave + addq using 16-bytes PR#7417 */
         LEAVE_FUNCTION
+        addq    $8, %rsp; CFI_ADJUST (-8)
 #endif
         popq    %rax; CFI_ADJUST(-8)       /* recover desired size */
         jmp     LBL(caml_allocN)
diff --git a/asmrun/arm64.S b/asmrun/arm64.S
index 60342fe1..2115be36 100644
--- a/asmrun/arm64.S
+++ b/asmrun/arm64.S
@@ -254,8 +254,8 @@ caml_alloc3:
     /* Try again */
         b       1b
         CFI_ENDPROC
-        .type   caml_alloc2, %function
-        .size   caml_alloc2, .-caml_alloc2
+        .type   caml_alloc3, %function
+        .size   caml_alloc3, .-caml_alloc3
 
         .align  2
         .globl  caml_allocN
diff --git a/asmrun/backtrace_prim.c b/asmrun/backtrace_prim.c
index 2ecf1591..682e082e 100644
--- a/asmrun/backtrace_prim.c
+++ b/asmrun/backtrace_prim.c
@@ -69,6 +69,14 @@ frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp)
   }
 }
 
+int caml_alloc_backtrace_buffer(void){
+  Assert(caml_backtrace_pos == 0);
+  caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE
+                                 * sizeof(backtrace_slot));
+  if (caml_backtrace_buffer == NULL) return -1;
+  return 0;
+}
+
 /* Stores the return addresses contained in the given stack fragment
    into the backtrace array ; this version is performance-sensitive as
    it is called at each [raise] in a program compiled with [-g], so we
@@ -81,12 +89,9 @@ void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp)
     caml_backtrace_pos = 0;
     caml_backtrace_last_exn = exn;
   }
-  if (caml_backtrace_buffer == NULL) {
-    Assert(caml_backtrace_pos == 0);
-    caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE
-                                   * sizeof(backtrace_slot));
-    if (caml_backtrace_buffer == NULL) return;
-  }
+
+  if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1)
+    return;
 
   /* iterate on each frame  */
   while (1) {
diff --git a/asmrun/clambda_checks.c b/asmrun/clambda_checks.c
index 7409fa1d..1d25ecbc 100644
--- a/asmrun/clambda_checks.c
+++ b/asmrun/clambda_checks.c
@@ -58,13 +58,15 @@ value caml_check_field_access(value v, value pos, value v_descr)
   const char* descr = String_val(v_descr);
   value orig_v = v;
   if (v == (value) 0) {
-    fprintf(stderr, "Access to field %lld of NULL: %s\n",
-      (ARCH_UINT64_TYPE) Long_val(pos), descr);
+    fprintf(stderr,
+      "Access to field %" ARCH_INT64_PRINTF_FORMAT
+      "u of NULL: %s\n", (ARCH_UINT64_TYPE) Long_val(pos), descr);
     abort();
   }
   if (!Is_block(v)) {
     fprintf(stderr,
-      "Access to field %lld of non-boxed value %p is illegal: %s\n",
+      "Access to field %" ARCH_INT64_PRINTF_FORMAT
+      "u of non-boxed value %p is illegal: %s\n",
       (ARCH_UINT64_TYPE) Long_val(pos), (void*) v, descr);
     abort();
   }
@@ -76,7 +78,8 @@ value caml_check_field_access(value v, value pos, value v_descr)
   assert(Long_val(pos) >= 0);
   if (Long_val(pos) >= Wosize_val(v)) {
     fprintf(stderr,
-      "Access to field %lld of value %p of size %lld is illegal: %s\n",
+      "Access to field %" ARCH_INT64_PRINTF_FORMAT
+      "u of value %p of size %" ARCH_INT64_PRINTF_FORMAT "u is illegal: %s\n",
       (ARCH_UINT64_TYPE) Long_val(pos), (void*) v,
       (ARCH_UINT64_TYPE) Wosize_val(v),
       descr);
diff --git a/asmrun/fail.c b/asmrun/fail.c
index ba56c477..d73cb885 100644
--- a/asmrun/fail.c
+++ b/asmrun/fail.c
@@ -121,11 +121,21 @@ void caml_failwith (char const *msg)
   caml_raise_with_string((value) caml_exn_Failure, msg);
 }
 
+void caml_failwith_value (value msg)
+{
+  caml_raise_with_arg((value) caml_exn_Failure, msg);
+}
+
 void caml_invalid_argument (char const *msg)
 {
   caml_raise_with_string((value) caml_exn_Invalid_argument, msg);
 }
 
+void caml_invalid_argument_value (value msg)
+{
+  caml_raise_with_arg((value) caml_exn_Invalid_argument, msg);
+}
+
 void caml_raise_out_of_memory(void)
 {
   caml_raise_constant((value) caml_exn_Out_of_memory);
diff --git a/asmrun/natdynlink.c b/asmrun/natdynlink.c
index 1d90b69b..e2599e65 100644
--- a/asmrun/natdynlink.c
+++ b/asmrun/natdynlink.c
@@ -26,7 +26,7 @@
 #include "caml/fail.h"
 #include "caml/signals.h"
 #ifdef WITH_SPACETIME
-#include "spacetime.h"
+#include "caml/spacetime.h"
 #endif
 
 #include "caml/hooks.h"
@@ -35,6 +35,14 @@ CAMLexport void (*caml_natdynlink_hook)(void* handle, char* unit) = NULL;
 
 #include 
 #include 
+#include 
+
+#define Handle_val(v) (*((void **) Data_abstract_val(v)))
+static value Val_handle(void* handle) {
+  value res = caml_alloc_small(1, Abstract_tag);
+  Handle_val(res) = handle;
+  return res;
+}
 
 static void *getsym(void *handle, char *module, char *name){
   char *fullname = caml_strconcat(3, "caml", module, name);
@@ -47,7 +55,7 @@ static void *getsym(void *handle, char *module, char *name){
 
 CAMLprim value caml_natdynlink_getmap(value unit)
 {
-  return (value)caml_globals_map;
+  return caml_input_value_from_block(caml_globals_map, INT_MAX);
 }
 
 CAMLprim value caml_natdynlink_globals_inited(value unit)
@@ -57,37 +65,41 @@ CAMLprim value caml_natdynlink_globals_inited(value unit)
 
 CAMLprim value caml_natdynlink_open(value filename, value global)
 {
-  CAMLparam1 (filename);
-  CAMLlocal1 (res);
+  CAMLparam2 (filename, global);
+  CAMLlocal3 (res, handle, header);
   void *sym;
-  void *handle;
+  void *dlhandle;
   char *p;
 
   /* TODO: dlclose in case of error... */
 
   p = caml_strdup(String_val(filename));
   caml_enter_blocking_section();
-  handle = caml_dlopen(p, 1, Int_val(global));
+  dlhandle = caml_dlopen(p, 1, Int_val(global));
   caml_leave_blocking_section();
   caml_stat_free(p);
 
-  if (NULL == handle)
-    CAMLreturn(caml_copy_string(caml_dlerror()));
+  if (NULL == dlhandle)
+    caml_failwith(caml_dlerror());
 
-  sym = caml_dlsym(handle, "caml_plugin_header");
+  sym = caml_dlsym(dlhandle, "caml_plugin_header");
   if (NULL == sym)
-    CAMLreturn(caml_copy_string("not an OCaml plugin"));
+    caml_failwith("not an OCaml plugin");
+
+  handle = Val_handle(dlhandle);
+  header = caml_input_value_from_block(sym, INT_MAX);
 
   res = caml_alloc_tuple(2);
-  Field(res, 0) = (value) handle;
-  Field(res, 1) = (value) (sym);
+  Field(res, 0) = handle;
+  Field(res, 1) = header;
   CAMLreturn(res);
 }
 
-CAMLprim value caml_natdynlink_run(void *handle, value symbol) {
-  CAMLparam1 (symbol);
+CAMLprim value caml_natdynlink_run(value handle_v, value symbol) {
+  CAMLparam2 (handle_v, symbol);
   CAMLlocal1 (result);
   void *sym,*sym2;
+  void* handle = Handle_val(handle_v);
   struct code_fragment * cf;
 
 #define optsym(n) getsym(handle,unit,n)
@@ -137,7 +149,7 @@ CAMLprim value caml_natdynlink_run(void *handle, value symbol) {
 CAMLprim value caml_natdynlink_run_toplevel(value filename, value symbol)
 {
   CAMLparam2 (filename, symbol);
-  CAMLlocal2 (res, v);
+  CAMLlocal3 (res, v, handle_v);
   void *handle;
   char *p;
 
@@ -154,8 +166,9 @@ CAMLprim value caml_natdynlink_run_toplevel(value filename, value symbol)
     v = caml_copy_string(caml_dlerror());
     Store_field(res, 0, v);
   } else {
+    handle_v = Val_handle(handle);
     res = caml_alloc(1,0);
-    v = caml_natdynlink_run(handle, symbol);
+    v = caml_natdynlink_run(handle_v, symbol);
     Store_field(res, 0, v);
   }
   CAMLreturn(res);
diff --git a/asmrun/signals_asm.c b/asmrun/signals_asm.c
index d08e2dbe..f124a076 100644
--- a/asmrun/signals_asm.c
+++ b/asmrun/signals_asm.c
@@ -30,7 +30,7 @@
 #include "caml/signals_machdep.h"
 #include "signals_osdep.h"
 #include "caml/stack.h"
-#include "spacetime.h"
+#include "caml/spacetime.h"
 
 #ifdef HAS_STACK_OVERFLOW_DETECTION
 #include 
diff --git a/asmrun/spacetime.c b/asmrun/spacetime.c
index b5e999f5..e95cf687 100644
--- a/asmrun/spacetime.c
+++ b/asmrun/spacetime.c
@@ -38,11 +38,12 @@
 #include "caml/minor_gc.h"
 #include "caml/misc.h"
 #include "caml/mlvalues.h"
+#include "caml/osdeps.h"
 #include "caml/roots.h"
 #include "caml/signals.h"
 #include "caml/stack.h"
 #include "caml/sys.h"
-#include "spacetime.h"
+#include "caml/spacetime.h"
 
 #ifdef WITH_SPACETIME
 
@@ -198,7 +199,7 @@ void caml_spacetime_initialize(void)
 
   caml_spacetime_static_shape_tables = &caml_spacetime_shapes;
 
-  ap_interval = getenv ("OCAML_SPACETIME_INTERVAL");
+  ap_interval = caml_secure_getenv ("OCAML_SPACETIME_INTERVAL");
   if (ap_interval != NULL) {
     unsigned int interval = 0;
     sscanf(ap_interval, "%u", &interval);
@@ -209,7 +210,7 @@ void caml_spacetime_initialize(void)
       int dir_ok = 1;
 
       user_specified_automatic_snapshot_dir =
-        getenv("OCAML_SPACETIME_SNAPSHOT_DIR");
+        caml_secure_getenv("OCAML_SPACETIME_SNAPSHOT_DIR");
 
       if (user_specified_automatic_snapshot_dir == NULL) {
 #ifdef HAS_GETCWD
diff --git a/asmrun/spacetime_offline.c b/asmrun/spacetime_offline.c
index 221c6a66..8191a300 100644
--- a/asmrun/spacetime_offline.c
+++ b/asmrun/spacetime_offline.c
@@ -34,7 +34,7 @@
 #include "caml/signals.h"
 #include "caml/stack.h"
 #include "caml/sys.h"
-#include "spacetime.h"
+#include "caml/spacetime.h"
 
 #include "../config/s.h"
 
diff --git a/asmrun/spacetime_snapshot.c b/asmrun/spacetime_snapshot.c
index 9c582a83..0f425e19 100644
--- a/asmrun/spacetime_snapshot.c
+++ b/asmrun/spacetime_snapshot.c
@@ -37,7 +37,7 @@
 #include "caml/signals.h"
 #include "caml/stack.h"
 #include "caml/sys.h"
-#include "spacetime.h"
+#include "caml/spacetime.h"
 
 #ifdef WITH_SPACETIME
 
diff --git a/asmrun/startup.c b/asmrun/startup.c
index ccf87d02..70bbc436 100644
--- a/asmrun/startup.c
+++ b/asmrun/startup.c
@@ -37,7 +37,7 @@
 #include "caml/startup_aux.h"
 #include "caml/sys.h"
 #ifdef WITH_SPACETIME
-#include "spacetime.h"
+#include "caml/spacetime.h"
 #endif
 #ifdef HAS_UI
 #include "caml/ui.h"
@@ -100,11 +100,9 @@ extern void caml_install_invalid_parameter_handler();
 
 #endif
 
-void caml_main(char **argv)
+value caml_startup_exn(char **argv)
 {
-  char * exe_name;
-  static char proc_self_exe[256];
-  value res;
+  char * exe_name, * proc_self_exe;
   char tos;
 
 #ifdef WITH_SPACETIME
@@ -133,21 +131,29 @@ void caml_main(char **argv)
   caml_debugger_init (); /* force debugger.o stub to be linked */
   exe_name = argv[0];
   if (exe_name == NULL) exe_name = "";
-  if (caml_executable_name(proc_self_exe, sizeof(proc_self_exe)) == 0)
+  proc_self_exe = caml_executable_name();
+  if (proc_self_exe != NULL)
     exe_name = proc_self_exe;
   else
     exe_name = caml_search_exe_in_path(exe_name);
   caml_sys_init(exe_name, argv);
   if (sigsetjmp(caml_termination_jmpbuf.buf, 0)) {
     if (caml_termination_hook != NULL) caml_termination_hook(NULL);
-    return;
+    return Val_unit;
   }
-  res = caml_start_program();
-  if (Is_exception_result(res))
-    caml_fatal_uncaught_exception(Extract_exception(res));
+  return caml_start_program();
 }
 
 void caml_startup(char **argv)
 {
-  caml_main(argv);
+  value res = caml_startup_exn(argv);
+
+  if (Is_exception_result(res)) {
+    caml_fatal_uncaught_exception(Extract_exception(res));
+  }
+}
+
+void caml_main(char **argv)
+{
+  caml_startup(argv);
 }
diff --git a/boot/ocamlc b/boot/ocamlc
index 0c31cda09d709fa2c9ad4d2ef22b83be88379b8b..d8c427d3d43b5330f81414c3e991d2b0698c4d02 100755
GIT binary patch
delta 390254
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

n=lqWI30P0aaq{i$=CX1-zTtz_ACUb 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 z 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ξ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

m_6nW;f8NuH&x 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 delta 365680 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 z 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≷?1#U~~Vq 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 TXT2PM5Jjs(p-}cB6_x)1YXPjD diff --git a/boot/ocamldep b/boot/ocamldep index eacfcf04200dd699ae73276c2cfa33ceb120eb52..bd7e0bb9c3c1ca7c2ac91aa26736ff03d128deb5 100755 GIT binary patch literal 2077996 zcmeF)3%KQ1Ss(r+lgpU~1tPhLN#>lnWNv|EAdv*foG_Dw5HKYWq6v`18OQ`e0wN-T z5Hw*D1?5suDwWzw5k;}B)LJXmh$1SA3gQI{RI626{G(LGYyRKQp7oAv7JHv_W-OZ;|89cp^p#5Nndd?UJT{}KJr7mIGDx%psZaKtPc7;({dmu%f*hK<#^~^ zj_1o(!1LuD&!&tw2USC3ZJw63GlO%2#|C0@MeudOuHc2itAcM2-W0qocxN!Jrr2L` zU&y$x&x*PDP2($h%kfp6F2`qGESKY}dR>mMYIZrks@vuGs&-*FrzA|fl zZC@Dr^5DAQ#lhXdTZ11B{!8$_;Maox9(+3Z`{1|~=WyCr=l5{gH#gWP?$hdM+Vf}{-*|@QQ+~;nJ9{dh<`)BfUlS|YLr%Zv zVDBWh*k5SwYsT(NZQ<|lyRWC;H_$Krhx_isSNGOM zh&1t46XyqN`RT!HlgRP8@{G)@HEkt+;;a1Do$j74xpcy-11&1|zwaAcD_ix~2OkKW z>$?IC-?^>#IYLwCw+7C#@ht(n!FgX7*ykS6o)x@5U@JSzK4T!~*}<;|czPcWh37X` zAm?KpPlgj4KicN#)Y$#A!E$zco|oMjPWJs`w{NMrUz)=A(r#{6tbV8Qh?U0Hj|63F z&Gq)z+|PAWlGQU1xXU*AT{P3XG+(~%VzjL}Ju;;V)-FF{7mj#vQ(T|;3v&Vit+L=P@&ucw7 z3jv-QTSq^p^>pG{3^Y3H9e~_=?&2#S_(NX#VjgW?T&@iIxbSW0I zZ(zfX0h{QnbBw3>OK+woJaqH#VE3`tUb;5~s{*b3oV8|tn_fgJr@a7|Et?`dPXtvWXb&!|(|xUX^fC+m}eu{+&+j^~7D1ey990{J6rKI0Dr&Rf~`i;b>$d3R$ETW$$TPM!P3%xQFxTRO|$Ig4o<12$_f z2#U`>^enqdw_J=m#oXBtldS<>?auhFXHU)Z=WUtiYw5E0n4r%Q8D*PXoDuK=pM7#A zCeH1epnTexai4EvI`0lN@iSMn{G%&opUk*?ygg&JP`S33KKCO#>=TQESg#A%!q)QV zaN5A{rEIu9>mLZjp<=QpV-X{XB zbdPt$`?GdU;N6vec6qNQf8_nS%;6==I$mS;X!Mh(8RIYBvfaL2f!qSykIrPtDZay* zpA({Ex%_-6JZuny2f_w1UCsvIA&oYO7l@~GuqUY6zCPo!TMo+Z<@S`G%A51#j?;Dq zYG+5VIv8tUsd}N;z2hv3qdfD+{MOc|JL31-UBjne4d}B+&b6C^AI~P|!)H)&t22<{ z0qgAU*DD4~osnP3p5@L6-}%7CD}(KUc1=(|xu?X5o%HeJWr2A1{_{%=-WX{3PYRsR ztAeTvGJM7*=am6D#|7sG=G|p@Hv|BEP-fxQD)s69<7W8uHKwCR~SffLJb_cWMosl)RIT!Mwk?9#n z=9-}PqUSq0!~M@v{MtRieZjE-{)J$aU-C9(ZF3;^TIE~JYFxR$rOkN{v%aV6J-==U z#D*+qu6Rz!crK{*3@84u_r@S4bf5UWq|KKt>RVG&TG?#;f{yNeu(xva!i>eS-(U4k zmhr5;?^(g#uuRUkbFhd=yLMl<|DITEw0XH$8=M#Pd(i6wHT#e_peDBj+NTqno_3## zyWCtI*sE?9gUu#XSeMI+n2k0{gT3q|} zO#`jg`gML5-P?X`^s5{1Jb2{w;>`6t=QW;(bUddFJb#<-^ZGrX8R*{(-S2;2Xg-(D z*A4vN*yydzrgTRf@wfZlr}^>0;HJR%SAyqtuK0dsq_xwTcmVrKUpg)uE zF~w`XlkrP!ZlRldd**sOzH6YrZJ=)*=xamw@wp;&Z}-m7?AX-lJfq3zWA=-Gv+uJB zUi18R9zXkc2g?6==-%EB4D^Me$vCmeP$!RSbKcdhd7hU1GuxW`%9`g$tv!5L^DMzr zF?D8-Z#?F~y{dPIlY{4PQxE362kJdrO2;3zwVGq^Z%vu|V4FLs$vCZ(@iT3W?c{sr zl>GM$YwW_~T$X)rZ#?DSn#SX77tfm-Px)6dkfS@=TFvp{g>9~4?mnZpmwA17`r5fF z^zn_auYt=l|DepXh3pGMd!CSI4%o3R^J?RQps$fLGmqE(R5FfjbL`n3XuU0eo_ah! zbH)FAq5JiZwskVuT6Z=3=&Cqd7X$Z}d3Nc^?rnT;2Kt=?{kDOA^FV)F=nJFc z*g)%LzbtEP@a*a5UognnJqiZC{PkZS80$}mX3x%H-zNsXUvGR*YkJ^kdt6@2~lb+Wd~zU)=gjTYp*WFK>O>eMO_$NzT(+ zKic(zHh*jDU)1^+xBexqe`)J)YyB%)|H{_Cs`cO6`ny`cxAph5{@Yvs+SY$(>tEmc zH@5z}TL0$Oe|PJ@r}h7;^>1ta_qG1}yWUyxPNuo1pB$(&wdym{OLAa0rQaMl;~;AER9JCD*vmGhKat*M_FYy!tsVV9PAI;)kDnpQAP7 zGbW=0YZWiuWbX**wfBTTT*@bW=2i#%E1MQG*4UyxHTT%j!LGo(T0A#+L{MiT!^!6+ zHB)uMC$Z@5cV;y9duP+w%SQID#Qs&`<5&5_e)%z{&9e8ASzF3pa@j0)74NcHR|ZE${BarD|I&)kfvpb3_iDt>xnF-F{lUd%b;)-ydDGYOL2a zt+webe|r53nRgBs1Fd+L^LbXTdpjz}YU^<8KOr)w#ay1}gR1EaCq7kukI%&A&h)f< zvj2=ij~dqcvpY*)A6I+quV>)SjO(5n@2#?%Z{wOh?yAK=8|lT#?7le6Wz6SC2XZZj z{aqGvQV(RXO`bL5dhhG)WEa}msobk4=SXc?@9S$Zv_>~uG|w0Ds@NE_5grqq6=>@N z=dtWnQ|zas?DbBlu@|4Vl)d!~Qcvt*^Q!}mTyuc0c=)z9pmQ;?wTh*Bx+QR~-0kFJ3+yv-^%9KeD)w9UB5M6x;I}@GS<~_-r#* zF(Ti4uU5K@>B3WS7MIc`cDn=q9UW-)vf;*nUA5NdfAqVzL0q*v_jQvz81^=l&&%0T zGVGPRdk9LKW?%2eG+X6C>utSo-_*osG1n?iJ2F-i=sG{O*I8Q#PJ|7$v_|D(^OnqKJdk@o` zPu~M+{rTLyZ|Z>aDV8uR4t3`G`-?4eO;**;w7gB*!{2_s&r``QpQyllQ^3Y=4(Ks= zYhbUjcV732IGTG@qwVSGJ)vukzsCliJ@(bJWY+!of5Ow>k6+o{k0(#LA3q*`t&jhQ z_e~uTf4X-B?1E{}>h+m-Zul~7y>isokyw(a-LtQo#7_MC8k@EUPe0%DPm_B^_?NP; zYNMCQm&HJvCe!*-wocn$cjB}dl?}Zwy*+GDOIpQinhpJ#oVI@{oBO?`Pu%ET%I4nJ zQRkTBX*MsnzwW}NZ0Pm&F)Tl(#jW4d`#x>Ixb^%!PrtYHxg+Wx^z-MsGu(sDzvdo1 zdonuk96IaTjzH}7OP#+uUw9V-jU987(LdHp)mR_zX?ytE&-eT#xBQ_3?{asb_vQW$ zbpNCIMSjtHx;gjetou(bYz zHqHm)Tbrbi3c9}ePo~+^GQ|A26hgLP9ubSXL^zT4b7d~gRflbra<$qVu*8$$eK zF|>LnZ*?j0Un)Mmj9&IMdHm`5d!Bx8>F=Kf zXJv2Qot_2m4sE<2+(G8fu$ZPE=+V;+)BLGBzPG8jl}+`$=;wR>;wd|`Wup70^!9u) z-*aCR{ry>ccW6zl-ZdE=c-CG%W$qi=Tp!c%tkwN{Pvd=5`Z{Ohnw+bNKKFe*`#4uk z)ES#4tKZ+tohFO!p1*!^fpXEotzn42r7C(Cao~Peiy8CmrHG8XG zohv+=y72i#^PH`7sJ#CcJFCmlXq9|i~U~v`EYVz%un`B^K*6MA*=U+{oWdQNh&rsvf$NJdf*R}?1hhK@0{AZiI=;g%ouY4_De&Asr9(qR}zVpML zK5zDt%?JDEgT+7_^TH>#_OkKycKb6)c-TXxTu-xSn$49{cG$=NQ5Qc>474$ackP>= z)Ry7)MzdR9$h#wmiIYE5(ECUCH2=hFZ=lTu@+p^NKFO{)WO&4fTO7n-Rvhs0$K9{Z z@`vr(O8j8o`9ayo{_%{Mo95RA-M$R>@9X{g^%;KQ=Zm`5_~Ndsn6m4!!Dv_2e!q9e zl)aCevA3@eKB=q4Kr7wGdxE~MdY``i|L%KUYzYq;ArJWT7=JX-9~tO-2YURobT7zy z`F%>{uMT?suNd@S*yQy*cQ>AK@0&B<^Zn2uYwcj$2~%YMkI=#&2HKzp_g^b{bGj?R?l(n2@CdP;nsHpu&if&QL>{`Jri zIg#y5(cyb7y4`JW%exlc#|NGl*43T<(LwQD(*7J)Uz5Kz==#5*J;%uLOd^A?eP23i z{iL?;{NQtz_1?Mk-ih^VS}#86b*=Xf(DT>6Gur%o>-mB2tkyrW^AUw=;LqDH&htUs~!Pip;BhWX1IedW-*C++{*)?eNFYg_-U)?e598(P1s z^}e&Ue_QKsOwU$+X`V%V;t$(>9y#jB1E0eoCv_kP;_PmHS+FrUDo{V01AN7MYsR&n z;pES$-;iESX|E1$3+nmdIsK{JRrZjf_2aukUljEFuL<4nUlY3D(~s?^-@A!+PeA`e z5oy*x74++W8QMLlS^r$n>;H$)z5bQh-^*uzum5L4_v;@G-RuAD(7paogzojP3ElhL zkJ*oQzO*}oX9mY1()I>&@R&diJSR}|YGstOCUd=AXNLZ|0RQ%&=O@>@w7SvMFZ%Rl zfJfcB2a5MAGp1uPC>>~Z(bG>DXlJn2Gn~Zm=JejPoF8W$EgpM<2L(?HZVYxe`bFvS zI8V0(Hw8VPyja(}%kY0g(C>L(=y4BvU{m*K>Awz8${JwD^!){qlE=TVbyt*@v1 zLeB+awlk1x_nx*ssJ#^{ccb=yhIfja2l|Nvy>6f%GSGk5o?j*Z&)Rbi?d<@Y+rr(*vvMK%MfUn?wUDL*5B6sRVe65kK(c|nu zZwp#Z?hVuhsMCdDTi|RsD|C_B^NMrj$9Ppx_Q^M}!F#kZ`{?WKvriL`l3jN0$(*>{ z5P1H%D|#FF!Cw4$`O4PfXS4eWYK^?oQ*&ehK0dDt_$8KF@!JcdUG(tdxIi<)ZhY{G(5Eo^B7Ezw+zSj7Pu7<(Io!{OH7AcYF1#Gj~G37dEX4*gyJhZaKf{ z)Ox@BJUJI^(0U)oJUub%qd)YM#g9II;xfjVFD1V}7qen6H{!ff`z{Ob7t+3{+wTwG zS5gyCnqs5;sNcHFJuk#$T_C=4Q?WeMTD&|m#@HN;-tnAN9@*U6IxX*e!XrLQ?aA`Q zzKhfInamA=xM*y*#^!#l;!^gNj=RFAk!5XTP&IG=e84XDUm38k=8U}yYxa#c91i=O z^WH|b^}6_RPQXU?)OlIm=-bm@6`UA&hv%dFv3xOJ2<%l){J~>CS;h|wDkisOOrF1g z%N^r>vZk?%&$D8ExO`#H=!^F>c{x}={&WdH__saKD!x@Wv*LVBc*{2N6lZ=r^J{`F zfoA_FqTAYQf(rtEX(ij*YXdc{o-5Yg*U9PW&5f2X>*`gbm(8`m)=$oy{Y9(wp0=*p ze|&HpB26uljiyJPXnTXXfSwxzbzmL+oHkY`yMxk0&W_-g!1%I&J3cXPlepWDPmFD}OhuL>$I z>RGN|6xbuaY+P<%>Cmey``LA{GU#4zpY!JI$=9jDN@5+hsd07=Gc!s=nyq*V*!U&$@dv=PurEF^x=qIp^}Fy(*v&>OOdR#?DOH&u-^j&c7;{ z51i}&ui0R4o&Du>Wy|DuFUTx?^-kRDa|TC!_57i4+J1Y+wOcdCHuGx7K4;?L!I{Bv z!HGdVk29R`=SK~b=gn(FA06;tyEAa#i(%zXOv&tNwrKd()5z~^6#uS_>1U%eQsYe- zZ*KGH_TRJos5`gLgmYAPv~_u}-ub#AkUKi~Qfnt*6j}pA4KGF{l`ch4|JUwPz3eD!%sMvq#?KS+1TEjJa|K?8o2Z zhR~-4;@HyjRje_TZ~|G17`w|IW?Efc?(aKMyJf8BX5a#i0BU zb11vy^~`{ro`>G5Lou?aX!6kf=wnZ&c=UDo)X<|n?6%)tbyV@QUo7B;KrS@?*`u*{ zePF*f(q#`DOFld0gnYf48Rg4)`OkN)_SfE(JTKTjAJ8RkPYcMCpOri>>Rg0<;`dT^ z(NR8$;q}4gfhK15Zb77Z9(Dw}V(+2tx1MPQpd;9;a{hrCzW)mU$e{I&yfjRpBYx|v+@_Fw-UlIEFj(0|Kwp(~f-{$rv0T)rbT87FnN{L41i$M!qgT;-LlZ)tNU zc6(ovxnBM)11%2y`n93i$A(i{?+!zs*7`GAKi7KxSr>DCJ+n#<8_ieG543k8eaV|| zw0qV3n%28d(e4cWw$?v-27O_hUu^wjTmSgh?`-`gt$$+cpVa!NwEl|LUpe&NpV@JB z>-{_jeQiLuI@H{iY&}09c}Jj*tdXsWuk#F^5$5Fp z?VkK(;Mosywh++o`6)$|wH0i|qsZe3!E}1fE%W-;lNWV7YvHcCCbO-3s}{Y?N0%RBY;VkT`3V zXZfkS%bN4+{eRl$AI~(gaDRwjA4Bop9b6NL(W>CQ0Ixm$y@wZ%SZi+#%HD){67xOj z*(R2rRsFqN@$Y>o|LD`y%k6>ZRQcsuJNiW~ztqYZ0iF0gx720zY7Wg8HmwQRKl*KM zIlt-DdcXTTxdYjt^*)YyQtP8X^pnMpK7Qgd#+WZ9zs^&?XNNV_W#E3|!e-uAXJKX(Tk13B);WV2nrEm$9@7j0``9)2`_ zixs`|f%9N&ZG0DCGaj)ldH71dd%5mk&m!+29&X5FSVaNiA(vyUvt*Y?cXr+$~(CkOrcs#tr5 zn7=)c6Y=yOMUOj%P1cRcH*ZhX+QTvybMvdUoe|LO4D(rB_XOf%T|XC?lfSir{pSQ~dre?(<SX zpF4kRP3HlOV0_rs^~tj^zwm8FReJjaBGt+nU(^F3|F!uq}K zd){8pse_Dnh3EKA#%rhS**NU^reV+3q50a&IW2SIQ?@-MwDVl_ry|pyHGy93S`(jN zZEN!xTXSA&?Y(UczqNJU+7Gui{MI}xYu{V5*4M@BIvr)x-hF!LDGO z6AwAI7v#os8P|u!TR;DMP3C)qUJ+hpy zoq>Hjf<1w?#kSVZotwE@Kd&1jv!$@ z;LQD0Xf{*~#6}LZAI=&%_ULo9P5N9LlRn32(&uPQ`uyl*(&xtylU@$(^M0w%A1$Bs z`6KU>K7aIn(toz~f8KiUC-}W9>HXf9-tS}S{eH9Fb5H-jTmL7m|KryC`w*=Euh#!z z>;Itj|1*8X-{(p>pX4h2=K^tbX6me-k+ImU3a-pv{A#R^+4%4MJ}!I@3QxT+ktZ+u zl5ZW2N8dlY(B32UC$+xpaVE@rx6+^9`ZcZZ?_=xz9g5!E__ntG5v@PF_1jv%(!0d@ zCwH;+b(d8Cls5n5)_+awFK>OVU(slH3VF_+e%$B&FfV6xvs-gF8M~XV3&?qEPVsWWF>om!)8{8VO zce~O^#L7c1={+6eWhRR{kMQjx^D@{>E(JhjdE|u+$fjL6%%s5IjDGyzOdc> zyAYIKy!Ma0hvN6wN6u*9G`~lkd=Q(`={&KiXmLWXB=)<)H`?HNKnJ-!#PgUaX3sIf zmO%ShyJwtVy3MoiCo+$gD|2k}d-Fx(c~Rr3JvW42-FWGCN64-BVe_T)so`@bjvwZq zka=fhF3_A2{x~DM183yZfu?@&@`o*BPRUjy7X@Pu@I&!DVG0j_fxqDV?F`70=UMtL zX*~AM;(7cO9yyzpx5qYqdDHm5Jt*I6Zn2x2rF%!?VV_2pyKj``-K*wi$-1ENlq`4R z9f4HT-be8%n?b>O*zpS?#VdAFsvCN~=0&XBww7mV`NPT5&^ zQOQ@Uqx^cGnkCD;`|mkHe+J3)tm|zpS@O$1F)+6Oxk0~weQ0@}7IS>!N%um)_gh+T zToguUr2&t^eDh|GP&2ee3_B_4lP$A7uYg zoYwzw>;EKueRkrrdalm{;^SWH{ke3YA3xBKYIL^lf45cZV%E!I#=ShW=fD2`zJorZ$?@Js-nM`*+zo+yKU=@?GrIjGW^aANG)`25t@HpyZSt=8V}de&c?+innYQlU@$_^p(wI_BLB9 z9nWsO;#9tjc8e8$v6y8yfB8S!T=}rK@_tLkrOViPrr$Y|Z#6`gypgvxu$N!omV7&p z#n;zcokRZixxhnT#nQO!BDd_KYfB(c{ytAOfjKdLSmw%BGT2wP$(O(PP=7^R6X#b1 z>W01Ao`5}icCyJHa-S2}^P)!6eQSWXe5-unGk$MC_89>gWZ`FD?a||36Id@^HBo%( zxAgS9&a3@&6pvi<0j!zlhy3uVVq0gGJo#7%@S?@8d=YnR_XHZ7w4TR4bk)2Zkz;;a zaArWi`H^>H=J;K9^*JY#Zn0xW*+d4q^kq1y1-do_V%N)iZfN%05u{A+>vMQp=F|Wi z#M6B|7n~c2`FR2Ti-C4+a8xiWPJ1z>ow~0(AWmwgj}w-Pt20<~dq2#vqu;kNv{+gj zW!75n|JQ|YE~uKSxL%Vv{N(U)MbzqNLtFyi~ z(SpIc5Y86`Kv$$l|WyVlAtI?FHbbY+9S*Eh?rz2Va; z*5%Wvt8~y$cCE{?I$8|0YlEs2e83MpTLS#w+3s)ogRKERYahwooo@2Z)9?BE?BRo2 zDSmPI)5c%C=6rUln(TT1D!lHdD}v_->?(iV6UNy(`3_xe)5mY`Hzx(p4A^->U~k<~ z_}sjE}vc+1|o zj28m&(${ComDvB^r`Uf}WK^yAjJ7+dxRhOGtFu~j_TdxP(bjRkY}^=LG4i?EzPiWM zsJL3^hxYJ*F0#~0&&$T1SI+F)7Kpi;+7xUK%!3+Y|FjzZc#8|0?01JQXQQ)=zqgaU zTY|d+jbDe`*56&Bt)t%FPVt-%+>OqcHZ6vIP9ErZvSF5u4@4ZN<-B}UKd_xqY0jwn z5u=2E$@|8>9f3X0Xw|TLa3N5Cmj!Babx<-_df$+(_Qj;Pm%OrfPsZ+x-e$VkRG*Fe z`?0r^eRM2kFJ1S?Ui(4)c^5X`8L*G;I;ZONx_~Y`Y!feIXMIE9Ip{2kiP&r8@=qhz zIql_&583h|KRyf4xiuggKAJqQN`F(pF1nnR3j(_ERQ!##z5BXJZp@WU#%!Ro>R~Zs z&3x5B`6RbmZ;ziH@5&ro`n;BHeLc_z`1o~Kpy4U|`9_|YmQCV<78iC^Y$^t2=U7Yb z%6iWAwZyi1P8qAoKA+@NKBv`_pR2R6f8L7e=+{BzS$X@a ztW``rXW3Ws$rb!RCPf6~lw6Tei*z2UD}|hw{CzSurJx%!BoD z+WXste{sOKOXRt3c`7WmBqYfGSwKlk=?6}oD@zB}pXzBxQ<5f53<81|eq(0`HdLHhkaJJ8=d(9a#{ zO#}Ur`~qb!@7)7^>p(xN(Oa9n>5h0`ez{U#J}eA-e)sPV)bT?D{apin(?CCNpua4% z+Lwo`gY$x0gT>%;K_Abj;|15xqI+bM(!LxB0W$`q{1D*7`@cUR*8= ze3sVuP1pIs3xlTz;+cnjsm9(C^fh*S=&F++8rELftu0r7ZyokJUnTe74QsFJ z*4{9zeM@L{(A!`_4mJ; zUT4`obx%-r@>j#!w{>gF)!&~Cd%wNg``KabHQn0p4QsCrt!~_z`tJ<-`dLZ+Jtlju zYx~??&O)xO$-VfxjK$$I0r{^F%71qDy2iWlN7~)DC4AZ&2YPR4`mBrZOWS&e56E5V z4)xrg;5=U;e0*u5r#@ddK;)tL8U_ zXLG=&@>7iXe@j3PyVcTsV4r8nxX-!M$S*nlzB=c%UkqzJ%34k*{dAPhhcsGDz3;NY z7}(&PTp1h}tPOfw_*u5B%D8MP9V?M}X7-V-T^f+d2V*r@Hpy$PPqXdJ#=kqg{Z9$z z0&(K+iGg#lI=CRXDcCaw&I=yzYo83zVp4HnpIqYE5@`OdWp&R+t#oe6xUUcT@UVlt zvjRS?3&=e-(8y)8?>+FY55)AOz_b)S$b>nYlf9M&PqBdDD2S4j!6y`_zcN z-k_eA838?)lkgt@6*`HNi0fKc5hMb#PrECJzpJo1Yi@ zg+b-pIjOke=R>crx37-}KRk=y7?dnEG9PG_SGB?SlLNBQy?plf{q@5py(=Y{W00iVPSuRMKg*36;R&`U$tI{LEEy{@wcy8d2= z()|y^cWIv)=-(OWUl{108tDHx&_6iP-#5^A4fNMHTFtu;)wsH-+Sec7Xf=dZXU>bU zeR?s{i;Z4Q>5I=8PHDa81lluIe_HF;rB|coG`2Xy-k0ATxcASLm^An9DM^BQm5W_L zjWe7)>(%`FplzAV&4+eQM&5CrJnsN2oe%4Tzs~Hf9W6dZ(_Q!6Xv1=Qo#}D!iJ7yH z4))HH|LUx1_*S}yypqlSx>wEjwy2S%czc`ZS10`V+rWE+`$i7MV^ttubmgetw=KOK z;$ipJ05AMf*2@<*0A4cc{wiK;y)WpU0XvN8rgz#tb$WWhhUotM%%VxF0zn2B_ z@4jFoS?n!Yt1>QGbdY6^9KH6&01tWPGri{q-xZYI{BVb{xz|;D=+!*mZ=8(w@v@Kq z;z5Ud$Dd^#&j4TKo-M_Tr)rFho~P=JAHX&|Wv_gS|JHy^alIz>?){Q4VuYvssxd!m zEUq=SzsARPWA}N@v!TwoIdw^%+Eg1gN0vG9pkH5WRYQ7lR#ztkWG@8jK%Dqmddb5> zX361S*~t$3%ZIY7d`0tBjnsa;;#xFW>ab{ji|dYHtVetC${jn{>sf}MoowF{;PLMV z$QfHMYjbZ*&v*OmIU``dIl9D*t$P|xkGgwdAO>p!>&4GM_Lsc6^YA<`5Py5gGj=}T z+i12HO~;!9jXl%m#j)n)knQH!1$0!djQJymWxqXZ0`XWCSQnRyK`+NUN6F}8(8~~G zGM+R;hP;%Fi!+{Pha8Y`c`(fmwNNrH$#|NKOiyGyIlZ`(Cojeu1No6J_k-ucdBJxF zi^1mt^82;7gkB7+;r*9^{rE<(r}Ea1d%l~)vpeY5Yp(LS)EZeM|FpRa!zbpNv*8?w z@3lDxYOm-Wq2&>+JudY2eZ$E<^(XH2-dVir<|l{u=r0eAw`6;dW<$|G9h#h?e>im2 zXwAJPb95H{odfONxL^10Wc2h4LzCJ2{M^iy-B~)~x<(s6D8OI6GlX__`#n!-ay>Jw zdxq+ZpP%T$O4j=v)%*PUk?}o&XXlpV^S?ATJRk7Mo%HCylJO%0wi}-nh=sBEvCVi> zATP#e2W&MyGmsBs>ujHE^oB-@f%Wx`E*t2_Uv`*Bmo4_8%N}ykWz)Jwmt6~uF5CEv zzwBGnXmjjwKNyP}`t(MNJNmRn*B!jA(eh{A^TqypPJ4!(S<|R~^*5 z7d_U=wO;vW2fFghPPF?7KR?`M#%ls=#vlghI(uS-79+K@HqbT(M+Ne{IXJT68R;L} z#_n9X*%`>mjzI3@gHLGk_{vu?WB**BvBMeR z%d|W!r-LsgyY#I@2cI-?mrrrOJkX4vFd6NuG3(QO6l*oeM(gTrXP^f8r#8&p5zxoh z+XM3H#lvR&`toIMqs>*G=n$ilRXTckY6c%zC$IW#8I#+~8};L*v*Jfi+3ozPi48$t zlg@3;WjOIoTr~cxQ~n+kXzZwbs~z#evoYY`xdA_}4K#bjP&*iT+xKnRFLzgHI_T8M zEj#5-j@eSRz+Sv%FWz#|$U0*sz*=qM+1^k&6zcaGNFMg1{lKAZjpF91k zK-{#7le#3&dk>wxe;Y!JdBt~E8_%-s@mW7u+bXy6M>n79PM}*WTRqFkALGxbS^ubqqz&$EF&uWWMHq<2omRGf^( zkiYI?=SoiPG0(P&_jo>bv~~OH{D=?!ey(Dw#^rC+T{=eHWs_V_(_LqVzS3WF)ysRW z^>*-`e06(Fp!IZrFInsJWl9ZLRmgI-e_kcV?`yS+j>M_L!50 z^1&TseVng5xSprAAAjv-$C#JO^{%Xm#nC}OUTGZ8$v*9H#DR_4QgNWC_f2m3qW;`H z)BGow%zj_R&AzcFmWqSimz{LUr@XRjMg2&eEM3YjUo!1>doOy<&=&FHm&(K<@6K>L$a9jmMA<5X&z!vB~*Nn2|e3oo_$tpR<%gHMHH#E6rXCLd`Su@Yp zKJIFd&-J{V7GL*I*{crhLC*(jw$|w9Tj{k{x{OPg&)vq;bn#p5>BVhrz&|wIa$aj^ zX1qEen{TUv(no&jJGG6c>7%QB5r@ie`9x>c1U)rhzS4V4Q1Qice{AsHHO&U|YGWxI zrp3LF!&%usEAC^CE9Udr!)Ir!>R8OgL>|kYdKZ!p4S&t4IdvgcbAcv@S zeC^NULZcVcYiy`$OAF< zeWS4$@K+6~9W^Ar>R~>>tIjoZc*UT6l zE@M8J@ALAd;QRL2q*YCRp<_^IKzvHKF&s+%?VFbWOi$(?=={?^E&udC(D^?U-yewl zA509U<-b3F&en40&pC4+EClYwx|`f9Z0UVGlsjrU8#hPCEF0NVd1v2J&vt8g>)CBg zu9~g6)fsD^JvHYJ9-r|gtL`9oRqsd0$@#j)AkDpsM;!Ie9)9|*k=L)e(`T(+w8WY- zUi-v`9(ScXl5dqupYMH7bxt5|zL!2GSRb&D4DspcN~jm5Oa zPWB~Kh`-!$1|&{Hy&+l!xm{L^@?vq576|K;0r(VZ<0b#EGLY$WqF z!Ky%=Si3r~7p#lv69SFyJ;7q2kuBbu99h%Ug1r^zn=-a07W)44(qd?htYasmeX_hy zYh=+&{;7f1%O{f_{yZ-rUu;XKe2+S3>7NU4ea=$5j}A1t)tJ`Xvw7dt0dwj}n`WbW zVJn;2x|EHF>VsJEL9OsXZp)_(_s2n8ijVWZkt-}6D;IppjOw37n+`@LxUjt=ajd)i)iF<$H7+-zx+dG)s-S#gfB9g2A;9a5kN)G^6_lOD+tYRL@kvt;#`cj%#_n$1+mY#s z?5ZQRqLE>a-F0u)-8-K-W44QlSka*d=qvww`ir5H&*Cap`u<+2xRhOTs_}bnGTQeu z13uLGbYAg^t2?52#pse?7O#2d&R(|M9@x7xFlT&08(*BBY-?h?BdA=9yPSx-@hby+ z&B=l1Ugcu#WMrQff$51TQtGH?6YOZY6kLTf-%zdHG z!{N3&rcd%zaZxks!8w=nU2QA|TLR6$$tT7||7>V`*k;bYzs~RbnUmYCf&Jz`nSbc7 z_WfbwQC~gJ8Tm&6@sE4AWj@mrJ^k~!_R854!c#QfHx2aL2l~ec`u(BZWBe;QZ24&B z(@pB2YLg$Ug15wvrZLDIz~~EuW9{1Z~c|6_nfoOb6Wqkt-q%A&usm(TYr7)zrOXmTmRhF?@7;A?<$&jR862? zm~-x~(<=WT%0KkFec#mn_r>!=e}BNfM<2g$QBLLqxxF+%TQYX8<=WVN=I%4r%e^sP zYsPF)3&wi)gYj{JILtMAZKLs9e`KS}hRSQ%;Xby%Y^nMxd%O=@FPn^^>^iH_W!siU zmwjh8+8*{)-I0s-S=Ji8=&E0Kq1~_6)jPWC-8&k(>ef7ZQ-EK5(d!#6_UNjAa?#}A zr}yGEW|OsJ8|^Hi`Goh3M%S}#O{0%aua@LoQ%gq$Y+|P|s9p7GOs;+6?M#R>JH&Tq zAg((C`7-7QdLfY0y8=yojtlI6SwIK-)CI6bO_(E_AL#1MvE8~>{Kk9zFHKC{iT03L z{kDwN9eemO>ZgZ1>!qJQyz;Ov5CgXBOK$bOd@)!`ewHWxkq@K%-I?1H&<)0;->WiL zIpZ&gr@R`=lk;+MK*r91?Ug5bXXS~1Bm8?$k#T2jmWv4>pEoIOD2x_}LQCEt2sTxYi$T?{n-*;_VR2m0j1n2pQDaXvh~ zjbd9iigDSfw%BOB;x(7?Kb3gZ^W;ki6sWbbRs%L@L@B5+Lz029^y`Z;sXK2rd z9f7;iy*1jnCv%=>R|R;rz5BY!{YhRu5BM^{*w+BA2ofT;E-{0@{fjF|M z~&cA@2{*2RgR%jva`-b;gu z^CcOJiL)V3I|Fj%iw%8T@Ts@?0M7{ly=9{{IW9hX$9H8im$P$ScqcOp9zh{a#rn&h1gU)*JjMdiWOS?YyHfO#fl!av?{3gD!NLybF!RnHubf`X0%o{ zBu3_s4d|-*sx3BH+Z`CQ>u}lQSvJic^UK+@D?Fn;Y=g>;@g;#+Ppk9FL-p#$y;HsV zmY@Ed%cZ#M-Dl$Do~fAhHn_7^VuRdQ{^=`w^arC`{xtQ(K5@7?(2T!+GWy4R0FU^{ zf%wqp9;kbpO?78D<9O?A;jcK^W2|m>bn|y)%zrgiKerPT?>}_T1@=vYJZuZr1V;z6 zV&YkEy>yiwrSH_N(Nntmo{ruY@vxtbW8d4-=Y)PT>z*~c&T-OBbu^)On@LF4m-r8UK?G;;j<=@!%x<{SohX3CM8w0tkTo{W3 zdF0Erw3IhS7j_uy8)N>Lg6~V6 z+xvU>@~7&^yS!ZTbtQ4-qy6Fn6_<*odNeQh{hIumTNTJ79|7;!dv}rtYo)J`yYrw~ zFMWDGSX&pUvAW;cCRfXyk&;*Tptl8O3prI2EAh{Mu@YBfdDHj)S%+Evl|KD6|J)~H z#2#a3tZne(Bcq;wN}fzh;kk$=_TcE|tFwCpy@ul@2+mee=Wkj?iS>5|Fbh zsG2Z8ttM9Tc}*_a&KCB{S^2b>v9>t*|AGFP>iyXhS`PWkw%(qQlly{iV*6+lX~vJ3 zjQ%kOv*Ij9Y_zT>)vX$s3&f4hr{~#Oo~f&jb3=p5tUz&6fW~S02st*`A7h z<(n+yetvgo{N^hj>P;h?ty=^6TNS(~zk6jrJ*AruJx#Y59~+cR`!#D7A_Qm+T zHWowchcm|N=gua-V!>x;la2cR88wZUe{;d=K%VsFznnwSl?!uyd_zv^Nsey}63Qk2 zy!cXic-JB3K@Q1P3*v0NBj6ue5Awb)5HG&kXPu8L$*uhwJ@x)!Zax_A=8By)^#Nim z-ttm*(65f{mp^gTdU~mPn`RS#X4ypdG@JU^ti&cZj%SY_RU5`-w>WF~#a*lSQ-1dE z8*;ZRkgwvGujTm3aaY?f*7doZtg4N#Yh&lp`EVZT*%^4I>|&pKVjsD^e)H;T>}Tn({d{vz*vqc5 z?``kx#pgNx&S3oRo=j^$IAzUUuO=!-cq>P{GgkLva7`PF0iVQR+H*&~D>q_Q<33N~ zS}~vIx7hNh?`Qcr6#iLxde@XS zdD8e(u~a9OJH5{ZM+cgGnv<&@-pS-tbFY!HDcBs~m-9VA<;Qs3I`r|O`EHJ!AJ6agi9yfz1DWHO z`rjImh4&5l{ckqaocX`bT+tzqIKBO@b?( z@s%fg%~@anKP@Qza{WKsy63j_(}(rH z&w8fzKZnl97~eura-7u@+V5Fgdk{L1gNnub+V2ostD5xhXcX`I%$GcNy|l@z^$p#+ zxcx@f#b1s0HDK*)@;l6I>gUP))6Baw`r0tRHovc2xZkbBue>@x*0e8{ZoaU!d|}s~z!?>5by+;~8MD*6Iqri#mCx?dHwGnZ zDSdM99N_gH*6S7TxnP=ZcSNt-I}tOk3D_a->{l!1KbB|i=u4(2cCuIPu|Z9!%kzRC z2^NFT1--14*a6S?_qXSH>3YXN-#O6Nhn{tpn7=SkR~o;(J2|884%G06R{i695kG-% zFAvn<+Te^p-I61JI|K3E5r|#A6JDC}nm}#x(H^|FwDFVDYj^GICVcJ>{9>k&e`}x~ zz!^O=aDL<>=I(!wlMA>z(B}4a``_#6zdhiGHM)K@D0?$J;P=GTGaKmb$jV$hcQ1qtJVf=-x*lj z(P%tm%m=0S;Tek=+edwMCd`XVe-DS;FGJkLQEbM%vlpD>PX_Gbdx5=dAY*I54nFz! zOLnC%n;w)g9oDL*O18CE25OWIYE&$o2lB+=*+E}d>{O4MysJm|4w)5ya@n^Kl-=f> zEoT>;1F=~ZtPK_ejr=iR;(10u27d1$>fib2zr36f%mreyCLn|EvWd>J!Cb;L`S&2m zTFMsjsJMwq#ifs%Id+SI#-=`QcZU{J_G;)G0y)w42I6>f;9fi>(A4~OfqmxrsM&u( z(C@z}G=K5&T_e{!huoHp;>S+0sMyq5w6FIyS|ECi(ebuBplAH}eznA>d(Z{K; zFEwMYI;mLIIZ=1Dzib@sJu^IVb5bx%PQ^lHh7rzXXa9yPAr8K@=e8d`0rZSni}!FhpPF9w?0x-sy)v6oIXyNWIwt-;P< zPeA{U*4MMiyV1IUy<%K@#R2T2>#D#yes#)c@~pX2jtkiQAA*vd;pDvPFAl1P*mFxz zd({(NYQcG0XmrK);i1K?w{I!m$e89+?P1@Q0bl2X(z_vJai|y+|Fbgp$v__1RQ4P5 z%l_UM`}kVEoRP7+oNT$a-#M2H@m0HImtEwo3B*Ms>q&w9_V%p`4c4LdmtSSWx~$nZ z7nE=IjrqlIzR$Tm=J;B1xHV(E<#Xl!KW1*sy}kV5vz!}Giy8aq=ws&0kgd00>~;j= zwYuxe?=f!VRouj~e3u`M%-){5zwqu3dV8uq`OOBO3$^~vDqVaYb@5q_w+9;g-QVKt z*{G5Gyx@fayDkef^Yt#k<~lphq<`;vSNi^3+G|hc=agZ6l=X_NJHu=l<*2dn$KgvnCLGjg55Efe(Foura{1E8wS?YnKFL z%-C~po3Fj(^?S)Pr?Io>O&M)B_Wk90eO^vkh25T8{+?H5n{>b2rv4?cS;-)#O*!DzF**^j>m`)>$5 z%lRM|-G#`3SAUlJJ#r%_&Wf?U>=myIgVHO$##;jIzvrxrVbSBi zk9_a2{?>th?m$0rptle7c>}$6pg+*Qi)N4b{9tG?DEhg>`qM)5vDVKV)=v&C7PWqC zX#Q>u$k#rT?_2fmkhuV_Tzt5FUy9a#W}x3b(61Zl3qw~f)H^xO(~ssmRr7Uc>HGE9 zx9?m%&&%%5#zuB)=Iuf2`R5)qt~KA6OruY3^X>xc&Yb@A)~{*(LhIMHenack5B|-8 zx}rzZ`&@T^@Sg*<`SeTw@f?daTs`R@JbCWg<4)(Jx_17q2D;eY=@^8dm?@_%3j{9&0qquo6k-;L#DKDa5kC8%??tBu7@8_%x0 zV}0<5!1-MaE(@*<>I{EV#&-nw1aAnwCm7|9c5DxiR(2Rq<6+lwJV&j7XVnULJTsTm zR#6Vy9GF}Yk0{r~YoEK~TnN+L&KIiA6z%#^N{%O#sg%>1%sZm2YSOmf7J{-Hl@Bc2lZU_+&n($KU1C+`sUzW z!Jh=1!n`N=f#45=^*IQ;gP#fhF!-`n`K~m$G0;lZ$r;x4z2;937J?0dnE3qcvl)H96C>C6 zXa7F7ln!=?89saa&&WPg_WQmg`+EAj2YUNJUpCNB8|Y^Zw0M_YqwoA%%Kw%6{-RFD zG~el$htc=18EpO9f%d_pkIg?D=!XsT=>xqn^isYr<^M{3-`44v=6gzis_zdTY&~_L z@6E>E_g^09-yG;q4)h;~Ue5Pf{;$;c&vrVd`5u?1`u=N!t-m|a-#XB*9q8{G=3P%Qs3Xx>6qrbJ7-$WzhSWTtpmMdpr10(R}b_J1O5EaEA@T!f2F>^q|-6Y z_xf&aJnvTywmx&9j~?hRALvsCdSRfqhCUeId;eGJ`+1#?X}vUFewij|{ecVxad9^y>%udj|UL z1O4vM`S0_-L#=m=S-$u4^&DImIr6tPI6HWBATLSRUWZ=hEndEox92%Z1-=e^>~zm;PwdE*_wNsS`Ymm(^4#Y{4Y8x_K3ul>tX}r@wtRc$d-_EK{qoRd z!?YN){eiG`P2{q-x9tT3t@iu%e?HLHgkH*a=i`C0-F?{G_T+&+d7$S9ddono-=%!1 zpBGiF|8n@J)jByJTw?84mRS4MCDuN)#M-YdvF7(2X4&~0ORRl(iM5X`vG$uwtbKHe zwclD|?YC#FWqNX-c=CBpIX_yR`|2N+x%I)(7Sn3J`f+{V9d+vDE<7##8-hm$j}I;n zZU|l)d`Iy8f#3i5+28|#9E#7Uf=>s38MwQTNpU?aI4#%^JTiDp@PuGj)}50KC#~$- z7HU3lXK8r&sjY;^Gs|6vSKrH{%iN;_HO)uw$J(LpyCi$b^t^R%k)toY^1~NCxEtu6 z3l;)vHCOgn(^e{XRd`Fr;gqXx9tgSO{XobSzk`uGt(NMYd0M?WOJc3bvE0e=O6Jvu z8mStq+Ay~m$lJ!CE~9idcAzEn3iqMYtPf$Ry=&`d8Wl7EC=vZ9?BQ~IG0BUz1@|E;_H2Oe-`if z9qlu+My6)3m{iObGIk%BWB00{_j8oxUOpzfy|#%KTTQD^=djLN>0>*- z9c`VQV}erywctDc(blT_{@r3ed`}E+4gOv5vB3L*-%I#6f$viMyyD5hb%F1vE(mPX52oHg%zuZGN7@HvOT1EIJRxwxr0}q4#o(ycr<>FOTh%N-)a*Z1zgETe#XwWr)BL(5 z^ZdNHt;?UYDvl3rbN0!hdHE1u{9@SWo1DreeFbr@@k)C+sa&3rvD#lQpX>$vY`HMV zk)L2Oy+%KK#{7OE;!wI*8UuWXGY;d;f#al)S@7yl^tKqIFt=5 ziN)cJgU>RHf{<1=e6izDb}Sc*!x@LU_`fI!X{Eo9gZaAGelHJ$rQmK^YMm_in)^xb z4u$3JHtz%Oz{NmgXT1*`iY#~dVxWz(-0AN8vXlJf?DMQ&4EUng$fZXkJ1WZZWsF_NFfK${k$ zzs&qfAx0TT-sPhFHn&{u zmapEw76Xmk<<39ZK2!RxqIfGlcW3TUz&HD}^5I}}_Z8W@NI+U2pR(=x%mZEegGILN zx6PRoZ*i}8Z}dve1O4E>cv!F)Xlz!iTG=el1$%0|(w;1FyuUT#JF3M%TWO8>{>437 zb<*Fjn=-#SI4aQii$asHv0HtKaozE1*7%%YAsE-K)t$T)Pw_e5;<^}U^=w$om>j*v zCNb2$Sa!L`7lUbbO^auJzj$)?_$;_SxFYbp^Jn9C2hR__A$VEvs=yh1Q}AQKPX=1m zb${-U+qZN`Ye!{o)%UuL4;Au8R^@}8^_|~B#?xv;-ub*3h>Kp6Up}ePxxjY_+Tr&7 zOHJm^7$heDKYMoquV;DIiNE9oa*+DBg9NA}@q?-kl*E+E;li`)-R}KxU1X)02BV_9fg;8W55u zetr9P#KC-{tPr$dV>@4Le7yEeEMniECBS{KvA;HMe!TXrT*SVg zjD4fP#!>72wd1w#N70exGYlX2N4|TDpVmEhtmC)N_Wo!8@|}!vd*kA=aseK;9E&`*`#Jh_ z;CC3;2I|*y*qZTWLHRu2jqMrp(OACF==rb5+qY@4T$U~P#k2Zd8T;HZ2sHUUV>tT% z^85D8mkKuaX^E4!$}4}+nJ;Fyyz+MtXzVlBs{US|@p3?SOHbDE*vFp%A!(!Rdr{Vp z1?s4XW#8EuyR$T(7oE{TaB^U-7k6jNnNr{D z19bHsdU3|T8aVepXSQf?rmZGC_pf1pRR_d*jNAKF8?lH2>(NvD* zsO<0Ob}oBmW69Oy8FYQ|wzWZa@$sMj?SW^V`*x`^LOQHfIo9YXemVw0)fk`YD%oXM z->2HgTQSh%EuPjFaw})@2S@J2Bfn$2CUbdvR`7zrd3s&&mBDue?+<<{_;~QA!KZ>J z$DuXB`N4C8=LgpXUmmhY>QGEbA2Z8g(4rqDVzZkFmg?QC2 zyJmx`S@+I#H}9V%`uXe}y{+?^Z}haXS|9iUc%6yU12XWvu9HC?88ZPpDpvZ^DbCj{ z5a;4)=`Zfl^AjCCt&M}swS{6;wz+R*MP8f>c_f#-qS31(XTE&rGujog3GI9!7S6jk zvwMAj##}!eELHAr4`9P-}@JYR+vtK#s z_wEM!RG%pV>;AE{oKQSwl)wWzC0(O`$fUE!QO!W*97+jhk~yP-V%^Uet~Xl z>$~2)aiVC{!*2wm>fuD`_`g|>x|j{roEoe1qwm-0iHcLb@49c*s-EorJEiksf4THk z_jw&$7Oy*hlrHP_xgf)%p9@Z;&7<`G|MHLAk;hU4%Z+E%jF{J5c~VY;JKJ+~L*SnD zzVyQ2hTxUKYlAlhUm3hJ_~GC`1s@H5H6X9+VUqW&+P6y4v$cpZl5rKiz%K zFkULp4;%x}Hy#7e1INHKe+)cV9RrWQA>TgxmlEr9dOWj<`C|E5+2h$Ap8oUP{R-~8 zdafI*3(w+uCpo(xlVuexwA{X+K+xtv=1k&b6Mwe;9A@I2J;c#i*OFzPvO@4t=N zt8=O50sqGWu^j}HL7gw}A%1SXKE3m0ulPL+K)l7R-l@#d`5t3kVD7my2*@xOr^=hP zdQO!d^0ZdAv7G3SS3dn(*}`^XwhX%7oZaj!`^J4YgAT9v!TNVv?ww76J+W;eu71Y8 zH9cE?v#E7*W&`}r7X8rHEdR|%^(CAA_~;O~cXc}O&_TBIQJ-1rU0Od%2EH%pWXR8` zI%xCb{FM#9-!W&8HG13nAg}hsV-T>ha-cVthxOffoDJ+mZ@<;awpM3bgZ=s}UF;sE zZ$;LDp1#lSp(ny$ercn0T5I*1S3FNdtlRU_k1t(xlwHRYV|tcSSA44&pJ-pzjYjS$ zU#pJP7MkVOQ5#FTN=C`6JIA^@9CZC+cTjsD_w5!hc_|&swYfcO#_V!WklWsQ?v%#@ z?Sa7O-VG*chmLed?=5kxJIx)`!u^x~l>G4L5Nc~{z$gEW+fC`MnJ+~KUN(Pg!<*^R z`;QI$X!}-f*;xH3+tB-Oce0HvxtI-{Nioq^JTA$2MNsjOSM>M_bh-cA-ZR;JRNuEr z?XYQUK<2j2HqW5aHA)s*>!bQsN6D6lPj>Gld@R}Y@Y{a9OOPwaZQu8?owxePX?>#W zeVtxB^wP)f2Lg46-+IMa{cB{gfsD4V^-=vowxGYai9x0#W4P3ss@UqU=;ZQCV{^r| z>=$c(RA1|(`i1FZf%ZV){&X(1xRv7K~r3yU%^6KK1Cv^`q=Ue@|x@8ESGiaMsD!R}6eMb`Mkx)DC(%E-dHnZDUmR z$X9kev$M(FTRO;QkG}jJ)%X1@*%eE+uIS_&m;7hW9Q6T|9n@N7?@z|^L*J6cqDjR@IAqg1RoB5Irw<+hrwS2 zpA7unI=>6ME_hmSaj-XdW$>E7zcYR~cx#aV4Sg32_OYSzQSp?6bpd_0huJ``tidR~>ghz&PDf_z8y&50|EJh{S?rdx-GTUtr@997`kY%ow~#}7 zeEq+T_jqgE`E?e=uIjcuFU#4NFLmGYk2`N@(Y3jCkAm}}j^%Z0ppJjByTh%uH9byO z|12z(Z$so4?PBq$*gIFOV%KK}b*|N9(Nte|y&C2x|IoiB{+Wxn7#@p^H}z!r8OCn~ z-oeNm1lmmjTXzRb&DW?{tP6j8-&EYn*KxV&#~2+R@q+oF-i^h_-98iF=u!*o1G?B= zev}Mro?lfm`>Yuz_Q;bZjc**HP{olLPd8sQaSmtd~A(=;d@V`7K|_AE&3y zOX-u7@}c#qbXQKs`No&UWT>}_&r)jbj?feVw-PTi;AnO)CE&v?&lJcB^HG1wG{sqZ=5O?L<03CLR+;PY<% zdjY-HJlpBj9u3;_VQn!R`9bID0XylSf0S+X@u9WN*gAjI37^^c`$20X*;?O5^+N_b ze7@$7+9^L)WDNEz9%NN*TKC*pAKwK zZmzc01ae_d-RudRZ+qtI`40khG!@XdFTis}uqlwk(n-!-urtu+gXN6*6lmhC)%@&?)u^*gj=0VR&YyguS6gE7hrxkhd(isI9x>V!Oa)}%XWy;e z_|)`T>239}TP~fo@{1okf;~aq^ABe%2O9(Jp}@01UfJB<(fnE$$ir+P1~XlcZV+hv zkdvkK;@}=aYb<8#1HP$e?ZH6Jt5f-8n;s7vmeN=4=nn?PZ{F%WquX;oPINdg{d0rL zX`L~;WALkA^uT<^TQ+r`;=6N{|@yWXF3BX{hU=RHCHu4127ch&PVo(RYkuZ>-wZumDC zx1_H)$-^&22N}+|*ua`VjH@@^7w}=RT3TqIJ~=Hpm3R8j4CLPa)q(u9b3E>xrw5)R z?o@u3O#WUI;3MNeusx8YHV&-}V`uzN0`k?;@%F7x&IuS2Sc+k&kD zdp?*tEV&P4F2~Od_)t0Ff9=t)J$R%W=6x<>x!w?nr#d(kXlh9-eswN4e-^YnnGWw0 zy5@sHppi$e{AqnT|08ST)IY(Pssh!_9aIUBG=uE@|@ zd-=xyzX;^F;#M(OpEWd-LCNd;Y`^xFqU$e1znCsI{m(%B#@WQ5#bU;OaT*n~hqKOZ zHQBe{y`}9B1_o(l@Rem{<@oXUXuY=+-|C_-18y5q1wtD6| zTJolY`ED*&=Hdx*_&`8+owo-w*6^|y4O{S<_v>+E*62f1JTn>ND<9S3Qe(>(KL2gt zES?{X^P3OkmW_DX*w^oF?Z^0kWv%?8?~}n|`snHF+m|(G`-*@LGTHD?ZN1J2ALOgf z|NL=`J!{l2nOg&~@tsz!tJzxrg=XC|rq(~)tb0eQ_4hXGbkzF4ZPvYy*7~<)y*`^d z%eCJAZ6bO1%~`efb6NYx#0R3k>@a4_I~$w6su%AmHG+URb|Mt+94c=qQ2EJ=#vz2{|#k8KiMW^ms z+r*n~D`VSSdUrK_;x6yC}-plXeNF;j2aOknMhNg6uexzKY>Aa~&N44&P+@yU9~E|tvvF{`Dh02 zoBING_U|n7bpbiGe^JJLJ@%Y=J{}CnA4MnUa&kP+M|U(ii^Uy{T19stxHn*@xw_jG zu(yp%Js%&518cG;r{X*nRNYqX*SzYj=5kLyT|QG)FCM;&mKRez*8U(6cm6FF8@_2JU#!TldBsSsHV0J$yEC@uS%PP#>y3eJ?vzUdcLlWZH5Z?% z;~g=0GV}J%xI1(A7J2s02-vYD*c13}UM$rco6&wG=*t;Zf9&JCJ@;Yja~tC)^4;OD zVm}+ifz4CFe89GTZCPWZp1swxUreR~_pkM1siiZ*Hy7}io&&+&plW)Mv06P5HB~y; zeLOWKW((ES+fQ0rEmX|a8Q+~PwX5A841)GfzdG~wIfS;g!`VY~U#H(^*QMme-CF0D zEv?KtC-afHrlYHxA)9@5HZIQi@4ETM^izTJ#-{5Vn;ybO$s4 z+I-$(-*o|7;MQP&z#hD0IE!V+o{XK*if`RfHD~v9P;)hCZr%MzZ`hB{FY4B((u;rj zU47A`8+U(J?e*`^s`H9J|Bj{B>+UF@s-}*&)}8I0f#$yG-=CfX*2PPne>V8%m=}Kk zQ_71vTqrN{(dOlinNJ4J%Y(rSgSnv1ReP5EXQ=;NsJg9sqpQx4caDQWogwp4XQ+K% z6#YVHsA{}_hU$FR8B(*ylB+s1=6SHwJZ(?l`8G=LNge%C{qj5* zrFTUq$2lFPSKj1nb->Pvj$Z!RrS|LH+u<>~eHUh*o&4~AptjXytsTmETX06R<{ldaX9j%j(@$p&f5~_#;|&4b=&jfH6ns|G zbAi47xj4Ct^HSm%_ThJ-^0YZ{Zo@u=JH_XV%9R|RlFd!&R|J|En5(z;_kea~F5a3L z*+1VT?O^bw-Mi8w8Iz?J+Gl|OK8SW*AO_&hlN)34BL|uHtBV3LIWJfhw6e|#QJ)9> zAIAnU^3FEX^<)hKXL)C!@y|0%~6{GFKod*3))=R?1ct$&gIrP@l?AQ)%s zq3p5irvr`cQ^BtW8r$pl(ZzYXgZgf9NpIfn-QMke@d7k0eLMcD@O*v4_stoGp>#fWKYcuf>E}W zoQ3%Df?Dd=V)2*F3D zd725ld)(0V>cW{>7fc6p!Ht1?Q{KtIqZawuK3DLfN6T089}Vj4)}HlxK9NDUT2Nb_ z3H6*JZ}^-_@17=;ZR>+QK|P}mWz5$;{cTyhG?0hNfAK#vYd3d$>(YCdP{aJWKMHdLP6x%}nBD4X$|8in+Yvs0|KvW-vWXKS0k?SG5IeE zG<(?^z6(8)vG_hOV2d*gf zN6hP=nU>DovlAe<1Oiu-MN6>LRXL>IDYUJ60J3;>FR1c+dHe zhDz3*p;as5Sm&axxv8v=Iz#Lj1Y*bbsyAy|#d=iT@cVOvQFVh}S@?P=%on_RLoY7Y~9L39*(_-8peZLmfTw9BLU`Kmatf@h| zrUT8K|7}gWN1*bdrqs%LLBHk~(u20u!^T$6q0F}jYDP1EdEnWk_3gMYYh?qyWuLP+ z5!@D#S3c2QF)i91S=$)2@j|nZAAB!A)LiSs!;FH|2(K_Aa(OGu! zfgVj9HU#|F=-`*{BFPvRmsQ<9o%q#~*6QrXDbdaK$T6>GA@!epDxUnTe7H|qzbgOi!_)dDHyT^q z75;m=Y>)$XRu0&xsSjsOe_!C4dq!|`fX1CIE}r$%0lDO@4eaBsIN@WD^?L%c{0wm} zeZ?@tqcY@yFRe{@$K6>|*<%BF;<37$i>0|cd27H1&v0`3>;BD_wE|y?=lioqmRM9R zO=VoP+cFlzlY{Tf%i#xuzYIRV^Km}w?f`nLuNsj{XP|7F%9t2K>#DP9>83Y==oJH{!FW;}W zdu5aJ{h2Y^T!S;X;^1<)2v$exs`O6Nr7M=CJJ@)#!VH-ZW{+|rmn2>Q!z&5qS=6>AR zzAg~g*?_#6u77pc57KLLPL9tWpA}tn;u{3oO+m$;Z(7v_x&@A&Rwe?v z#gpA~u5R4b_SOZ10L{)oV~?7!Pfzjf$yhxPy7f`?{k7I^HqleLV$+&#jXw6$2~@i-p# zJ{;@~z9`Vl?+vz_q&XA!2alShkySt6x-MgOf&1J2dRyT9w{^%*eywK@?jLsy6i6&6a1TlW91L)&|db_r9Bvs>A6($#rX8Z*uCA>OvQMz zp+!@4l|#Oijid4_7V2{puN;!E(fwV`GioYxF>Y&PYv!67obKSJ0EM*-{ zYoBLD&F3-}`;&rw%{as1c{`Bavp`e7cLv^7HL)1=yLaTP%aSbzrO(-Mzm+a~nw-Bd zkb_%;vdMk_*)dN3$s7b)d*7d&IXQBthE5OU%lSGKXna6JkM=bIpKE@yNgDcnfqKyF z?+-o|sKu25+t`Ax#$=Z+=dhLSuF&jXA9(-M%*C_S^~TKUqia=A^3BDqo#U%HeWkz7 zk@+ZJek$waiCghk%=x7)rOto&2LPe0*=`Pwvgtb?s-kq!`Js*4_o4UrU8|q(1GaH8jpjpVqvk-<7#L^Rt3$ z12w?+s-=F+c4n`Q;d6R(vPQ|PTJ6i*I);8#)+@HHzBN61wLKZI*E!eEH{)8Xen!ON5!Lb zjIv`?JkE^XrNrZj_W!IU+98K$hjyW7f*iKb1ZTN&`G$;JUpyPc^fLozLS3jw@vA)O zD|XHdT6R1&f+}Zn0q&%#BYL%mgDZlyCTZ^1w>9q(YK`2s_Q}`W9sGgGz?pJ>om*?0 z0_R{~GqzXvnLTqp6m5n>n|7yfpXWc;+0@s`55AGJDkwRvy`@KNY9GDNDm5P!XLij8 z73)!P{+zBhCPOza&TUS;A7~E;Pek11s(iY&8S}U9zKVylRkRr%bKLn}az@47omKnn zSl!G=#eF{e6?6Tlxc|!~#67G><2-GWwv_sI=W1=Ot;$^8@}-{7;y4$yzFBMMYNF;D z9&?QA8DF_`&PuMBItT4s9%}Bqes1Em(7oiGYvg!0P%A#u@%foS`<+9@fp6kbbmaTp zN^|zE?|QN}2U`MnAJ7BNIKFek=es97YIrhOjAzXV9==Xxolf#L27I$VJz~9dWNUc$ z;wzihHuBwPd}`@49p1}q)n)>*Y0m&(-G6+oxNObX`p3IF&7A&U&Yb?5|4ioc+~;!_ zihX~*KL61rFKC?cQ@g%wFvrVoz1l8Wdhyru*=Jqx5X)^{&!)@&;PBxW2X79(DVYDm z!-pRW?*600hd&X#Ex)XHM}8Ra$^1tK_vSyI{EpzFzd3w(kpIy9Q$Bh4@FT(Z1b-5| z@b3;Ez9*Q=4{N?T_;B!|e9!K`Va&$q;N`)`g86_?Y?52`QaNdBi@j?D`IrsFRen4J zoa_2~TJ}9>#UBm%y8>-fAm{3b3^6Sk<FYh1e36#Z(O&#iv(UrfKcZ}mT% z`T2nw(;f<*9f*nVJlLf@7;F#NWu09s0ybJRE*sfUHo7a=b#dUoEl5Ax@wjvStsHq{ zld;_4u_s65ryI69@kpHw0+;=6yM}Bh%jgplqi9 zmf)N~D|$B5dvYLl_^P(~B}eUDz=!r8qyM9cjd*=Ua8^K!4S{Es zCJyxTA0No2T9Hp@m_6c7humxUYFzcl7W~@+zLWWy#EN`0TLLs>@xilIV=Gzco)K&d zGx=Oa);@aop7YN~F=MA^nw;48-_Ml;{`_b_PU(7jqYJHnw^p*NHnKGI zM;z*`lJ(XAEk75d{k>(-e#tUu`7+9eEDzri#G-t?p!1Ere5!capAPtUZcy_B8MpV7 z`Gx?UdueST7saQhtlbtoty?cTI!oUf8J9lwh=)C`+)R&trlGUy)tPh7Ku%W&>d5^? zCR({r2Nwi#`mEsdy77)E5-NO z{(@$HBI5DFMxJ=Qs5k%o-u$ZG{KdWbOM3H{_U13^&9Cmwuj$RN?ai<2&He3@6ImZO zH1fpb#@_s<-u&j?{N=s*p5ENw-Yk2`e?@P8OK<)Kz4=^kzOOgGwVA6AcaY~`JySf7 z>iOk4qI^OrE_Sq1zNAJP9XW3FV%xCOb=J`^ei9H{m9eDO==9dTU`_yC2 z`xLp*zEk{cZ~mQ`YYzpxf^QAHYkVls4h2)e9f3yY*5JJ+Y2x#X&3lmN4A5DdpBe7G$!)xZ?G~jLXkT9Rq4j|HVPQ---d9?8mQ0$--N4Ab+BpPo*cL9~X9cUqT0JW@8{$ za!)?Y2W^auN9Bvo#{&FfT>RoH2iEQkmMZI!(DLca0?m7x*pdMS5`V?AFB8A`FBUuT(yGQc zXS^Zs{5Ezj(LjAhL(5NV(}6SM^N2IBGAKSiLG7>27@s*j5ICC`1!NrxH2SsKfE~`- zNr?`B3t~{?rS|RJ&Q@(EV3VFrmBU>bYny^ohoi^;`~WKYM9rB-({fmRE zg1dq@2k#0#5_}?hq@0SUxv+7k*3d)4}fse;+($Mf3#E3vLa*B=EQ9-x^WslB4N#{V6`#^B^YJ60X|ma3zz;c@;lR^3U+GelyQ(cyy;-WoKHoPpd%f7{IxGc1CusdKQo9awEgYIJMa^sAFoZ~4S zdbCpkI(hYuQvQmMwiI3X)Qg<7cORYXXmz?jrvmXj5jyXPoKLsT7k(ObE+vohIu$IG zN9Rm_HUyQAsx$XQt?A{a&c^eay`q=5ad&{b?UlKoN?zTObd2I@&y(6HKE1kS$3!3w zRh#V77UETt3-RvGK6}U@d!hKO%zkTE#V5;;TVItqozB9&&0fVVVR;n_zP+nFva>%Q^h}$jAUK_VjHF&H#UbhS# zqiR*%O*b<5u$-EA)^1AzDwZvOwubBKWVt$yH6CBs>2&We7V{^vRuhuP#pLA7owIQ@ z*5+p19XZjHS+$nsp)Pks8|T*lQFqs|#Mt+y^JDVOw^6m-`eq-z$BKvhmL2;wie`}t<{PldY?gRuVN>UbQ}zfea3R;jqeHQ z^mBQ>`z&S8xF2u#&6WV4RzB$6!FuOT@42COZuDg7#YbPyD0Z2PmEIk!=aasCRTrLt zd=mF<0XxLyZ}R(e?4^sIjRC&a-twougAxnhQP7X4V$XlECz}s@0^eJbUHP_$Z=rbl znKzy8dbYQ=;6D_|EkDhxp4g6FjqcBebw1a6hQrUzvLsLJ&}ITLRi}D-CjxDuJ)fyo zg%S^c#nWd`zKXy4rh98}e!#BVV;A}CHh)!bexNshb#H!0Z+>TQepfS(_@nmI$!D#6 z8nw1R`@YMNM~x5e_}4_P_3eQ=t(aDB#J$d37Y%Dt}22&%}=dxDuE?fEaM8}MdvT>mp zPKK`RDnFdDmiHesm+p`?f!;mSAN#qywSK?cJfU9~l;2h7qw-g^_CV;b4cr0N4h7n( zz#0F-ERxsWMXfwMGr@u2X@NVn?#m31o;%N;>A-%;lHbZ3IdJ5=o+ICfos#)kL0{i& z*2tmP{Uxq-M#!kMUOMfUPBPIHFFD04ep`a_LHtJ9C|+nWKPi`9SXOAiL~XC=Y!<<)!bZ`?zv9 z&QJTJY$`rI*{%O#+3q{Tl^bLAabBQ?>THbDU;BEs(&~|m&4GKKJ~$K*iq^az2kZ5W zkn42;*%ceMtqsInUG>+=EMG?L9mqa`b$>WV#nbwbe^NB86|r&$xcgf=F$H%;#j1QI z2l~D_AN=1CtPV8uK_J!|nf3gno1f@weQmckXx7x(LbNS^(YCgReHe3kw*_qB?>+f} z>pOxE1)mHaO-%fIGB({5IER%hYnsnC?lrR5>fV)8`+I_xXI19T-gIzvAimb>PQ~Ln zQ#@=JL#=%t<0%~nGL|p#$A3p}{`t*3!=vy2>?o+40v`(W7u0mYeetvgYNEh~%YxRX zSN7(&_U5~Lb23`~%X{Jz4;q^ z^Xq%_JDYii!}mizsPWmrxp`@@DmX7_?-6+gb@8!4J>Zi&d0G>=@71qo=1icT$fZMl zI`eeg95^>qU7v0!3y-=X_lkh;tI7f1sX&}G zv{wf8yc8RHw9-M=z(SgRKKFfeeou}ka^pGYyln`!1@8Er!3zR8dUbGr@YTUPf_De+ z4L%Z(jaI9kPI0Zh>e2M~#A6&EAII%E^ZmUn9nHTus*UMj5U{7ES5I2iOP}8UD0;a; zi%$;4T3@=1FAd}bS{aq6<;altdkM=ymC*5nB155Nw#^+U3%<-1)smxDn=70C8$J76DZ~lSa z{7`TH>deK@dx0~qH>XdGF3G;yDgF26Zwz>cs`>uj{3V%-RlR5E%U<%PvOj81O#Ujt zXz9iJ!&$4?sav|yl&xipJN9j%rORIVG?_7ayn0|e`u&|gd*#owI(_&{7ybB3rZZA9 zP78gTuMhpN$IrhvbG#+X8N$ooughMW+dDd1G}{9H!^$5%e7NSBKI!9`>&2Pv@nk-HG0Nhu*ud{&Tzj+^%2O_0F;VEdkrfIjghXx_1G+`^dgLpPRo`Aug@m zKi=7GjsJYR`bQ5RzUsY4{F4*yMIShP_zQv`$RD2miQwY@c=+&@!CdydV|jPFICyOY z4ATE?(8lqDInd_(uUNmTS*u#8_|#k+*~SjIG&)}v%>TsU!|x3a{p8`pZw=gS{DqRg zJM!B)xG8_Lqn+RSmye%6uQ&hXUp#*Q`+M`-d-JuK(_cAydS}m$uD_`3#R=WB0=Dw& zH~#$a;kM>~CUa-TzMTAr-u&H}w|Bs|^!Qh2-un7u|Ko^l>m!S9cd!2Q0y@;kcZ8;L zw3HflCde39yK2+^_O8D&y<9pI^dyU42ZyW#fGug*i_Z2_8R1op)a-rcQ>eY-yUOGoH0>8<}l*0VIU z-&tjg^YOgSmdeY0`GId6=TGEs!?g1cW-g{h|428l`>@VGd--=$*E>_@o}v0%0y4-x zvy)MGOx+n3=L_c1LK*7r%``?dzZ2&F!138-3kRySw@2 zU4L!Y7d;!$^IKo_H?DTh>FB%T8au^7%QbpfeTjkE+8n55wCorJ?0-+7O$Sd7_-LITIbR!SMT;LT*&70%eOlS} zX99BAV*c^iVm{wN{7Q#=!+9o0&NO>+?A~vE$n@x*_5R*m)+!!-o9J)jlWTMsAGuLC z+CL_L+3S3Q7>d7Gweeb&Ih*yxBgVkTiYs3$ca^J&tQAjRkKDM=+WR|yI%@cHGPTgp zQ^^^nTOOZC-ResFli0`4ntPva=kLl~P1|SZH}&RU)|t2 zHJP6ldNi7|ZeL7|?dfZ7&zy~Vack-5Hh1s25AbX517r8W>*JXF;H6>SoPJACIdOlv zSIuVwdaAC>$uMV+vCodr5AZpU_%;P{uXa2`b_DJewz}`_x$oV9WOz2cA&kzhT4bNL zJ|NRsD?8Po?KRWs16zhIW4rFaA;1B(5VRy;KL!a7Zf7zGeQ9JM! zec31HZ#?NAu8)ePIQQ#_o$@ss@P8(t=UD1P&A0VY^*~14B_HLNUyyS~7x*frWKpkr>f7zfW#AaK72kmd=Uhzy5tE$Vk zo~+BG{7eTo24u^rT)8jUU(Y=DlZ(b!do-v#*`tpvch25G+j*oL>Z!5&L;h;6M%M&v znhf}&X7%dB*gE^q4d|Z=P7d66Y;Nrr5Awyg^?@w$nGMkJ^X@FjpLY&Eh{>%%^7aPWd?2<{f!G{tOzv%L zXB*p3L`=T8k^6sIOzvxJKanxHzmdD#nAAB`qv}IbpK7~(4`8o%ZD+kuXU|-H)m&|_ z57dtuuk(F8y67nRbg9$QQ|~3M9=g!A*q^!c%(l9lGJM?q@7?P;!DYcq0_WmD@U_8v zgWn0BoFK0b{2eL3r>}__oA~RjPXt=6yL0SK2Vz_AKgMFO*DChxM%(7VUG|LNV00Rj z>HO{rvNZHmN$*o}3Db=HaZ>JA`|cJ~GrKox6gN{Db=>OG6*fs73D&HwRA*yxZ{aV1Spb z$-vs4K;6b6Zr(Yk49eK{lm&F+Im>U`S6;IhCwHvi~h|5t>T z{p9#wgOBFqJkr~{CTncs4}Cu0)Yv=3nt)z*d{#jIS4M`jI~nlV=N9%%1^V`RGn+Zv zb_e2YPA*&B1LTvdHmuiYEqio*Ri}#$eO+phF1E3Kb5L<8*?rr;dKtE># zxg}sD9(Jl%^&v;V2em^F8S2sexw(7U|E2)1-277DuD>Dpz5pGW^%>Hbzw$*-eXsCv z#$>!Tm$}YDS$lK0H=kbK>5x10YSi6gt!>Dqv_;~W;w3(MIoDTi<%rI00b9xZ`ut-bu@J}UfKTZ7#4e2zt_XgJl z>vIn0(r*gHMxC-1kMs4?plXAk=*TQT)f5|Ad-0aciHy;+u`m1kvUVb6vw?1RoHH+1 z;8@CWe7^V&ch{&g1X`6DJ91NO9hw`Km}pzh%ehc>FI0-5V6WHQ+ovH9*t9>(nMX zdtV=Zx-0(H{GGR5>9xV||Ht1c>ac8LAO5!1uo+Iyh%lny=ytxBF?Z~&d zep3W`UXxw#YU?vrNAf@)o7iT)CTMHr?I9rNo4fw8^lE1+AOoNMZ^^oI>8|PP5-&2{ zF~8;WrlJx(D^*3}m*l$QP5XLCk*AZ|1JF@7(ZVUC`3g z%`Z9sH(}rh-<^3pW$Voui$~dCIktZ=pv(BqfL*o5R{HSsgMRz-LD}B!4YIDW1N~e; zm%5RQcSO-3{oe*;w0qyWz}~ktdum}@z-H|&`ERX>mzG}xecbPq_#GAJ$3FT&=6tI8 zGrE1gSX&YNdiTs1uUh+Hw^n@L-J8E9bNn>?e}*IZ4Q z7tZL$XLkMB>FML^GxNLPt?WF^{OjAzO?)OY44!;tnKL5=4xk-b*dZ>JVo zS>KcSfzVsq-^o~;-kK(7buL;t+Zw*pLNgr{4?E1!Yv$@lEcxud(_7b{)9W{P^XkPI zo#)o5-W_7yJKCjzJZj>=muCgvo0_Rlj(bk#g z?~Z_Me82{CXZSlq>`riJtBdmjGBxMmGea z!xxRt?LlAXXN-~MnLiouLoUnT8#AsL&39uyw|3xtLx5L&)wuI0AJ*J~J_i_22d4&j z^!CJ(t#sMf<0Xeqd5+mfzY9{!^r!`GCTL}zlDT@3H?<;fC6gX9TYJ#r|D1q+IsUFF ztQ?Ce8SE)r)hbwLTg&_1BX~nHlJ}CVvx%&dt@hZ#Z@SBWF*z&XU#stXM(ATx$!l$0 ziaxQboQs8~&h8GxeKPR8eP^e)>TE;S#7KKIkYk^tJo@agenq#3 zPO~;0$X(UEytVvAL(e!GwZoPb5&U3!t!x~}Q##yJY7N~W(E7HvzSs^4IY$`k2amB{_5iWD}uCed(KuwW< zSs+%sgU<|R19yOZt<^_P>0`In>XSX|9h9HmKdPqC(7!gQT)W#fI;}b1?+T-P zlJ5E(vM%HH-l@3M8eQy=f8#R(G{*M??E3Z8$y|Co_O$X3op{LIGlK8Uf>>I|Q}>0u z^I>B!5o`{&1n8jRi%yKuk=dscZ@%K03B(o8Qsb)LmK)dai!$#-71s=hpC2lQ?(^e` zt9Yqf@q2f4@u$^QvB>i9T=HRc@SugX;{CVbt=Nd*Z{tqK)*#zY z`dDf~J+^1i9{<(RnqX}p$93k_vNNw{cL!?J9=qkU?Ek?i5KFx5`Jv3keKzonm<;6H zSj|rdYT@69uHuDvDsaBrdqgd<5g!@!TAK^Rtj2sRx$o)8>)RTd8#Ata zlwS6-Lyqe?T)NS+KWc~1-8KjH3>GVKWMj!EkN=+E&QXm$Z_sIVzUcqq#xK15x-}?1 zvDpx?YdJRXvDNb$R>o~C)DD~HgF2gR zBI}euBg2|lizWZ*=dZcC(|ks${M7o7#-GY3y2&wgKi1H(kxp?}lWpG5&fGr#*t9#a zZ>|oD@4b=d%)6u6;ye{9-}M=0efIc@ztv6tvFLtZqnq5)s~@MEt*vf)k45)?I0oJ9 zqMN_YqxZu@={5163)tcraC%U6V0}Iix7w>7eZAKiSKX?;je$DQ)C@XzK-3P;@{4j` zuFhC4@ownW(+!_l?0h6phwjB&12&N3T<#CVQ>@L^(fcEu4VClrGFBJbb-_f3syDUz zf$;E^9`g@2^L?4q+3NU@Jstd98MOC7NFEnUzOd`IK${M(37lDt?LR(3F552&@UcUj zDtC1TTNxi(M22{ck|7>i5v-cg^+cK|xdavsC%Qif-S!;d0pf_LBo3F^+St=fKeB(8& z$=lNP&Jy`g3)sd^jUQ9Nvx1K#Zda%G-xSpj28Qk~arJu(?3@k`1ZqjXM(w{L>vsgs zd?#-BHz;>yUhf_cXM9T_CfY-Rd&+&Nx2In24A>&?tvvLX2lS&Sdm(x<@@E2u_47!^ z;;E+UeTMI=0<9NxMg zGabfJU2FMs8biD2v_{`!StHB+;m*DwaL%kbBkV_iUvN$E)Sy1&-k$MYfqP&&pjVA* z=J@RG4bBT<+EAVt8LL+|81sXC|2Em(EnfCCa$g#34mJehsj;_W!Tx?Mema8tu@LvE zU@5+;>++Q!Ri9#`F4e&o1!`kD5D#=>B6cqe=rcz9+F%rI#iMwtR>Vd8YkyR{eq{;q zQb(FvR^Q^suJZ%+So2#lrYnDnWq9}Ak#U^`^kU49is=;@J4fWpjd-ycS~_)!PRz98 zpUHSS;NuNlPfyej|HhDbzdyJ!VCQ7e%6)O>__araaeI7dZB$pFKB28I^5p2e;FO^J zsycl*YnnV;tGT$Ev!Uwp&Wy=-cAQc6i^b0*Kox^bkG{jSHto&&2ZFLa!;yA65BRjw zJD)MVt&FG~zN4wO|9JP#l&zsp&Pe@yiyqG#G1t4}^=R}(=RBFO4m_98Yu3fdbLnTJT#bEA z7fjC}bub%Lji1@AU7p^Vso2kDEcTa02A*2a@aX$W$=jW^l4pO^daK8oYvmO^8~8a& zmOXxr+Y_g8dvY;uPyN;!T=zhRNAElKi2D}?^dAV4>YdJrJ4f#A+p|_@ zhHPio`i_8pYnrp+P8p|DPMlA=&JFeldv{Aa8AzY3glc9|avE)M=n zjFlH>=-z-m_P?_0t(7nB`fIX&ZGisdK>o@nvDNrwe<7dVp8fKPt>q72?9us-0L^o| zepPzD6m9w5(zm|o2R82u$Y|}J&;0HHO-y)Ptjt?_cKmjL*3owV{?`z-G~)J>pdZUxLo0Sb-i2MS zE^AJHzZTg-_G3ZmTidODclxra&2{no^$4Cn8N`t| z>F0u~bG+cbS2J4G3p#bxf8H#WU%c4=sz40H!so6xq-VSHczaOizui+)`-3_QwKv~e z6Ndu3<+xwxRg-6AZ#v*_t%(!A%{`l)-3`G+(8}4Gx#nl2r>3uY{_NiHdy=cN_8@{Z zca0eBG)eQkCznh)Ldy>^aKDi!KKBLJ1fLz$=K<@d2jVdkR6hBM?_gleH#&^(3COAc z4i|a$oU>mJLD|Iy^4X#8Dkf@VZMV)o@$K7478~nKkfToJOFoVH`Y(by167m!u}6os zD*|%Va!W(!bU+>+I>eyly*^`gZ{5DUwlONd#bmKq`5E_I=!(Z!eO?);t5w0~U`s&W znt-k4zgU*-#_X94*dwlY1#FlK>Mn9l*<3p0h+h1a6TZGL7zEm;fc~mKe}|0Rn){sA z&R?9lSc@SVI-b(4nUi%&=JwfNG=J0k4zYe8a9hWN?_2VHUb-QVx&J1CT(mSl*rPcV z8a2|={8o=oY?-P zteIrTXns~VcaNIO|7C$3lc`xRd8Mc9S*)&# zuKdxH&3=vjWca-Ks|l_%@|*-|bNVfTc!PM}A6y%-RofKEkLSVOfXv$iI`0ZRqejt_ z*V66Cd}Bav=`{xY+q$v)k^Q>^Hq)~wkoyM%P5jt|_F$0fYFNWpWGv?7t?I^nf)@mQ z5o3*Pm<{+vr+s{ynouVN_OB1fXOnvwy?Oalaissuz?_Zf=@C1AnbY0(Yh~8(l-vx5 zbQL?cdCsb{n}Sh##b&vB$-}cV&=%5Pev5zUHwJ#Y%PKeJFJFzJ@3UH;2;@lq#K8E< zpmddeas=XWUT|u#FJLbjWe*v^9(gyO3GmJaaw-pUT)D8eHee6FErEvb^nfnwY@6)n z*3E$)=S&=(FLKc7i@$m{RLx~LjLVhj`A{2fr49o~h*FDH-&DJvMI$>}xXtAGZc*>isFhp`8PRG`VFL8PfqjikD12@sE9% z1#15CfPG?X%ttvh7R!3>h_@U~2KMxoGjp|PPN%uvoZaSnb2gak&DmnEH!qv?=4F?@ z<`su`=1!$oOz@*&FS@d)^p^aRQ*>g6-t$rKIjHw}SMM{X{+zDIe`z2_n*5Scc@#@f zquaW%9N-gse(_z7tUJ$W|G7Lb`hJOp{D_m<(!^j#;0&w^PQ>$~uUGBT`{{UI^mVKK zi9qdL5r~2DmBCyf7Gbn->*}yZ>m@TEFgwp}(F@bcspb)y}z?i=i>vtAaOlbF}q7CC0 z@~Fwdbbx*kXymUPj*je$-^syTU{CBSmd4P}&95F~Zc1L8oARl0DlhzgL7I-SxSzYF z#9A$BGePBp9oF@uVy%YcQ_Zw7etPEGI9cOj+{$ZX>)E6&ByUt~TX_q`w7vhwjYq{) zF4qR5?w0wi%a^n19&yIk2hQ1KQ1YCAF>G@*N*-CTE6|F@+HCOYxR1(a_GGRLzKueerp1phoz*IuHvreQvNa;KSB{Tz_+%Z}!xbb$maRbv3vxKnEYn_bus$ zF)q5dgid{laZCFr9j#p07jHbyi+|s1joy~$?>nA)SCh-)`I+wfGJLhp&L8N$C$rYd zIxXv28tU%*$A*`7eD=uXYx#6Z_Qb=xik@$JXGE{2^mwglPY%SD9P;p#k9zz1ibwfa z-^0~=s63*p_s=!me7ft`rN1hod8(joLFJ?|TBe)r=ghx&{D#>~YFE&XJY zAqFkaqnT^^&B2y{9Z)%1YAn?$o8@|;m^ou&wx*+HlQ@YFofSLrC(E9gR_{)o3i!s( z#bWupy;xRk=v``TLOQG=c4%^qw_>D@&G{f+@~!O%HUw-H8#!Tf8|zFTSHtX;^QFf9 z>7lI}7BhA%6n`}${_J3H#an#EaynQ_T>C#mz`K)qFUt6nUz9AsLa$9HGo*1YJ_fenMnz{nD zy)JNHO$A!*?K(0Y^4DFwx7(*nOzKXN*DHd3L7gi#@rG`W)*VKVdjUTi`B!(YI92@6 z+0*dyiT`}598@jI!GnROo;2~F4$uz*jePOaDnIni1@^?gVrdN9y59KLx^qJ2a`IBL z_)vW1Pn`uh;qwauZIsXSx}U1<%4hMUV`rf8#hOOug~QQ!nRO1ABDdnZSbo?_u6`+U z(P_n_Hq?c>tNhSiWB%26BIADEmJ(}qq|F4C4|Z7BkBYVW5$k@8pPn^soUCy%ZsoPH zJ^P5b1?7#3Z7Xk~m_8%&#qg$J+<2jwj=ERoBTK%VOLvGIt`D5C$)Myp`(h~OXx0X! z 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

L>$D7ZDPh2 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

Vx~_%tmAr=$J?BI_3dPzU+gXd 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%0D>>0lx;KRR&4~z8g4frwcefhAbo{t6m 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≫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

biDw>aWzhs&C*q;< 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%0ApnToblG-sJJ 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ⅈ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ⅇj9GriuDOUhjVP`(=j&q%sn=gK{i5bY><#W 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 V4!{mIZy#dI%KG~HQ_afC{{xF=Oyd9m delta 145776 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�PP{ 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 diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml index 79384c1f..d8fb5c68 100644 --- a/bytecomp/bytegen.ml +++ b/bytecomp/bytegen.ml @@ -315,7 +315,9 @@ let comp_primitive p args = | Pintcomp cmp -> Kintcomp cmp | Pmakeblock(tag, _mut, _) -> Kmakeblock(List.length args, tag) | Pfield n -> Kgetfield n + | Pfield_computed -> Kgetvectitem | Psetfield(n, _ptr, _init) -> Ksetfield n + | Psetfield_computed(_ptr, _init) -> Ksetvectitem | Pfloatfield n -> Kgetfloatfield n | Psetfloatfield (n, _init) -> Ksetfloatfield n | Pduprecord _ -> Kccall("caml_obj_dup", 1) diff --git a/bytecomp/bytelibrarian.ml b/bytecomp/bytelibrarian.ml index e89676a9..a3ba3ba4 100644 --- a/bytecomp/bytelibrarian.ml +++ b/bytecomp/bytelibrarian.ml @@ -29,7 +29,7 @@ exception Error of error let copy_compunit ic oc compunit = seek_in ic compunit.cu_pos; compunit.cu_pos <- pos_out oc; - compunit.cu_force_link <- !Clflags.link_everything; + compunit.cu_force_link <- compunit.cu_force_link || !Clflags.link_everything; copy_file_chunk ic oc compunit.cu_codesize; if compunit.cu_debug > 0 then begin seek_in ic compunit.cu_debug; diff --git a/bytecomp/bytelink.ml b/bytecomp/bytelink.ml index 660c1eaa..8f82fc96 100644 --- a/bytecomp/bytelink.ml +++ b/bytecomp/bytelink.ml @@ -501,6 +501,13 @@ let link_bytecode_as_c ppf tolink outfile = \n caml_sections, sizeof(caml_sections),\ \n argv);\ \n}\ +\nvalue caml_startup_exn(char ** argv)\ +\n{\ +\n return caml_startup_code_exn(caml_code, sizeof(caml_code),\ +\n caml_data, sizeof(caml_data),\ +\n caml_sections, sizeof(caml_sections),\ +\n argv);\ +\n}\ \n#ifdef __cplusplus\ \n}\ \n#endif\n"; diff --git a/bytecomp/bytepackager.ml b/bytecomp/bytepackager.ml index 2471ad59..94c11821 100644 --- a/bytecomp/bytepackager.ml +++ b/bytecomp/bytepackager.ml @@ -101,26 +101,28 @@ let read_member_info file = ( let name = String.capitalize_ascii(Filename.basename(chop_extensions file)) in let kind = - if Filename.check_suffix file ".cmo" then begin - let ic = open_in_bin file in - try - let buffer = - really_input_string ic (String.length Config.cmo_magic_number) - in - if buffer <> Config.cmo_magic_number then - raise(Error(Not_an_object_file file)); - let compunit_pos = input_binary_int ic in - seek_in ic compunit_pos; - let compunit = (input_value ic : compilation_unit) in - if compunit.cu_name <> name - then raise(Error(Illegal_renaming(name, file, compunit.cu_name))); - close_in ic; - PM_impl compunit - with x -> - close_in ic; - raise x - end else - PM_intf in + (* PR#7479: make sure it is either a .cmi or a .cmo *) + if Filename.check_suffix file ".cmi" then + PM_intf + else begin + let ic = open_in_bin file in + try + let buffer = + really_input_string ic (String.length Config.cmo_magic_number) + in + if buffer <> Config.cmo_magic_number then + raise(Error(Not_an_object_file file)); + let compunit_pos = input_binary_int ic in + seek_in ic compunit_pos; + let compunit = (input_value ic : compilation_unit) in + if compunit.cu_name <> name + then raise(Error(Illegal_renaming(name, file, compunit.cu_name))); + close_in ic; + PM_impl compunit + with x -> + close_in ic; + raise x + end in { pm_file = file; pm_name = name; pm_kind = kind } ) diff --git a/bytecomp/cmo_format.mli b/bytecomp/cmo_format.mli index 7fbb35a0..4f4e7bbf 100644 --- a/bytecomp/cmo_format.mli +++ b/bytecomp/cmo_format.mli @@ -63,3 +63,9 @@ type library = ... object code for last library member library descriptor *) + +(* Tables for numbering objects *) + +type 'a numtable = + { num_cnt: int; (* The next number *) + num_tbl: ('a, int) Tbl.t } (* The table of already numbered objects *) diff --git a/bytecomp/emitcode.ml b/bytecomp/emitcode.ml index 7857202e..5cdc620e 100644 --- a/bytecomp/emitcode.ml +++ b/bytecomp/emitcode.ml @@ -393,7 +393,7 @@ let to_file outchan unit_name objfile ~required_globals code = cu_primitives = List.map Primitive.byte_name !Translmod.primitive_declarations; cu_required_globals = Ident.Set.elements required_globals; - cu_force_link = false; + cu_force_link = !Clflags.link_everything; cu_debug = pos_debug; cu_debugsize = size_debug } in init(); (* Free out_buffer and reloc_info *) diff --git a/bytecomp/lambda.ml b/bytecomp/lambda.ml index b087ca52..9932e789 100644 --- a/bytecomp/lambda.ml +++ b/bytecomp/lambda.ml @@ -39,8 +39,9 @@ type immediate_or_pointer = | Pointer type initialization_or_assignment = - | Initialization | Assignment + | Heap_initialization + | Root_initialization type is_safe = | Safe @@ -60,7 +61,9 @@ type primitive = (* Operations on heap blocks *) | Pmakeblock of int * mutable_flag * block_shape | Pfield of int + | Pfield_computed | Psetfield of int * immediate_or_pointer * initialization_or_assignment + | Psetfield_computed of immediate_or_pointer * initialization_or_assignment | Pfloatfield of int | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int @@ -213,6 +216,7 @@ type function_attribute = { inline : inline_attribute; specialise : specialise_attribute; is_a_functor: bool; + stub: bool; } type lambda = @@ -286,8 +290,12 @@ let default_function_attribute = { inline = Default_inline; specialise = Default_specialise; is_a_functor = false; + stub = false; } +let default_stub_attribute = + { default_function_attribute with stub = true } + (* Build sharing keys *) (* Those keys are later compared with Pervasives.compare. diff --git a/bytecomp/lambda.mli b/bytecomp/lambda.mli index f346b0e7..6a058857 100644 --- a/bytecomp/lambda.mli +++ b/bytecomp/lambda.mli @@ -39,11 +39,14 @@ type immediate_or_pointer = | Pointer type initialization_or_assignment = - (* CR-someday mshinwell: For multicore, perhaps it might be necessary to - split [Initialization] into two cases, depending on whether the place - being initialized is in the heap or not. *) - | Initialization | Assignment + (* Initialization of in heap values, like [caml_initialize] C primitive. The + field should not have been read before and initialization should happen + only once. *) + | Heap_initialization + (* Initialization of roots only. Compiles to a simple store. + No checks are done to preserve GC invariants. *) + | Root_initialization type is_safe = | Safe @@ -63,7 +66,9 @@ type primitive = (* Operations on heap blocks *) | Pmakeblock of int * mutable_flag * block_shape | Pfield of int + | Pfield_computed | Psetfield of int * immediate_or_pointer * initialization_or_assignment + | Psetfield_computed of immediate_or_pointer * initialization_or_assignment | Pfloatfield of int | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int @@ -229,6 +234,7 @@ type function_attribute = { inline : inline_attribute; specialise : specialise_attribute; is_a_functor: bool; + stub: bool; } type lambda = @@ -332,6 +338,7 @@ val commute_comparison : comparison -> comparison val negate_comparison : comparison -> comparison val default_function_attribute : function_attribute +val default_stub_attribute : function_attribute (***********************) (* For static failures *) diff --git a/bytecomp/matching.ml b/bytecomp/matching.ml index b2dcd248..8159cc51 100644 --- a/bytecomp/matching.ml +++ b/bytecomp/matching.ml @@ -456,7 +456,7 @@ let pretty_precompiled_res first nexts = (* However, as shown by PR#6359 such sharing may hinders the lambda-code invariant that all bound idents are unique, - when switchs are compiled to test sequences. + when switches are compiled to test sequences. The definitive fix is the systematic introduction of exit/catch in case action sharing is present. *) @@ -537,7 +537,7 @@ let up_ok_action act1 act2 = with | Exit -> false -(* Nothing is kown about exception/extension patterns, +(* Nothing is known about exception/extension patterns, because of potential rebind *) let rec exc_inside p = match p.pat_desc with | Tpat_construct (_,{cstr_tag=Cstr_extension _},_) -> true @@ -571,11 +571,11 @@ let up_ok (ps,act_p) l = (* Simplify fonction normalize the first column of the match - - records are expanded so that they posses all fields + - records are expanded so that they possess all fields - aliases are removed and replaced by bindings in actions. However or-patterns are simplified differently, - aliases are not removed - - or patterns (_|p) are changed into _ + - or-patterns (_|p) are changed into _ *) exception Var of pattern @@ -646,7 +646,7 @@ let simplify_cases args cls = match args with -(* Once matchings are simplified one easily finds +(* Once matchings are simplified one can easily find their nature *) let rec what_is_cases cases = match cases with @@ -659,10 +659,10 @@ let rec what_is_cases cases = match cases with -(* A few operation on default environments *) +(* A few operations on default environments *) let as_matrix cases = get_mins le_pats (List.map (fun (ps,_) -> ps) cases) -(* For extension matching, record no imformation in matrix *) +(* For extension matching, record no information in matrix *) let as_matrix_omega cases = get_mins le_pats (List.map @@ -853,7 +853,7 @@ let insert_or_append p ps act ors no = ors,(p::ps,act)::no else (* p # q, go on with append/insert *) attempt (cl::seen) rem - end else (* q is not a or-pat, go on with append/insert *) + end else (* q is not an or-pat, go on with append/insert *) attempt (cl::seen) rem | _ -> (* [] in fact *) (p::ps,act)::ors,no in (* success in appending *) @@ -883,7 +883,7 @@ let rebuild_nexts arg nexts k = Splitting is first directed by or-patterns, then by tests (e.g. constructors)/variable transitions. - The approach is greedy, every split function attempt to + The approach is greedy, every split function attempts to raise rows as much as possible in the top matrix, then splitting applies again to the remaining rows. @@ -938,7 +938,7 @@ let rec split_or argo cls args def = do_split [] [] [] cls -(* Ultra-naive spliting, close to semantics, used for extension, +(* Ultra-naive splitting, close to semantics, used for extension, as potential rebind prevents any kind of optimisation *) and split_naive cls args def k = @@ -1058,7 +1058,7 @@ and split_constr cls args def k = end | [ps,_ as cl] when List.for_all group_var ps && yes <> [] -> - (* This enables an extra division in some frequent case : + (* This enables an extra division in some frequent cases : last row is made of variables only *) split_noex yes (cl::no) [] | (p::_,_) as cl::rem -> @@ -1228,15 +1228,15 @@ let divide_line make_ctx make get_args pat ctx pm = There is one set of functions per matching style (constants, constructors etc.) - - matcher function are arguments to make_default (for defaukt handlers) + - matcher functions are arguments to make_default (for default handlers) They may raise NoMatch or OrPat and perform the full matching (selection + arguments). - get_args and get_key are for the compiled matrices, note that - selection and geting arguments are separed. + selection and getting arguments are separated. - - make_ _matching combines the previous functions for produicing + - make_ _matching combines the previous functions for producing new ``pattern_matching'' records. *) @@ -1468,8 +1468,8 @@ let matcher_lazy p rem = match p.pat_desc with | _ -> get_arg_lazy p rem (* Inlining the tag tests before calling the primitive that works on - lazy blocks. This is alse used in translcore.ml. - No call other than Obj.tag when the value has been forced before. + lazy blocks. This is also used in translcore.ml. + No other call than Obj.tag when the value has been forced before. *) let prim_obj_tag = @@ -1841,7 +1841,7 @@ let share_actions_tree sw d = let hs,handle_shared = handle_shared () in let acts = Array.map handle_shared acts in -(* Recontruct default and switch list *) +(* Reconstruct default and switch list *) let d = match d with | None -> None | Some d -> Some (acts.(d)) in @@ -2104,7 +2104,7 @@ let as_interval_nofail l = let inters = match l with | (i,act)::rem -> let act_index = - (* In case there is some hole and that a switch is emited, + (* In case there is some hole and that a switch is emitted, action 0 will be used as the action of unreacheable cases (cf. switch.ml, make_switch). Hence, this action will be shared *) @@ -2218,7 +2218,7 @@ let mk_failaction_pos partial seen ctx defs = pretty_jumps jmps end ; None,fail,jmps - end else begin (* Two many non-matched constructors -> reduced information *) + end else begin (* Too many non-matched constructors -> reduced information *) if dbg then eprintf "POS->NEG!!!\n%!" ; let fail,jumps = mk_failaction_neg partial ctx defs in if dbg then @@ -2247,8 +2247,8 @@ let combine_constant loc arg cst partial ctx def const_lambda_list in call_switcher fail arg 0 255 int_lambda_list | Const_string _ -> -(* Note as the bytecode compiler may resort to dichotmic search, - the clauses of strinswitch are sorted with duplicate removed. +(* Note as the bytecode compiler may resort to dichotomic search, + the clauses of stringswitch are sorted with duplicates removed. This partly applies to the native code compiler, which requires no duplicates *) let const_lambda_list = sort_lambda_list const_lambda_list in @@ -2515,11 +2515,11 @@ let rec event_branch repr lam = This exception is raised when the compiler cannot produce code because control cannot reach the compiled clause, - Unused is raised initialy in compile_test. + Unused is raised initially in compile_test. compile_list (for compiling switch results) catch Unused - comp_match_handlers (for compililing splitted matches) + comp_match_handlers (for compiling splitted matches) may reraise Unused @@ -2645,7 +2645,7 @@ let rec comp_match_handlers comp_fun partial ctx arg first_match next_matchs = | rem -> let rec c_rec body total_body = function | [] -> body, total_body - (* Hum, -1 meant never taken + (* Hum, -1 means never taken | (-1,pm)::rem -> c_rec body total_body rem *) | (i,pm)::rem -> let ctx_i,total_rem = jumps_extract i total_body in @@ -2806,10 +2806,10 @@ and compile_no_test divide up_ctx repr partial ctx to_match = Notice that exhaustiveness information is trusted by the compiler, that is, a match flagged as Total should not fail at runtime. - More specifically, for instance if match y with x::_ -> x uis flagged + More specifically, for instance if match y with x::_ -> x is flagged total (as it happens during JoCaml compilation) then y cannot be [] at runtime. As a consequence, the static Total exhaustiveness information - have to to be downgraded to Partial, in the dubious cases where guards + have to be downgraded to Partial, in the dubious cases where guards or lazy pattern execute arbitrary code that may perform side effects and change the subject values. LM: @@ -2957,7 +2957,7 @@ let simple_for_let loc param pat body = didn't optimize situations where the rhs tuples are hidden under a more complex context. - The idea comes from Alain Frisch which suggested and implemented + The idea comes from Alain Frisch who suggested and implemented the following compilation method, based on Lassign: let x = dummy in let y = dummy in diff --git a/bytecomp/printlambda.ml b/bytecomp/printlambda.ml index 94513920..36594f00 100644 --- a/bytecomp/printlambda.ml +++ b/bytecomp/printlambda.ml @@ -143,6 +143,7 @@ let primitive ppf = function | Pmakeblock(tag, Mutable, shape) -> fprintf ppf "makemutable %i%a" tag block_shape shape | Pfield n -> fprintf ppf "field %i" n + | Pfield_computed -> fprintf ppf "field_computed" | Psetfield(n, ptr, init) -> let instr = match ptr with @@ -151,15 +152,30 @@ let primitive ppf = function in let init = match init with - | Initialization -> "(init)" + | Heap_initialization -> "(heap-init)" + | Root_initialization -> "(root-init)" | Assignment -> "" in fprintf ppf "setfield_%s%s %i" instr init n + | Psetfield_computed (ptr, init) -> + let instr = + match ptr with + | Pointer -> "ptr" + | Immediate -> "imm" + in + let init = + match init with + | Heap_initialization -> "(heap-init)" + | Root_initialization -> "(root-init)" + | Assignment -> "" + in + fprintf ppf "setfield_%s%s_computed" instr init | Pfloatfield n -> fprintf ppf "floatfield %i" n | Psetfloatfield (n, init) -> let init = match init with - | Initialization -> "(init)" + | Heap_initialization -> "(heap-init)" + | Root_initialization -> "(root-init)" | Assignment -> "" in fprintf ppf "setfloatfield%s %i" init n @@ -323,7 +339,9 @@ let name_of_primitive = function | Psetglobal _ -> "Psetglobal" | Pmakeblock _ -> "Pmakeblock" | Pfield _ -> "Pfield" + | Pfield_computed -> "Pfield_computed" | Psetfield _ -> "Psetfield" + | Psetfield_computed _ -> "Psetfield_computed" | Pfloatfield _ -> "Pfloatfield" | Psetfloatfield _ -> "Psetfloatfield" | Pduprecord _ -> "Pduprecord" @@ -412,9 +430,11 @@ let name_of_primitive = function | Pint_as_pointer -> "Pint_as_pointer" | Popaque -> "Popaque" -let function_attribute ppf { inline; specialise; is_a_functor } = +let function_attribute ppf { inline; specialise; is_a_functor; stub } = if is_a_functor then fprintf ppf "is_a_functor@ "; + if stub then + fprintf ppf "stub@ "; begin match inline with | Default_inline -> () | Always_inline -> fprintf ppf "always_inline@ " diff --git a/middle_end/semantics_of_primitives.ml b/bytecomp/semantics_of_primitives.ml similarity index 75% rename from middle_end/semantics_of_primitives.ml rename to bytecomp/semantics_of_primitives.ml index 3cedc03f..f963d867 100644 --- a/middle_end/semantics_of_primitives.ml +++ b/bytecomp/semantics_of_primitives.ml @@ -22,19 +22,19 @@ type coeffects = No_coeffects | Has_coeffects let for_primitive (prim : Lambda.primitive) = match prim with | Pignore | Pidentity | Pbytes_to_string | Pbytes_of_string -> - No_effects, No_coeffects + No_effects, No_coeffects | Pmakeblock _ | Pmakearray (_, Mutable) -> Only_generative_effects, No_coeffects | Pmakearray (_, Immutable) -> No_effects, No_coeffects | Pduparray (_, Immutable) -> - No_effects, No_coeffects (* Pduparray (_, Immutable) is allowed only on - immutable arrays. *) + No_effects, No_coeffects (* Pduparray (_, Immutable) is allowed only on + immutable arrays. *) | Pduparray (_, Mutable) | Pduprecord _ -> - Only_generative_effects, Has_coeffects + Only_generative_effects, Has_coeffects | Pccall { prim_name = - ( "caml_format_float" | "caml_format_int" | "caml_int32_format" - | "caml_nativeint_format" | "caml_int64_format" ) } -> - No_effects, No_coeffects + ( "caml_format_float" | "caml_format_int" | "caml_int32_format" + | "caml_nativeint_format" | "caml_int64_format" ) } -> + No_effects, No_coeffects | Plazyforce | Pccall _ -> Arbitrary_effects, Has_coeffects | Praise _ -> Arbitrary_effects, No_coeffects @@ -54,12 +54,12 @@ let for_primitive (prim : Lambda.primitive) = | Pmodbint { is_safe = Unsafe } | Pdivint Unsafe | Pmodint Unsafe -> - No_effects, No_coeffects (* Will not raise [Division_by_zero]. *) + No_effects, No_coeffects (* Will not raise [Division_by_zero]. *) | Pdivbint { is_safe = Safe } | Pmodbint { is_safe = Safe } | Pdivint Safe | Pmodint Safe -> - Arbitrary_effects, No_coeffects + Arbitrary_effects, No_coeffects | Poffsetint _ -> No_effects, No_coeffects | Poffsetref _ -> Arbitrary_effects, Has_coeffects | Pintoffloat @@ -73,7 +73,7 @@ let for_primitive (prim : Lambda.primitive) = | Pfloatcomp _ -> No_effects, No_coeffects | Pstringlength | Pbyteslength | Parraylength _ -> - No_effects, Has_coeffects (* That old chestnut: [Obj.truncate]. *) + No_effects, Has_coeffects (* That old chestnut: [Obj.truncate]. *) | Pisint | Pisout | Pbittest @@ -92,8 +92,9 @@ let for_primitive (prim : Lambda.primitive) = | Pasrbint _ | Pbintcomp _ -> No_effects, No_coeffects | Pbigarraydim _ -> - No_effects, Has_coeffects (* Some people resize bigarrays in place. *) + No_effects, Has_coeffects (* Some people resize bigarrays in place. *) | Pfield _ + | Pfield_computed | Pfloatfield _ | Pgetglobal _ | Parrayrefu _ @@ -106,7 +107,7 @@ let for_primitive (prim : Lambda.primitive) = | Pbigstring_load_16 true | Pbigstring_load_32 true | Pbigstring_load_64 true -> - No_effects, Has_coeffects + No_effects, Has_coeffects | Parrayrefs _ | Pstringrefs | Pbytesrefs @@ -117,9 +118,10 @@ let for_primitive (prim : Lambda.primitive) = | Pbigstring_load_16 false | Pbigstring_load_32 false | Pbigstring_load_64 false -> - (* May trigger a bounds check exception. *) - Arbitrary_effects, Has_coeffects + (* May trigger a bounds check exception. *) + Arbitrary_effects, Has_coeffects | Psetfield _ + | Psetfield_computed _ | Psetfloatfield _ | Psetglobal _ | Parraysetu _ @@ -133,23 +135,26 @@ let for_primitive (prim : Lambda.primitive) = | Pbigstring_set_16 _ | Pbigstring_set_32 _ | Pbigstring_set_64 _ -> - (* Whether or not some of these are "unsafe" is irrelevant; they always - have an effect. *) - Arbitrary_effects, No_coeffects + (* Whether or not some of these are "unsafe" is irrelevant; they always + have an effect. *) + Arbitrary_effects, No_coeffects | Pctconst _ -> No_effects, No_coeffects | Pbswap16 | Pbbswap _ -> No_effects, No_coeffects | Pint_as_pointer -> No_effects, No_coeffects | Popaque -> Arbitrary_effects, Has_coeffects | Ploc _ -> - Misc.fatal_error "[Ploc] should have been eliminated by [Translcore]" + (* Removed by [Translcore]. *) + No_effects, No_coeffects | Prevapply - | Pdirapply + | Pdirapply -> + (* Removed by [Simplif], but there is no reason to prevent using + the current analysis function before/during Simplif. *) + Arbitrary_effects, Has_coeffects | Psequand | Psequor -> - Misc.fatal_errorf "The primitive %a should have been eliminated by the \ - [Closure_conversion] pass." - Printlambda.primitive prim + (* Removed by [Closure_conversion] in the flambda pipeline. *) + No_effects, No_coeffects type return_type = | Float @@ -167,6 +172,6 @@ let return_type_of_primitive (prim:Lambda.primitive) = | Pfloatfield _ | Parrayrefu Pfloatarray | Parrayrefs Pfloatarray -> - Float + Float | _ -> - Other + Other diff --git a/middle_end/semantics_of_primitives.mli b/bytecomp/semantics_of_primitives.mli similarity index 96% rename from middle_end/semantics_of_primitives.mli rename to bytecomp/semantics_of_primitives.mli index 32205cee..c0c2b9aa 100644 --- a/middle_end/semantics_of_primitives.mli +++ b/bytecomp/semantics_of_primitives.mli @@ -60,12 +60,10 @@ type coeffects = No_coeffects | Has_coeffects the (non-)(co)effectfulness of the arguments in a primitive application. To determine whether such an application is (co)effectful, the arguments must also be analysed. *) -val for_primitive - : Lambda.primitive - -> effects * coeffects +val for_primitive: Lambda.primitive -> effects * coeffects type return_type = | Float | Other -val return_type_of_primitive : Lambda.primitive -> return_type +val return_type_of_primitive: Lambda.primitive -> return_type diff --git a/bytecomp/simplif.ml b/bytecomp/simplif.ml index 4a66f71e..7baf04b3 100644 --- a/bytecomp/simplif.ml +++ b/bytecomp/simplif.ml @@ -632,8 +632,7 @@ and list_emit_tail_infos is_tail = 'Some' constructor, only to deconstruct it immediately in the function's body. *) -let split_default_wrapper ?(create_wrapper_body = fun lam -> lam) - ~id:fun_id ~kind ~params ~body ~attr ~wrapper_attr ~loc () = +let split_default_wrapper ~id:fun_id ~kind ~params ~body ~attr ~loc = let rec aux map = function | Llet(Strict, k, id, (Lifthenelse(Lvar optparam, _, _) as def), rest) when Ident.name optparam = "*opt*" && List.mem optparam params @@ -675,9 +674,9 @@ let split_default_wrapper ?(create_wrapper_body = fun lam -> lam) (wrapper_body, (inner_id, inner_fun)) in try - let wrapper_body, inner = aux [] body in - [(fun_id, Lfunction{kind; params; body = create_wrapper_body wrapper_body; - attr = wrapper_attr; loc}); inner] + let body, inner = aux [] body in + let attr = default_stub_attribute in + [(fun_id, Lfunction{kind; params; body; attr; loc}); inner] with Exit -> [(fun_id, Lfunction{kind; params; body; attr; loc})] diff --git a/bytecomp/simplif.mli b/bytecomp/simplif.mli index 6736ffc3..4b0a3032 100644 --- a/bytecomp/simplif.mli +++ b/bytecomp/simplif.mli @@ -23,15 +23,12 @@ open Lambda val simplify_lambda: string -> lambda -> lambda val split_default_wrapper - : ?create_wrapper_body:(lambda -> lambda) - -> id:Ident.t + : id:Ident.t -> kind:function_kind -> params:Ident.t list -> body:lambda -> attr:function_attribute - -> wrapper_attr:function_attribute -> loc:Location.t - -> unit -> (Ident.t * lambda) list (* To be filled by asmcomp/selectgen.ml *) diff --git a/bytecomp/symtable.ml b/bytecomp/symtable.ml index 8e96f498..d2936f41 100644 --- a/bytecomp/symtable.ml +++ b/bytecomp/symtable.ml @@ -30,12 +30,6 @@ type error = exception Error of error -(* Tables for numbering objects *) - -type 'a numtable = - { num_cnt: int; (* The next number *) - num_tbl: ('a, int) Tbl.t } (* The table of already numbered objects *) - let empty_numtable = { num_cnt = 0; num_tbl = Tbl.empty } let find_numtable nt key = diff --git a/bytecomp/symtable.mli b/bytecomp/symtable.mli index 2aa0eaa9..22dec581 100644 --- a/bytecomp/symtable.mli +++ b/bytecomp/symtable.mli @@ -29,6 +29,7 @@ val output_primitive_names: out_channel -> unit val output_primitive_table: out_channel -> unit val data_global_map: unit -> Obj.t val data_primitive_names: unit -> string +val transl_const: Lambda.structured_constant -> Obj.t (* Functions for the toplevel *) diff --git a/bytecomp/translattribute.ml b/bytecomp/translattribute.ml index fae55ccb..c2b42484 100644 --- a/bytecomp/translattribute.ml +++ b/bytecomp/translattribute.ml @@ -144,14 +144,14 @@ let get_specialise_attribute l = let add_inline_attribute expr loc attributes = match expr, get_inline_attribute attributes with | expr, Default_inline -> expr - | Lfunction({ attr } as funct), inline_attribute -> + | Lfunction({ attr = { stub = false } as attr } as funct), inline -> begin match attr.inline with | Default_inline -> () | Always_inline | Never_inline | Unroll _ -> Location.prerr_warning loc (Warnings.Duplicated_attribute "inline") end; - let attr = { attr with inline = inline_attribute } in + let attr = { attr with inline } in Lfunction { funct with attr = attr } | expr, (Always_inline | Never_inline | Unroll _) -> Location.prerr_warning loc @@ -161,14 +161,14 @@ let add_inline_attribute expr loc attributes = let add_specialise_attribute expr loc attributes = match expr, get_specialise_attribute attributes with | expr, Default_specialise -> expr - | Lfunction({ attr } as funct), specialise_attribute -> + | Lfunction({ attr = { stub = false } as attr } as funct), specialise -> begin match attr.specialise with | Default_specialise -> () | Always_specialise | Never_specialise -> Location.prerr_warning loc (Warnings.Duplicated_attribute "specialise") end; - let attr = { attr with specialise = specialise_attribute } in + let attr = { attr with specialise } in Lfunction { funct with attr } | expr, (Always_specialise | Never_specialise) -> Location.prerr_warning loc diff --git a/bytecomp/translclass.ml b/bytecomp/translclass.ml index fe5a203f..2504a870 100644 --- a/bytecomp/translclass.ml +++ b/bytecomp/translclass.ml @@ -66,12 +66,8 @@ let transl_meth_list lst = (0, List.map (fun lab -> Const_immstring lab) lst)) let set_inst_var obj id expr = - let kind = - match Typeopt.maybe_pointer expr with - | Pointer -> Paddrarray - | Immediate -> Pintarray - in - Lprim(Parraysetu kind, [Lvar obj; Lvar id; transl_exp expr], Location.none) + Lprim(Psetfield_computed (Typeopt.maybe_pointer expr, Assignment), + [Lvar obj; Lvar id; transl_exp expr], Location.none) let transl_val tbl create name = mkappl (oo_prim (if create then "new_variable" else "get_variable"), @@ -684,7 +680,7 @@ let transl_class ids cl_id pub_meths cl vflag = [lfunction (self :: args) (if not (IdentSet.mem env (free_variables body')) then body' else Llet(Alias, Pgenval, env, - Lprim(Parrayrefu Paddrarray, + Lprim(Pfield_computed, [Lvar self; Lvar env2], Location.none), body'))] @@ -695,7 +691,7 @@ let transl_class ids cl_id pub_meths cl vflag = let env1 = Ident.create "env" and env1' = Ident.create "env'" in let copy_env self = if top then lambda_unit else - Lifused(env2, Lprim(Parraysetu Paddrarray, + Lifused(env2, Lprim(Psetfield_computed (Pointer, Assignment), [Lvar self; Lvar env2; Lvar env1'], Location.none)) and subst_env envs l lam = diff --git a/bytecomp/translcore.ml b/bytecomp/translcore.ml index 8b30d9fe..6748c159 100644 --- a/bytecomp/translcore.ml +++ b/bytecomp/translcore.ml @@ -359,6 +359,9 @@ let primitives_table = create_hashtable 57 [ let find_primitive prim_name = Hashtbl.find primitives_table prim_name +let prim_restore_raw_backtrace = + Primitive.simple ~name:"caml_restore_raw_backtrace" ~arity:2 ~alloc:false + let specialize_comparison table env ty = let (gencomp, intcomp, floatcomp, stringcomp, bytescomp, nativeintcomp, int32comp, int64comp, _) = table in @@ -443,7 +446,7 @@ let transl_primitive loc p env ty path = Lfunction{kind = Curried; params = [parm]; body = Matching.inline_lazy_force (Lvar parm) Location.none; loc = loc; - attr = default_function_attribute } + attr = default_stub_attribute } | Ploc kind -> let lam = lam_of_loc kind loc in begin match p.prim_arity with @@ -451,7 +454,7 @@ let transl_primitive loc p env ty path = | 1 -> (* TODO: we should issue a warning ? *) let param = Ident.create "prim" in Lfunction{kind = Curried; params = [param]; - attr = default_function_attribute; + attr = default_stub_attribute; loc = loc; body = Lprim(Pmakeblock(0, Immutable, None), [lam; Lvar param], loc)} @@ -462,7 +465,7 @@ let transl_primitive loc p env ty path = if n <= 0 then [] else Ident.create "prim" :: make_params (n-1) in let params = make_params p.prim_arity in Lfunction{ kind = Curried; params; - attr = default_function_attribute; + attr = default_stub_attribute; loc = loc; body = Lprim(prim, List.map (fun id -> Lvar id) params, loc) } @@ -566,16 +569,6 @@ let extract_float = function Const_base(Const_float f) -> f | _ -> fatal_error "Translcore.extract_float" -(* To find reasonable names for let-bound and lambda-bound idents *) - -let rec name_pattern default = function - [] -> Ident.create default - | {c_lhs=p; _} :: rem -> - match p.pat_desc with - Tpat_var (id, _) -> id - | Tpat_alias(_, id, _) -> id - | _ -> name_pattern default rem - (* Push the default values under the functional abstractions *) (* Also push bindings of module patterns, since this sound *) @@ -586,10 +579,12 @@ type binding = let rec push_defaults loc bindings cases partial = match cases with [{c_lhs=pat; c_guard=None; - c_rhs={exp_desc = Texp_function(l, pl,partial)} as exp}] -> - let pl = push_defaults exp.exp_loc bindings pl partial in + c_rhs={exp_desc = Texp_function { arg_label; param; cases; partial; } } + as exp}] -> + let cases = push_defaults exp.exp_loc bindings cases partial in [{c_lhs=pat; c_guard=None; - c_rhs={exp with exp_desc = Texp_function(l, pl, partial)}}] + c_rhs={exp with exp_desc = Texp_function { arg_label; param; cases; + partial; }}}] | [{c_lhs=pat; c_guard=None; c_rhs={exp_attributes=[{txt="#default"},_]; exp_desc = Texp_let @@ -617,7 +612,7 @@ let rec push_defaults loc bindings cases partial = in [{case with c_rhs=exp}] | {c_lhs=pat; c_rhs=exp; c_guard=_} :: _ when bindings <> [] -> - let param = name_pattern "param" cases in + let param = Typecore.name_pattern "param" cases in let name = Ident.name param in let exp = { exp with exp_loc = loc; exp_desc = @@ -719,14 +714,14 @@ and transl_exp0 e = let kind = if public_send then Public else Self in let obj = Ident.create "obj" and meth = Ident.create "meth" in Lfunction{kind = Curried; params = [obj; meth]; - attr = default_function_attribute; + attr = default_stub_attribute; loc = e.exp_loc; body = Lsend(kind, Lvar meth, Lvar obj, [], e.exp_loc)} else if p.prim_name = "%sendcache" then let obj = Ident.create "obj" and meth = Ident.create "meth" in let cache = Ident.create "cache" and pos = Ident.create "pos" in Lfunction{kind = Curried; params = [obj; meth; cache; pos]; - attr = default_function_attribute; + attr = default_stub_attribute; loc = e.exp_loc; body = Lsend(Cached, Lvar meth, Lvar obj, [Lvar cache; Lvar pos], e.exp_loc)} @@ -741,12 +736,13 @@ and transl_exp0 e = Lconst(Const_base cst) | Texp_let(rec_flag, pat_expr_list, body) -> transl_let rec_flag pat_expr_list (event_before body (transl_exp body)) - | Texp_function (_, pat_expr_list, partial) -> + | Texp_function { arg_label = _; param; cases; partial; } -> let ((kind, params), body) = event_function e (function repr -> - let pl = push_defaults e.exp_loc [] pat_expr_list partial in - transl_function e.exp_loc !Clflags.native_code repr partial pl) + let pl = push_defaults e.exp_loc [] cases partial in + transl_function e.exp_loc !Clflags.native_code repr partial + param pl) in let attr = { default_function_attribute with @@ -794,6 +790,26 @@ and transl_exp0 e = match argl with [obj; meth; cache; pos] -> wrap (Lsend(Cached, meth, obj, [cache; pos], e.exp_loc)) | _ -> assert false + else if p.prim_name = "%raise_with_backtrace" then begin + let texn1 = List.hd args (* Should not fail by typing *) in + let texn2,bt = match argl with + | [a;b] -> a,b + | _ -> assert false (* idem *) + in + let vexn = Ident.create "exn" in + Llet(Strict, Pgenval, vexn, texn2, + event_before e begin + Lsequence( + wrap (Lprim (Pccall prim_restore_raw_backtrace, + [Lvar vexn;bt], + e.exp_loc)), + wrap0 (Lprim(Praise Raise_reraise, + [event_after texn1 (Lvar vexn)], + e.exp_loc)) + ) + end + ) + end else begin let prim = transl_primitive_application e.exp_loc p e.exp_env prim_type (Some path) args in @@ -841,7 +857,7 @@ and transl_exp0 e = | Texp_match(arg, pat_expr_list, exn_pat_expr_list, partial) -> transl_match e arg pat_expr_list exn_pat_expr_list partial | Texp_try(body, pat_expr_list) -> - let id = name_pattern "exn" pat_expr_list in + let id = Typecore.name_pattern "exn" pat_expr_list in Ltrywith(transl_exp body, id, Matching.for_trywith (Lvar id) (transl_cases_try pat_expr_list)) | Texp_tuple el -> @@ -994,7 +1010,7 @@ and transl_exp0 e = ap_inlined=Default_inline; ap_specialised=Default_specialise} | Texp_instvar(path_self, path, _) -> - Lprim(Parrayrefu Paddrarray, + Lprim(Pfield_computed, [transl_normal_path path_self; transl_normal_path path], e.exp_loc) | Texp_setinstvar(path_self, path, _, expr) -> transl_setinstvar e.exp_loc (transl_normal_path path_self) path expr @@ -1038,7 +1054,7 @@ and transl_exp0 e = | Texp_constant ( Const_int _ | Const_char _ | Const_string _ | Const_int32 _ | Const_int64 _ | Const_nativeint _ ) - | Texp_function(_, _, _) + | Texp_function _ | Texp_construct (_, {cstr_arity = 0}, _) -> transl_exp e | Texp_constant(Const_float _) -> @@ -1177,7 +1193,7 @@ and transl_apply ?(should_be_tailcall=false) ?(inlined = Default_inline) loc} | lam -> Lfunction{kind = Curried; params = [id_arg]; body = lam; - attr = default_function_attribute; loc = loc} + attr = default_stub_attribute; loc = loc} in List.fold_left (fun body (id, lam) -> Llet(Strict, Pgenval, id, lam, body)) @@ -1192,14 +1208,14 @@ and transl_apply ?(should_be_tailcall=false) ?(inlined = Default_inline) sargs) : Lambda.lambda) -and transl_function loc untuplify_fn repr partial cases = +and transl_function loc untuplify_fn repr partial param cases = match cases with [{c_lhs=pat; c_guard=None; - c_rhs={exp_desc = Texp_function(_, pl,partial')} as exp}] + c_rhs={exp_desc = Texp_function { arg_label = _; param = param'; cases; + partial = partial'; }} as exp}] when Parmatch.fluid pat -> - let param = name_pattern "param" cases in let ((_, params), body) = - transl_function exp.exp_loc false repr partial' pl in + transl_function exp.exp_loc false repr partial' param' cases in ((Curried, param :: params), Matching.for_function loc None (Lvar param) [pat, body] partial) | {c_lhs={pat_desc = Tpat_tuple pl}} :: _ when untuplify_fn -> @@ -1215,13 +1231,11 @@ and transl_function loc untuplify_fn repr partial cases = Matching.for_tupled_function loc params (transl_tupled_cases pats_expr_list) partial) with Matching.Cannot_flatten -> - let param = name_pattern "param" cases in ((Curried, [param]), Matching.for_function loc repr (Lvar param) (transl_cases cases) partial) end | _ -> - let param = name_pattern "param" cases in ((Curried, [param]), Matching.for_function loc repr (Lvar param) (transl_cases cases) partial) @@ -1266,12 +1280,8 @@ and transl_let rec_flag pat_expr_list body = Lletrec(List.map2 transl_case pat_expr_list idlist, body) and transl_setinstvar loc self var expr = - let prim = - match maybe_pointer expr with - | Pointer -> Paddrarray - | Immediate -> Pintarray - in - Lprim(Parraysetu prim, [self; transl_normal_path var; transl_exp expr], loc) + Lprim(Psetfield_computed (maybe_pointer expr, Assignment), + [self; transl_normal_path var; transl_exp expr], loc) and transl_record loc env fields repres opt_init_expr = let size = Array.length fields in @@ -1374,7 +1384,7 @@ and transl_record loc env fields repres opt_init_expr = end and transl_match e arg pat_expr_list exn_pat_expr_list partial = - let id = name_pattern "exn" exn_pat_expr_list + let id = Typecore.name_pattern "exn" exn_pat_expr_list and cases = transl_cases pat_expr_list and exn_cases = transl_cases_try exn_pat_expr_list in let static_catch body val_ids handler = @@ -1389,14 +1399,14 @@ and transl_match e arg pat_expr_list exn_pat_expr_list partial = | {exp_desc = Texp_tuple argl}, [] -> Matching.for_multiple_match e.exp_loc (transl_list argl) cases partial | {exp_desc = Texp_tuple argl}, _ :: _ -> - let val_ids = List.map (fun _ -> name_pattern "val" []) argl in + let val_ids = List.map (fun _ -> Typecore.name_pattern "val" []) argl in let lvars = List.map (fun id -> Lvar id) val_ids in static_catch (transl_list argl) val_ids (Matching.for_multiple_match e.exp_loc lvars cases partial) | arg, [] -> Matching.for_function e.exp_loc None (transl_exp arg) cases partial | arg, _ :: _ -> - let val_id = name_pattern "val" pat_expr_list in + let val_id = Typecore.name_pattern "val" pat_expr_list in static_catch [transl_exp arg] [val_id] (Matching.for_function e.exp_loc None (Lvar val_id) cases partial) diff --git a/bytecomp/translmod.ml b/bytecomp/translmod.ml index f2f6263a..c7ce0a9f 100644 --- a/bytecomp/translmod.ml +++ b/bytecomp/translmod.ml @@ -368,7 +368,8 @@ let rec transl_module cc rootpath mexp = Lfunction{kind = Curried; params = [param]; attr = { inline = inline_attribute; specialise = Default_specialise; - is_a_functor = true }; + is_a_functor = true; + stub = false; }; loc = loc; body = transl_module Tcoerce_none bodypath body} | Tcoerce_functor(ccarg, ccres) -> @@ -376,7 +377,8 @@ let rec transl_module cc rootpath mexp = Lfunction{kind = Curried; params = [param']; attr = { inline = inline_attribute; specialise = Default_specialise; - is_a_functor = true }; + is_a_functor = true; + stub = false; }; loc = loc; body = Llet(Alias, Pgenval, param, apply_coercion loc Alias ccarg @@ -665,6 +667,10 @@ let rec more_idents = function | Tstr_open _ -> more_idents rem | Tstr_class _ -> more_idents rem | Tstr_class_type _ -> more_idents rem + | Tstr_include{incl_mod={mod_desc = + Tmod_constraint ({mod_desc = Tmod_structure str}, + _, _, _)}} -> + all_idents str.str_items @ more_idents rem | Tstr_include _ -> more_idents rem | Tstr_module {mb_expr={mod_desc = Tmod_structure str}} | Tstr_module{mb_expr={mod_desc = @@ -694,8 +700,14 @@ and all_idents = function | Tstr_class cl_list -> List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ all_idents rem | Tstr_class_type _ -> all_idents rem + + | Tstr_include{incl_type; incl_mod={mod_desc = + Tmod_constraint ({mod_desc = Tmod_structure str}, + _, _, _)}} -> + bound_value_identifiers incl_type @ all_idents str.str_items @ all_idents rem | Tstr_include incl -> bound_value_identifiers incl.incl_type @ all_idents rem + | Tstr_module {mb_id;mb_expr={mod_desc = Tmod_structure str}} | Tstr_module{mb_id; mb_expr={mod_desc = @@ -726,6 +738,15 @@ let nat_toplevel_name id = with Not_found -> fatal_error("Translmod.nat_toplevel_name: " ^ Ident.unique_name id) +let field_of_str loc str = + let ids = Array.of_list (defined_idents str.str_items) in + fun (pos, cc) -> + match cc with + | Tcoerce_primitive { pc_loc; pc_desc; pc_env; pc_type; } -> + transl_primitive pc_loc pc_desc pc_env pc_type None + | _ -> apply_coercion loc Strict cc (Lvar ids.(pos)) + + let transl_store_structure glob map prims str = let rec transl_store rootpath subst = function [] -> @@ -802,13 +823,7 @@ let transl_store_structure glob map prims str = in (* Careful: see next case *) let subst = !transl_store_subst in - let ids = Array.of_list (defined_idents str.str_items) in - let field (pos, cc) = - match cc with - | Tcoerce_primitive { pc_loc; pc_desc; pc_env; pc_type; } -> - transl_primitive pc_loc pc_desc pc_env pc_type None - | _ -> apply_coercion loc Strict cc (Lvar ids.(pos)) - in + let field = field_of_str loc str in Lsequence(lam, Llet(Strict, Pgenval, id, subst_lambda subst @@ -850,6 +865,43 @@ let transl_store_structure glob map prims str = in Lsequence(subst_lambda subst lam, transl_store rootpath (add_idents false ids subst) rem) + + | Tstr_include{ + incl_loc=loc; + incl_mod= { + mod_desc = Tmod_constraint ( + ({mod_desc = Tmod_structure str} as mexp), _, _, + (Tcoerce_structure (map, _)))}; + incl_attributes; + incl_type; + } -> + List.iter (Translattribute.check_attribute_on_module mexp) + incl_attributes; + (* Shouldn't we use mod_attributes instead of incl_attributes? + Same question for the Tstr_module cases above, btw. *) + let lam = + transl_store None subst str.str_items + (* It is tempting to pass rootpath instead of None + in order to give a more precise name to exceptions + in the included structured, but this would introduce + a difference of behavior compared to bytecode. *) + in + let subst = !transl_store_subst in + let field = field_of_str loc str in + let ids0 = bound_value_identifiers incl_type in + let rec loop ids args = + match ids, args with + | [], [] -> + transl_store rootpath (add_idents true ids0 subst) rem + | id :: ids, arg :: args -> + Llet(Alias, Pgenval, id, subst_lambda subst (field arg), + Lsequence(store_ident loc id, + loop ids args)) + | _ -> assert false + in + Lsequence(lam, loop ids0 map) + + | Tstr_include incl -> let ids = bound_value_identifiers incl.incl_type in let modl = incl.incl_mod in @@ -875,7 +927,7 @@ let transl_store_structure glob map prims str = try let (pos, cc) = Ident.find_same id map in let init_val = apply_coercion loc Alias cc (Lvar id) in - Lprim(Psetfield(pos, Pointer, Initialization), + Lprim(Psetfield(pos, Pointer, Root_initialization), [Lprim(Pgetglobal glob, [], loc); init_val], loc) with Not_found -> @@ -903,7 +955,7 @@ let transl_store_structure glob map prims str = List.fold_right (add_ident may_coerce) idlist subst and store_primitive (pos, prim) cont = - Lsequence(Lprim(Psetfield(pos, Pointer, Initialization), + Lsequence(Lprim(Psetfield(pos, Pointer, Root_initialization), [Lprim(Pgetglobal glob, [], Location.none); transl_primitive Location.none prim.pc_desc prim.pc_env prim.pc_type None], @@ -1159,7 +1211,7 @@ let transl_store_package component_names target_name coercion = (List.length component_names, make_sequence (fun pos id -> - Lprim(Psetfield(pos, Pointer, Initialization), + Lprim(Psetfield(pos, Pointer, Root_initialization), [Lprim(Pgetglobal target_name, [], Location.none); get_component id], Location.none)) @@ -1176,7 +1228,7 @@ let transl_store_package component_names target_name coercion = apply_coercion Location.none Strict coercion components, make_sequence (fun pos _id -> - Lprim(Psetfield(pos, Pointer, Initialization), + Lprim(Psetfield(pos, Pointer, Root_initialization), [Lprim(Pgetglobal target_name, [], Location.none); Lprim(Pfield pos, [Lvar blk], Location.none)], Location.none)) diff --git a/bytecomp/translobj.ml b/bytecomp/translobj.ml index 67f469c0..17560db2 100644 --- a/bytecomp/translobj.ml +++ b/bytecomp/translobj.ml @@ -140,7 +140,7 @@ let transl_store_label_init glob size f arg = if !method_count = 0 then (size, expr) else (size+1, Lsequence( - Lprim(Psetfield(size, Pointer, Initialization), + Lprim(Psetfield(size, Pointer, Root_initialization), [Lprim(Pgetglobal glob, [], Location.none); Lprim (Pccall prim_makearray, [int !method_count; int 0], diff --git a/byterun/.depend b/byterun/.depend index c3f82b66..c177d13f 100644 --- a/byterun/.depend +++ b/byterun/.depend @@ -1,920 +1,856 @@ -alloc.o: alloc.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/stacks.h -array.o: array.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ - spacetime.h -backtrace.o: backtrace.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ - caml/exec.h caml/backtrace_prim.h caml/fail.h +afl.o: afl.c caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/osdeps.h +alloc.o: alloc.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/stacks.h +array.o: array.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/spacetime.h +backtrace.o: backtrace.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/fail.h backtrace_prim.o: backtrace_prim.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h caml/misc.h \ - caml/alloc.h caml/custom.h caml/io.h caml/instruct.h caml/intext.h \ - caml/exec.h caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/alloc.h \ + caml/custom.h caml/io.h caml/instruct.h caml/intext.h caml/exec.h \ + caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/startup.h \ caml/stacks.h caml/sys.h caml/backtrace.h caml/fail.h \ caml/backtrace_prim.h -callback.o: callback.c caml/callback.h caml/compatibility.h \ - caml/mlvalues.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h +callback.o: callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/interp.h caml/instruct.h \ + caml/fix_code.h caml/stacks.h compact.o: compact.c caml/address_class.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/compatibility.h \ - caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/gc_ctrl.h caml/weak.h caml/compact.h -compare.o: compare.c caml/custom.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ - caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/gc_ctrl.h \ + caml/weak.h caml/compact.h +compare.o: compare.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ caml/minor_gc.h caml/address_class.h -custom.o: custom.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -debugger.o: debugger.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/fix_code.h \ +custom.o: custom.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +debugger.o: debugger.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/debugger.h caml/osdeps.h caml/fail.h caml/fix_code.h \ caml/instruct.h caml/intext.h caml/io.h caml/stacks.h caml/memory.h \ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ caml/address_class.h caml/sys.h dynlink.o: dynlink.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/prims.h caml/signals.h -extern.o: extern.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \ - caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/reverse.h -fail.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/prims.h caml/signals.h +extern.o: extern.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h caml/md5.h \ + caml/memory.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +fail.o: fail.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/io.h caml/gc.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/printexc.h \ + caml/signals.h caml/stacks.h +finalise.o: finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/compact.h \ + caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/printexc.h caml/signals.h caml/stacks.h -finalise.o: finalise.c caml/callback.h caml/compatibility.h \ - caml/mlvalues.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/compact.h caml/fail.h \ - caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h + caml/signals.h fix_code.o: fix_code.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/debugger.h caml/misc.h \ - caml/mlvalues.h caml/fix_code.h caml/instruct.h caml/intext.h \ - caml/io.h caml/md5.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -floats.o: floats.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h \ - caml/stacks.h + caml/../../config/s.h caml/debugger.h caml/misc.h caml/mlvalues.h \ + caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/md5.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +floats.o: floats.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h caml/stacks.h freelist.o: freelist.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/freelist.h caml/misc.h \ - caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h \ - caml/minor_gc.h caml/address_class.h -gc_ctrl.o: gc_ctrl.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ - caml/startup_aux.h -globroots.o: globroots.c caml/memory.h caml/compatibility.h caml/config.h \ + caml/../../config/s.h caml/freelist.h caml/misc.h caml/mlvalues.h \ + caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h caml/minor_gc.h \ + caml/address_class.h +gc_ctrl.o: gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/compact.h caml/custom.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \ + caml/signals.h caml/stacks.h caml/startup_aux.h +globroots.o: globroots.c caml/memory.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/gc.h caml/mlvalues.h \ caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ caml/address_class.h caml/roots.h caml/globroots.h -hash.o: hash.c caml/mlvalues.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/custom.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/hash.h +hash.o: hash.c caml/mlvalues.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/custom.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/hash.h instrtrace.o: instrtrace.c -intern.o: intern.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h caml/gc.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -interp.o: interp.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ - caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ - caml/jumptbl.h -ints.o: ints.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -io.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/alloc.h caml/misc.h caml/mlvalues.h \ - caml/custom.h caml/fail.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/signals.h caml/sys.h -lexing.o: lexing.c caml/fail.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h -main.o: main.c caml/misc.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h caml/sys.h -major_gc.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/misc.h caml/mlvalues.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ +intern.o: intern.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/callback.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +interp.o: interp.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/callback.h caml/debugger.h \ + caml/fail.h caml/fix_code.h caml/instrtrace.h caml/instruct.h \ + caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/signals.h \ + caml/stacks.h caml/startup_aux.h caml/jumptbl.h +ints.o: ints.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/intext.h caml/io.h caml/memory.h \ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/weak.h -md5.o: md5.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ + caml/address_class.h +io.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h \ + caml/io.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ + caml/sys.h +lexing.o: lexing.c caml/fail.h caml/misc.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h caml/md5.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -memory.o: memory.c caml/address_class.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/compatibility.h \ - caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/signals.h -meta.o: meta.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ - caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - caml/stacks.h -minor_gc.o: minor_gc.c caml/custom.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +main.o: main.c caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/sys.h +major_gc.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/mlvalues.h caml/custom.h \ caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ caml/gc_ctrl.h caml/signals.h caml/weak.h +md5.o: md5.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +memory.o: memory.c caml/address_class.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \ + caml/major_gc.h caml/memory.h caml/minor_gc.h caml/signals.h +meta.o: meta.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/fix_code.h caml/interp.h caml/intext.h caml/io.h \ + caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/stacks.h +minor_gc.o: minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \ + caml/signals.h caml/weak.h misc.o: misc.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/misc.h caml/memory.h caml/gc.h \ + caml/misc.h caml/memory.h caml/gc.h caml/mlvalues.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/version.h +obj.o: obj.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/gc.h \ + caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/spacetime.h +parsing.o: parsing.c caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/alloc.h +prims.o: prims.c caml/mlvalues.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/prims.h +printexc.o: printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/exec.h \ + caml/callback.h caml/debugger.h caml/fail.h caml/printexc.h +roots.o: roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/memory.h caml/gc.h \ caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/version.h -obj.o: obj.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +signals.o: signals.c caml/alloc.h caml/misc.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - spacetime.h -parsing.o: parsing.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h caml/misc.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/alloc.h -prims.o: prims.c caml/mlvalues.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/prims.h -printexc.o: printexc.c caml/backtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/printexc.h -roots.o: roots.c caml/finalise.h caml/roots.h caml/misc.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/globroots.h caml/stacks.h -signals.o: signals.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/roots.h caml/signals.h caml/signals_machdep.h caml/sys.h + caml/callback.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/signals_machdep.h caml/sys.h signals_byt.o: signals_byt.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/memory.h caml/gc.h \ - caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ + caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ + caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h \ caml/signals_machdep.h -spacetime.o: spacetime.c caml/fail.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h +spacetime.o: spacetime.c caml/fail.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h stacks.o: stacks.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/fail.h caml/misc.h \ - caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h + caml/../../config/s.h caml/fail.h caml/misc.h caml/mlvalues.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h startup.o: startup.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/custom.h caml/debugger.h caml/dynlink.h caml/fail.h \ - caml/fix_code.h caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h \ - caml/interp.h caml/intext.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/prims.h caml/printexc.h caml/reverse.h caml/signals.h \ - caml/stacks.h caml/sys.h caml/startup.h caml/startup_aux.h \ - caml/version.h + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/callback.h caml/custom.h \ + caml/debugger.h caml/dynlink.h caml/fail.h caml/fix_code.h \ + caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h caml/interp.h \ + caml/intext.h caml/io.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/prims.h \ + caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h caml/sys.h \ + caml/startup.h caml/startup_aux.h caml/version.h startup_aux.o: startup_aux.c caml/backtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/exec.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/startup_aux.h -str.o: str.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h + caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/exec.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/startup_aux.h +str.o: str.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h sys.o: sys.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/alloc.h caml/misc.h caml/mlvalues.h \ - caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/instruct.h caml/io.h \ - caml/osdeps.h caml/signals.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/sys.h caml/version.h + caml/alloc.h caml/misc.h caml/mlvalues.h caml/debugger.h caml/fail.h \ + caml/gc_ctrl.h caml/instruct.h caml/io.h caml/osdeps.h caml/signals.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/sys.h caml/version.h terminfo.o: terminfo.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/fail.h caml/io.h + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/fail.h caml/io.h unix.o: unix.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/fail.h caml/misc.h caml/mlvalues.h \ + caml/fail.h caml/misc.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/sys.h caml/io.h +weak.o: weak.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/weak.h +afl.d.o: afl.c caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/osdeps.h +alloc.d.o: alloc.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/stacks.h +array.d.o: array.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/spacetime.h +backtrace.d.o: backtrace.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ - caml/sys.h caml/io.h -weak.o: weak.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/weak.h -alloc.d.o: alloc.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/stacks.h -array.d.o: array.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ - spacetime.h -backtrace.d.o: backtrace.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ - caml/exec.h caml/backtrace_prim.h caml/fail.h + caml/minor_gc.h caml/address_class.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/fail.h backtrace_prim.d.o: backtrace_prim.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h caml/misc.h \ - caml/alloc.h caml/custom.h caml/io.h caml/instruct.h caml/intext.h \ - caml/exec.h caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/alloc.h \ + caml/custom.h caml/io.h caml/instruct.h caml/intext.h caml/exec.h \ + caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/startup.h \ caml/stacks.h caml/sys.h caml/backtrace.h caml/fail.h \ caml/backtrace_prim.h -callback.d.o: callback.c caml/callback.h caml/compatibility.h \ - caml/mlvalues.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h +callback.d.o: callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/interp.h caml/instruct.h \ + caml/fix_code.h caml/stacks.h compact.d.o: compact.c caml/address_class.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/compatibility.h \ - caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/gc_ctrl.h caml/weak.h caml/compact.h -compare.d.o: compare.c caml/custom.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ - caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/gc_ctrl.h \ + caml/weak.h caml/compact.h +compare.d.o: compare.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ caml/minor_gc.h caml/address_class.h -custom.d.o: custom.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -debugger.d.o: debugger.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/fix_code.h \ +custom.d.o: custom.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +debugger.d.o: debugger.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/debugger.h caml/osdeps.h caml/fail.h caml/fix_code.h \ caml/instruct.h caml/intext.h caml/io.h caml/stacks.h caml/memory.h \ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ caml/address_class.h caml/sys.h dynlink.d.o: dynlink.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/prims.h caml/signals.h -extern.d.o: extern.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \ - caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/reverse.h -fail.d.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/prims.h caml/signals.h +extern.d.o: extern.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h caml/md5.h \ + caml/memory.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +fail.d.o: fail.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/io.h caml/gc.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/printexc.h \ + caml/signals.h caml/stacks.h +finalise.d.o: finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/compact.h \ + caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/printexc.h caml/signals.h caml/stacks.h -finalise.d.o: finalise.c caml/callback.h caml/compatibility.h \ - caml/mlvalues.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/compact.h caml/fail.h \ - caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h + caml/signals.h fix_code.d.o: fix_code.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/debugger.h caml/misc.h \ - caml/mlvalues.h caml/fix_code.h caml/instruct.h caml/intext.h \ - caml/io.h caml/md5.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -floats.d.o: floats.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h \ - caml/stacks.h + caml/../../config/s.h caml/debugger.h caml/misc.h caml/mlvalues.h \ + caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/md5.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +floats.d.o: floats.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h caml/stacks.h freelist.d.o: freelist.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/freelist.h caml/misc.h \ - caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h \ - caml/minor_gc.h caml/address_class.h -gc_ctrl.d.o: gc_ctrl.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ - caml/startup_aux.h -globroots.d.o: globroots.c caml/memory.h caml/compatibility.h caml/config.h \ + caml/../../config/s.h caml/freelist.h caml/misc.h caml/mlvalues.h \ + caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h caml/minor_gc.h \ + caml/address_class.h +gc_ctrl.d.o: gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/compact.h caml/custom.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \ + caml/signals.h caml/stacks.h caml/startup_aux.h +globroots.d.o: globroots.c caml/memory.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/gc.h caml/mlvalues.h \ caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ caml/address_class.h caml/roots.h caml/globroots.h -hash.d.o: hash.c caml/mlvalues.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/custom.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/hash.h +hash.d.o: hash.c caml/mlvalues.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/custom.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/hash.h instrtrace.d.o: instrtrace.c caml/instrtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/instruct.h caml/opnames.h \ - caml/prims.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/startup_aux.h -intern.d.o: intern.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h caml/gc.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -interp.d.o: interp.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ - caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h -ints.d.o: ints.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/instruct.h caml/opnames.h caml/prims.h caml/stacks.h \ caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -io.d.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/alloc.h caml/misc.h caml/mlvalues.h \ - caml/custom.h caml/fail.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/signals.h caml/sys.h -lexing.d.o: lexing.c caml/fail.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h -main.d.o: main.c caml/misc.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h caml/sys.h -major_gc.d.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/misc.h caml/mlvalues.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/startup_aux.h +intern.d.o: intern.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/callback.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +interp.d.o: interp.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/callback.h caml/debugger.h \ + caml/fail.h caml/fix_code.h caml/instrtrace.h caml/instruct.h \ + caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/signals.h \ + caml/stacks.h caml/startup_aux.h +ints.d.o: ints.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/intext.h caml/io.h caml/memory.h \ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/weak.h -md5.d.o: md5.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ + caml/address_class.h +io.d.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h \ + caml/io.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ + caml/sys.h +lexing.d.o: lexing.c caml/fail.h caml/misc.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h caml/md5.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -memory.d.o: memory.c caml/address_class.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/compatibility.h \ - caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/signals.h -meta.d.o: meta.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ - caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - caml/stacks.h -minor_gc.d.o: minor_gc.c caml/custom.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +main.d.o: main.c caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/sys.h +major_gc.d.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/mlvalues.h caml/custom.h \ caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ caml/gc_ctrl.h caml/signals.h caml/weak.h +md5.d.o: md5.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +memory.d.o: memory.c caml/address_class.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \ + caml/major_gc.h caml/memory.h caml/minor_gc.h caml/signals.h +meta.d.o: meta.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/fix_code.h caml/interp.h caml/intext.h caml/io.h \ + caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/stacks.h +minor_gc.d.o: minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \ + caml/signals.h caml/weak.h misc.d.o: misc.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/misc.h caml/memory.h caml/gc.h \ + caml/misc.h caml/memory.h caml/gc.h caml/mlvalues.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/version.h +obj.d.o: obj.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/gc.h \ + caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/spacetime.h +parsing.d.o: parsing.c caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/alloc.h +prims.d.o: prims.c caml/mlvalues.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/prims.h +printexc.d.o: printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/exec.h \ + caml/callback.h caml/debugger.h caml/fail.h caml/printexc.h +roots.d.o: roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/memory.h caml/gc.h \ caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/version.h -obj.d.o: obj.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +signals.d.o: signals.c caml/alloc.h caml/misc.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - spacetime.h -parsing.d.o: parsing.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h caml/misc.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/alloc.h -prims.d.o: prims.c caml/mlvalues.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/prims.h -printexc.d.o: printexc.c caml/backtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/printexc.h -roots.d.o: roots.c caml/finalise.h caml/roots.h caml/misc.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/globroots.h caml/stacks.h -signals.d.o: signals.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/roots.h caml/signals.h caml/signals_machdep.h caml/sys.h + caml/callback.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/signals_machdep.h caml/sys.h signals_byt.d.o: signals_byt.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/memory.h caml/gc.h \ - caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ + caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ + caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h \ caml/signals_machdep.h -spacetime.d.o: spacetime.c caml/fail.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h +spacetime.d.o: spacetime.c caml/fail.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h stacks.d.o: stacks.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/fail.h caml/misc.h \ - caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h + caml/../../config/s.h caml/fail.h caml/misc.h caml/mlvalues.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h startup.d.o: startup.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/custom.h caml/debugger.h caml/dynlink.h caml/fail.h \ - caml/fix_code.h caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h \ - caml/interp.h caml/intext.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/prims.h caml/printexc.h caml/reverse.h caml/signals.h \ - caml/stacks.h caml/sys.h caml/startup.h caml/startup_aux.h \ - caml/version.h + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/callback.h caml/custom.h \ + caml/debugger.h caml/dynlink.h caml/fail.h caml/fix_code.h \ + caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h caml/interp.h \ + caml/intext.h caml/io.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/prims.h \ + caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h caml/sys.h \ + caml/startup.h caml/startup_aux.h caml/version.h startup_aux.d.o: startup_aux.c caml/backtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/exec.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/startup_aux.h -str.d.o: str.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h + caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/exec.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/startup_aux.h +str.d.o: str.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h sys.d.o: sys.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/alloc.h caml/misc.h caml/mlvalues.h \ - caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/instruct.h caml/io.h \ - caml/osdeps.h caml/signals.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/sys.h caml/version.h + caml/alloc.h caml/misc.h caml/mlvalues.h caml/debugger.h caml/fail.h \ + caml/gc_ctrl.h caml/instruct.h caml/io.h caml/osdeps.h caml/signals.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/sys.h caml/version.h terminfo.d.o: terminfo.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/fail.h caml/io.h + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/fail.h caml/io.h unix.d.o: unix.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/fail.h caml/misc.h caml/mlvalues.h \ + caml/fail.h caml/misc.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/sys.h caml/io.h +weak.d.o: weak.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/weak.h +afl.i.o: afl.c caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/osdeps.h +alloc.i.o: alloc.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/stacks.h +array.i.o: array.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/spacetime.h +backtrace.i.o: backtrace.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ - caml/sys.h caml/io.h -weak.d.o: weak.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/weak.h -alloc.i.o: alloc.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/stacks.h -array.i.o: array.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ - spacetime.h -backtrace.i.o: backtrace.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ - caml/exec.h caml/backtrace_prim.h caml/fail.h + caml/minor_gc.h caml/address_class.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/fail.h backtrace_prim.i.o: backtrace_prim.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h caml/misc.h \ - caml/alloc.h caml/custom.h caml/io.h caml/instruct.h caml/intext.h \ - caml/exec.h caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/alloc.h \ + caml/custom.h caml/io.h caml/instruct.h caml/intext.h caml/exec.h \ + caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/startup.h \ caml/stacks.h caml/sys.h caml/backtrace.h caml/fail.h \ caml/backtrace_prim.h -callback.i.o: callback.c caml/callback.h caml/compatibility.h \ - caml/mlvalues.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h +callback.i.o: callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/interp.h caml/instruct.h \ + caml/fix_code.h caml/stacks.h compact.i.o: compact.c caml/address_class.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/compatibility.h \ - caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/gc_ctrl.h caml/weak.h caml/compact.h -compare.i.o: compare.c caml/custom.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ - caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/gc_ctrl.h \ + caml/weak.h caml/compact.h +compare.i.o: compare.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ caml/minor_gc.h caml/address_class.h -custom.i.o: custom.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -debugger.i.o: debugger.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/fix_code.h \ +custom.i.o: custom.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +debugger.i.o: debugger.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/debugger.h caml/osdeps.h caml/fail.h caml/fix_code.h \ caml/instruct.h caml/intext.h caml/io.h caml/stacks.h caml/memory.h \ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ caml/address_class.h caml/sys.h dynlink.i.o: dynlink.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/prims.h caml/signals.h -extern.i.o: extern.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \ - caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/reverse.h -fail.i.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/prims.h caml/signals.h +extern.i.o: extern.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h caml/md5.h \ + caml/memory.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +fail.i.o: fail.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/io.h caml/gc.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/printexc.h \ + caml/signals.h caml/stacks.h +finalise.i.o: finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/compact.h \ + caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/printexc.h caml/signals.h caml/stacks.h -finalise.i.o: finalise.c caml/callback.h caml/compatibility.h \ - caml/mlvalues.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/compact.h caml/fail.h \ - caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h + caml/signals.h fix_code.i.o: fix_code.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/debugger.h caml/misc.h \ - caml/mlvalues.h caml/fix_code.h caml/instruct.h caml/intext.h \ - caml/io.h caml/md5.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -floats.i.o: floats.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h \ - caml/stacks.h + caml/../../config/s.h caml/debugger.h caml/misc.h caml/mlvalues.h \ + caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/md5.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +floats.i.o: floats.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h caml/stacks.h freelist.i.o: freelist.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/freelist.h caml/misc.h \ - caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h \ - caml/minor_gc.h caml/address_class.h -gc_ctrl.i.o: gc_ctrl.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ - caml/startup_aux.h -globroots.i.o: globroots.c caml/memory.h caml/compatibility.h caml/config.h \ + caml/../../config/s.h caml/freelist.h caml/misc.h caml/mlvalues.h \ + caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h caml/minor_gc.h \ + caml/address_class.h +gc_ctrl.i.o: gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/compact.h caml/custom.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \ + caml/signals.h caml/stacks.h caml/startup_aux.h +globroots.i.o: globroots.c caml/memory.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/gc.h caml/mlvalues.h \ caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ caml/address_class.h caml/roots.h caml/globroots.h -hash.i.o: hash.c caml/mlvalues.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/custom.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/hash.h +hash.i.o: hash.c caml/mlvalues.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/custom.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/hash.h instrtrace.i.o: instrtrace.c -intern.i.o: intern.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h caml/gc.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -interp.i.o: interp.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ - caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ - caml/jumptbl.h -ints.i.o: ints.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -io.i.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/alloc.h caml/misc.h caml/mlvalues.h \ - caml/custom.h caml/fail.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/signals.h caml/sys.h -lexing.i.o: lexing.c caml/fail.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h -main.i.o: main.c caml/misc.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h caml/sys.h -major_gc.i.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/misc.h caml/mlvalues.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ +intern.i.o: intern.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/callback.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +interp.i.o: interp.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/callback.h caml/debugger.h \ + caml/fail.h caml/fix_code.h caml/instrtrace.h caml/instruct.h \ + caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/signals.h \ + caml/stacks.h caml/startup_aux.h caml/jumptbl.h +ints.i.o: ints.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/intext.h caml/io.h caml/memory.h \ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/weak.h -md5.i.o: md5.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ + caml/address_class.h +io.i.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h \ + caml/io.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ + caml/sys.h +lexing.i.o: lexing.c caml/fail.h caml/misc.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h caml/md5.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -memory.i.o: memory.c caml/address_class.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/compatibility.h \ - caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/signals.h -meta.i.o: meta.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ - caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - caml/stacks.h -minor_gc.i.o: minor_gc.c caml/custom.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +main.i.o: main.c caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/sys.h +major_gc.i.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/mlvalues.h caml/custom.h \ caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ caml/gc_ctrl.h caml/signals.h caml/weak.h +md5.i.o: md5.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +memory.i.o: memory.c caml/address_class.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \ + caml/major_gc.h caml/memory.h caml/minor_gc.h caml/signals.h +meta.i.o: meta.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/fix_code.h caml/interp.h caml/intext.h caml/io.h \ + caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/stacks.h +minor_gc.i.o: minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \ + caml/signals.h caml/weak.h misc.i.o: misc.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/misc.h caml/memory.h caml/gc.h \ + caml/misc.h caml/memory.h caml/gc.h caml/mlvalues.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/version.h +obj.i.o: obj.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/gc.h \ + caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/spacetime.h +parsing.i.o: parsing.c caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/alloc.h +prims.i.o: prims.c caml/mlvalues.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/prims.h +printexc.i.o: printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/exec.h \ + caml/callback.h caml/debugger.h caml/fail.h caml/printexc.h +roots.i.o: roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/memory.h caml/gc.h \ caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/version.h -obj.i.o: obj.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +signals.i.o: signals.c caml/alloc.h caml/misc.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - spacetime.h -parsing.i.o: parsing.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h caml/misc.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/alloc.h -prims.i.o: prims.c caml/mlvalues.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/prims.h -printexc.i.o: printexc.c caml/backtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/printexc.h -roots.i.o: roots.c caml/finalise.h caml/roots.h caml/misc.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/globroots.h caml/stacks.h -signals.i.o: signals.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/roots.h caml/signals.h caml/signals_machdep.h caml/sys.h + caml/callback.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/signals_machdep.h caml/sys.h signals_byt.i.o: signals_byt.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/memory.h caml/gc.h \ - caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ + caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ + caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h \ caml/signals_machdep.h -spacetime.i.o: spacetime.c caml/fail.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h +spacetime.i.o: spacetime.c caml/fail.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h stacks.i.o: stacks.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/fail.h caml/misc.h \ - caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h + caml/../../config/s.h caml/fail.h caml/misc.h caml/mlvalues.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h startup.i.o: startup.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/custom.h caml/debugger.h caml/dynlink.h caml/fail.h \ - caml/fix_code.h caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h \ - caml/interp.h caml/intext.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/prims.h caml/printexc.h caml/reverse.h caml/signals.h \ - caml/stacks.h caml/sys.h caml/startup.h caml/startup_aux.h \ - caml/version.h + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/callback.h caml/custom.h \ + caml/debugger.h caml/dynlink.h caml/fail.h caml/fix_code.h \ + caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h caml/interp.h \ + caml/intext.h caml/io.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/prims.h \ + caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h caml/sys.h \ + caml/startup.h caml/startup_aux.h caml/version.h startup_aux.i.o: startup_aux.c caml/backtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/exec.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/startup_aux.h -str.i.o: str.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h + caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/exec.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/startup_aux.h +str.i.o: str.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h sys.i.o: sys.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/alloc.h caml/misc.h caml/mlvalues.h \ - caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/instruct.h caml/io.h \ - caml/osdeps.h caml/signals.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/sys.h caml/version.h + caml/alloc.h caml/misc.h caml/mlvalues.h caml/debugger.h caml/fail.h \ + caml/gc_ctrl.h caml/instruct.h caml/io.h caml/osdeps.h caml/signals.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/sys.h caml/version.h terminfo.i.o: terminfo.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/fail.h caml/io.h + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/fail.h caml/io.h unix.i.o: unix.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/fail.h caml/misc.h caml/mlvalues.h \ + caml/fail.h caml/misc.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/sys.h caml/io.h +weak.i.o: weak.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/weak.h +afl.pic.o: afl.c caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/osdeps.h +alloc.pic.o: alloc.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/stacks.h +array.pic.o: array.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/spacetime.h +backtrace.pic.o: backtrace.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ - caml/sys.h caml/io.h -weak.i.o: weak.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/weak.h -alloc.pic.o: alloc.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/stacks.h -array.pic.o: array.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ - spacetime.h -backtrace.pic.o: backtrace.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ - caml/exec.h caml/backtrace_prim.h caml/fail.h + caml/minor_gc.h caml/address_class.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/fail.h backtrace_prim.pic.o: backtrace_prim.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h caml/misc.h \ - caml/alloc.h caml/custom.h caml/io.h caml/instruct.h caml/intext.h \ - caml/exec.h caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/alloc.h \ + caml/custom.h caml/io.h caml/instruct.h caml/intext.h caml/exec.h \ + caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/startup.h \ caml/stacks.h caml/sys.h caml/backtrace.h caml/fail.h \ caml/backtrace_prim.h -callback.pic.o: callback.c caml/callback.h caml/compatibility.h \ - caml/mlvalues.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h +callback.pic.o: callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/interp.h caml/instruct.h \ + caml/fix_code.h caml/stacks.h compact.pic.o: compact.c caml/address_class.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/compatibility.h \ - caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/gc_ctrl.h caml/weak.h caml/compact.h -compare.pic.o: compare.c caml/custom.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ - caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/gc_ctrl.h \ + caml/weak.h caml/compact.h +compare.pic.o: compare.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ caml/minor_gc.h caml/address_class.h -custom.pic.o: custom.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -debugger.pic.o: debugger.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/fix_code.h \ +custom.pic.o: custom.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +debugger.pic.o: debugger.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/debugger.h caml/osdeps.h caml/fail.h caml/fix_code.h \ caml/instruct.h caml/intext.h caml/io.h caml/stacks.h caml/memory.h \ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ caml/address_class.h caml/sys.h dynlink.pic.o: dynlink.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/prims.h caml/signals.h -extern.pic.o: extern.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \ - caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/reverse.h -fail.pic.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/prims.h caml/signals.h +extern.pic.o: extern.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h caml/md5.h \ + caml/memory.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +fail.pic.o: fail.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/io.h caml/gc.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/printexc.h \ + caml/signals.h caml/stacks.h +finalise.pic.o: finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/compact.h \ + caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/printexc.h caml/signals.h caml/stacks.h -finalise.pic.o: finalise.c caml/callback.h caml/compatibility.h \ - caml/mlvalues.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/compact.h caml/fail.h \ - caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h + caml/signals.h fix_code.pic.o: fix_code.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/debugger.h caml/misc.h \ - caml/mlvalues.h caml/fix_code.h caml/instruct.h caml/intext.h \ - caml/io.h caml/md5.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -floats.pic.o: floats.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h \ - caml/stacks.h + caml/../../config/s.h caml/debugger.h caml/misc.h caml/mlvalues.h \ + caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/md5.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +floats.pic.o: floats.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h caml/stacks.h freelist.pic.o: freelist.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/freelist.h caml/misc.h \ - caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h \ - caml/minor_gc.h caml/address_class.h -gc_ctrl.pic.o: gc_ctrl.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ - caml/startup_aux.h -globroots.pic.o: globroots.c caml/memory.h caml/compatibility.h caml/config.h \ + caml/../../config/s.h caml/freelist.h caml/misc.h caml/mlvalues.h \ + caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h caml/minor_gc.h \ + caml/address_class.h +gc_ctrl.pic.o: gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/compact.h caml/custom.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \ + caml/signals.h caml/stacks.h caml/startup_aux.h +globroots.pic.o: globroots.c caml/memory.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/gc.h caml/mlvalues.h \ caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ caml/address_class.h caml/roots.h caml/globroots.h -hash.pic.o: hash.c caml/mlvalues.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/custom.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/hash.h +hash.pic.o: hash.c caml/mlvalues.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/custom.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/hash.h instrtrace.pic.o: instrtrace.c -intern.pic.o: intern.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h caml/gc.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -interp.pic.o: interp.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ - caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ - caml/jumptbl.h -ints.pic.o: ints.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -io.pic.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/alloc.h caml/misc.h caml/mlvalues.h \ - caml/custom.h caml/fail.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/signals.h caml/sys.h -lexing.pic.o: lexing.c caml/fail.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h -main.pic.o: main.c caml/misc.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h caml/sys.h -major_gc.pic.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/misc.h caml/mlvalues.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ +intern.pic.o: intern.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/callback.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +interp.pic.o: interp.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/callback.h caml/debugger.h \ + caml/fail.h caml/fix_code.h caml/instrtrace.h caml/instruct.h \ + caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/signals.h \ + caml/stacks.h caml/startup_aux.h caml/jumptbl.h +ints.pic.o: ints.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/custom.h caml/fail.h caml/intext.h caml/io.h caml/memory.h \ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/weak.h -md5.pic.o: md5.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ + caml/address_class.h +io.pic.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h \ + caml/io.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ + caml/sys.h +lexing.pic.o: lexing.c caml/fail.h caml/misc.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h caml/md5.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -memory.pic.o: memory.c caml/address_class.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/compatibility.h \ - caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/signals.h -meta.pic.o: meta.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ - caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - caml/stacks.h -minor_gc.pic.o: minor_gc.c caml/custom.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +main.pic.o: main.c caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/sys.h +major_gc.pic.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/mlvalues.h caml/custom.h \ caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ caml/gc_ctrl.h caml/signals.h caml/weak.h +md5.pic.o: md5.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/reverse.h +memory.pic.o: memory.c caml/address_class.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \ + caml/major_gc.h caml/memory.h caml/minor_gc.h caml/signals.h +meta.pic.o: meta.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/fix_code.h caml/interp.h caml/intext.h caml/io.h \ + caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/stacks.h +minor_gc.pic.o: minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \ + caml/signals.h caml/weak.h misc.pic.o: misc.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/misc.h caml/memory.h caml/gc.h \ + caml/misc.h caml/memory.h caml/gc.h caml/mlvalues.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/version.h +obj.pic.o: obj.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/gc.h \ + caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/prims.h caml/spacetime.h +parsing.pic.o: parsing.c caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/alloc.h +prims.pic.o: prims.c caml/mlvalues.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/misc.h caml/prims.h +printexc.pic.o: printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/exec.h \ + caml/callback.h caml/debugger.h caml/fail.h caml/printexc.h +roots.pic.o: roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/memory.h caml/gc.h \ caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/version.h -obj.pic.o: obj.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +signals.pic.o: signals.c caml/alloc.h caml/misc.h caml/config.h \ caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - spacetime.h -parsing.pic.o: parsing.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h caml/misc.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/alloc.h -prims.pic.o: prims.c caml/mlvalues.h caml/compatibility.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/prims.h -printexc.pic.o: printexc.c caml/backtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/printexc.h -roots.pic.o: roots.c caml/finalise.h caml/roots.h caml/misc.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/globroots.h caml/stacks.h -signals.pic.o: signals.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/roots.h caml/signals.h caml/signals_machdep.h caml/sys.h + caml/callback.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/signals_machdep.h caml/sys.h signals_byt.pic.o: signals_byt.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/memory.h caml/gc.h \ - caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ + caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ + caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h \ caml/signals_machdep.h -spacetime.pic.o: spacetime.c caml/fail.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h +spacetime.pic.o: spacetime.c caml/fail.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h stacks.pic.o: stacks.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/fail.h caml/misc.h \ - caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h + caml/../../config/s.h caml/fail.h caml/misc.h caml/mlvalues.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h startup.pic.o: startup.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/custom.h caml/debugger.h caml/dynlink.h caml/fail.h \ - caml/fix_code.h caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h \ - caml/interp.h caml/intext.h caml/io.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/prims.h caml/printexc.h caml/reverse.h caml/signals.h \ - caml/stacks.h caml/sys.h caml/startup.h caml/startup_aux.h \ - caml/version.h + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/backtrace.h caml/exec.h caml/callback.h caml/custom.h \ + caml/debugger.h caml/dynlink.h caml/fail.h caml/fix_code.h \ + caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h caml/interp.h \ + caml/intext.h caml/io.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/prims.h \ + caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h caml/sys.h \ + caml/startup.h caml/startup_aux.h caml/version.h startup_aux.pic.o: startup_aux.c caml/backtrace.h caml/mlvalues.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/misc.h caml/exec.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/startup_aux.h -str.pic.o: str.c caml/alloc.h caml/compatibility.h caml/misc.h caml/config.h \ - caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ - caml/fail.h + caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \ + caml/exec.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/startup_aux.h +str.pic.o: str.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \ + caml/../../config/s.h caml/mlvalues.h caml/fail.h sys.pic.o: sys.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/alloc.h caml/misc.h caml/mlvalues.h \ - caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/instruct.h caml/io.h \ - caml/osdeps.h caml/signals.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/sys.h caml/version.h + caml/alloc.h caml/misc.h caml/mlvalues.h caml/debugger.h caml/fail.h \ + caml/gc_ctrl.h caml/instruct.h caml/io.h caml/osdeps.h caml/signals.h \ + caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/sys.h caml/version.h terminfo.pic.o: terminfo.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/fail.h caml/io.h + caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \ + caml/fail.h caml/io.h unix.pic.o: unix.c caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/compatibility.h caml/fail.h caml/misc.h caml/mlvalues.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \ - caml/sys.h caml/io.h -weak.pic.o: weak.c caml/alloc.h caml/compatibility.h caml/misc.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/weak.h + caml/fail.h caml/misc.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/sys.h caml/io.h +weak.pic.o: weak.c caml/alloc.h caml/misc.h caml/config.h \ + caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \ + caml/fail.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \ + caml/minor_gc.h caml/address_class.h caml/weak.h diff --git a/byterun/Makefile b/byterun/Makefile index 5070c695..74aa3d06 100644 --- a/byterun/Makefile +++ b/byterun/Makefile @@ -13,78 +13,209 @@ #* * #************************************************************************** -include Makefile.common +include ../config/Makefile -CFLAGS=-DCAML_NAME_SPACE $(BYTECCCOMPOPTS) $(IFLEXDIR) -DFLAGS=-DCAML_NAME_SPACE -g -DDEBUG $(BYTECCCOMPOPTS) $(IFLEXDIR) -IFLAGS=$(CFLAGS) -DCAML_INSTR - -OBJS=$(COMMONOBJS) $(UNIX_OR_WIN32).o main.o -DOBJS=$(OBJS:.o=.d.o) instrtrace.d.o -IOBJS=$(OBJS:.o=.i.o) -PICOBJS=$(OBJS:.o=.pic.o) - -all:: all-$(SHARED) - -ocamlrun$(EXE): libcamlrun.a prims.o - $(MKEXE) $(BYTECCLINKOPTS) -o ocamlrun$(EXE) \ - prims.o libcamlrun.a $(BYTECCLIBS) - -ocamlrund$(EXE): libcamlrund.a prims.o - $(MKEXE) $(MKEXEDEBUGFLAG) $(BYTECCLINKOPTS) -o ocamlrund$(EXE) \ - prims.o libcamlrund.a $(BYTECCLIBS) - -ocamlruni$(EXE): prims.o libcamlruni.a - $(MKEXE) $(BYTECCLINKOPTS) -o $@ $^ $(BYTECCLIBS) - -libcamlrun.a: $(OBJS) - $(ARCMD) rc libcamlrun.a $(OBJS) - $(RANLIB) libcamlrun.a +INSTALL_BINDIR=$(DESTDIR)$(BINDIR) +INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) -libcamlrund.a: $(DOBJS) - $(ARCMD) rc libcamlrund.a $(DOBJS) - $(RANLIB) libcamlrund.a +# The PROGRAMS (resp. LIBRARIES) variable list the files to build and +# install as programs in $(INSTALL_BINDIR) (resp. libraries in +# $(INSTALL_LIBDIR)) -libcamlruni.a: $(IOBJS) - $(ARCMD) rc $@ $^ - $(RANLIB) $@ +PROGRAMS = ocamlrun$(EXE) +LIBRARIES = ld.conf libcamlrun.$(A) -all-noshared: -.PHONY: all-noshared +ifeq "$(RUNTIMED)" "true" +PROGRAMS += ocamlrund$(EXE) +LIBRARIES += libcamlrund.$(A) +endif -all-shared: libcamlrun_pic.a libcamlrun_shared.so -.PHONY: all-shared +ifeq "$(RUNTIMEI)" "true" +PROGRAMS += ocamlruni$(EXE) +LIBRARIES += libcamlruni.$(A) +endif -libcamlrun_pic.a: $(PICOBJS) - $(ARCMD) rc libcamlrun_pic.a $(PICOBJS) - $(RANLIB) libcamlrun_pic.a +ifeq "$(UNIX_OR_WIN32)" "unix" +ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" +LIBRARIES += libcamlrun_pic.$(A) libcamlrun_shared.$(SO) +endif +endif -libcamlrun_shared.so: $(PICOBJS) - $(MKDLL) -o libcamlrun_shared.so $(PICOBJS) $(BYTECCLIBS) +CC=$(BYTECC) -install:: install-$(SHARED) +ifdef BOOTSTRAPPING_FLEXLINK +CFLAGS=-DBOOTSTRAPPING_FLEXLINK +else +CFLAGS= +endif -install-noshared: -.PHONY: install-noshared +# On Windows, OCAML_STDLIB_DIR needs to be defined dynamically -install-shared: - cp libcamlrun_shared.so "$(INSTALL_LIBDIR)/libcamlrun_shared.so" - cp libcamlrun_pic.a "$(INSTALL_LIBDIR)/libcamlrun_pic.a" - cd "$(INSTALL_LIBDIR)"; $(RANLIB) libcamlrun_pic.a -.PHONY: install-shared +ifeq "$(UNIX_OR_WIN32)" "win32" +CFLAGS += -DOCAML_STDLIB_DIR='"$(LIBDIR)"' +endif -clean:: - rm -f libcamlrun_shared.so libcamlrun_pic.a - -%.d.o: %.c - $(CC) -c $(DFLAGS) $< -o $@ - -%.i.o: %.c - $(CC) -c $(IFLAGS) -o $@ $< - -%.pic.o: %.c - $(CC) -c $(CFLAGS) $(SHAREDCCCOMPOPTS) $< -o $@ +CFLAGS += $(IFLEXDIR) $(BYTECCCOMPOPTS) +DFLAGS=$(CFLAGS) -DDEBUG +IFLAGS=$(CFLAGS) -DCAML_INSTR +PICFLAGS=$(CFLAGS) $(SHAREDCCCOMPOPTS) + +ifneq "$(CCOMPTYPE)" "msvc" +DFLAGS += -g +endif + +ifeq "$(CCOMPTYPE)" "msvc" +OUTPUTOBJ=-Fo +else +OUTPUTOBJ=-o +endif +DBGO=d.$(O) + +ifeq "$(UNIX_OR_WIN32)" "win32" +LIBS = $(call SYSLIB,ws2_32) $(EXTRALIBS) +ifdef BOOTSTRAPPING_FLEXLINK +MAKE_OCAMLRUN=$(MKEXE_BOOT) +else +MAKE_OCAMLRUN = $(MKEXE) -o $(1) $(2) +endif +else +LIBS = $(BYTECCLIBS) +MAKE_OCAMLRUN = $(MKEXE) $(BYTECCLINKOPTS) -o $(1) $(2) +endif + +PRIMS=\ + alloc.c array.c compare.c extern.c floats.c gc_ctrl.c hash.c \ + intern.c interp.c ints.c io.c lexing.c md5.c meta.c obj.c parsing.c \ + signals.c str.c sys.c terminfo.c callback.c weak.c finalise.c stacks.c \ + dynlink.c backtrace_prim.c backtrace.c spacetime.c afl.c + +OBJS=$(addsuffix .$(O), \ + interp misc stacks fix_code startup_aux startup \ + freelist major_gc minor_gc memory alloc roots globroots \ + fail signals signals_byt printexc backtrace_prim backtrace \ + compare ints floats str array io extern intern \ + hash sys meta parsing gc_ctrl terminfo md5 obj \ + lexing callback debugger weak compact finalise custom \ + dynlink spacetime afl $(UNIX_OR_WIN32) main) + +DOBJS=$(OBJS:.$(O)=.$(DBGO)) instrtrace.$(DBGO) +IOBJS=$(OBJS:.$(O)=.i.$(O)) +PICOBJS=$(OBJS:.$(O)=.pic.$(O)) + +.PHONY: all +all: $(LIBRARIES) $(PROGRAMS) + +ld.conf: ../config/Makefile + echo "$(STUBLIBDIR)" > $@ + echo "$(LIBDIR)" >> $@ + +.PHONY: install +install: + cp $(PROGRAMS) "$(INSTALL_BINDIR)" + cp $(LIBRARIES) "$(INSTALL_LIBDIR)" + mkdir -p "$(INSTALL_LIBDIR)/caml" + for i in caml/*.h; do \ + sed -f ../tools/cleanup-header $$i \ + > "$(INSTALL_LIBDIR)/$$i"; \ + done + +# If primitives contain duplicated lines (e.g. because the code is defined +# like +# #ifdef X +# CAMLprim value caml_foo() ... +# #else +# CAMLprim value caml_foo() ... +# end), horrible things will happen (duplicated entries in Runtimedef -> +# double registration in Symtable -> empty entry in the PRIM table -> +# the bytecode interpreter is confused). +# We sort the primitive file and remove duplicates to avoid this problem. + +# Warning: we use "sort | uniq" instead of "sort -u" because in the MSVC +# port, the "sort" program in the path is Microsoft's and not cygwin's + +# Warning: POSIX sort is locale dependent, that's why we set LC_ALL explicitly. +# Sort is unstable for "is_directory" and "isatty" +# see http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html: +# "using sort to process pathnames, it is recommended that LC_ALL .. set to C" + + +primitives : $(PRIMS) + sed -n -e "s/CAMLprim value \([a-z0-9_][a-z0-9_]*\).*/\1/p" $(PRIMS) \ + | LC_ALL=C sort | uniq > primitives + +prims.c : primitives + (echo '#define CAML_INTERNALS'; \ + echo '#include "caml/mlvalues.h"'; \ + echo '#include "caml/prims.h"'; \ + sed -e 's/.*/extern value &();/' primitives; \ + echo 'c_primitive caml_builtin_cprim[] = {'; \ + sed -e 's/.*/ &,/' primitives; \ + echo ' 0 };'; \ + echo 'char * caml_names_of_builtin_cprim[] = {'; \ + sed -e 's/.*/ "&",/' primitives; \ + echo ' 0 };') > prims.c + +caml/opnames.h : caml/instruct.h + sed -e '/\/\*/d' \ + -e '/^#/d' \ + -e 's/enum /char * names_of_/' \ + -e 's/{$$/[] = {/' \ + -e 's/\([[:upper:]][[:upper:]_0-9]*\)/"\1"/g' caml/instruct.h \ + > caml/opnames.h + +# caml/jumptbl.h is required only if you have GCC 2.0 or later +caml/jumptbl.h : caml/instruct.h + sed -n -e '/^ /s/ \([A-Z]\)/ \&\&lbl_\1/gp' \ + -e '/^}/q' caml/instruct.h > caml/jumptbl.h + +caml/version.h : ../VERSION ../tools/make-version-header.sh + ../tools/make-version-header.sh ../VERSION > caml/version.h + +.PHONY: clean +clean: + rm -f $(LIBRARIES) $(PROGRAMS) *.$(O) *.$(A) *.$(SO) + rm -f primitives prims.c caml/opnames.h caml/jumptbl.h + rm -f caml/version.h + +ocamlrun$(EXE): prims.$(O) libcamlrun.$(A) + $(call MAKE_OCAMLRUN,$@,$^ $(LIBS)) + +libcamlrun.$(A): $(OBJS) + $(call MKLIB,$@, $^) + +ocamlrund$(EXE): prims.$(O) libcamlrund.$(A) + $(MKEXE) $(MKEXEDEBUGFLAG) $(BYTECCLINKOPTS) -o $@ $^ $(LIBS) + +libcamlrund.$(A): $(DOBJS) + $(call MKLIB,$@, $^) + +ocamlruni$(EXE): prims.$(O) libcamlruni.$(A) + $(MKEXE) $(BYTECCLINKOPTS) -o $@ $^ $(LIBS) + +libcamlruni.$(A): $(IOBJS) + $(call MKLIB,$@, $^) + +libcamlrun_pic.$(A): $(PICOBJS) + $(call MKLIB,$@, $^) + +libcamlrun_shared.$(SO): $(PICOBJS) + $(MKDLL) -o $@ $^ $(BYTECCLIBS) + +%.$(O): %.c + $(CC) $(CFLAGS) -c $< + +%.$(DBGO): %.c + $(CC) $(DFLAGS) -c $(OUTPUTOBJ)$@ $< + +%.i.$(O): %.c + $(CC) $(IFLAGS) -c $(OUTPUTOBJ)$@ $< + +%.pic.$(O): %.c + $(CC) $(PICFLAGS) -c $(OUTPUTOBJ)$@ $< + +ifneq "$(TOOLCHAIN)" "msvc" +.PHONY: depend depend : prims.c caml/opnames.h caml/jumptbl.h caml/version.h -$(CC) -MM $(BYTECCCOMPOPTS) *.c > .depend -$(CC) -MM $(BYTECCCOMPOPTS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' \ @@ -92,6 +223,29 @@ depend : prims.c caml/opnames.h caml/jumptbl.h caml/version.h -$(CC) -MM $(BYTECCCOMPOPTS) -DCAML_INSTR *.c | sed -e 's/\.o/.i.o/' \ >> .depend -$(CC) -MM $(BYTECCCOMPOPTS) *.c | sed -e 's/\.o/.pic.o/' >> .depend -.PHONY: depend - +endif + +ifeq "$(UNIX_OR_WIN32)" "win32" +.depend.nt: .depend + rm -f .depend.win32 + echo "win32.o: win32.c caml/fail.h caml/compatibility.h \\"\ + >> .depend.win32 + echo " caml/misc.h caml/config.h ../config/m.h ../config/s.h \\"\ + >> .depend.win32 + echo " caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \\"\ + >> .depend.win32 + echo " caml/freelist.h caml/minor_gc.h caml/osdeps.h caml/signals.h"\ + >> .depend.win32 + cat .depend >> .depend.win32 + sed -ne '/\.pic\.o/q' \ + -e 's/^\(.*\)\.d\.o:/\1.$$(DBGO):/' \ + -e 's/^\(.*\)\.o:/\1.$$(O):/' \ + -e p \ + .depend.win32 > .depend.nt + rm -f .depend.win32 + +include .depend.nt + +else include .depend +endif diff --git a/byterun/Makefile.common b/byterun/Makefile.common deleted file mode 100644 index 144d3a3e..00000000 --- a/byterun/Makefile.common +++ /dev/null @@ -1,143 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include ../config/Makefile -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc - -CC=$(BYTECC) - -COMMONOBJS=\ - interp.o misc.o stacks.o fix_code.o startup_aux.o startup.o \ - freelist.o major_gc.o minor_gc.o memory.o alloc.o roots.o globroots.o \ - fail.o signals.o signals_byt.o printexc.o backtrace_prim.o backtrace.o \ - compare.o ints.o floats.o str.o array.o io.o extern.o intern.o \ - hash.o sys.o meta.o parsing.o gc_ctrl.o terminfo.o md5.o obj.o \ - lexing.o callback.o debugger.o weak.o compact.o finalise.o custom.o \ - dynlink.o spacetime.o - -PRIMS=\ - alloc.c array.c compare.c extern.c floats.c gc_ctrl.c hash.c \ - intern.c interp.c ints.c io.c lexing.c md5.c meta.c obj.c parsing.c \ - signals.c str.c sys.c terminfo.c callback.c weak.c finalise.c stacks.c \ - dynlink.c backtrace_prim.c backtrace.c spacetime.c - -all:: ocamlrun$(EXE) ld.conf libcamlrun.$(A) all-$(RUNTIMED) primitives -.PHONY: all - -all-noruntimed: -.PHONY: all-noruntimed - -all-runtimed: ocamlrund$(EXE) libcamlrund.$(A) -.PHONY: all-runtimed - -ifeq "$(RUNTIMEI)" "true" -all:: ocamlruni$(EXE) libcamlruni.$(A) -endif - -ld.conf: ../config/Makefile - echo "$(STUBLIBDIR)" > ld.conf - echo "$(LIBDIR)" >> ld.conf - -# Installation - -INSTALL_BINDIR=$(DESTDIR)$(BINDIR) -INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) - - -install:: - cp $(CAMLRUN)$(EXE) "$(INSTALL_BINDIR)/ocamlrun$(EXE)" - cp libcamlrun.$(A) "$(INSTALL_LIBDIR)/libcamlrun.$(A)" - cd "$(INSTALL_LIBDIR)"; $(RANLIB) libcamlrun.$(A) - if test -d "$(INSTALL_LIBDIR)/caml"; then : ; \ - else mkdir "$(INSTALL_LIBDIR)/caml"; fi - for i in caml/*.h; do \ - sed -f ../tools/cleanup-header $$i \ - > "$(INSTALL_LIBDIR)/$$i"; \ - done - cp ld.conf "$(INSTALL_LIBDIR)/ld.conf" -.PHONY: install - -install:: install-$(RUNTIMED) - -install-noruntimed: -.PHONY: install-noruntimed - -# TODO: when cross-compiling, do not install ocamlrund -# it doesn't hurt to install it, but it's useless and might be confusing -# because it's an executable for the target machine, while we're installing -# binaries for the host. -install-runtimed: - cp ocamlrund$(EXE) "$(INSTALL_BINDIR)/ocamlrund$(EXE)" - cp libcamlrund.$(A) "$(INSTALL_LIBDIR)/libcamlrund.$(A)" -.PHONY: install-runtimed - -ifeq "$(RUNTIMEI)" "true" -install:: - cp ocamlruni$(EXE) $(INSTALL_BINDIR)/ocamlruni$(EXE) - cp libcamlruni.$(A) $(INSTALL_LIBDIR)/libcamlruni.$(A) -endif - -# If primitives contain duplicated lines (e.g. because the code is defined -# like -# #ifdef X -# CAMLprim value caml_foo() ... -# #else -# CAMLprim value caml_foo() ... -# end), horrible things will happen (duplicated entries in Runtimedef -> -# double registration in Symtable -> empty entry in the PRIM table -> -# the bytecode interpreter is confused). -# We sort the primitive file and remove duplicates to avoid this problem. - -# Warning: we use "sort | uniq" instead of "sort -u" because in the MSVC -# port, the "sort" program in the path is Microsoft's and not cygwin's - -primitives : $(PRIMS) - sed -n -e "s/CAMLprim value \([a-z0-9_][a-z0-9_]*\).*/\1/p" $(PRIMS) \ - | sort | uniq > primitives - -prims.c : primitives - (echo '#define CAML_INTERNALS'; \ - echo '#include "caml/mlvalues.h"'; \ - echo '#include "caml/prims.h"'; \ - sed -e 's/.*/extern value &();/' primitives; \ - echo 'c_primitive caml_builtin_cprim[] = {'; \ - sed -e 's/.*/ &,/' primitives; \ - echo ' 0 };'; \ - echo 'char * caml_names_of_builtin_cprim[] = {'; \ - sed -e 's/.*/ "&",/' primitives; \ - echo ' 0 };') > prims.c - -caml/opnames.h : caml/instruct.h - sed -e '/\/\*/d' \ - -e '/^#/d' \ - -e 's/enum /char * names_of_/' \ - -e 's/{$$/[] = {/' \ - -e 's/\([[:upper:]][[:upper:]_0-9]*\)/"\1"/g' caml/instruct.h \ - > caml/opnames.h - -# caml/jumptbl.h is required only if you have GCC 2.0 or later -caml/jumptbl.h : caml/instruct.h - sed -n -e '/^ /s/ \([A-Z]\)/ \&\&lbl_\1/gp' \ - -e '/^}/q' caml/instruct.h > caml/jumptbl.h - -caml/version.h : ../VERSION ../tools/make-version-header.sh - ../tools/make-version-header.sh ../VERSION > caml/version.h - -clean :: - rm -f ocamlrun$(EXE) ocamlrund$(EXE) *.$(O) *.$(A) *.$(SO) - rm -f primitives prims.c caml/opnames.h caml/jumptbl.h ld.conf - rm -f caml/version.h -.PHONY: clean diff --git a/byterun/Makefile.nt b/byterun/Makefile.nt index e74bdd9c..ed9900bb 100644 --- a/byterun/Makefile.nt +++ b/byterun/Makefile.nt @@ -13,59 +13,4 @@ #* * #************************************************************************** -include Makefile.common - -CFLAGS=-DOCAML_STDLIB_DIR='"$(LIBDIR)"' $(IFLEXDIR) -DFLAGS=$(CFLAGS) -DDEBUG - -ifdef BOOTSTRAPPING_FLEXLINK -MAKE_OCAMLRUN=$(MKEXE_BOOT) -CFLAGS:=-DBOOTSTRAPPING_FLEXLINK $(CFLAGS) -else -MAKE_OCAMLRUN=$(MKEXE) -o $(1) $(2) -endif - -DBGO=d.$(O) -OBJS=$(COMMONOBJS:.o=.$(O)) win32.$(O) main.$(O) -DOBJS=$(OBJS:.$(O)=.$(DBGO)) instrtrace.$(DBGO) - -ocamlrun$(EXE): libcamlrun.$(A) prims.$(O) - $(call MAKE_OCAMLRUN,ocamlrun$(EXE),prims.$(O) libcamlrun.$(A) \ - $(call SYSLIB,ws2_32) $(EXTRALIBS)) - -ocamlrund$(EXE): libcamlrund.$(A) prims.$(O) main.$(O) - $(MKEXE) -o ocamlrund$(EXE) prims.$(O) \ - $(call SYSLIB,ws2_32) $(EXTRALIBS) libcamlrund.$(A) - -libcamlrun.$(A): $(OBJS) - $(call MKLIB,libcamlrun.$(A),$(OBJS)) - -libcamlrund.$(A): $(DOBJS) - $(call MKLIB,libcamlrund.$(A),$(DOBJS)) - -%.$(O): %.c - $(CC) $(CFLAGS) $(BYTECCCOMPOPTS) -c $< - -# It is imperative that there is no space after $(NAME_OBJ_FLAG) -%.$(DBGO): %.c - $(CC) $(DFLAGS) $(BYTECCDBGCOMPOPTS) -c $(NAME_OBJ_FLAG)$@ $< - -.depend.nt: .depend - rm -f .depend.win32 - echo "win32.o: win32.c caml/fail.h caml/compatibility.h \\"\ - >> .depend.win32 - echo " caml/misc.h caml/config.h ../config/m.h ../config/s.h \\"\ - >> .depend.win32 - echo " caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \\"\ - >> .depend.win32 - echo " caml/freelist.h caml/minor_gc.h caml/osdeps.h caml/signals.h"\ - >> .depend.win32 - cat .depend >> .depend.win32 - sed -ne '/\.pic\.o/q' \ - -e 's/^\(.*\)\.d\.o:/\1.$$(DBGO):/' \ - -e 's/^\(.*\)\.o:/\1.$$(O):/' \ - -e p \ - .depend.win32 > .depend.nt - rm -f .depend.win32 - -include .depend.nt +include Makefile diff --git a/byterun/afl.c b/byterun/afl.c new file mode 100644 index 00000000..bd87ce8d --- /dev/null +++ b/byterun/afl.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Stephen Dolan, University of Cambridge */ +/* */ +/* Copyright 2016 Stephen Dolan. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Runtime support for afl-fuzz */ + +/* Android's libc does not implement System V shared memory. */ +#if defined(_WIN32) || defined(__ANDROID__) + +#include "caml/mlvalues.h" + +CAMLprim value caml_setup_afl (value unit) +{ + return Val_unit; +} + +CAMLprim value caml_reset_afl_instrumentation(value unused) +{ + return Val_unit; +} + +#else + +#include +#include +#include +#include +#include +#include +#include + +#define CAML_INTERNALS +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/osdeps.h" + +static int afl_initialised = 0; + +/* afl uses abnormal termination (SIGABRT) to check whether + to count a testcase as "crashing" */ +extern int caml_abort_on_uncaught_exn; + +/* Values used by the instrumentation logic (see cmmgen.ml) */ +static unsigned char afl_area_initial[1 << 16]; +unsigned char* caml_afl_area_ptr = afl_area_initial; +uintnat caml_afl_prev_loc; + +/* File descriptors used to synchronise with afl-fuzz */ +#define FORKSRV_FD_READ 198 +#define FORKSRV_FD_WRITE 199 + +static void afl_write(uint32_t msg) +{ + if (write(FORKSRV_FD_WRITE, &msg, 4) != 4) + caml_fatal_error("writing to afl-fuzz"); +} + +static uint32_t afl_read() +{ + uint32_t msg; + if (read(FORKSRV_FD_READ, &msg, 4) != 4) + caml_fatal_error("reading from afl-fuzz"); + return msg; +} + +CAMLprim value caml_setup_afl(value unit) +{ + if (afl_initialised) return Val_unit; + afl_initialised = 1; + + char* shm_id_str = caml_secure_getenv("__AFL_SHM_ID"); + if (shm_id_str == NULL) { + /* Not running under afl-fuzz, continue as normal */ + return Val_unit; + } + + /* if afl-fuzz is attached, we want it to know about uncaught exceptions */ + caml_abort_on_uncaught_exn = 1; + + char* shm_id_end; + long int shm_id = strtol(shm_id_str, &shm_id_end, 10); + if (!(*shm_id_str != '\0' && *shm_id_end == '\0')) + caml_fatal_error("afl-fuzz: bad shm id"); + + caml_afl_area_ptr = shmat((int)shm_id, NULL, 0); + if (caml_afl_area_ptr == (void*)-1) + caml_fatal_error("afl-fuzz: could not attach shm area"); + + /* poke the bitmap so that afl-fuzz knows we exist, even if the + application has sparse instrumentation */ + caml_afl_area_ptr[0] = 1; + + /* synchronise with afl-fuzz */ + uint32_t startup_msg = 0; + if (write(FORKSRV_FD_WRITE, &startup_msg, 4) != 4) { + /* initial write failed, so assume we're not meant to fork. + afl-tmin uses this mode. */ + return Val_unit; + } + afl_read(); + + while (1) { + int child_pid = fork(); + if (child_pid < 0) caml_fatal_error("afl-fuzz: could not fork"); + else if (child_pid == 0) { + /* Run the program */ + close(FORKSRV_FD_READ); + close(FORKSRV_FD_WRITE); + return Val_unit; + } + + /* As long as the child keeps raising SIGSTOP, we re-use the same process */ + while (1) { + afl_write((uint32_t)child_pid); + + int status; + /* WUNTRACED means wait until termination or SIGSTOP */ + if (waitpid(child_pid, &status, WUNTRACED) < 0) + caml_fatal_error("afl-fuzz: waitpid failed"); + + afl_write((uint32_t)status); + + uint32_t was_killed = afl_read(); + if (WIFSTOPPED(status)) { + /* child stopped, waiting for another test case */ + if (was_killed) { + /* we saw the child stop, but since then afl-fuzz killed it. + we should wait for it before forking another child */ + if (waitpid(child_pid, &status, 0) < 0) + caml_fatal_error("afl-fuzz: waitpid failed"); + break; + } else { + kill(child_pid, SIGCONT); + } + } else { + /* child died */ + break; + } + } + } +} + +CAMLprim value caml_reset_afl_instrumentation(value full) +{ + if (full != Val_int(0)) { + memset(caml_afl_area_ptr, 0, sizeof(afl_area_initial)); + } + caml_afl_prev_loc = 0; + return Val_unit; +} + +#endif /* _WIN32 */ diff --git a/byterun/alloc.c b/byterun/alloc.c index 7bda3921..8894d6f5 100644 --- a/byterun/alloc.c +++ b/byterun/alloc.c @@ -158,6 +158,9 @@ CAMLprim value caml_alloc_float_array(mlsize_t len) { mlsize_t wosize = len * Double_wosize; value result; + /* For consistency with [caml_make_vect], which can't tell whether it should + create a float array or not when the size is zero, the tag is set to + zero when the size is zero. */ if (wosize == 0) return Atom(0); else if (wosize <= Max_young_wosize){ diff --git a/byterun/array.c b/byterun/array.c index 900182db..11f2b51a 100644 --- a/byterun/array.c +++ b/byterun/array.c @@ -23,7 +23,8 @@ #include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/signals.h" -#include "spacetime.h" +/* Why is caml/spacetime.h included conditionnally sometimes and not here ? */ +#include "caml/spacetime.h" static const mlsize_t mlsize_t_max = -1; diff --git a/byterun/backtrace.c b/byterun/backtrace.c index a5bc7809..8dfe9b7e 100644 --- a/byterun/backtrace.c +++ b/byterun/backtrace.c @@ -49,9 +49,11 @@ CAMLprim value caml_record_backtrace(value vflag) caml_backtrace_active = flag; caml_backtrace_pos = 0; caml_backtrace_last_exn = Val_unit; - /* Note: lazy initialization of caml_backtrace_buffer in - caml_stash_backtrace to simplify the interface with the thread - libraries */ + /* Note: We do lazy initialization of caml_backtrace_buffer when + needed in order to simplify the interface with the thread + library (thread creation doesn't need to allocate + caml_backtrace_buffer). So we don't have to allocate it here. + */ } return Val_unit; } @@ -167,6 +169,41 @@ CAMLprim value caml_get_exception_raw_backtrace(value unit) CAMLreturn(res); } +/* Copy back a backtrace and exception to the global state. + This function should be used only with Printexc.raw_backtrace */ +/* noalloc (caml value): so no CAMLparam* CAMLreturn* */ +CAMLprim value caml_restore_raw_backtrace(value exn, value backtrace) +{ + intnat i; + mlsize_t bt_size; + + caml_backtrace_last_exn = exn; + + bt_size = Wosize_val(backtrace); + if(bt_size > BACKTRACE_BUFFER_SIZE){ + bt_size = BACKTRACE_BUFFER_SIZE; + } + + /* We don't allocate if the backtrace is empty (no -g or backtrace + not activated) */ + if(bt_size == 0){ + caml_backtrace_pos = 0; + return Val_unit; + } + + /* Allocate if needed and copy the backtrace buffer */ + if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1){ + return Val_unit; + } + + caml_backtrace_pos = bt_size; + for(i=0; i < caml_backtrace_pos; i++){ + caml_backtrace_buffer[i] = Backtrace_slot_val(Field(backtrace, i)); + } + + return Val_unit; +} + #define Val_debuginfo(bslot) (Val_long((uintnat)(bslot)>>1)) #define Debuginfo_val(vslot) ((debuginfo)(Long_val(vslot) << 1)) diff --git a/byterun/backtrace_prim.c b/byterun/backtrace_prim.c index c81955a4..7a46e1d6 100644 --- a/byterun/backtrace_prim.c +++ b/byterun/backtrace_prim.c @@ -217,6 +217,13 @@ CAMLprim value caml_remove_debug_info(code_t start) CAMLreturn(Val_unit); } +int caml_alloc_backtrace_buffer(void){ + Assert(caml_backtrace_pos == 0); + caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE * sizeof(code_t)); + if (caml_backtrace_buffer == NULL) return -1; + return 0; +} + /* Store the return addresses contained in the given stack fragment into the backtrace array */ @@ -228,11 +235,8 @@ void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise) caml_backtrace_last_exn = exn; } - if (caml_backtrace_buffer == NULL) { - Assert(caml_backtrace_pos == 0); - caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE * sizeof(code_t)); - if (caml_backtrace_buffer == NULL) return; - } + if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1) + return; if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; /* testing the code region is needed: PR#1554 */ diff --git a/byterun/caml/backtrace_prim.h b/byterun/caml/backtrace_prim.h index 025242d0..2484b294 100644 --- a/byterun/caml/backtrace_prim.h +++ b/byterun/caml/backtrace_prim.h @@ -70,6 +70,9 @@ void caml_debuginfo_location(debuginfo dbg, /*out*/ struct caml_loc_info * li); #define Val_backtrace_slot(bslot) (Val_long(((uintnat)(bslot))>>1)) #define Backtrace_slot_val(vslot) ((backtrace_slot)(Long_val(vslot) << 1)) +/* Allocate the caml_backtrace_buffer. Returns 0 on success, -1 otherwise */ +int caml_alloc_backtrace_buffer(void); + #define BACKTRACE_BUFFER_SIZE 1024 /* Besides decoding backtrace info, [backtrace_prim] has two other diff --git a/byterun/caml/callback.h b/byterun/caml/callback.h index 58d3faff..147eb718 100644 --- a/byterun/caml/callback.h +++ b/byterun/caml/callback.h @@ -49,6 +49,7 @@ CAMLextern void caml_iterate_named_values(caml_named_action f); CAMLextern void caml_main (char ** argv); CAMLextern void caml_startup (char ** argv); +CAMLextern value caml_startup_exn (char ** argv); CAMLextern int caml_callback_depth; diff --git a/byterun/caml/fail.h b/byterun/caml/fail.h index 07cb37d1..3ae82b1e 100644 --- a/byterun/caml/fail.h +++ b/byterun/caml/fail.h @@ -83,11 +83,19 @@ CAMLextern void caml_raise_with_string (value tag, char const * msg) CAMLnoreturn_end; CAMLnoreturn_start -CAMLextern void caml_failwith (char const *) +CAMLextern void caml_failwith (char const *msg) CAMLnoreturn_end; CAMLnoreturn_start -CAMLextern void caml_invalid_argument (char const *) +CAMLextern void caml_failwith_value (value msg) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_invalid_argument (char const *msg) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_invalid_argument_value (value msg) CAMLnoreturn_end; CAMLnoreturn_start diff --git a/byterun/caml/gc.h b/byterun/caml/gc.h index 776ddc77..c430afc0 100644 --- a/byterun/caml/gc.h +++ b/byterun/caml/gc.h @@ -46,21 +46,25 @@ + (tag_t) (tag))) \ ) -#ifdef WITH_SPACETIME -struct ext_table; -extern uintnat caml_spacetime_my_profinfo(struct ext_table**, uintnat); +#ifdef WITH_PROFINFO #define Make_header_with_profinfo(wosize, tag, color, profinfo) \ (Make_header(wosize, tag, color) \ | ((((intnat) profinfo) & PROFINFO_MASK) << PROFINFO_SHIFT) \ ) +#else +#define Make_header_with_profinfo(wosize, tag, color, profinfo) \ + Make_header(wosize, tag, color) +#endif + +#ifdef WITH_SPACETIME +struct ext_table; +extern uintnat caml_spacetime_my_profinfo(struct ext_table**, uintnat); #define Make_header_allocated_here(wosize, tag, color) \ (Make_header_with_profinfo(wosize, tag, color, \ caml_spacetime_my_profinfo(NULL, wosize)) \ ) #else #define Make_header_allocated_here Make_header -#define Make_header_with_profinfo(wosize, tag, color, profinfo) \ - Make_header(wosize | (profinfo & (intnat) 0), tag, color) #endif #define Is_white_val(val) (Color_val(val) == Caml_white) diff --git a/byterun/caml/memory.h b/byterun/caml/memory.h index 608b702a..e366fd83 100644 --- a/byterun/caml/memory.h +++ b/byterun/caml/memory.h @@ -36,16 +36,16 @@ extern "C" { CAMLextern value caml_alloc_shr (mlsize_t wosize, tag_t); -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) +#ifdef WITH_PROFINFO CAMLextern value caml_alloc_shr_with_profinfo (mlsize_t, tag_t, intnat); CAMLextern value caml_alloc_shr_preserving_profinfo (mlsize_t, tag_t, - header_t); + header_t); #else #define caml_alloc_shr_with_profinfo(size, tag, profinfo) \ caml_alloc_shr(size, tag) #define caml_alloc_shr_preserving_profinfo(size, tag, header) \ caml_alloc_shr(size, tag) -#endif +#endif /* WITH_PROFINFO */ CAMLextern value caml_alloc_shr_no_raise (mlsize_t wosize, tag_t); CAMLextern void caml_adjust_gc_speed (mlsize_t, mlsize_t); CAMLextern void caml_alloc_dependent_memory (mlsize_t bsz); diff --git a/byterun/caml/misc.h b/byterun/caml/misc.h index be7d00d4..e953540f 100644 --- a/byterun/caml/misc.h +++ b/byterun/caml/misc.h @@ -167,6 +167,9 @@ extern intnat (*caml_cplugins_prim)(int,intnat,intnat,intnat); #define CAML_SYS_STRING_PRIM_1(code,prim,arg1) \ (caml_cplugins_prim == NULL) ? prim(arg1) : \ (char*)caml_cplugins_prim(code,(intnat) (arg1),0,0) +#define CAML_SYS_VOID_PRIM_1(code,prim,arg1) \ + (caml_cplugins_prim == NULL) ? prim(arg1) : \ + (void)caml_cplugins_prim(code,(intnat) (arg1),0,0) #define CAML_SYS_PRIM_2(code,prim,arg1,arg2) \ (caml_cplugins_prim == NULL) ? prim(arg1,arg2) : \ caml_cplugins_prim(code,(intnat) (arg1), (intnat) (arg2),0) @@ -175,7 +178,7 @@ extern intnat (*caml_cplugins_prim)(int,intnat,intnat,intnat); caml_cplugins_prim(code,(intnat) (arg1), (intnat) (arg2),(intnat) (arg3)) #define CAML_SYS_EXIT(retcode) \ - CAML_SYS_PRIM_1(CAML_CPLUGINS_EXIT,exit,retcode) + CAML_SYS_VOID_PRIM_1(CAML_CPLUGINS_EXIT,exit,retcode) #define CAML_SYS_OPEN(filename,flags,perm) \ CAML_SYS_PRIM_3(CAML_CPLUGINS_OPEN,open,filename,flags,perm) #define CAML_SYS_CLOSE(fd) \ diff --git a/byterun/caml/mlvalues.h b/byterun/caml/mlvalues.h index c4d31b99..04ff65a4 100644 --- a/byterun/caml/mlvalues.h +++ b/byterun/caml/mlvalues.h @@ -108,19 +108,19 @@ bits 63 (64-P) (63-P) 10 9 8 7 0 #define PROFINFO_MASK ((1ull << PROFINFO_WIDTH) - 1ull) #define Tag_hd(hd) ((tag_t) ((hd) & 0xFF)) -#ifdef WITH_SPACETIME +#ifdef WITH_PROFINFO #define Hd_no_profinfo(hd) ((hd) & ~(PROFINFO_MASK << PROFINFO_SHIFT)) #define Wosize_hd(hd) ((mlsize_t) ((Hd_no_profinfo(hd)) >> 10)) #else #define Wosize_hd(hd) ((mlsize_t) ((hd) >> 10)) -#endif /* SPACETIME */ -#ifdef ARCH_SIXTYFOUR +#endif /* WITH_PROFINFO */ +#if defined(ARCH_SIXTYFOUR) && defined(WITH_PROFINFO) /* [Profinfo_hd] is used when the compiler is not configured for Spacetime (e.g. when decoding profiles). */ #define Profinfo_hd(hd) (((mlsize_t) ((hd) >> PROFINFO_SHIFT)) & PROFINFO_MASK) #else #define Profinfo_hd(hd) ((hd) & 0) -#endif /* ARCH_SIXTYFOUR */ +#endif /* ARCH_SIXTYFOUR && WITH_PROFINFO */ #define Hd_val(val) (((header_t *) (val)) [-1]) /* Also an l-value. */ #define Hd_op(op) (Hd_val (op)) /* Also an l-value. */ @@ -136,14 +136,10 @@ bits 63 (64-P) (63-P) 10 9 8 7 0 #define Num_tags (1 << 8) #ifdef ARCH_SIXTYFOUR -#ifdef WITH_SPACETIME #define Max_wosize (((intnat)1 << (54-PROFINFO_WIDTH)) - 1) #else -#define Max_wosize (((intnat)1 << 54) - 1) -#endif -#else #define Max_wosize ((1 << 22) - 1) -#endif +#endif /* ARCH_SIXTYFOUR */ #define Wosize_val(val) (Wosize_hd (Hd_val (val))) #define Wosize_op(op) (Wosize_val (op)) @@ -252,6 +248,7 @@ CAMLextern value caml_hash_variant(char const * tag); this tag cannot be mistaken for pointers (see caml_obj_truncate). */ #define Abstract_tag 251 +#define Data_abstract_val(v) ((void*) Op_val(v)) /* Strings. */ #define String_tag 252 diff --git a/byterun/caml/osdeps.h b/byterun/caml/osdeps.h index 7fcf903a..bf9a4817 100644 --- a/byterun/caml/osdeps.h +++ b/byterun/caml/osdeps.h @@ -82,8 +82,14 @@ extern char * caml_dlerror(void); extern int caml_read_directory(char * dirname, struct ext_table * contents); /* Recover executable name if possible (/proc/sef/exe under Linux, - GetModuleFileName under Windows). */ -extern int caml_executable_name(char * name, int name_len); + GetModuleFileName under Windows). Return NULL on error, + string allocated with [caml_stat_alloc] on success. */ +extern char * caml_executable_name(void); + +/* Secure version of [getenv]: returns NULL if the process has special + privileges (setuid bit, setgid bit, capabilities). +*/ +extern char *caml_secure_getenv(char const *var); #endif /* CAML_INTERNALS */ diff --git a/asmrun/spacetime.h b/byterun/caml/spacetime.h similarity index 98% rename from asmrun/spacetime.h rename to byterun/caml/spacetime.h index bb61bb3c..68bf1d20 100644 --- a/asmrun/spacetime.h +++ b/byterun/caml/spacetime.h @@ -15,6 +15,8 @@ #ifndef CAML_SPACETIME_H #define CAML_SPACETIME_H +#ifdef NATIVE_CODE + #include "caml/io.h" #include "caml/misc.h" #include "caml/stack.h" @@ -188,4 +190,12 @@ extern void caml_spacetime_automatic_snapshot (void); profinfo = (uintnat) 0; #endif +#else + +#define Get_my_profinfo_with_cached_backtrace(profinfo, size) \ + profinfo = (uintnat) 0; + +#endif /* NATIVE_CODE */ + + #endif diff --git a/byterun/caml/startup.h b/byterun/caml/startup.h index 3df4206a..0c38dac0 100644 --- a/byterun/caml/startup.h +++ b/byterun/caml/startup.h @@ -29,6 +29,12 @@ CAMLextern void caml_startup_code( char *section_table, asize_t section_table_size, char **argv); +CAMLextern value caml_startup_code_exn( + code_t code, asize_t code_size, + char *data, asize_t data_size, + char *section_table, asize_t section_table_size, + char **argv); + enum { FILE_NOT_FOUND = -1, BAD_BYTECODE = -2 }; extern int caml_attempt_open(char **name, struct exec_trailer *trail, diff --git a/byterun/compact.c b/byterun/compact.c index cd46623a..1d480692 100644 --- a/byterun/compact.c +++ b/byterun/compact.c @@ -49,7 +49,7 @@ extern void caml_shrink_heap (char *); /* memory.c */ XXX (see [caml_register_global_roots]) XXX Should be able to fix it to only assume 2-byte alignment. */ -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) +#ifdef WITH_PROFINFO #define Make_ehd(s,t,c,p) \ (((s) << 10) | (t) << 2 | (c) | ((p) << PROFINFO_SHIFT)) #else @@ -273,14 +273,17 @@ static void do_compaction (void) size_t sz; tag_t t; char *newadr; +#ifdef WITH_PROFINFO uintnat profinfo; +#endif word *infixes = NULL; while (Ecolor (q) == 0) q = * (word *) q; sz = Whsize_ehd (q); t = Tag_ehd (q); +#ifdef WITH_PROFINFO profinfo = Profinfo_ehd (q); - +#endif if (t == Infix_tag){ /* Get the original header of this block. */ infixes = p + sz; diff --git a/byterun/debugger.c b/byterun/debugger.c index 2edbaa0c..f4000872 100644 --- a/byterun/debugger.c +++ b/byterun/debugger.c @@ -27,6 +27,7 @@ #include "caml/config.h" #include "caml/debugger.h" #include "caml/misc.h" +#include "caml/osdeps.h" int caml_debugger_in_use = 0; uintnat caml_event_count; @@ -172,7 +173,7 @@ void caml_debugger_init(void) Store_field(marshal_flags, 0, Val_int(1)); /* Marshal.Closures */ Store_field(marshal_flags, 1, Val_emptylist); - address = getenv("CAML_DEBUG_SOCKET"); + address = caml_secure_getenv("CAML_DEBUG_SOCKET"); if (address == NULL) return; dbg_addr = address; diff --git a/byterun/dynlink.c b/byterun/dynlink.c index f80d1f7f..ed678df3 100644 --- a/byterun/dynlink.c +++ b/byterun/dynlink.c @@ -81,8 +81,8 @@ static char * parse_ld_conf(void) struct stat st; int ldconf, nread; - stdlib = getenv("OCAMLLIB"); - if (stdlib == NULL) stdlib = getenv("CAMLLIB"); + stdlib = caml_secure_getenv("OCAMLLIB"); + if (stdlib == NULL) stdlib = caml_secure_getenv("CAMLLIB"); if (stdlib == NULL) stdlib = OCAML_STDLIB_DIR; ldconfname = caml_strconcat(3, stdlib, "/", LD_CONF_NAME); if (stat(ldconfname, &st) == -1) { @@ -150,7 +150,7 @@ void caml_build_primitive_table(char * lib_path, - directories specified in the executable - directories specified in the file /ld.conf */ tofree1 = caml_decompose_path(&caml_shared_libs_path, - getenv("CAML_LD_LIBRARY_PATH")); + caml_secure_getenv("CAML_LD_LIBRARY_PATH")); if (lib_path != NULL) for (p = lib_path; *p != 0; p += strlen(p) + 1) caml_ext_table_add(&caml_shared_libs_path, p); diff --git a/byterun/extern.c b/byterun/extern.c index eca115d8..51240d0b 100644 --- a/byterun/extern.c +++ b/byterun/extern.c @@ -434,10 +434,10 @@ static void extern_rec(value v) if (tag < 16) { write(PREFIX_SMALL_BLOCK + tag); } else { -#if !(defined(NATIVE_CODE) && defined(WITH_SPACETIME)) - writecode32(CODE_BLOCK32, hd); -#else +#ifdef WITH_PROFINFO writecode32(CODE_BLOCK32, Hd_no_profinfo(hd)); +#else + writecode32(CODE_BLOCK32, hd); #endif } goto next_item; @@ -551,10 +551,10 @@ static void extern_rec(value v) write(PREFIX_SMALL_BLOCK + tag + (sz << 4)); } else { #ifdef ARCH_SIXTYFOUR -#if !(defined(NATIVE_CODE) && defined(WITH_SPACETIME)) - header_t hd_erased = hd; -#else +#ifdef WITH_PROFINFO header_t hd_erased = Hd_no_profinfo(hd); +#else + header_t hd_erased = hd; #endif if (sz > 0x3FFFFF && (extern_flags & COMPAT_32)) extern_failwith("output_value: array cannot be read back on " diff --git a/byterun/fail.c b/byterun/fail.c index 80eca18a..6396aeb6 100644 --- a/byterun/fail.c +++ b/byterun/fail.c @@ -81,25 +81,68 @@ CAMLexport void caml_raise_with_string(value tag, char const *msg) CAMLnoreturn; } -/* PR#5115: Failure and Invalid_argument can be triggered by - input_value while reading the initial value of [caml_global_data]. */ - -CAMLexport void caml_failwith (char const *msg) +/* PR#5115: Built-in exceptions can be triggered by input_value + while reading the initial value of [caml_global_data]. + + We check against this issue here in byterun/fail.c instead of + byterun/intern.c. Having the check here means that these calls will + be slightly slower for all bytecode programs (not just the calls + coming from intern). Because intern.c is shared between byterun/ + and asmrun/, putting checks there would slow do input_value for + natively-compiled programs that do not need these checks. +*/ +static void check_global_data(char const *exception_name) { if (caml_global_data == 0) { - fprintf(stderr, "Fatal error: exception Failure(\"%s\")\n", msg); + fprintf(stderr, "Fatal error: exception %s\n", exception_name); exit(2); } - caml_raise_with_string(Field(caml_global_data, FAILURE_EXN), msg); } -CAMLexport void caml_invalid_argument (char const *msg) +static void check_global_data_param(char const *exception_name, char const *msg) { if (caml_global_data == 0) { - fprintf(stderr, "Fatal error: exception Invalid_argument(\"%s\")\n", msg); + fprintf(stderr, "Fatal error: exception %s(\"%s\")\n", exception_name, msg); exit(2); } - caml_raise_with_string(Field(caml_global_data, INVALID_EXN), msg); +} + +static inline value caml_get_failwith_tag (char const *msg) +{ + check_global_data_param("Failure", msg); + return Field(caml_global_data, FAILURE_EXN); +} + +CAMLexport void caml_failwith (char const *msg) +{ + caml_raise_with_string(caml_get_failwith_tag(msg), msg); +} + +CAMLexport void caml_failwith_value (value msg) +{ + CAMLparam1(msg); + value tag = caml_get_failwith_tag(String_val(msg)); + caml_raise_with_arg(tag, msg); + CAMLnoreturn; +} + +static inline value caml_get_invalid_argument_tag (char const *msg) +{ + check_global_data_param("Invalid_argument", msg); + return Field(caml_global_data, INVALID_EXN); +} + +CAMLexport void caml_invalid_argument (char const *msg) +{ + caml_raise_with_string(caml_get_invalid_argument_tag(msg), msg); +} + +CAMLexport void caml_invalid_argument_value (value msg) +{ + CAMLparam1(msg); + value tag = caml_get_invalid_argument_tag(String_val(msg)); + caml_raise_with_arg(tag, msg); + CAMLnoreturn; } CAMLexport void caml_array_bound_error(void) @@ -109,40 +152,52 @@ CAMLexport void caml_array_bound_error(void) CAMLexport void caml_raise_out_of_memory(void) { + check_global_data("Out_of_memory"); caml_raise_constant(Field(caml_global_data, OUT_OF_MEMORY_EXN)); } CAMLexport void caml_raise_stack_overflow(void) { + check_global_data("Stack_overflow"); caml_raise_constant(Field(caml_global_data, STACK_OVERFLOW_EXN)); } CAMLexport void caml_raise_sys_error(value msg) { + check_global_data_param("Sys_error", String_val(msg)); caml_raise_with_arg(Field(caml_global_data, SYS_ERROR_EXN), msg); } CAMLexport void caml_raise_end_of_file(void) { + check_global_data("End_of_file"); caml_raise_constant(Field(caml_global_data, END_OF_FILE_EXN)); } CAMLexport void caml_raise_zero_divide(void) { + check_global_data("Division_by_zero"); caml_raise_constant(Field(caml_global_data, ZERO_DIVIDE_EXN)); } CAMLexport void caml_raise_not_found(void) { + check_global_data("Not_found"); caml_raise_constant(Field(caml_global_data, NOT_FOUND_EXN)); } CAMLexport void caml_raise_sys_blocked_io(void) { + check_global_data("Sys_blocked_io"); caml_raise_constant(Field(caml_global_data, SYS_BLOCKED_IO)); } int caml_is_special_exception(value exn) { + /* this function is only used in caml_format_exception to produce + a more readable textual representation of some exceptions. It is + better to fall back to the general, less readable representation + than to abort with a fatal error as above. */ + if (caml_global_data == 0) return 0; return exn == Field(caml_global_data, MATCH_FAILURE_EXN) || exn == Field(caml_global_data, ASSERT_FAILURE_EXN) || exn == Field(caml_global_data, UNDEFINED_RECURSIVE_MODULE_EXN); diff --git a/byterun/finalise.c b/byterun/finalise.c index 91088cf1..d5f1d4ef 100644 --- a/byterun/finalise.c +++ b/byterun/finalise.c @@ -26,7 +26,7 @@ #include "caml/roots.h" #include "caml/signals.h" #if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "../asmrun/spacetime.h" +#include "caml/spacetime.h" #endif struct final { diff --git a/byterun/fix_code.c b/byterun/fix_code.c index b55d8ffb..09581cfa 100644 --- a/byterun/fix_code.c +++ b/byterun/fix_code.c @@ -21,6 +21,8 @@ #ifdef HAS_UNISTD #include +#else +#include #endif #include "caml/debugger.h" diff --git a/byterun/gc_ctrl.c b/byterun/gc_ctrl.c index 4e3f833c..bfc170a3 100644 --- a/byterun/gc_ctrl.c +++ b/byterun/gc_ctrl.c @@ -635,14 +635,14 @@ CAMLprim value caml_runtime_parameters (value unit) { CAMLassert (unit == Val_unit); return caml_alloc_sprintf - ("a=%d,b=%s,H=%lu,i=%lu,l=%lu,o=%lu,O=%lu,p=%d,s=%lu,t=%d,v=%lu,w=%d,W=%lu", - /* a */ caml_allocation_policy, + ("a=%d,b=%d,H=%lu,i=%lu,l=%lu,o=%lu,O=%lu,p=%d,s=%lu,t=%lu,v=%lu,w=%d,W=%lu", + /* a */ (int) caml_allocation_policy, /* b */ caml_backtrace_active, /* h */ /* missing */ /* FIXME add when changed to min_heap_size */ /* H */ caml_use_huge_pages, /* i */ caml_major_heap_increment, #ifdef NATIVE_CODE - /* l */ 0, + /* l */ 0UL, #else /* l */ caml_max_stack_size, #endif diff --git a/byterun/ints.c b/byterun/ints.c index c49f42f0..16326395 100644 --- a/byterun/ints.c +++ b/byterun/ints.c @@ -501,13 +501,6 @@ value caml_int64_direct_bswap(value v) { return caml_swap64(v); } #endif -/* Microsoft introduced the LL integer literal suffix in Visual C++ .NET 2003 */ -#if defined(_MSC_VER) && _MSC_VER < 1400 -#define INT64_LITERAL(s) s ## i64 -#else -#define INT64_LITERAL(s) s ## LL -#endif - CAMLprim value caml_int64_bswap(value v) { int64_t x = Int64_val(v); diff --git a/byterun/memory.c b/byterun/memory.c index 038eaa56..77d1b9e1 100644 --- a/byterun/memory.c +++ b/byterun/memory.c @@ -534,8 +534,10 @@ CAMLexport value caml_alloc_shr_no_raise (mlsize_t wosize, tag_t tag) return caml_alloc_shr_aux(wosize, tag, 0, 0); } -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "spacetime.h" +#ifdef WITH_PROFINFO + +/* Use this to debug problems with macros... */ +#define NO_PROFINFO 0xff CAMLexport value caml_alloc_shr_with_profinfo (mlsize_t wosize, tag_t tag, intnat profinfo) @@ -549,6 +551,13 @@ CAMLexport value caml_alloc_shr_preserving_profinfo (mlsize_t wosize, return caml_alloc_shr_with_profinfo (wosize, tag, Profinfo_hd(old_header)); } +#else +#define NO_PROFINFO 0 +#endif /* WITH_PROFINFO */ + +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) +#include "caml/spacetime.h" + CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) { return caml_alloc_shr_with_profinfo (wosize, tag, @@ -557,7 +566,7 @@ CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) #else CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) { - return caml_alloc_shr_aux (wosize, tag, 1, 0); + return caml_alloc_shr_aux (wosize, tag, 1, NO_PROFINFO); } #endif @@ -621,9 +630,9 @@ CAMLexport void caml_adjust_gc_speed (mlsize_t res, mlsize_t max) /* PR#6084 workaround: define it as a weak symbol */ CAMLexport CAMLweakdef void caml_initialize (value *fp, value val) { - CAMLassert(Is_in_heap(fp)); + CAMLassert(Is_in_heap_or_young(fp)); *fp = val; - if (Is_block (val) && Is_young (val)) { + if (!Is_young((value)fp) && Is_block (val) && Is_young (val)) { add_to_ref_table (&caml_ref_table, fp); } } diff --git a/byterun/minor_gc.c b/byterun/minor_gc.c index 2596e7a5..5c971d01 100644 --- a/byterun/minor_gc.c +++ b/byterun/minor_gc.c @@ -85,8 +85,8 @@ static void alloc_generic_table (struct generic_table *tbl, asize_t sz, tbl->size = sz; tbl->reserve = rsv; - new_table = (void *) caml_stat_alloc ((tbl->size + tbl->reserve) - * element_size); + new_table = (void *) malloc((tbl->size + tbl->reserve) * element_size); + if (new_table == NULL) caml_fatal_error ("Fatal error: not enough memory\n"); if (tbl->base != NULL) caml_stat_free (tbl->base); tbl->base = new_table; tbl->ptr = tbl->base; diff --git a/byterun/misc.c b/byterun/misc.c index 447b933f..9d33ac11 100644 --- a/byterun/misc.c +++ b/byterun/misc.c @@ -21,6 +21,7 @@ #include "caml/config.h" #include "caml/misc.h" #include "caml/memory.h" +#include "caml/osdeps.h" #include "caml/version.h" caml_timing_hook caml_major_slice_begin_hook = NULL; @@ -37,7 +38,7 @@ int caml_failed_assert (char * expr, char * file, int line) fprintf (stderr, "file %s; line %d ### Assertion failed: %s\n", file, line, expr); fflush (stderr); - exit (100); + abort(); } void caml_set_fields (value v, unsigned long start, unsigned long filler) @@ -228,10 +229,10 @@ void CAML_INSTR_INIT (void) char *s; CAML_INSTR_STARTTIME = 0; - s = getenv ("OCAML_INSTR_START"); + s = caml_secure_getenv ("OCAML_INSTR_START"); if (s != NULL) CAML_INSTR_STARTTIME = atol (s); CAML_INSTR_STOPTIME = LONG_MAX; - s = getenv ("OCAML_INSTR_STOP"); + s = caml_secure_getenv ("OCAML_INSTR_STOP"); if (s != NULL) CAML_INSTR_STOPTIME = atol (s); } @@ -242,7 +243,7 @@ void CAML_INSTR_ATEXIT (void) FILE *f = NULL; char *fname; - fname = getenv ("OCAML_INSTR_FILE"); + fname = caml_secure_getenv ("OCAML_INSTR_FILE"); if (fname != NULL){ char *mode = "a"; char buf [1000]; diff --git a/byterun/obj.c b/byterun/obj.c index 861f5c1e..b0f764fd 100644 --- a/byterun/obj.c +++ b/byterun/obj.c @@ -28,7 +28,7 @@ #include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/prims.h" -#include "spacetime.h" +#include "caml/spacetime.h" /* [size] is a value encoding a number of bytes */ CAMLprim value caml_static_alloc(value size) diff --git a/byterun/printexc.c b/byterun/printexc.c index 971f1724..cb32e61b 100644 --- a/byterun/printexc.c +++ b/byterun/printexc.c @@ -131,6 +131,8 @@ static void default_fatal_uncaught_exception(value exn) caml_print_exception_backtrace(); } +int caml_abort_on_uncaught_exn = 0; /* see afl.c */ + void caml_fatal_uncaught_exception(value exn) { value *handle_uncaught_exception; @@ -143,6 +145,10 @@ void caml_fatal_uncaught_exception(value exn) else default_fatal_uncaught_exception(exn); /* Terminate the process */ - CAML_SYS_EXIT(2); - exit(2); /* Second exit needed for the Noreturn flag */ + if (caml_abort_on_uncaught_exn) { + abort(); + } else { + CAML_SYS_EXIT(2); + exit(2); /* Second exit needed for the Noreturn flag */ + } } diff --git a/byterun/signals.c b/byterun/signals.c index 4763f7a9..6f1811f2 100644 --- a/byterun/signals.c +++ b/byterun/signals.c @@ -32,7 +32,7 @@ #include "caml/sys.h" #if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "../asmrun/spacetime.h" +#include "caml/spacetime.h" #endif #ifndef NSIG diff --git a/byterun/spacetime.h b/byterun/spacetime.h deleted file mode 100644 index ffb006bf..00000000 --- a/byterun/spacetime.h +++ /dev/null @@ -1,21 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Mark Shinwell and Leo White, Jane Street Europe */ -/* */ -/* Copyright 2016, Jane Street Group, LLC */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_SPACETIME_H -#define CAML_SPACETIME_H - -#define Get_my_profinfo_with_cached_backtrace(profinfo, size) \ - profinfo = (uintnat) 0; - -#endif diff --git a/byterun/startup.c b/byterun/startup.c index ac19ee3f..4e5583bd 100644 --- a/byterun/startup.c +++ b/byterun/startup.c @@ -97,11 +97,11 @@ int caml_attempt_open(char **name, struct exec_trailer *trail, char buf [2]; truename = caml_search_exe_in_path(*name); - *name = truename; caml_gc_message(0x100, "Opening bytecode executable %s\n", (uintnat) truename); fd = open(truename, O_RDONLY | O_BINARY); if (fd == -1) { + caml_stat_free(truename); caml_gc_message(0x100, "Cannot open file\n", 0); return FILE_NOT_FOUND; } @@ -109,6 +109,7 @@ int caml_attempt_open(char **name, struct exec_trailer *trail, err = read (fd, buf, 2); if (err < 2 || (buf [0] == '#' && buf [1] == '!')) { close(fd); + caml_stat_free(truename); caml_gc_message(0x100, "Rejected #! script\n", 0); return BAD_BYTECODE; } @@ -116,9 +117,11 @@ int caml_attempt_open(char **name, struct exec_trailer *trail, err = read_trailer(fd, trail); if (err != 0) { close(fd); + caml_stat_free(truename); caml_gc_message(0x100, "Not a bytecode executable\n", 0); return err; } + *name = truename; return fd; } @@ -279,8 +282,7 @@ CAMLexport void caml_main(char **argv) struct channel * chan; value res; char * shared_lib_path, * shared_libs, * req_prims; - char * exe_name; - static char proc_self_exe[256]; + char * exe_name, * proc_self_exe; ensure_spacetime_dot_o_is_included++; @@ -308,10 +310,13 @@ CAMLexport void caml_main(char **argv) exe_name = argv[0]; fd = caml_attempt_open(&exe_name, &trail, 0); - /* Should we really do that at all? The current executable is ocamlrun - itself, it's never a bytecode program. */ - if (fd < 0 - && caml_executable_name(proc_self_exe, sizeof(proc_self_exe)) == 0) { + /* Little grasshopper wonders why we do that at all, since + "The current executable is ocamlrun itself, it's never a bytecode + program". Little grasshopper "ocamlc -custom" in mind should keep. + With -custom, we have an executable that is ocamlrun itself + concatenated with the bytecode. So, if the attempt with argv[0] + failed, it is worth trying again with executable_name. */ + if (fd < 0 && (proc_self_exe = caml_executable_name()) != NULL) { exe_name = proc_self_exe; fd = caml_attempt_open(&exe_name, &trail, 0); } @@ -372,7 +377,7 @@ CAMLexport void caml_main(char **argv) caml_sys_init(exe_name, argv + pos); #ifdef _WIN32 /* Start a thread to handle signals */ - if (getenv("CAMLSIGPIPE")) + if (caml_secure_getenv("CAMLSIGPIPE")) _beginthread(caml_signal_thread, 4096, NULL); #endif /* Execute the program */ @@ -391,16 +396,14 @@ CAMLexport void caml_main(char **argv) /* Main entry point when code is linked in as initialized data */ -CAMLexport void caml_startup_code( +CAMLexport value caml_startup_code_exn( code_t code, asize_t code_size, char *data, asize_t data_size, char *section_table, asize_t section_table_size, char **argv) { - value res; char * cds_file; char * exe_name; - static char proc_self_exe[256]; caml_init_ieee_floats(); #if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L @@ -410,14 +413,13 @@ CAMLexport void caml_startup_code( #ifdef DEBUG caml_verb_gc = 63; #endif - cds_file = getenv("CAML_DEBUG_FILE"); + cds_file = caml_secure_getenv("CAML_DEBUG_FILE"); if (cds_file != NULL) { caml_cds_file = caml_strdup(cds_file); } caml_parse_ocamlrunparam(); - exe_name = argv[0]; - if (caml_executable_name(proc_self_exe, sizeof(proc_self_exe)) == 0) - exe_name = proc_self_exe; + exe_name = caml_executable_name(); + if (exe_name == NULL) exe_name = caml_search_exe_in_path(argv[0]); caml_external_raise = NULL; /* Initialize the abstract machine */ caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz, @@ -458,7 +460,20 @@ CAMLexport void caml_startup_code( caml_sys_init(exe_name, argv); /* Execute the program */ caml_debugger(PROGRAM_START); - res = caml_interprete(caml_start_code, caml_code_size); + return caml_interprete(caml_start_code, caml_code_size); +} + +CAMLexport void caml_startup_code( + code_t code, asize_t code_size, + char *data, asize_t data_size, + char *section_table, asize_t section_table_size, + char **argv) +{ + value res; + + res = caml_startup_code_exn(code, code_size, data, data_size, + section_table, section_table_size, + argv); if (Is_exception_result(res)) { caml_exn_bucket = Extract_exception(res); if (caml_debugger_in_use) { diff --git a/byterun/startup_aux.c b/byterun/startup_aux.c index 109f71c3..721da615 100644 --- a/byterun/startup_aux.c +++ b/byterun/startup_aux.c @@ -21,6 +21,7 @@ #include #include "caml/backtrace.h" #include "caml/memory.h" +#include "caml/osdeps.h" #include "caml/startup_aux.h" @@ -73,10 +74,10 @@ static void scanmult (char *opt, uintnat *var) void caml_parse_ocamlrunparam(void) { - char *opt = getenv ("OCAMLRUNPARAM"); + char *opt = caml_secure_getenv ("OCAMLRUNPARAM"); uintnat p; - if (opt == NULL) opt = getenv ("CAMLRUNPARAM"); + if (opt == NULL) opt = caml_secure_getenv ("CAMLRUNPARAM"); if (opt != NULL){ while (*opt != '\0'){ diff --git a/byterun/sys.c b/byterun/sys.c index 78ec5fe7..3706e900 100644 --- a/byterun/sys.c +++ b/byterun/sys.c @@ -26,7 +26,7 @@ #include #include #include -#if _WIN32 +#ifdef _WIN32 #include /* for isatty */ #else #include @@ -314,7 +314,7 @@ CAMLprim value caml_sys_getcwd(value unit) return caml_copy_string(buff); } -CAMLprim value caml_sys_getenv(value var) +CAMLprim value caml_sys_unsafe_getenv(value var) { char * res; @@ -324,6 +324,16 @@ CAMLprim value caml_sys_getenv(value var) return caml_copy_string(res); } +CAMLprim value caml_sys_getenv(value var) +{ + char * res; + + if (! caml_string_is_c_safe(var)) caml_raise_not_found(); + res = caml_secure_getenv(String_val(var)); + if (res == 0) caml_raise_not_found(); + return caml_copy_string(res); +} + char * caml_exe_name; char ** caml_main_argv; @@ -382,14 +392,23 @@ CAMLprim value caml_sys_system_command(value command) CAMLreturn (Val_int(retcode)); } -double caml_sys_time_unboxed(value unit) +double caml_sys_time_include_children_unboxed(value include_children) { #ifdef HAS_GETRUSAGE struct rusage ru; + double acc = 0.; getrusage (RUSAGE_SELF, &ru); - return ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 + acc += ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6; + + if (Bool_val(include_children)) { + getrusage (RUSAGE_CHILDREN, &ru); + acc += ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 + + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6; + } + + return acc; #else #ifdef HAS_TIMES #ifndef CLK_TCK @@ -400,15 +419,30 @@ double caml_sys_time_unboxed(value unit) #endif #endif struct tms t; + clock_t acc = 0; times(&t); - return (double)(t.tms_utime + t.tms_stime) / CLK_TCK; + acc += t.tms_utime + t.tms_stime; + if (Bool_val(include_children)) { + acc += t.tms_cutime + t.tms_cstime; + } + return (double)acc / CLK_TCK; #else - /* clock() is standard ANSI C */ + /* clock() is standard ANSI C. We have no way of getting + subprocess times in this branch. */ return (double)clock() / CLOCKS_PER_SEC; #endif #endif } +CAMLprim value caml_sys_time_include_children(value include_children) +{ + return caml_copy_double(caml_sys_time_include_children_unboxed(include_children)); +} + +double caml_sys_time_unboxed(value unit) { + return caml_sys_time_include_children_unboxed(Val_false); +} + CAMLprim value caml_sys_time(value unit) { return caml_copy_double(caml_sys_time_unboxed(unit)); @@ -602,7 +636,7 @@ void caml_load_plugin(char *plugin) void caml_cplugins_load(char *env_variable) { - char *plugins = getenv(env_variable); + char *plugins = caml_secure_getenv(env_variable); if(plugins != NULL){ char* curs = plugins; while(*curs != 0){ diff --git a/byterun/unix.c b/byterun/unix.c index 150af2b2..a5c5ed45 100644 --- a/byterun/unix.c +++ b/byterun/unix.c @@ -19,6 +19,7 @@ #define _GNU_SOURCE /* Helps finding RTLD_DEFAULT in glibc */ + /* also secure_getenv */ #include #include @@ -43,6 +44,9 @@ #else #include #endif +#ifdef __APPLE__ +#include +#endif #include "caml/fail.h" #include "caml/memory.h" #include "caml/misc.h" @@ -356,28 +360,69 @@ CAMLexport int caml_read_directory(char * dirname, struct ext_table * contents) /* Recover executable name from /proc/self/exe if possible */ -#ifdef __linux__ - -int caml_executable_name(char * name, int name_len) +char * caml_executable_name(void) { - int retcode; +#if defined(__linux__) + int namelen, retcode; + char * name; struct stat st; - retcode = readlink("/proc/self/exe", name, name_len); - if (retcode == -1 || retcode >= name_len) return -1; + /* lstat("/proc/self/exe") returns st_size == 0 so we cannot use it + to determine the size of the buffer. Instead, we guess and adjust. */ + namelen = 256; + while (1) { + name = caml_stat_alloc(namelen + 1); + retcode = readlink("/proc/self/exe", name, namelen); + if (retcode == -1) { caml_stat_free(name); return NULL; } + if (retcode <= namelen) break; + caml_stat_free(name); + if (namelen >= 1024*1024) return NULL; /* avoid runaway and overflow */ + namelen *= 2; + } + /* readlink() does not zero-terminate its result */ name[retcode] = 0; /* Make sure that the contents of /proc/self/exe is a regular file. (Old Linux kernels return an inode number instead.) */ - if (stat(name, &st) != 0) return -1; - if (! S_ISREG(st.st_mode)) return -1; - return 0; -} - + if (stat(name, &st) == -1 || ! S_ISREG(st.st_mode)) { + caml_stat_free(name); return NULL; + } + return name; + +#elif defined(__APPLE__) + unsigned int namelen; + char * name; + + namelen = 256; + name = caml_stat_alloc(namelen); + if (_NSGetExecutablePath(name, &namelen) == 0) return name; + caml_stat_free(name); + /* Buffer is too small, but namelen now contains the size needed */ + name = caml_stat_alloc(namelen); + if (_NSGetExecutablePath(name, &namelen) == 0) return name; + caml_stat_free(name); + return NULL; + #else + return NULL; -int caml_executable_name(char * name, int name_len) -{ - return -1; +#endif } +char *caml_secure_getenv (char const *var) +{ +#ifdef HAS_SECURE_GETENV + return secure_getenv (var); +#elif defined (HAS___SECURE_GETENV) + return __secure_getenv (var); +#elif defined(HAS_ISSETUGID) + if (!issetugid ()) + return CAML_SYS_GETENV (var); + else + return NULL; +#else + if (geteuid () == getuid () && getegid () == getgid ()) + return CAML_SYS_GETENV (var); + else + return NULL; #endif +} diff --git a/byterun/weak.c b/byterun/weak.c index 308d153c..2b81fa01 100644 --- a/byterun/weak.c +++ b/byterun/weak.c @@ -285,7 +285,8 @@ CAMLprim value caml_ephe_get_key_copy (value ar, value n) if (is_ephe_key_none(ar, offset)) CAMLreturn (None_val); v = Field (ar, offset); - if (Is_block (v) && Is_in_heap_or_young(v)) { + /** Don't copy custom_block #7279 */ + if (Is_block (v) && Is_in_heap_or_young(v) && Tag_val(v) != Custom_tag ) { elt = caml_alloc (Wosize_val (v), Tag_val (v)); /* The GC may erase or move v during this call to caml_alloc. */ v = Field (ar, offset); @@ -303,6 +304,9 @@ CAMLprim value caml_ephe_get_key_copy (value ar, value n) memmove (Bp_val (elt), Bp_val (v), Bosize_val (v)); } }else{ + if ( caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(v) ){ + caml_darken (v, NULL); + }; elt = v; } res = caml_alloc_small (1, Some_tag); @@ -326,7 +330,8 @@ CAMLprim value caml_ephe_get_data_copy (value ar) v = Field (ar, offset); if (caml_gc_phase == Phase_clean) caml_ephe_clean(ar); if (v == caml_ephe_none) CAMLreturn (None_val); - if (Is_block (v) && Is_in_heap_or_young(v)) { + /** Don't copy custom_block #7279 */ + if (Is_block (v) && Is_in_heap_or_young(v) && Tag_val(v) != Custom_tag ) { elt = caml_alloc (Wosize_val (v), Tag_val (v)); /* The GC may erase or move v during this call to caml_alloc. */ v = Field (ar, offset); @@ -345,6 +350,9 @@ CAMLprim value caml_ephe_get_data_copy (value ar) memmove (Bp_val (elt), Bp_val (v), Bosize_val (v)); } }else{ + if ( caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(v) ){ + caml_darken (v, NULL); + }; elt = v; } res = caml_alloc_small (1, Some_tag); diff --git a/byterun/win32.c b/byterun/win32.c index 59d13000..a69dd5fb 100644 --- a/byterun/win32.c +++ b/byterun/win32.c @@ -364,10 +364,15 @@ static void expand_pattern(char * pat) return; } prefix = caml_strdup(pat); + /* We need to stop at the first directory or drive boundary, because the + * _findata_t structure contains the filename, not the leading directory. */ for (i = strlen(prefix); i > 0; i--) { char c = prefix[i - 1]; if (c == '\\' || c == '/' || c == ':') { prefix[i] = 0; break; } } + /* No separator was found, it's a filename pattern without a leading directory. */ + if (i == 0) + prefix[0] = 0; do { name = caml_strconcat(2, prefix, ffblk.name); store_argument(name); @@ -437,7 +442,8 @@ void caml_signal_thread(void * lpParam) char *endptr; HANDLE h; /* Get an hexa-code raw handle through the environment */ - h = (HANDLE) (uintptr_t) strtol(getenv("CAMLSIGPIPE"), &endptr, 16); + h = (HANDLE) (uintptr_t) + strtol(caml_secure_getenv("CAMLSIGPIPE"), &endptr, 16); while (1) { DWORD numread; BOOL ret; @@ -617,13 +623,22 @@ void caml_install_invalid_parameter_handler() /* Recover executable name */ -int caml_executable_name(char * name, int name_len) +char * caml_executable_name(void) { - int retcode; - - int ret = GetModuleFileName(NULL, name, name_len); - if (0 == ret || ret >= name_len) return -1; - return 0; + char * name; + DWORD namelen, ret; + + namelen = 256; + while (1) { + name = caml_stat_alloc(namelen); + ret = GetModuleFileName(NULL, name, namelen); + if (ret == 0) { caml_stat_free(name); return NULL; } + if (ret < namelen) break; + caml_stat_free(name); + if (namelen >= 1024*1024) return NULL; /* avoid runaway and overflow */ + namelen *= 2; + } + return name; } /* snprintf emulation */ @@ -674,3 +689,9 @@ int caml_snprintf(char * buf, size_t size, const char * format, ...) return len; } #endif + +char *caml_secure_getenv (char const *var) +{ + /* Win32 doesn't have a notion of setuid bit, so getenv is safe. */ + return CAML_SYS_GETENV (var); +} diff --git a/config/Makefile-templ b/config/Makefile-templ index 1cd797eb..8b530df2 100644 --- a/config/Makefile-templ +++ b/config/Makefile-templ @@ -166,17 +166,14 @@ RANLIBCMD=ranlib ### Whether profiling with gprof is supported # If yes: (e.g. x86/Linux, Sparc/Solaris): -#PROFILING=prof +#PROFILING=true # If no: -#PROFILING=noprof +#PROFILING=false ### Option to give to the C compiler for profiling #CC_PROFILE=-pg #CC_PROFILE=-xpg -### How to perform a partial link -PARTIALLD=ld -r $(NATIVECCLINKOPTS) - ############# Configuration for the contributed libraries ### Which libraries to compile and install diff --git a/config/Makefile.mingw b/config/Makefile.mingw index f2d04116..da1346d3 100644 --- a/config/Makefile.mingw +++ b/config/Makefile.mingw @@ -28,6 +28,9 @@ WITH_OCAMLDOC=ocamldoc ### Where to install the binaries BINDIR=$(PREFIX)/bin +### Standard runtime system +BYTERUN=ocamlrun + ### Where to install the standard library LIBDIR=$(PREFIX)/lib @@ -63,42 +66,49 @@ EXT_ASM=.$(S) MANEXT=1 HASHBANGSCRIPTS=false PTHREAD_LINK= +PTHREAD_CAML_LINK= X11_INCLUDES= X11_LINK= BYTECCRPATH= SUPPORTS_SHARED_LIBRARIES=true -SHAREDCCCOMPOPTS=-O +SHAREDCCCOMPOPTS= MKSHAREDLIBRPATH= NATIVECCPROFOPTS= NATIVECCRPATH= ASM=$(TOOLPREF)as ASPP=$(TOOLPREF)gcc -c ASPPPROFFLAGS= -PROFILING=noprof +PROFILING=false DYNLINKOPTS= CC_PROFILE= SYSTHREAD_SUPPORT=true EXTRALIBS= NATDYNLINK=true +NATDYNLINKOPTS= CMXS=cmxs -RUNTIMED=noruntimed +RUNTIMED=false ASM_CFI_SUPPORTED=false +WITH_FRAME_POINTERS=false +UNIX_OR_WIN32=win32 UNIXLIB=win32unix GRAPHLIB=win32graph FLAMBDA=false WITH_SPACETIME=false +WITH_PROFINFO=false LIBUNWIND_AVAILABLE=false LIBUNWIND_LINK_FLAGS= PROFINFO_WIDTH=26 SAFE_STRING=false +AFL_INSTRUMENT=false ########## Configuration for the bytecode compiler ### Which C compiler to use for the bytecode interpreter. -BYTECC=$(TOOLPREF)gcc +BYTECC=$(TOOLPREF)gcc -O -mms-bitfields +BYTECODE_C_COMPILER=$(BYTECC) ### Additional compile-time options for $(BYTECC). (For static linking.) -BYTECCCOMPOPTS=-O -mms-bitfields -Wall -Wno-unused +BYTECCCOMPOPTS=-DCAML_NAME_SPACE -Wall -Wno-unused ### Additional compile-time options for $(BYTECC). (For debug version.) BYTECCDBGCOMPOPTS=-g @@ -109,9 +119,6 @@ NAME_OBJ_FLAG=-o ### Additional link-time options for $(BYTECC). (For static linking.) BYTECCLINKOPTS= -### Additional compile-time options for $(BYTECC). (For building a DLL.) -DLLCCCOMPOPTS=-O -mms-bitfields -Wall -Wno-unused -DCAML_DLL - ### Libraries needed BYTECCLIBS=-lws2_32 NATIVECCLIBS=-lws2_32 @@ -123,7 +130,7 @@ CPP=$(BYTECC) -E FLEXLINK_CMD=flexlink FLEXDLL_CHAIN=mingw # FLEXLINK_FLAGS must be safe to insert in an OCaml string -# (see ocamlmklibconfig.ml in tools/Makefile.nt) +# (see ocamlmklibconfig.ml in tools/Makefile) FLEXLINK_FLAGS=-chain $(FLEXDLL_CHAIN) -stack 16777216 -link -static-libgcc FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS) FLEXDIR:=$(shell $(FLEXLINK) -where 2>/dev/null) @@ -137,6 +144,7 @@ endif # or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) MKEXE=$(FLEXLINK) -exe +MKEXEDEBUGFLAG=-g MKMAINDLL=$(FLEXLINK) -maindll ### Native command to build ocamlrun.exe without flexlink @@ -172,9 +180,10 @@ SYSTEM=mingw ### Which C compiler to use for the native-code compiler. NATIVECC=$(BYTECC) +NATIVE_C_COMPILER=$(NATIVECC) ### Additional compile-time options for $(NATIVECC). -NATIVECCCOMPOPTS=-O -mms-bitfields -Wall -Wno-unused +NATIVECCCOMPOPTS=-DCAML_NAME_SPACE -Wall -Wno-unused ### Additional link-time options for $(NATIVECC) NATIVECCLINKOPTS= @@ -190,16 +199,11 @@ OTHERLIBRARIES=win32unix str num win32graph dynlink bigarray systhreads BNG_ARCH=ia32 BNG_ASM_LEVEL=1 -############# Aliases for common commands - -MAKEREC=$(MAKE) -f Makefile.nt -MAKECMD=$(MAKE) - ############# for the testsuite makefiles #ml let topdir = "" and wintopdir = "";; OTOPDIR=$(WINTOPDIR) CTOPDIR=$(TOPDIR) CYGPATH=cygpath -m -DIFF=diff -q --strip-trailing-cr +DIFF=/usr/bin/diff -q --strip-trailing-cr SET_LD_PATH=PATH="$(PATH):$(LD_PATH)" MAX_TESTSUITE_DIR_RETRIES=1 diff --git a/config/Makefile.mingw64 b/config/Makefile.mingw64 index 14c575b3..286147b1 100644 --- a/config/Makefile.mingw64 +++ b/config/Makefile.mingw64 @@ -28,6 +28,9 @@ WITH_OCAMLDOC=ocamldoc ### Where to install the binaries BINDIR=$(PREFIX)/bin +### Standard runtime system +BYTERUN=ocamlrun + ### Where to install the standard library LIBDIR=$(PREFIX)/lib @@ -63,42 +66,49 @@ EXT_ASM=.$(S) MANEXT=1 HASHBANGSCRIPTS=false PTHREAD_LINK= +PTHREAD_CAML_LINK= X11_INCLUDES= X11_LINK= BYTECCRPATH= SUPPORTS_SHARED_LIBRARIES=true -SHAREDCCCOMPOPTS=-O +SHAREDCCCOMPOPTS= MKSHAREDLIBRPATH= NATIVECCPROFOPTS= NATIVECCRPATH= ASM=$(TOOLPREF)as ASPP=$(TOOLPREF)gcc -c ASPPPROFFLAGS= -PROFILING=noprof +PROFILING=false DYNLINKOPTS= CC_PROFILE= SYSTHREAD_SUPPORT=true EXTRALIBS= NATDYNLINK=true +NATDYNLINKOPTS= CMXS=cmxs -RUNTIMED=noruntimed +RUNTIMED=false ASM_CFI_SUPPORTED=false +WITH_FRAME_POINTERS=false +UNIX_OR_WIN32=win32 UNIXLIB=win32unix GRAPHLIB=win32graph FLAMBDA=false +WITH_PROFINFO=false WITH_SPACETIME=false LIBUNWIND_AVAILABLE=false LIBUNWIND_LINK_FLAGS= PROFINFO_WIDTH=26 SAFE_STRING=false +AFL_INSTRUMENT=false ########## Configuration for the bytecode compiler ### Which C compiler to use for the bytecode interpreter. -BYTECC=$(TOOLPREF)gcc +BYTECC=$(TOOLPREF)gcc -O -mms-bitfields +BYTECODE_C_COMPILER=$(BYTECC) ### Additional compile-time options for $(BYTECC). (For static linking.) -BYTECCCOMPOPTS=-O -mms-bitfields -Wall -Wno-unused +BYTECCCOMPOPTS=-DCAML_NAME_SPACE -Wall -Wno-unused ### Additional compile-time options for $(BYTECC). (For debug version.) BYTECCDBGCOMPOPTS=-g @@ -109,9 +119,6 @@ NAME_OBJ_FLAG=-o ### Additional link-time options for $(BYTECC). (For static linking.) BYTECCLINKOPTS= -### Additional compile-time options for $(BYTECC). (For building a DLL.) -DLLCCCOMPOPTS=-O -mms-bitfields -Wall -Wno-unused -DCAML_DLL - ### Libraries needed BYTECCLIBS=-lws2_32 NATIVECCLIBS=-lws2_32 @@ -123,7 +130,7 @@ CPP=$(BYTECC) -E FLEXLINK_CMD=flexlink FLEXDLL_CHAIN=mingw64 # FLEXLINK_FLAGS must be safe to insert in an OCaml string -# (see ocamlmklibconfig.ml in tools/Makefile.nt) +# (see ocamlmklibconfig.ml in tools/Makefile) FLEXLINK_FLAGS=-chain $(FLEXDLL_CHAIN) -stack 33554432 FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS) FLEXDIR:=$(shell $(FLEXLINK) -where 2>/dev/null) @@ -137,6 +144,7 @@ endif # or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) MKEXE=$(FLEXLINK) -exe +MKEXEDEBUGFLAG=-g MKMAINDLL=$(FLEXLINK) -maindll ### Native command to build ocamlrun.exe without flexlink @@ -172,9 +180,10 @@ SYSTEM=mingw64 ### Which C compiler to use for the native-code compiler. NATIVECC=$(BYTECC) +NATIVE_C_COMPILER=$(NATIVECC) ### Additional compile-time options for $(NATIVECC). -NATIVECCCOMPOPTS=-O -mms-bitfields -Wall -Wno-unused +NATIVECCCOMPOPTS=-DCAML_NAME_SPACE -Wall -Wno-unused ### Additional link-time options for $(NATIVECC) NATIVECCLINKOPTS= @@ -190,16 +199,11 @@ OTHERLIBRARIES=win32unix str num win32graph dynlink bigarray systhreads BNG_ARCH=amd64 BNG_ASM_LEVEL=1 -############# Aliases for common commands - -MAKEREC=$(MAKE) -f Makefile.nt -MAKECMD=$(MAKE) - ############# for the testsuite makefiles #ml let topdir = "" and wintopdir = "";; OTOPDIR=$(WINTOPDIR) CTOPDIR=$(TOPDIR) CYGPATH=cygpath -m -DIFF=diff -q --strip-trailing-cr +DIFF=/usr/bin/diff -q --strip-trailing-cr SET_LD_PATH=PATH="$(PATH):$(LD_PATH)" MAX_TESTSUITE_DIR_RETRIES=1 diff --git a/config/Makefile.msvc b/config/Makefile.msvc index 5ffd6c0e..d8cd9f8a 100644 --- a/config/Makefile.msvc +++ b/config/Makefile.msvc @@ -22,6 +22,9 @@ PREFIX=C:/ocamlms ### Where to install the binaries. BINDIR=$(PREFIX)/bin +### Standard runtime system +BYTERUN=ocamlrun + ### Where to install the standard library LIBDIR=$(PREFIX)/lib @@ -58,41 +61,48 @@ EXT_ASM=.$(S) MANEXT=1 HASHBANGSCRIPTS=false PTHREAD_LINK= +PTHREAD_CAML_LINK= X11_INCLUDES= X11_LINK= BYTECCRPATH= SUPPORTS_SHARED_LIBRARIES=true -SHAREDCCCOMPOPTS=-Ox +SHAREDCCCOMPOPTS= NATIVECCPROFOPTS= NATIVECCRPATH= ASM=ml -nologo -coff -Cp -c -Fo ASPP= ASPPPROFFLAGS= -PROFILING=noprof +PROFILING=false DYNLINKOPTS= CC_PROFILE= SYSTHREAD_SUPPORT=true EXTRALIBS= CMXS=cmxs NATDYNLINK=true -RUNTIMED=noruntimed +NATDYNLINKOPTS= +RUNTIMED=false ASM_CFI_SUPPORTED=false +WITH_FRAME_POINTERS=false +UNIX_OR_WIN32=win32 UNIXLIB=win32unix GRAPHLIB=win32graph FLAMBDA=false +WITH_PROFINFO=false WITH_SPACETIME=false LIBUNWIND_AVAILABLE=false LIBUNWIND_LINK_FLAGS= PROFINFO_WIDTH=26 SAFE_STRING=false +AFL_INSTRUMENT=false ########## Configuration for the bytecode compiler ### Which C compiler to use for the bytecode interpreter. -BYTECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE +BYTECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE -O2 -Gy- -MD +BYTECODE_C_COMPILER=$(BYTECC) ### Additional compile-time options for $(BYTECC). (For static linking.) -BYTECCCOMPOPTS=-O2 -Gy- -MD +BYTECCCOMPOPTS=-DCAML_NAME_SPACE ### Additional compile-time options for $(BYTECC). (For debug version.) BYTECCDBGCOMPOPTS=-Zi @@ -103,9 +113,6 @@ NAME_OBJ_FLAG=-Fo ### Additional link-time options for $(BYTECC). (For static linking.) BYTECCLINKOPTS= -### Additional compile-time options for $(BYTECC). (For building a DLL.) -DLLCCCOMPOPTS=-O2 -Gy- -MD - ### Libraries needed BYTECCLIBS=advapi32.lib ws2_32.lib NATIVECCLIBS=advapi32.lib ws2_32.lib @@ -117,7 +124,7 @@ CPP=cl -nologo -EP FLEXLINK_CMD=flexlink FLEXDLL_CHAIN=msvc # FLEXLINK_FLAGS must be safe to insert in an OCaml string -# (see ocamlmklibconfig.ml in tools/Makefile.nt) +# (see ocamlmklibconfig.ml in tools/Makefile) FLEXLINK_FLAGS=-merge-manifest -stack 16777216 FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS) FLEXDIR:=$(shell $(FLEXLINK) -where 2>/dev/null) @@ -131,6 +138,7 @@ endif # or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) MKEXE=$(FLEXLINK) -exe +MKEXEDEBUGFLAG= MKMAINDLL=$(FLEXLINK) -maindll ### Native command to build ocamlrun.exe without flexlink @@ -169,10 +177,10 @@ MODEL=default SYSTEM=win32 ### Which C compiler to use for the native-code compiler. -NATIVECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE - +NATIVECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE -O2 -Gy- -MD +NATIVE_C_COMPILER=$(NATIVECC) ### Additional compile-time options for $(NATIVECC). -NATIVECCCOMPOPTS=-O2 -Gy- -MD +NATIVECCCOMPOPTS=-DCAML_NAME_SPACE ### Additional link-time options for $(NATIVECC) NATIVECCLINKOPTS= @@ -194,17 +202,12 @@ OTHERLIBRARIES=win32unix systhreads str num win32graph dynlink bigarray BNG_ARCH=generic BNG_ASM_LEVEL=0 -############# Aliases for common commands - -MAKEREC=$(MAKE) -f Makefile.nt -MAKECMD=$(MAKE) - ############# for the testsuite makefiles #ml let topdir = "" and wintopdir = "";; OTOPDIR=$(WINTOPDIR) CTOPDIR=$(WINTOPDIR) CYGPATH=cygpath -m -DIFF=diff -q --strip-trailing-cr +DIFF=/usr/bin/diff -q --strip-trailing-cr FIND=/usr/bin/find SORT=/usr/bin/sort SET_LD_PATH=PATH="$(PATH):$(LD_PATH)" diff --git a/config/Makefile.msvc64 b/config/Makefile.msvc64 index 720b2e14..4e2653ae 100644 --- a/config/Makefile.msvc64 +++ b/config/Makefile.msvc64 @@ -22,6 +22,9 @@ PREFIX=C:/ocamlms64 ### Where to install the binaries. BINDIR=$(PREFIX)/bin +### Standard runtime system +BYTERUN=ocamlrun + ### Where to install the standard library LIBDIR=$(PREFIX)/lib @@ -58,40 +61,47 @@ EXT_ASM=.$(S) MANEXT=1 HASHBANGSCRIPTS=false PTHREAD_LINK= +PTHREAD_CAML_LINK= X11_INCLUDES= X11_LINK= BYTECCRPATH= SUPPORTS_SHARED_LIBRARIES=true -SHAREDCCCOMPOPTS=-Ox +SHAREDCCCOMPOPTS= NATIVECCPROFOPTS= NATIVECCRPATH= ASM=ml64 -nologo -Cp -c -Fo ASPP= ASPPPROFFLAGS= -PROFILING=noprof +PROFILING=false DYNLINKOPTS= CC_PROFILE= SYSTHREAD_SUPPORT=true CMXS=cmxs NATDYNLINK=true -RUNTIMED=noruntimed +NATDYNLINKOPTS= +RUNTIMED=false ASM_CFI_SUPPORTED=false +WITH_FRAME_POINTERS=false +UNIX_OR_WIN32=win32 UNIXLIB=win32unix GRAPHLIB=win32graph FLAMBDA=false +WITH_PROFINFO=false WITH_SPACETIME=false LIBUNWIND_AVAILABLE=false LIBUNWIND_LINK_FLAGS= PROFINFO_WIDTH=26 SAFE_STRING=false +AFL_INSTRUMENT=false ########## Configuration for the bytecode compiler ### Which C compiler to use for the bytecode interpreter. -BYTECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE +BYTECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE -O2 -Gy- -MD +BYTECODE_C_COMPILER=$(BYTECC) ### Additional compile-time options for $(BYTECC). (For static linking.) -BYTECCCOMPOPTS=-O2 -Gy- -MD +BYTECCCOMPOPTS=-DCAML_NAME_SPACE ### Additional compile-time options for $(BYTECC). (For debug version.) BYTECCDBGCOMPOPTS=-Zi @@ -102,9 +112,6 @@ NAME_OBJ_FLAG=-Fo ### Additional link-time options for $(BYTECC). (For static linking.) BYTECCLINKOPTS= -### Additional compile-time options for $(BYTECC). (For building a DLL.) -DLLCCCOMPOPTS=-O2 -Gy- -MD - ### Libraries needed #EXTRALIBS=bufferoverflowu.lib # for the old PSDK compiler only EXTRALIBS= @@ -118,7 +125,7 @@ CPP=cl -nologo -EP FLEXLINK_CMD=flexlink FLEXDLL_CHAIN=msvc64 # FLEXLINK_FLAGS must be safe to insert in an OCaml string -# (see ocamlmklibconfig.ml in tools/Makefile.nt) +# (see ocamlmklibconfig.ml in tools/Makefile) FLEXLINK_FLAGS=-x64 -merge-manifest -stack 33554432 FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS) FLEXDIR:=$(shell $(FLEXLINK) -where 2>/dev/null) @@ -132,6 +139,7 @@ endif # or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) MKEXE=$(FLEXLINK) -exe +MKEXEDEBUGFLAG= MKMAINDLL=$(FLEXLINK) -maindll ### Native command to build ocamlrun.exe without flexlink @@ -171,10 +179,11 @@ MODEL=default SYSTEM=win64 ### Which C compiler to use for the native-code compiler. -NATIVECC=cl -nologo +NATIVECC=cl -nologo -O2 -Gy- -MD +NATIVE_C_COMPILER=$(NATIVECC) ### Additional compile-time options for $(NATIVECC). -NATIVECCCOMPOPTS=-O2 -Gy- -MD +NATIVECCCOMPOPTS=-DCAML_NAME_SPACE ### Additional link-time options for $(NATIVECC) NATIVECCLINKOPTS= @@ -196,17 +205,12 @@ OTHERLIBRARIES=win32unix systhreads str num win32graph dynlink bigarray BNG_ARCH=generic BNG_ASM_LEVEL=0 -############# Aliases for common commands - -MAKEREC=$(MAKE) -f Makefile.nt -MAKECMD=$(MAKE) - ############# for the testsuite makefiles #ml let topdir = "" and wintopdir = "";; OTOPDIR=$(WINTOPDIR) CTOPDIR=$(WINTOPDIR) CYGPATH=cygpath -m -DIFF=diff -q --strip-trailing-cr +DIFF=/usr/bin/diff -q --strip-trailing-cr FIND=/usr/bin/find SORT=/usr/bin/sort SET_LD_PATH=PATH="$(PATH):$(LD_PATH)" diff --git a/config/auto-aux/hashbang3 b/config/auto-aux/hashbang3 new file mode 100755 index 00000000..90002cbd --- /dev/null +++ b/config/auto-aux/hashbang3 @@ -0,0 +1,2 @@ +#! /usr/bin/env cat +exit 1 diff --git a/config/m-nt.h b/config/m-nt.h index 28a1815a..56a50feb 100644 --- a/config/m-nt.h +++ b/config/m-nt.h @@ -48,4 +48,11 @@ #undef NONSTANDARD_DIV_MOD -#define PROFINFO_WIDTH 26 +#define PROFINFO_WIDTH 0 + +/* Microsoft introduced the LL integer literal suffix in Visual C++ .NET 2003 */ +#if defined(_MSC_VER) && _MSC_VER < 1400 +#define INT64_LITERAL(s) s ## i64 +#else +#define INT64_LITERAL(s) s ## LL +#endif diff --git a/configure b/configure index f43893a4..ec5e73c5 100755 --- a/configure +++ b/configure @@ -45,7 +45,7 @@ pthread_wanted=yes dl_defs='' verbose=no with_curses=yes -debugruntime=noruntimed +debugruntime=false with_instrumented_runtime=false with_sharedlibs=yes partialld="ld -r" @@ -53,12 +53,15 @@ with_debugger=ocamldebugger with_ocamldoc=ocamldoc with_frame_pointers=false with_spacetime=false +with_profinfo=false +profinfo_width=0 no_naked_pointers=false native_compiler=true TOOLPREF="" with_cfi=true flambda=false safe_string=false +afl_instrument=false max_testsuite_dir_retries=0 with_cplugins=true with_fpic=false @@ -166,7 +169,7 @@ while : ; do -verbose|--verbose) verbose=yes;; -with-debug-runtime|--with-debug-runtime) - debugruntime=runtimed;; + debugruntime=true;; -with-instrumented-runtime|--with-instrumented-runtime) with_instrumented_runtime=true;; -no-debugger|--no-debugger) @@ -180,7 +183,17 @@ while : ; do -no-naked-pointers|--no-naked-pointers) no_naked_pointers=true;; -spacetime|--spacetime) - with_spacetime=true;; + with_spacetime=true; with_profinfo=true; profinfo_width=26;; + -reserved-header-bits|--reserved-header-bits) + with_spacetime=false; with_profinfo=true; profinfo_width=$2;shift + case $profinfo_width in + 0) with_profinfo=false;; + [0123456789]);; + 1?|2?);; + 3[012]);; + *) err "--reserved-header-bits argument must be less than 32" + esac + ;; -no-cfi|--no-cfi) with_cfi=false;; -no-native-compiler|--no-native-compiler) @@ -193,6 +206,8 @@ while : ; do with_fpic=true;; -safe-string|--safe-string) safe_string=true;; + -afl-instrument) + afl_instrument=true;; *) if echo "$1" | grep -q -e '^--\?[a-zA-Z0-9-]\+='; then err "configure expects arguments of the form '-prefix /foo/bar'," \ "not '-prefix=/foo/bar' (note the '=')." @@ -247,6 +262,9 @@ case "$bindir" in bindir="$prefix/bin";; *) echo "BINDIR=$bindir" >> Makefile;; esac + +echo 'BYTERUN=$(BINDIR)/ocamlrun' >> Makefile + case "$libdir" in "") echo 'LIBDIR=$(PREFIX)/lib/ocaml' >> Makefile libdir="$prefix/lib/ocaml";; @@ -263,11 +281,11 @@ echo "MANEXT=$manext" >> Makefile # Determine the system type if test "$host_type" = "unknown"; then - if host_type=`../gnu/config.guess`; then :; else + if host_type=`sh ../gnu/config.guess`; then :; else err "Cannot guess host type. You must specify one with the -host option." fi fi -if host=`../gnu/config.sub $host_type`; then :; else +if host=`sh ../gnu/config.sub $host_type`; then :; else err "Please specify the correct host type with the -host option" fi inf "Configuring for host $host ..." @@ -316,12 +334,32 @@ esac # Configure the bytecode compiler +# The BYTECC make variable defines which compiler and options to use +# to compile C code intended to be used by OCaml bytecode programs. +# It is used inside OCaml's build system. + +# The BYTECODE_C_COMPILER make variable says how the C compiler should be +# invoked to process a third-party C source file passed to ocamlc +# when no -cc command-line option has been specified. + +# The BYTECCCOMPOPTS make variable contains options to pass to the C +# compiler but only when compiling C files that belong to the OCaml +# distribution. +# In other words, when ocamlc is called to compile a third-party C +# source file, it will _not_ pass these options to the C compiler. + +# The SHAREDCCCOMPOPTS make variable contains options to use to compile C +# source files so that the resulting object files can then be integrated +# into shared libraries. It is passed to BYTECC for both C source files +# in the OCaml distribution and third-party C source files compiled +# with ocamlc. + bytecc="$cc" mkexe="\$(BYTECC)" mkexedebugflag="-g" bytecccompopts="" +byteccprivatecompopts="" bytecclinkopts="" -dllccompopts="" ostype="Unix" exe="" iflexdir="" @@ -346,7 +384,8 @@ esac case "$ccfamily" in clang-*) - bytecccompopts="-O2 -fno-strict-aliasing -fwrapv $gcc_warnings";; + bytecccompopts="-O2 -fno-strict-aliasing -fwrapv"; + byteccprivatecompopts="$gcc_warnings";; gcc-[012]-*) # Some versions known to miscompile OCaml, e,g, 2.7.2.1, some 2.96. # Plus: C99 support unknown. @@ -356,13 +395,21 @@ case "$ccfamily" in # Known problems with -fwrapv fixed in 4.2 only. wrn "This version of GCC is rather old. Reducing optimization level." wrn "Consider using GCC version 4.2 or above." - bytecccompopts="-std=gnu99 -O $gcc_warnings";; + bytecccompopts="-std=gnu99 -O"; + byteccprivatecompopts="$gcc_warnings";; + gcc-4-*) + bytecccompopts="-std=gnu99 -O2 -fno-strict-aliasing -fwrapv \ +-fno-builtin-memcmp"; + byteccprivatecompopts="$gcc_warnings";; gcc-*) - bytecccompopts="-std=gnu99 -O2 -fno-strict-aliasing -fwrapv $gcc_warnings";; + bytecccompopts="-O2 -fno-strict-aliasing -fwrapv"; + byteccprivatecompopts="$gcc_warnings";; *) bytecccompopts="-O";; esac +byteccprivatecompopts="-DCAML_NAME_SPACE $byteccprivatecompopts" + # Adjust according to target case "$bytecc,$target" in @@ -418,7 +465,6 @@ case "$bytecc,$target" in *) err "unknown cygwin variant";; esac bytecccompopts="$bytecccompopts -U_WIN32" - dllccompopts="-U_WIN32 -DCAML_DLL" if test $with_sharedlibs = yes; then flexlink="flexlink -chain $flavor -merge-manifest -stack 16777216" flexdir=`$flexlink -where | tr -d '\015'` @@ -475,7 +521,7 @@ export cc cclibs verbose # Check C compiler. -cc="$bytecc $bytecccompopts $bytecclinkopts" sh ./runtest ansi.c +cc="$bytecc $bytecccompopts $byteccprivatecompopts $bytecclinkopts" sh ./runtest ansi.c case $? in 0) inf "The C compiler is ISO C99 compliant." ;; 1) wrn "The C compiler is ANSI / ISO C90 compliant, but not ISO C99" \ @@ -591,6 +637,7 @@ echo "#define SIZEOF_LONG $2" >> m.h echo "#define SIZEOF_PTR $3" >> m.h echo "#define SIZEOF_SHORT $4" >> m.h echo "#define SIZEOF_LONGLONG $5" >> m.h +echo "#define INT64_LITERAL(s) s ## LL" >> m.h # Determine endianness @@ -697,15 +744,6 @@ if test $with_sharedlibs = "yes"; then mksharedlib="$flexlink" mkmaindll="$flexlink -maindll" shared_libraries_supported=true;; - *-*-linux-gnu|*-*-linux|*-*-freebsd[3-9]*|*-*-freebsd[1-9][0-9]*\ - |*-*-openbsd*|*-*-netbsd*|*-*-dragonfly*|*-*-gnu*|*-*-haiku*) - sharedcccompopts="-fPIC" - mksharedlib="$bytecc -shared" - bytecclinkopts="$bytecclinkopts -Wl,-E" - byteccrpath="-Wl,-rpath," - mksharedlibrpath="-Wl,-rpath," - natdynlinkopts="-Wl,-E" - shared_libraries_supported=true;; alpha*-*-osf*) case "$bytecc" in *gcc*) @@ -765,17 +803,14 @@ if test $with_sharedlibs = "yes"; then bytecccompopts="$dl_defs $bytecccompopts" dl_needs_underscore=false shared_libraries_supported=true;; - m88k-*-openbsd*) - shared_libraries_supported=false;; - vax-*-openbsd*) - shared_libraries_supported=false;; - *-*-openbsd*) + *-*-linux-gnu|*-*-linux|*-*-freebsd[3-9]*|*-*-freebsd[1-9][0-9]*\ + |*-*-openbsd*|*-*-netbsd*|*-*-dragonfly*|*-*-gnu*|*-*-haiku*) sharedcccompopts="-fPIC" mksharedlib="$bytecc -shared" bytecclinkopts="$bytecclinkopts -Wl,-E" - natdynlinkopts="-Wl,-E" byteccrpath="-Wl,-rpath," mksharedlibrpath="-Wl,-rpath," + natdynlinkopts="-Wl,-E" shared_libraries_supported=true;; esac fi @@ -831,6 +866,20 @@ fi # Configure the native-code compiler +# The NATIVECC make variable defines which compiler and options to use +# to compile C code intended to be used by OCaml native programs. +# It is used inside OCaml's build system. + +# The NATIVE_C_COMPILER make variable says how the C compiler should be +# invoked to process a third-party C source file passed to ocamlopt +# when no -cc command-line option has been specified. + +# The NATIVECCCOMPOPTS make variable contains options to pass to the C +# compiler, but only when compiling C files that belong to the OCaml +# distribution. +# In other words, when ocamlopt is called to compile a third-party C +# source file, it will _not_ pass these options to the C compiler. + arch=none model=default system=unknown @@ -913,6 +962,7 @@ else fi nativecccompopts="$bytecccompopts" +nativeccprivatecompopts="$byteccprivatecompopts" nativeccprofopts='' nativecclinkopts='' # FIXME the naming of nativecclinkopts is broken: these are options for @@ -965,7 +1015,14 @@ case "$arch,$system" in aspp="${TOOLPREF}cc -c";; amd64,*|arm,*|arm64,*|i386,*|power,bsd*|sparc,*) as="${TOOLPREF}as" - aspp="${TOOLPREF}gcc -c";; + case "$ccfamily" in + clang-*) + aspp="${TOOLPREF}clang -c" + ;; + *) + aspp="${TOOLPREF}gcc -c" + ;; + esac;; esac if test -n "$asoption"; then as="$asoption"; fi @@ -973,25 +1030,25 @@ if test -n "$asppoption"; then aspp="$asppoption"; fi cc_profile='-pg' case "$arch,$system" in - i386,linux_elf) profiling='prof';; - i386,gnu) profiling='prof';; - i386,bsd_elf) profiling='prof';; - amd64,macosx) profiling='prof';; - i386,macosx) profiling='prof';; - sparc,bsd) profiling='prof';; + i386,linux_elf) profiling='true';; + i386,gnu) profiling='true';; + i386,bsd_elf) profiling='true';; + amd64,macosx) profiling='true';; + i386,macosx) profiling='true';; + sparc,bsd) profiling='true';; sparc,solaris) - profiling='prof' + profiling='true' case "$nativecc" in gcc*) ;; *) cc_profile='-xpg';; esac;; - amd64,linux) profiling='prof';; - amd64,openbsd) profiling='prof';; - amd64,freebsd) profiling='prof';; - amd64,netbsd) profiling='prof';; - arm,netbsd) profiling='prof';; - amd64,gnu) profiling='prof';; - arm,linux*) profiling='prof';; - power,elf) profiling='prof';; - power,bsd*) profiling='prof';; - *) profiling='noprof';; + amd64,linux) profiling='true';; + amd64,openbsd) profiling='true';; + amd64,freebsd) profiling='true';; + amd64,netbsd) profiling='true';; + arm,netbsd) profiling='true';; + amd64,gnu) profiling='true';; + arm,linux*) profiling='true';; + power,elf) profiling='true';; + power,bsd*) profiling='true';; + *) profiling='false';; esac # Where is ranlib? @@ -1016,7 +1073,10 @@ echo "#define OCAML_STDLIB_DIR \"$libdir\"" >> s.h # Do #! scripts work? -if (SHELL=/bin/sh; export SHELL; (./hashbang || ./hashbang2) >/dev/null); then +printf "#!%s\nexit 1\n" `command -v cat` > hashbang4 +chmod +x hashbang4 + +if ( (./hashbang || ./hashbang2 || ./hashbang3 || ./hashbang4) >/dev/null); then inf "#! appears to work in shell scripts." case "$target" in *-*-sunos*|*-*-unicos*) @@ -1081,6 +1141,19 @@ if sh ./hasgot times; then echo "#define HAS_TIMES" >> s.h fi +if sh ./hasgot2 -D_GNU_SOURCE -i stdlib.h secure_getenv; then + inf "secure_getenv() found." + echo "#define HAS_SECURE_GETENV" >> s.h +elif sh ./hasgot2 -D_GNU_SOURCE -i stdlib.h __secure_getenv; then + inf "__secure_getenv() found." + echo "#define HAS___SECURE_GETENV" >> s.h +fi + +if sh ./hasgot -i unistd.h issetugid; then + inf "issetugid() found." + echo "#define HAS_ISSETUGID" >> s.h +fi + # For the terminfo module if test "$with_curses" = "yes"; then @@ -1444,6 +1517,21 @@ if sh ./hasgot nice; then echo "#define HAS_NICE" >> s.h fi +if sh ./hasgot dup3; then + inf "dup3() found" + echo "#define HAS_DUP3" >> s.h +fi + +if sh ./hasgot pipe2; then + inf "pipe2() found" + echo "#define HAS_PIPE2" >> s.h +fi + +if sh ./hasgot accept4; then + inf "accept4() found" + echo "#define HAS_ACCEPT4" >> s.h +fi + # Determine if the debugger is supported if test -n "$with_debugger"; then @@ -1763,7 +1851,7 @@ fi if test "$with_frame_pointers" = "true"; then case "$target,$cc" in - x86_64-*-linux*,gcc*) + x86_64-*-linux*,gcc*|x86_64-*-linux*,clang*) nativecccompopts="$nativecccompopts -g -fno-omit-frame-pointer" bytecccompopts="$bytecccompopts -g -fno-omit-frame-pointer" nativecclinkopts="$nativecclinkopts -g" @@ -1793,8 +1881,11 @@ fi # The more bits used for profiling, the smaller will be Max_wosize. # Note that PROFINFO_WIDTH must still be defined even if not configuring # for Spacetime (see comment in byterun/caml/mlvalues.h on [Profinfo_hd]). -profinfo_width=26 echo "#define PROFINFO_WIDTH $profinfo_width" >> m.h +if $with_profinfo; then + echo "#define WITH_PROFINFO" >> m.h +fi + if $with_spacetime; then case "$arch,$system" in amd64,*) @@ -1905,8 +1996,10 @@ fi cclibs="$cclibs $mathlib" -echo "BYTECC=$bytecc" >> Makefile -echo "BYTECCCOMPOPTS=$bytecccompopts" >> Makefile +echo "BYTECC=$bytecc $bytecccompopts" >> Makefile +echo "BYTECODE_C_COMPILER=$bytecc $bytecccompopts $sharedcccompopts" \ + >> Makefile +echo "BYTECCCOMPOPTS=$byteccprivatecompopts" >> Makefile echo "BYTECCLINKOPTS=$bytecclinkopts" >> Makefile echo "BYTECCLIBS=$cclibs $dllib $curseslibs $pthread_link \ $instrumented_runtime_libs" >> Makefile @@ -1929,8 +2022,9 @@ EOF echo "ARCH=$arch" >> Makefile echo "MODEL=$model" >> Makefile echo "SYSTEM=$system" >> Makefile -echo "NATIVECC=$nativecc" >> Makefile -echo "NATIVECCCOMPOPTS=$nativecccompopts" >> Makefile +echo "NATIVECC=$nativecc $nativecccompopts" >> Makefile +echo "NATIVE_C_COMPILER=$nativecc $nativecccompopts" >> Makefile +echo "NATIVECCCOMPOPTS=$nativeccprivatecompopts" >> Makefile echo "NATIVECCPROFOPTS=$nativeccprofopts" >> Makefile echo "NATIVECCLINKOPTS=$nativecclinkopts" >> Makefile echo "NATIVECCRPATH=$nativeccrpath" >> Makefile @@ -1943,10 +2037,7 @@ echo "DYNLINKOPTS=$dllib" >> Makefile echo "OTHERLIBRARIES=$otherlibraries" >> Makefile echo "CC_PROFILE=$cc_profile" >> Makefile echo "SYSTHREAD_SUPPORT=$systhread_support" >> Makefile -echo "PARTIALLD=$partialld" >> Makefile -echo "PACKLD=\$(PARTIALLD) \$(NATIVECCLINKOPTS) -o " \ - | sed -e 's/ $/\\ /' >> Makefile -echo "DLLCCCOMPOPTS=$dllccompopts" >> Makefile +echo "PACKLD=$partialld $nativecclinkopts -o\\ " >> Makefile echo "IFLEXDIR=$iflexdir" >> Makefile echo "O=o" >> Makefile echo "A=a" >> Makefile @@ -1965,17 +2056,13 @@ echo "MKEXEDEBUGFLAG=$mkexedebugflag" >> Makefile echo "MKDLL=$mksharedlib" >> Makefile echo "MKMAINDLL=$mkmaindll" >> Makefile echo "RUNTIMED=${debugruntime}" >>Makefile -if $shared_libraries_supported; then - echo "SHARED=shared" >>Makefile -else - echo "SHARED=noshared" >>Makefile -fi echo "RUNTIMEI=${with_instrumented_runtime}" >>Makefile echo "WITH_DEBUGGER=${with_debugger}" >>Makefile echo "WITH_OCAMLDOC=${with_ocamldoc}" >>Makefile echo "ASM_CFI_SUPPORTED=$asm_cfi_supported" >> Makefile echo "WITH_FRAME_POINTERS=$with_frame_pointers" >> Makefile echo "WITH_SPACETIME=$with_spacetime" >> Makefile +echo "WITH_PROFINFO=$with_profinfo" >> Makefile echo "LIBUNWIND_AVAILABLE=$libunwind_available" >> Makefile echo "LIBUNWIND_INCLUDE_FLAGS=$libunwind_include" >> Makefile echo "LIBUNWIND_LINK_FLAGS=$libunwind_lib" >> Makefile @@ -1989,6 +2076,7 @@ if [ "$ostype" = Cygwin ]; then fi echo "FLAMBDA=$flambda" >> Makefile echo "SAFE_STRING=$safe_string" >> Makefile +echo "AFL_INSTRUMENT=$afl_instrument" >> Makefile echo "MAX_TESTSUITE_DIR_RETRIES=$max_testsuite_dir_retries" >> Makefile @@ -2058,6 +2146,11 @@ else else inf " spacetime profiling....... no" fi + if $with_profinfo; then + inf " reserved bits in header... $profinfo_width" + else + inf " reserved bits in header... no" + fi case "$arch,$system" in amd64,macosx) ;; @@ -2085,7 +2178,7 @@ else inf " compile with -fPIC........ no" fi inf " native dynlink ........... $natdynlink" - if test "$profiling" = "prof"; then + if $profiling; then inf " profiling with gprof ..... supported" else inf " profiling with gprof ..... not supported" @@ -2100,6 +2193,11 @@ else else inf " safe strings ............. no" fi + if test "$afl_instrument" = "true"; then + inf " afl-fuzz always enabled .. yes" + else + inf " afl-fuzz always enabled .. no" + fi fi if test "$with_debugger" = "ocamldebugger"; then @@ -2108,7 +2206,7 @@ else inf "Source-level replay debugger: not supported" fi -if test "$debugruntime" = "runtimed"; then +if $debugruntime; then inf "Debug runtime will be compiled and installed" fi diff --git a/debugger/.depend b/debugger/.depend index ed8ab4bf..86b18ab6 100644 --- a/debugger/.depend +++ b/debugger/.depend @@ -79,14 +79,14 @@ lexer.cmx : parser.cmx lexer.cmi lexer.cmi : parser.cmi loadprinter.cmo : ../typing/types.cmi ../bytecomp/symtable.cmi printval.cmi \ ../typing/printtyp.cmi ../typing/path.cmi ../utils/misc.cmi \ - ../parsing/longident.cmi ../typing/ident.cmi ../typing/env.cmi \ - ../typing/ctype.cmi ../utils/config.cmi ../driver/compdynlink.cmi \ - loadprinter.cmi + ../parsing/longident.cmi ../parsing/location.cmi ../typing/ident.cmi \ + ../typing/env.cmi ../typing/ctype.cmi ../utils/config.cmi \ + ../driver/compdynlink.cmi loadprinter.cmi loadprinter.cmx : ../typing/types.cmx ../bytecomp/symtable.cmx printval.cmx \ ../typing/printtyp.cmx ../typing/path.cmx ../utils/misc.cmx \ - ../parsing/longident.cmx ../typing/ident.cmx ../typing/env.cmx \ - ../typing/ctype.cmx ../utils/config.cmx ../driver/compdynlink.cmi \ - loadprinter.cmi + ../parsing/longident.cmx ../parsing/location.cmx ../typing/ident.cmx \ + ../typing/env.cmx ../typing/ctype.cmx ../utils/config.cmx \ + ../driver/compdynlink.cmi loadprinter.cmi loadprinter.cmi : ../parsing/longident.cmi ../driver/compdynlink.cmi main.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi time_travel.cmi \ show_information.cmi question.cmi program_management.cmi primitives.cmi \ diff --git a/debugger/Makefile b/debugger/Makefile index d0ac2565..2c130dd1 100644 --- a/debugger/Makefile +++ b/debugger/Makefile @@ -13,5 +13,118 @@ #* * #************************************************************************** +include ../config/Makefile UNIXDIR=../otherlibs/$(UNIXLIB) -include Makefile.shared +CAMLRUN ?= ../boot/ocamlrun +CAMLYACC ?= ../boot/ocamlyacc + +CAMLC=$(CAMLRUN) ../ocamlc -nostdlib -I ../stdlib +COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A \ + -safe-string -strict-sequence -strict-formats +LINKFLAGS=-linkall -I $(UNIXDIR) +YACCFLAGS= +CAMLLEX=$(CAMLRUN) ../boot/ocamllex +CAMLDEP=$(CAMLRUN) ../tools/ocamldep +DEPFLAGS=$(INCLUDES) + +INSTALL_BINDIR=$(DESTDIR)$(BINDIR) + +INCLUDES=\ + -I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../toplevel \ + -I ../driver -I $(UNIXDIR) + +OTHEROBJS=\ + $(UNIXDIR)/unix.cma \ + ../utils/config.cmo ../utils/tbl.cmo ../utils/misc.cmo \ + ../utils/identifiable.cmo ../utils/numbers.cmo \ + ../utils/arg_helper.cmo ../utils/clflags.cmo \ + ../utils/consistbl.cmo ../utils/warnings.cmo \ + ../utils/terminfo.cmo \ + ../parsing/location.cmo ../parsing/longident.cmo ../parsing/docstrings.cmo \ + ../parsing/syntaxerr.cmo \ + ../parsing/ast_helper.cmo ../parsing/ast_mapper.cmo \ + ../parsing/ast_iterator.cmo ../parsing/attr_helper.cmo \ + ../parsing/builtin_attributes.cmo \ + ../typing/ident.cmo ../typing/path.cmo ../typing/types.cmo \ + ../typing/btype.cmo ../typing/primitive.cmo ../typing/typedtree.cmo \ + ../typing/subst.cmo ../typing/predef.cmo \ + ../typing/datarepr.cmo ../typing/cmi_format.cmo ../typing/env.cmo \ + ../typing/oprint.cmo \ + ../typing/ctype.cmo ../typing/printtyp.cmo ../typing/mtype.cmo \ + ../typing/envaux.cmo \ + ../bytecomp/runtimedef.cmo ../bytecomp/bytesections.cmo \ + ../bytecomp/dll.cmo ../bytecomp/meta.cmo ../bytecomp/symtable.cmo \ + ../bytecomp/opcodes.cmo ../driver/compdynlink.cmo \ + ../toplevel/genprintval.cmo + + +OBJS=\ + int64ops.cmo \ + primitives.cmo \ + unix_tools.cmo \ + debugger_config.cmo \ + parameters.cmo \ + lexer.cmo \ + input_handling.cmo \ + question.cmo \ + debugcom.cmo \ + exec.cmo \ + source.cmo \ + pos.cmo \ + checkpoints.cmo \ + events.cmo \ + program_loading.cmo \ + symbols.cmo \ + breakpoints.cmo \ + trap_barrier.cmo \ + history.cmo \ + printval.cmo \ + show_source.cmo \ + time_travel.cmo \ + program_management.cmo \ + frames.cmo \ + eval.cmo \ + show_information.cmo \ + loadprinter.cmo \ + parser.cmo \ + command_line.cmo \ + main.cmo + +all: ocamldebug$(EXE) + +ocamldebug$(EXE): $(OBJS) $(OTHEROBJS) + $(CAMLC) $(LINKFLAGS) -o ocamldebug$(EXE) -linkall $(OTHEROBJS) $(OBJS) + +install: + cp ocamldebug$(EXE) "$(INSTALL_BINDIR)/ocamldebug$(EXE)" + +clean:: + rm -f ocamldebug$(EXE) + rm -f *.cmo *.cmi + +.SUFFIXES: +.SUFFIXES: .ml .cmo .mli .cmi + +.ml.cmo: + $(CAMLC) -c $(COMPFLAGS) $< + +.mli.cmi: + $(CAMLC) -c $(COMPFLAGS) $< + +depend: beforedepend + $(CAMLDEP) -slash $(DEPFLAGS) *.mli *.ml \ + | sed -e 's,$(UNIXDIR)/,$$(UNIXDIR)/,' > .depend + +lexer.ml: lexer.mll + $(CAMLLEX) lexer.mll +clean:: + rm -f lexer.ml +beforedepend:: lexer.ml + +parser.ml parser.mli: parser.mly + $(CAMLYACC) parser.mly +clean:: + rm -f parser.ml parser.mli +beforedepend:: parser.ml parser.mli + +include .depend diff --git a/debugger/Makefile.nt b/debugger/Makefile.nt index 86a6d00d..ed9900bb 100644 --- a/debugger/Makefile.nt +++ b/debugger/Makefile.nt @@ -13,5 +13,4 @@ #* * #************************************************************************** -UNIXDIR=../otherlibs/win32unix -include Makefile.shared +include Makefile diff --git a/debugger/Makefile.shared b/debugger/Makefile.shared deleted file mode 100644 index aed8aa12..00000000 --- a/debugger/Makefile.shared +++ /dev/null @@ -1,128 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include ../config/Makefile -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc - -CAMLC=$(CAMLRUN) ../ocamlc -nostdlib -I ../stdlib -COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A \ - -safe-string -strict-sequence -strict-formats -LINKFLAGS=-linkall -I $(UNIXDIR) -YACCFLAGS= -CAMLLEX=$(CAMLRUN) ../boot/ocamllex -CAMLDEP=$(CAMLRUN) ../tools/ocamldep -DEPFLAGS=$(INCLUDES) - -INSTALL_BINDIR=$(DESTDIR)$(BINDIR) - -INCLUDES=\ - -I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../toplevel \ - -I ../driver -I $(UNIXDIR) - -OTHEROBJS=\ - $(UNIXDIR)/unix.cma \ - ../utils/config.cmo ../utils/tbl.cmo ../utils/misc.cmo \ - ../utils/identifiable.cmo ../utils/numbers.cmo \ - ../utils/arg_helper.cmo ../utils/clflags.cmo \ - ../utils/consistbl.cmo ../utils/warnings.cmo \ - ../utils/terminfo.cmo \ - ../parsing/location.cmo ../parsing/longident.cmo ../parsing/docstrings.cmo \ - ../parsing/ast_helper.cmo ../parsing/ast_mapper.cmo \ - ../parsing/ast_iterator.cmo ../parsing/attr_helper.cmo \ - ../parsing/builtin_attributes.cmo \ - ../typing/ident.cmo ../typing/path.cmo ../typing/types.cmo \ - ../typing/btype.cmo ../typing/primitive.cmo ../typing/typedtree.cmo \ - ../typing/subst.cmo ../typing/predef.cmo \ - ../typing/datarepr.cmo ../typing/cmi_format.cmo ../typing/env.cmo \ - ../typing/oprint.cmo \ - ../typing/ctype.cmo ../typing/printtyp.cmo ../typing/mtype.cmo \ - ../typing/envaux.cmo \ - ../bytecomp/runtimedef.cmo ../bytecomp/bytesections.cmo \ - ../bytecomp/dll.cmo ../bytecomp/meta.cmo ../bytecomp/symtable.cmo \ - ../bytecomp/opcodes.cmo ../driver/compdynlink.cmo \ - ../toplevel/genprintval.cmo - - -OBJS=\ - int64ops.cmo \ - primitives.cmo \ - unix_tools.cmo \ - debugger_config.cmo \ - parameters.cmo \ - lexer.cmo \ - input_handling.cmo \ - question.cmo \ - debugcom.cmo \ - exec.cmo \ - source.cmo \ - pos.cmo \ - checkpoints.cmo \ - events.cmo \ - program_loading.cmo \ - symbols.cmo \ - breakpoints.cmo \ - trap_barrier.cmo \ - history.cmo \ - printval.cmo \ - show_source.cmo \ - time_travel.cmo \ - program_management.cmo \ - frames.cmo \ - eval.cmo \ - show_information.cmo \ - loadprinter.cmo \ - parser.cmo \ - command_line.cmo \ - main.cmo - -all: ocamldebug$(EXE) - -ocamldebug$(EXE): $(OBJS) $(OTHEROBJS) - $(CAMLC) $(LINKFLAGS) -o ocamldebug$(EXE) -linkall $(OTHEROBJS) $(OBJS) - -install: - cp ocamldebug$(EXE) "$(INSTALL_BINDIR)/ocamldebug$(EXE)" - -clean:: - rm -f ocamldebug$(EXE) - rm -f *.cmo *.cmi - -.SUFFIXES: -.SUFFIXES: .ml .cmo .mli .cmi - -.ml.cmo: - $(CAMLC) -c $(COMPFLAGS) $< - -.mli.cmi: - $(CAMLC) -c $(COMPFLAGS) $< - -depend: beforedepend - $(CAMLDEP) -slash $(DEPFLAGS) *.mli *.ml \ - | sed -e 's,$(UNIXDIR)/,$$(UNIXDIR)/,' > .depend - -lexer.ml: lexer.mll - $(CAMLLEX) lexer.mll -clean:: - rm -f lexer.ml -beforedepend:: lexer.ml - -parser.ml parser.mli: parser.mly - $(CAMLYACC) parser.mly -clean:: - rm -f parser.ml parser.mli -beforedepend:: parser.ml parser.mli - -include .depend diff --git a/debugger/command_line.ml b/debugger/command_line.ml index b8b09134..8c1c9760 100644 --- a/debugger/command_line.ml +++ b/debugger/command_line.ml @@ -791,7 +791,10 @@ let instr_list _ppf lexbuf = | Not_found -> error ("No source file for " ^ mdle ^ ".") in let point = if column <> -1 then - (point_of_coord buffer line 1) + column + try + (point_of_coord buffer line 1) + column + with Out_of_range -> + -1 else -1 in let beginning = diff --git a/debugger/loadprinter.ml b/debugger/loadprinter.ml index a1c2fcfe..510979e2 100644 --- a/debugger/loadprinter.ml +++ b/debugger/loadprinter.ml @@ -97,6 +97,11 @@ let rec eval_path = function | Pdot(p, _, pos) -> Obj.field (eval_path p) pos | Papply _ -> fatal_error "Loadprinter.eval_path" +(* PR#7258: get rid of module aliases before evaluating paths *) + +let eval_path path = + eval_path (Env.normalize_path (Some Location.none) Env.empty path) + (* Install, remove a printer (as in toplevel/topdirs) *) (* since 4.00, "topdirs.cmi" is not in the same directory as the standard diff --git a/debugger/show_source.ml b/debugger/show_source.ml index ac478717..357132da 100644 --- a/debugger/show_source.ml +++ b/debugger/show_source.ml @@ -23,18 +23,23 @@ open Source (* Print a line; return the beginning of the next line *) let print_line buffer line_number start point before = - let next = next_linefeed buffer start + let linefeed = next_linefeed buffer start and content = buffer_content buffer in printf "%i " line_number; - if point <= next && point >= start then + let line_end = + if linefeed > 0 && content.[linefeed - 1] = '\r' then + linefeed - 1 + else + linefeed in + if point <= line_end && point >= start then (print_string (String.sub content start (point - start)); print_string (if before then event_mark_before else event_mark_after); - print_string (String.sub content point (next - point))) + print_string (String.sub content point (line_end - point))) else - print_string (String.sub content start (next - start)); + print_string (String.sub content start (line_end - start)); print_newline (); - next + linefeed (* Tell Emacs we are nowhere in the source. *) let show_no_point () = diff --git a/driver/compenv.ml b/driver/compenv.ml index c829820c..f037328d 100644 --- a/driver/compenv.ml +++ b/driver/compenv.ml @@ -191,6 +191,9 @@ let read_one_param ppf position name v = | "g" -> set "g" [ Clflags.debug ] v | "p" -> set "p" [ Clflags.gprofile ] v | "bin-annot" -> set "bin-annot" [ Clflags.binary_annotations ] v + | "afl-instrument" -> set "afl-instrument" [ Clflags.afl_instrument ] v + | "afl-inst-ratio" -> + int_setter ppf "afl-inst-ratio" afl_inst_ratio v | "annot" -> set "annot" [ Clflags.annotations ] v | "absname" -> set "absname" [ Location.absname ] v | "compat-32" -> set "compat-32" [ bytecode_compatible_32 ] v @@ -335,7 +338,7 @@ let read_one_param ppf position name v = (Warnings.Bad_env_variable ("OCAMLPARAM", "bad value for \"color\", \ (expected \"auto\", \"always\" or \"never\")")) - | Some setting -> color := setting + | Some setting -> color := Some setting end | "intf-suffix" -> Config.interface_suffix := v diff --git a/driver/compile.ml b/driver/compile.ml index 0d7325d3..4e136e4c 100644 --- a/driver/compile.ml +++ b/driver/compile.ml @@ -35,24 +35,26 @@ let interface ppf sourcefile outputprefix = if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast; if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast; - let tsg = Typemod.type_interface sourcefile initial_env ast in - if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg; - let sg = tsg.sig_type in - if !Clflags.print_types then - Printtyp.wrap_printing_env initial_env (fun () -> - fprintf std_formatter "%a@." - Printtyp.signature (Typemod.simplify_signature sg)); - ignore (Includemod.signatures initial_env sg sg); - Typecore.force_delayed_checks (); - Warnings.check_fatal (); - if not !Clflags.print_types then begin - let deprecated = Builtin_attributes.deprecated_of_sig ast in - let sg = - Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi") - in - Typemod.save_signature modulename tsg outputprefix sourcefile - initial_env sg ; - end + Timings.(time_call (Typing sourcefile)) (fun () -> + let tsg = Typemod.type_interface sourcefile initial_env ast in + if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg; + let sg = tsg.sig_type in + if !Clflags.print_types then + Printtyp.wrap_printing_env initial_env (fun () -> + fprintf std_formatter "%a@." + Printtyp.signature (Typemod.simplify_signature sg)); + ignore (Includemod.signatures initial_env sg sg); + Typecore.force_delayed_checks (); + Warnings.check_fatal (); + if not !Clflags.print_types then begin + let deprecated = Builtin_attributes.deprecated_of_sig ast in + let sg = + Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi") + in + Typemod.save_signature modulename tsg outputprefix sourcefile + initial_env sg ; + end + ) (* Compile a .ml file *) diff --git a/driver/compmisc.ml b/driver/compmisc.ml index 36a2b81c..bf45f665 100644 --- a/driver/compmisc.ml +++ b/driver/compmisc.ml @@ -29,7 +29,9 @@ let init_path ?(dir="") native = else !Clflags.include_dirs in - let dirs = !last_include_dirs @ dirs @ !first_include_dirs in + let dirs = + !last_include_dirs @ dirs @ Config.flexdll_dirs @ !first_include_dirs + in let exp_dirs = List.map (Misc.expand_directory Config.standard_library) dirs in Config.load_path := dir :: @@ -44,7 +46,7 @@ let init_path ?(dir="") native = let open_implicit_module m env = let open Asttypes in let lid = {loc = Location.in_file "command line"; - txt = Longident.Lident m } in + txt = Longident.parse m } in snd (Typemod.type_open_ Override env lid.loc lid) let initial_env () = @@ -60,3 +62,18 @@ let initial_env () = List.fold_left (fun env m -> open_implicit_module m env ) env (!implicit_modules @ List.rev !Clflags.open_modules) + + +let read_color_env ppf = + try + match Clflags.parse_color_setting (Sys.getenv "OCAML_COLOR") with + | None -> + Location.print_warning Location.none ppf + (Warnings.Bad_env_variable + ("OCAML_COLOR", + "expected \"auto\", \"always\" or \"never\"")); + | Some x -> match !Clflags.color with + | None -> Clflags.color := Some x + | Some _ -> () + with + Not_found -> () diff --git a/driver/compmisc.mli b/driver/compmisc.mli index ade4761a..3dbcdaeb 100644 --- a/driver/compmisc.mli +++ b/driver/compmisc.mli @@ -15,3 +15,5 @@ val init_path : ?dir:string -> bool -> unit val initial_env : unit -> Env.t + +val read_color_env : Format.formatter -> unit diff --git a/driver/main.ml b/driver/main.ml index e9af202f..250c5ef8 100644 --- a/driver/main.ml +++ b/driver/main.ml @@ -104,9 +104,9 @@ module Options = Main_args.Make_bytecomp_options (struct let _warn_error = (Warnings.parse_options true) let _warn_help = Warnings.help_warnings let _color option = - begin match Clflags.parse_color_setting option with + begin match parse_color_setting option with | None -> () - | Some setting -> Clflags.color := setting + | Some setting -> color := Some setting end let _where = print_standard_library let _verbose = set verbose @@ -118,19 +118,33 @@ module Options = Main_args.Make_bytecomp_options (struct let _dlambda = set dump_lambda let _dinstr = set dump_instr let _dtimings = set print_timings + + let _args = Arg.read_arg + let _args0 = Arg.read_arg0 + let anonymous = anonymous end) let main () = + Clflags.add_arguments __LOC__ Options.list; try readenv ppf Before_args; - Arg.parse Options.list anonymous usage; - Compenv.process_deferred_actions - (ppf, - Compile.implementation, - Compile.interface, - ".cmo", - ".cma"); + Clflags.parse_arguments anonymous usage; + Compmisc.read_color_env ppf; + begin try + Compenv.process_deferred_actions + (ppf, + Compile.implementation, + Compile.interface, + ".cmo", + ".cma"); + with Arg.Bad msg -> + begin + prerr_endline msg; + Clflags.print_arguments usage; + exit 2 + end + end; readenv ppf Before_link; if List.length (List.filter (fun x -> !x) diff --git a/driver/main_args.ml b/driver/main_args.ml index b40d3da5..bf1fb8ef 100644 --- a/driver/main_args.ml +++ b/driver/main_args.ml @@ -724,6 +724,28 @@ let mk_no_strict_formats f = \ and instead fix invalid formats.)" ;; +let mk_args f = + "-args", Arg.Expand f, + " Read additional newline-terminated command line arguments\n\ + \ from " +;; + +let mk_args0 f = + "-args0", Arg.Expand f, + " Read additional null character terminated command line arguments\n\ + from " +;; + +let mk_afl_instrument f = + "-afl-instrument", Arg.Unit f, "Enable instrumentation for afl-fuzz" +;; + +let mk_afl_inst_ratio f = + "-afl-inst-ratio", Arg.Int f, + "Configure percentage of branches instrumented\n\ + \ (advanced, see afl-fuzz docs for AFL_INST_RATIO)" +;; + let mk__ f = "-", Arg.String f, " Treat as a file name (even if it starts with `-')" @@ -813,6 +835,9 @@ module type Compiler_options = sig val _nopervasives : unit -> unit val _dtimings : unit -> unit + + val _args: string -> string array + val _args0: string -> string array end ;; @@ -825,6 +850,8 @@ module type Toplevel_options = sig val _nopromptcont : unit -> unit val _plugin : string -> unit val _stdin : unit -> unit + val _args : string -> string array + val _args0 : string -> string array end ;; @@ -848,6 +875,7 @@ end;; module type Bytetop_options = sig include Toplevel_options val _dinstr : unit -> unit + end;; module type Optcommon_options = sig @@ -909,6 +937,8 @@ module type Optcomp_options = sig val _pp : string -> unit val _S : unit -> unit val _shared : unit -> unit + val _afl_instrument : unit -> unit + val _afl_inst_ratio : int -> unit end;; module type Opttop_options = sig @@ -1030,6 +1060,9 @@ struct mk_dlambda F._dlambda; mk_dinstr F._dinstr; mk_dtimings F._dtimings; + + mk_args F._args; + mk_args0 F._args0; ] end;; @@ -1083,6 +1116,9 @@ struct mk_drawlambda F._drawlambda; mk_dlambda F._dlambda; mk_dinstr F._dinstr; + + mk_args F._args; + mk_args0 F._args0; ] end;; @@ -1091,6 +1127,8 @@ struct let list = [ mk_a F._a; mk_absname F._absname; + mk_afl_instrument F._afl_instrument; + mk_afl_inst_ratio F._afl_inst_ratio; mk_annot F._annot; mk_binannot F._binannot; mk_inline_branch_factor F._inline_branch_factor; @@ -1214,6 +1252,9 @@ struct mk_dstartup F._dstartup; mk_dtimings F._dtimings; mk_dump_pass F._dump_pass; + + mk_args F._args; + mk_args0 F._args0; ] end;; diff --git a/driver/main_args.mli b/driver/main_args.mli index b5b0eaae..dfe90c00 100644 --- a/driver/main_args.mli +++ b/driver/main_args.mli @@ -100,6 +100,9 @@ module type Compiler_options = sig val _nopervasives : unit -> unit val _dtimings : unit -> unit + + val _args: string -> string array + val _args0: string -> string array end ;; @@ -112,6 +115,9 @@ module type Toplevel_options = sig val _nopromptcont : unit -> unit val _plugin : string -> unit val _stdin : unit -> unit + val _args: string -> string array + val _args0: string -> string array + end ;; @@ -196,6 +202,8 @@ module type Optcomp_options = sig val _pp : string -> unit val _S : unit -> unit val _shared : unit -> unit + val _afl_instrument : unit -> unit + val _afl_inst_ratio : int -> unit end;; module type Opttop_options = sig diff --git a/driver/optcompile.ml b/driver/optcompile.ml index 991b9f52..876b1cc9 100644 --- a/driver/optcompile.ml +++ b/driver/optcompile.ml @@ -35,24 +35,26 @@ let interface ppf sourcefile outputprefix = let ast = Pparse.parse_interface ~tool_name ppf sourcefile in if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast; if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast; - let tsg = Typemod.type_interface sourcefile initial_env ast in - if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg; - let sg = tsg.sig_type in - if !Clflags.print_types then - Printtyp.wrap_printing_env initial_env (fun () -> - fprintf std_formatter "%a@." - Printtyp.signature (Typemod.simplify_signature sg)); - ignore (Includemod.signatures initial_env sg sg); - Typecore.force_delayed_checks (); - Warnings.check_fatal (); - if not !Clflags.print_types then begin - let deprecated = Builtin_attributes.deprecated_of_sig ast in - let sg = - Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi") - in - Typemod.save_signature modulename tsg outputprefix sourcefile - initial_env sg ; - end + Timings.(time_call (Typing sourcefile)) (fun () -> + let tsg = Typemod.type_interface sourcefile initial_env ast in + if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg; + let sg = tsg.sig_type in + if !Clflags.print_types then + Printtyp.wrap_printing_env initial_env (fun () -> + fprintf std_formatter "%a@." + Printtyp.signature (Typemod.simplify_signature sg)); + ignore (Includemod.signatures initial_env sg sg); + Typecore.force_delayed_checks (); + Warnings.check_fatal (); + if not !Clflags.print_types then begin + let deprecated = Builtin_attributes.deprecated_of_sig ast in + let sg = + Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi") + in + Typemod.save_signature modulename tsg outputprefix sourcefile + initial_env sg ; + end + ) (* Compile a .ml file *) diff --git a/driver/optmain.ml b/driver/optmain.ml index 2c6d60e9..53904c1c 100644 --- a/driver/optmain.ml +++ b/driver/optmain.ml @@ -47,6 +47,8 @@ module Options = Main_args.Make_optcomp_options (struct let _a = set make_archive let _absname = set Location.absname + let _afl_instrument = set afl_instrument + let _afl_inst_ratio n = afl_inst_ratio := n let _annot = set annotations let _binannot = set binary_annotations let _c = set compile_only @@ -185,9 +187,9 @@ module Options = Main_args.Make_optcomp_options (struct let _warn_error s = Warnings.parse_options true s let _warn_help = Warnings.help_warnings let _color option = - begin match Clflags.parse_color_setting option with + begin match parse_color_setting option with | None -> () - | Some setting -> Clflags.color := setting + | Some setting -> color := Some setting end let _where () = print_standard_library () @@ -223,6 +225,9 @@ module Options = Main_args.Make_optcomp_options (struct let _dtimings = set print_timings let _opaque = set opaque + let _args = Arg.read_arg + let _args0 = Arg.read_arg0 + let anonymous = anonymous end);; @@ -231,13 +236,25 @@ let main () = let ppf = Format.err_formatter in try readenv ppf Before_args; - Arg.parse (Arch.command_line_options @ Options.list) anonymous usage; - Compenv.process_deferred_actions - (ppf, - Optcompile.implementation ~backend, - Optcompile.interface, - ".cmx", - ".cmxa"); + Clflags.add_arguments __LOC__ (Arch.command_line_options @ Options.list); + Clflags.parse_arguments anonymous usage; + Compmisc.read_color_env ppf; + if !gprofile && not Config.profiling then + fatal "Profiling with \"gprof\" is not supported on this platform."; + begin try + Compenv.process_deferred_actions + (ppf, + Optcompile.implementation ~backend, + Optcompile.interface, + ".cmx", + ".cmxa"); + with Arg.Bad msg -> + begin + prerr_endline msg; + Clflags.print_arguments usage; + exit 2 + end + end; readenv ppf Before_link; if List.length (List.filter (fun x -> !x) diff --git a/driver/pparse.ml b/driver/pparse.ml index 5fbaa91e..b00ded40 100644 --- a/driver/pparse.ml +++ b/driver/pparse.ml @@ -38,7 +38,7 @@ let preprocess sourcefile = match !Clflags.preprocessor with None -> sourcefile | Some pp -> - Timings.(time (Preprocessing sourcefile)) + Timings.(time (Dash_pp sourcefile)) (call_external_preprocessor sourcefile) pp @@ -166,6 +166,7 @@ let parse (type a) (kind : a ast_kind) lexbuf : a = let file_aux ppf ~tool_name inputfile (type a) parse_fun invariant_fun (kind : a ast_kind) = let ast_magic = magic_of_kind kind in + let source_file = !Location.input_name in let (ic, is_ast_file) = open_and_check_magic inputfile ast_magic in let ast = try @@ -181,12 +182,15 @@ let file_aux ppf ~tool_name inputfile (type a) parse_fun invariant_fun Location.input_name := inputfile; let lexbuf = Lexing.from_channel ic in Location.init lexbuf inputfile; - parse_fun lexbuf + Timings.(time_call (Parser source_file)) (fun () -> + parse_fun lexbuf) end with x -> close_in ic; raise x in close_in ic; - let ast = apply_rewriters ~restore:false ~tool_name kind ast in + let ast = + Timings.(time_call (Dash_ppx source_file)) (fun () -> + apply_rewriters ~restore:false ~tool_name kind ast) in if is_ast_file || !Clflags.all_ppx <> [] then invariant_fun ast; ast @@ -212,8 +216,7 @@ let parse_file ~tool_name invariant_fun apply_hooks kind ppf sourcefile = Location.input_name := sourcefile; let inputfile = preprocess sourcefile in let ast = - let parse_fun = Timings.(time (Parsing sourcefile)) (parse kind) in - try file_aux ppf ~tool_name inputfile parse_fun invariant_fun kind + try file_aux ppf ~tool_name inputfile (parse kind) invariant_fun kind with exn -> remove_preprocessed inputfile; raise exn @@ -230,8 +233,10 @@ module InterfaceHooks = Misc.MakeHooks(struct end) let parse_implementation ppf ~tool_name sourcefile = - parse_file ~tool_name Ast_invariants.structure - ImplementationHooks.apply_hooks Structure ppf sourcefile + Timings.(time_call (Parsing sourcefile)) (fun () -> + parse_file ~tool_name Ast_invariants.structure + ImplementationHooks.apply_hooks Structure ppf sourcefile) let parse_interface ppf ~tool_name sourcefile = - parse_file ~tool_name Ast_invariants.signature - InterfaceHooks.apply_hooks Signature ppf sourcefile + Timings.(time_call (Parsing sourcefile)) (fun () -> + parse_file ~tool_name Ast_invariants.signature + InterfaceHooks.apply_hooks Signature ppf sourcefile) diff --git a/emacs/caml-types.el b/emacs/caml-types.el index 306fa5c5..cc5d9152 100644 --- a/emacs/caml-types.el +++ b/emacs/caml-types.el @@ -221,7 +221,7 @@ See `caml-types-location-re' for annotation file format." (right (caml-types-get-pos target-buf (elt node 1))) (kind (cdr (assoc "call" (elt node 2))))) (move-overlay caml-types-expr-ovl left right target-buf) - (caml-types-feedback kind))))) + (caml-types-feedback kind "%s call"))))) (if (and (= arg 4) (not (window-live-p (get-buffer-window caml-types-buffer)))) (display-buffer caml-types-buffer)) diff --git a/lex/output.ml b/lex/output.ml index 17df3b3e..9716a2aa 100644 --- a/lex/output.ml +++ b/lex/output.ml @@ -50,22 +50,22 @@ let output_byte_array oc v = let output_tables oc tbl = output_string oc "let __ocaml_lex_tables = {\n"; - fprintf oc " Lexing.lex_base = \n%a;\n" output_array tbl.tbl_base; - fprintf oc " Lexing.lex_backtrk = \n%a;\n" output_array tbl.tbl_backtrk; - fprintf oc " Lexing.lex_default = \n%a;\n" output_array tbl.tbl_default; - fprintf oc " Lexing.lex_trans = \n%a;\n" output_array tbl.tbl_trans; - fprintf oc " Lexing.lex_check = \n%a;\n" output_array tbl.tbl_check; - fprintf oc " Lexing.lex_base_code = \n%a;\n" output_array tbl.tbl_base_code; - - fprintf oc " Lexing.lex_backtrk_code = \n%a;\n" + fprintf oc " Lexing.lex_base =\n%a;\n" output_array tbl.tbl_base; + fprintf oc " Lexing.lex_backtrk =\n%a;\n" output_array tbl.tbl_backtrk; + fprintf oc " Lexing.lex_default =\n%a;\n" output_array tbl.tbl_default; + fprintf oc " Lexing.lex_trans =\n%a;\n" output_array tbl.tbl_trans; + fprintf oc " Lexing.lex_check =\n%a;\n" output_array tbl.tbl_check; + fprintf oc " Lexing.lex_base_code =\n%a;\n" output_array tbl.tbl_base_code; + + fprintf oc " Lexing.lex_backtrk_code =\n%a;\n" output_array tbl.tbl_backtrk_code; - fprintf oc " Lexing.lex_default_code = \n%a;\n" + fprintf oc " Lexing.lex_default_code =\n%a;\n" output_array tbl.tbl_default_code; - fprintf oc " Lexing.lex_trans_code = \n%a;\n" + fprintf oc " Lexing.lex_trans_code =\n%a;\n" output_array tbl.tbl_trans_code; - fprintf oc " Lexing.lex_check_code = \n%a;\n" + fprintf oc " Lexing.lex_check_code =\n%a;\n" output_array tbl.tbl_check_code; - fprintf oc " Lexing.lex_code = \n%a;\n" output_byte_array tbl.tbl_code; + fprintf oc " Lexing.lex_code =\n%a;\n" output_byte_array tbl.tbl_code; output_string oc "}\n\n" @@ -74,20 +74,21 @@ let output_tables oc tbl = let output_entry ic oc has_refill oci e = let init_num, init_moves = e.auto_initial_state in - fprintf oc "%s %alexbuf =\ -\n %a%a __ocaml_lex_%s_rec %alexbuf %d\n" + fprintf oc + "%s %alexbuf =\ + \n %a%a __ocaml_lex_%s_rec %alexbuf %d\n" e.auto_name - output_args e.auto_args + output_args e.auto_args (fun oc x -> if x > 0 then - fprintf oc "lexbuf.Lexing.lex_mem <- Array.make %d (-1) ; " x) + fprintf oc "lexbuf.Lexing.lex_mem <- Array.make %d (-1);" x) e.auto_mem_size (output_memory_actions " ") init_moves e.auto_name output_args e.auto_args init_num; fprintf oc "and __ocaml_lex_%s_rec %alexbuf __ocaml_lex_state =\n" - e.auto_name output_args e.auto_args ; + e.auto_name output_args e.auto_args; fprintf oc " match Lexing.%sengine" (if e.auto_mem_size == 0 then "" else "new_"); fprintf oc " __ocaml_lex_tables __ocaml_lex_state lexbuf with\n "; @@ -101,13 +102,13 @@ let output_entry ic oc has_refill oci e = e.auto_actions; if has_refill then fprintf oc - " | __ocaml_lex_state -> __ocaml_lex_refill \ - \n (fun lexbuf -> lexbuf.Lexing.refill_buff lexbuf; \ + " | __ocaml_lex_state -> __ocaml_lex_refill\ + \n (fun lexbuf -> lexbuf.Lexing.refill_buff lexbuf;\ \n __ocaml_lex_%s_rec %alexbuf __ocaml_lex_state) lexbuf\n\n" e.auto_name output_args e.auto_args else fprintf oc - " | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; \ + " | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf;\ \n __ocaml_lex_%s_rec %alexbuf __ocaml_lex_state\n\n" e.auto_name output_args e.auto_args @@ -131,7 +132,7 @@ let output_lexdef ic oc oci header rh tables entry_points trailer = Array.length tables.tbl_check_code) + Array.length tables.tbl_code) in if size_groups > 0 && not !Common.quiet_mode then - Printf.printf "%d additional bytes used for bindings\n" size_groups ; + Printf.printf "%d additional bytes used for bindings\n" size_groups; flush stdout; if Array.length tables.tbl_trans > 0x8000 then raise Table_overflow; copy_chunk ic oc oci header false; diff --git a/man/ocamlc.m b/man/ocamlc.m index 23c98170..4d76da9d 100644 --- a/man/ocamlc.m +++ b/man/ocamlc.m @@ -282,6 +282,9 @@ and the current heuristic checks that the "TERM" environment variable exists and is not empty or "dumb", and that isatty(stderr) holds. +The environment variable "OCAML_COLOR" is considered if \-color is not +provided. Its values are auto/always/never as above. + .TP .B \-compat\-32 Check that the generated bytecode executable can run on 32-bit @@ -312,6 +315,11 @@ Never use the command on executables produced by .BR ocamlc\ \-custom , this would remove the bytecode part of the executable. + +Security warning: never set the "setuid" or "setgid" bits on +executables produced by +.BR ocamlc\ \-custom , +this would make them vulnerable to attacks. .TP .BI \-dllib\ \-l libname Arrange for the C shared library @@ -425,6 +433,12 @@ setting the .B \-linkall option forces all subsequent links of programs involving that library to link all the modules contained in the library. +When compiling a module (option +.BR \-c ), +setting the +.B \-linkall +option ensures that this module will +always be linked if it is put in a library and this library is linked. .TP .B \-make\-runtime Build a custom runtime system (in the file specified by option @@ -493,6 +507,14 @@ file, without linking, in which case it sets the name of the cmi or cmo file, and also sets the module name to the file name up to the first dot. .TP +.B \-opaque +Interface file compiled with this option are marked so that other +compilation units depending on it will not rely on any implementation +details of the compiled implementation. The native compiler will not +access the .cmx file of this unit -- nor warn if it is absent. This can +improve speed of compilation, for both initial and incremental builds, +at the expense of performance of the generated code. +.TP .BI \-open \ module Opens the given module before processing the interface or implementation files. If several diff --git a/man/ocamldep.m b/man/ocamldep.m index ee6a641a..a47cb397 100644 --- a/man/ocamldep.m +++ b/man/ocamldep.m @@ -155,6 +155,23 @@ Assume that module is opened before parsing each of the following files. .TP +.BI \-plugin \ plugin +Dynamically load the code of the given +.I plugin +(a .cmo, .cma or .cmxs file) in +.BR ocamldep (1). +The plugin must exist in +the same kind of code as the tool ( +.BR ocamldep.byte +must load bytecode +plugins, while +.BR ocamldep.opt +must load native code plugins), and +extension adaptation is done automatically for .cma files (to .cmxs files +if +.BR ocamldep (1) +is compiled in native code). +.TP .BI \-pp \ command Cause .BR ocamldep (1) diff --git a/man/ocamlopt.m b/man/ocamlopt.m index f3fb3470..c5278d46 100644 --- a/man/ocamlopt.m +++ b/man/ocamlopt.m @@ -217,6 +217,30 @@ Pass the given option to the C compiler and linker. For instance, causes the C linker to search for C libraries in directory .IR dir . +.TP +.BI \-color \ mode +Enable or disable colors in compiler messages (especially warnings and errors). +The following modes are supported: + +.B auto +use heuristics to enable colors only if the output supports them (an +ANSI-compatible tty terminal); + +.B always +enable colors unconditionally; + +.B never +disable color output. + +The default setting is +.B auto, +and the current heuristic +checks that the "TERM" environment variable exists and is +not empty or "dumb", and that isatty(stderr) holds. + +The environment variable "OCAML_COLOR" is considered if \-color is not +provided. Its values are auto/always/never as above. + .TP .B \-compact Optimize the produced code for space rather than for time. This @@ -326,6 +350,12 @@ flag), setting the flag forces all subsequent links of programs involving that library to link all the modules contained in the library. +When compiling a module (option +.BR \-c ), +setting the +.B \-linkall +option ensures that this module will +always be linked if it is put in a library and this library is linked. .TP .B \-no-alias-deps Do not record dependencies for module aliases. @@ -383,6 +413,13 @@ file, without linking, in which case it sets the name of the cmi or cmo file, and also sets the module name to the file name up to the first dot. .TP +.B \-opaque +When compiling a .mli interface file, this has the same effect as the +.B \-opaque +option of the bytecode compiler. When compiling a .ml implementation +file, this produces a .cmx file without cross-module optimization +information, which reduces recompilation on module change. +.TP .BI \-open \ module Opens the given module before processing the interface or implementation files. If several diff --git a/middle_end/base_types/set_of_closures_id.ml b/middle_end/base_types/set_of_closures_id.ml index d6ac221c..52db870a 100644 --- a/middle_end/base_types/set_of_closures_id.ml +++ b/middle_end/base_types/set_of_closures_id.ml @@ -25,3 +25,4 @@ include Identifiable.Make (Unit_id) let create = Unit_id.create let get_compilation_unit = Unit_id.unit +let name = Unit_id.name diff --git a/middle_end/base_types/set_of_closures_id.mli b/middle_end/base_types/set_of_closures_id.mli index 724c6416..811cb661 100755 --- a/middle_end/base_types/set_of_closures_id.mli +++ b/middle_end/base_types/set_of_closures_id.mli @@ -22,4 +22,5 @@ include Identifiable.S val create : ?name:string -> Compilation_unit.t -> t +val name : t -> string option val get_compilation_unit : t -> Compilation_unit.t diff --git a/middle_end/base_types/set_of_closures_origin.ml b/middle_end/base_types/set_of_closures_origin.ml index ce10a740..9e7db69f 100644 --- a/middle_end/base_types/set_of_closures_origin.ml +++ b/middle_end/base_types/set_of_closures_origin.ml @@ -19,3 +19,4 @@ include Set_of_closures_id let create t = t +let rename f t = f t diff --git a/middle_end/base_types/set_of_closures_origin.mli b/middle_end/base_types/set_of_closures_origin.mli index 2f2c6341..4c9cfdcf 100644 --- a/middle_end/base_types/set_of_closures_origin.mli +++ b/middle_end/base_types/set_of_closures_origin.mli @@ -19,3 +19,4 @@ include Identifiable.S val create : Set_of_closures_id.t -> t val get_compilation_unit : t -> Compilation_unit.t +val rename : (Set_of_closures_id.t -> Set_of_closures_id.t) -> t -> t diff --git a/middle_end/closure_conversion.ml b/middle_end/closure_conversion.ml index 93f907f5..2a6a2bcc 100755 --- a/middle_end/closure_conversion.ml +++ b/middle_end/closure_conversion.ml @@ -32,17 +32,6 @@ type t = { } let add_default_argument_wrappers lam = - (* CR-someday mshinwell: Temporary hack to mark default argument wrappers - as stubs. Other possibilities: - 1. Change Lambda.inline_attribute to add another ("stub") case; - 2. Add a "stub" field to the Lfunction record. *) - let stubify body : Lambda.lambda = - let stub_prim = - Primitive.simple ~name:Closure_conversion_aux.stub_hack_prim_name - ~arity:1 ~alloc:false - in - Lprim (Pccall stub_prim, [body], Location.none) - in let defs_are_all_functions (defs : (_ * Lambda.lambda) list) = List.for_all (function (_, Lambda.Lfunction _) -> true | _ -> false) defs in @@ -51,9 +40,8 @@ let add_default_argument_wrappers lam = | Llet (( Strict | Alias | StrictOpt), _k, id, Lfunction {kind; params; body = fbody; attr; loc}, body) -> begin match - Simplif.split_default_wrapper ~id ~kind ~params ~body:fbody - ~attr ~wrapper_attr:Lambda.default_function_attribute - ~loc ~create_wrapper_body:stubify () + Simplif.split_default_wrapper ~id ~kind ~params + ~body:fbody ~attr ~loc with | [fun_id, def] -> Llet (Alias, Pgenval, fun_id, def, body) | [fun_id, def; inner_fun_id, def_inner] -> @@ -69,8 +57,7 @@ let add_default_argument_wrappers lam = (function | (id, Lambda.Lfunction {kind; params; body; attr; loc}) -> Simplif.split_default_wrapper ~id ~kind ~params ~body - ~attr ~wrapper_attr:Lambda.default_function_attribute - ~loc ~create_wrapper_body:stubify () + ~attr ~loc | _ -> assert false) defs) in @@ -218,8 +205,7 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t = let set_of_closures = let decl = Function_decl.create ~let_rec_ident:None ~closure_bound_var ~kind - ~params ~body ~inline:attr.inline ~specialise:attr.specialise - ~is_a_functor:attr.is_a_functor ~loc + ~params ~body ~attr ~loc in close_functions t env (Function_decls.create [decl]) in @@ -266,8 +252,7 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t = let function_declaration = Function_decl.create ~let_rec_ident:(Some let_rec_ident) ~closure_bound_var ~kind ~params ~body - ~inline:attr.inline ~specialise:attr.specialise - ~is_a_functor:attr.is_a_functor ~loc + ~attr ~loc in Some function_declaration | _ -> None) @@ -577,11 +562,7 @@ and close_functions t external_env function_declarations : Flambda.named = argument with a default value, make sure it always gets inlined. CR-someday pchambart: eta-expansion wrapper for a primitive are not marked as stub but certainly should *) - let stub, body = - match Function_decl.primitive_wrapper decl with - | None -> false, body - | Some wrapper_body -> true, wrapper_body - in + let stub = Function_decl.stub decl in let params = List.map (Env.find_var closure_env) params in let closure_bound_var = Function_decl.closure_bound_var decl in let body = close t closure_env body in @@ -641,8 +622,7 @@ and close_let_bound_expression t ?let_rec_ident let_bound_var env let closure_bound_var = Variable.rename let_bound_var in let decl = Function_decl.create ~let_rec_ident ~closure_bound_var ~kind ~params - ~body ~inline:attr.inline ~specialise:attr.specialise - ~is_a_functor:attr.is_a_functor ~loc + ~body ~attr ~loc in let set_of_closures_var = Variable.rename let_bound_var ~append:"_set_of_closures" diff --git a/middle_end/closure_conversion_aux.ml b/middle_end/closure_conversion_aux.ml index becac905..2dbc38e3 100644 --- a/middle_end/closure_conversion_aux.ml +++ b/middle_end/closure_conversion_aux.ml @@ -82,8 +82,6 @@ module Env = struct let not_at_toplevel t = { t with at_toplevel = false; } end -let stub_hack_prim_name = "*stub*" - module Function_decls = struct module Function_decl = struct type t = { @@ -93,14 +91,12 @@ module Function_decls = struct params : Ident.t list; body : Lambda.lambda; free_idents_of_body : IdentSet.t; - inline : Lambda.inline_attribute; - specialise : Lambda.specialise_attribute; - is_a_functor : bool; + attr : Lambda.function_attribute; loc : Location.t; } - let create ~let_rec_ident ~closure_bound_var ~kind ~params ~body ~inline - ~specialise ~is_a_functor ~loc = + let create ~let_rec_ident ~closure_bound_var ~kind ~params ~body + ~attr ~loc = let let_rec_ident = match let_rec_ident with | None -> Ident.create "unnamed_function" @@ -112,9 +108,7 @@ module Function_decls = struct params; body; free_idents_of_body = Lambda.free_variables body; - inline; - specialise; - is_a_functor; + attr; loc; } @@ -124,16 +118,12 @@ module Function_decls = struct let params t = t.params let body t = t.body let free_idents t = t.free_idents_of_body - let inline t = t.inline - let specialise t = t.specialise - let is_a_functor t = t.is_a_functor + let inline t = t.attr.inline + let specialise t = t.attr.specialise + let is_a_functor t = t.attr.is_a_functor + let stub t = t.attr.stub let loc t = t.loc - let primitive_wrapper t = - match t.body with - | Lprim (Pccall { Primitive. prim_name; }, [body], _) - when prim_name = stub_hack_prim_name -> Some body - | _ -> None end type t = { diff --git a/middle_end/closure_conversion_aux.mli b/middle_end/closure_conversion_aux.mli index b51ef52a..67ba1e11 100755 --- a/middle_end/closure_conversion_aux.mli +++ b/middle_end/closure_conversion_aux.mli @@ -58,9 +58,7 @@ module Function_decls : sig -> kind:Lambda.function_kind -> params:Ident.t list -> body:Lambda.lambda - -> inline:Lambda.inline_attribute - -> specialise:Lambda.specialise_attribute - -> is_a_functor:bool + -> attr:Lambda.function_attribute -> loc:Location.t -> t @@ -72,13 +70,9 @@ module Function_decls : sig val inline : t -> Lambda.inline_attribute val specialise : t -> Lambda.specialise_attribute val is_a_functor : t -> bool + val stub : t -> bool val loc : t -> Location.t - (* [primitive_wrapper t] is [None] iff [t] is not a wrapper for a function - with default optional arguments. Otherwise it is [Some body], where - [body] is the body of the wrapper. *) - val primitive_wrapper : t -> Lambda.lambda option - (* Like [all_free_idents], but for just one function. *) val free_idents : t -> Lambda.IdentSet.t end @@ -98,5 +92,3 @@ module Function_decls : sig It also contains the globals bindings of the provided environment. *) val closure_env_without_parameters : Env.t -> t -> Env.t end - -val stub_hack_prim_name : string diff --git a/middle_end/debuginfo.ml b/middle_end/debuginfo.ml index a93f4258..d979cc1e 100644 --- a/middle_end/debuginfo.ml +++ b/middle_end/debuginfo.ml @@ -76,6 +76,11 @@ let inline loc t = let concat dbg1 dbg2 = dbg1 @ dbg2 +(* CR-someday afrisch: FWIW, the current compare function does not seem very + good, since it reverses the two lists. I don't know how long the lists are, + nor if the specific currently implemented ordering is useful in other + contexts, but if one wants to use Map, a more efficient comparison should + be considered. *) let compare dbg1 dbg2 = let rec loop ds1 ds2 = match ds1, ds2 with @@ -94,3 +99,23 @@ let compare dbg1 dbg2 = loop ds1 ds2 in loop (List.rev dbg1) (List.rev dbg2) + +let hash t = + List.fold_left (fun hash item -> Hashtbl.hash (hash, item)) 0 t + +let rec print_compact ppf t = + let print_item item = + Format.fprintf ppf "%a:%i" + Location.print_filename item.dinfo_file + item.dinfo_line; + if item.dinfo_char_start >= 0 then begin + Format.fprintf ppf ",%i--%i" item.dinfo_char_start item.dinfo_char_end + end + in + match t with + | [] -> () + | [item] -> print_item item + | item::t -> + print_item item; + Format.fprintf ppf ";"; + print_compact ppf t diff --git a/middle_end/debuginfo.mli b/middle_end/debuginfo.mli index 993928c0..26a8bb19 100644 --- a/middle_end/debuginfo.mli +++ b/middle_end/debuginfo.mli @@ -37,3 +37,7 @@ val concat: t -> t -> t val inline: Location.t -> t -> t val compare : t -> t -> int + +val hash : t -> int + +val print_compact : Format.formatter -> t -> unit diff --git a/middle_end/flambda.ml b/middle_end/flambda.ml index b26de62e..68bd83b7 100644 --- a/middle_end/flambda.ml +++ b/middle_end/flambda.ml @@ -1036,6 +1036,15 @@ let update_function_declarations function_decls ~funs = funs; } +let import_function_declarations_for_pack function_decls + import_set_of_closures_id import_set_of_closures_origin = + { set_of_closures_id = + import_set_of_closures_id function_decls.set_of_closures_id; + set_of_closures_origin = + import_set_of_closures_origin function_decls.set_of_closures_origin; + funs = function_decls.funs; + } + let create_set_of_closures ~function_decls ~free_vars ~specialised_args ~direct_call_surrogates = if !Clflags.flambda_invariant_checks then begin diff --git a/middle_end/flambda.mli b/middle_end/flambda.mli index 6826e9ee..4ad1a765 100755 --- a/middle_end/flambda.mli +++ b/middle_end/flambda.mli @@ -567,6 +567,12 @@ val update_function_declarations -> funs:function_declaration Variable.Map.t -> function_declarations +val import_function_declarations_for_pack + : function_declarations + -> (Set_of_closures_id.t -> Set_of_closures_id.t) + -> (Set_of_closures_origin.t -> Set_of_closures_origin.t) + -> function_declarations + (** Create a set of closures. Checks are made to ensure that [free_vars] and [specialised_args] are reasonable. *) val create_set_of_closures diff --git a/middle_end/flambda_invariants.ml b/middle_end/flambda_invariants.ml index bde0b881..42fa15c2 100755 --- a/middle_end/flambda_invariants.ml +++ b/middle_end/flambda_invariants.ml @@ -77,6 +77,7 @@ exception Access_to_global_module_identifier of Lambda.primitive exception Pidentity_should_not_occur exception Pdirapply_should_be_expanded exception Prevapply_should_be_expanded +exception Ploc_should_be_expanded exception Sequential_logical_operator_primitives_must_be_expanded of Lambda.primitive exception Var_within_closure_bound_multiple_times of Var_within_closure.t @@ -468,6 +469,7 @@ let primitive_invariants flam ~no_access_to_global_module_identifiers = | Pidentity -> raise Pidentity_should_not_occur | Pdirapply -> raise Pdirapply_should_be_expanded | Prevapply -> raise Prevapply_should_be_expanded + | Ploc _ -> raise Ploc_should_be_expanded | _ -> () end | _ -> ()) @@ -809,10 +811,13 @@ let check_exn ?(kind=Normal) ?(cmxfile=false) (flam:Flambda.program) = Flambda expression (see closure_conversion.ml)" | Pdirapply_should_be_expanded -> Format.eprintf ">> The Pdirapply primitive should never occur in an \ - Flambda expression (see closure_conversion.ml); use Apply instead" + Flambda expression (see simplif.ml); use Apply instead" | Prevapply_should_be_expanded -> Format.eprintf ">> The Prevapply primitive should never occur in an \ - Flambda expression (see closure_conversion.ml); use Apply instead" + Flambda expression (see simplif.ml); use Apply instead" + | Ploc_should_be_expanded -> + Format.eprintf ">> The Ploc primitive should never occur in an \ + Flambda expression (see translcore.ml); use Apply instead" | Move_to_a_closure_not_in_the_free_variables (start_from, move_to) -> Format.eprintf ">> A Move_within_set_of_closures from the closure %a \ to closures that are not parts of its free variables: %a" diff --git a/middle_end/inline_and_simplify.ml b/middle_end/inline_and_simplify.ml index 75b47a1a..20264e00 100755 --- a/middle_end/inline_and_simplify.ml +++ b/middle_end/inline_and_simplify.ml @@ -212,14 +212,14 @@ let simplify_project_closure env r ~(project_closure : Flambda.project_closure) | Wrong -> Misc.fatal_errorf "Wrong approximation when projecting closure: %a" Flambda.print_project_closure project_closure - | Unresolved symbol -> + | Unresolved value -> (* A set of closures coming from another compilation unit, whose .cmx is missing; as such, we cannot have rewritten the function and don't need to do any freshening. *) Project_closure { set_of_closures; closure_id = project_closure.closure_id; - }, ret r (A.value_unresolved symbol) + }, ret r (A.value_unresolved value) | Unknown -> (* CR-soon mshinwell: see CR comment in e.g. simple_value_approx.ml [check_approx_for_closure_allowing_unresolved] *) @@ -227,11 +227,11 @@ let simplify_project_closure env r ~(project_closure : Flambda.project_closure) set_of_closures; closure_id = project_closure.closure_id; }, ret r (A.value_unknown Other) - | Unknown_because_of_unresolved_symbol symbol -> + | Unknown_because_of_unresolved_value value -> Project_closure { set_of_closures; closure_id = project_closure.closure_id; - }, ret r (A.value_unknown (Unresolved_symbol symbol)) + }, ret r (A.value_unknown (Unresolved_value value)) | Ok (set_of_closures_var, value_set_of_closures) -> let closure_id = A.freshen_and_check_closure_id value_set_of_closures @@ -300,7 +300,7 @@ let simplify_move_within_set_of_closures env r move_to = move_within_set_of_closures.move_to; }, ret r (A.value_unknown Other) - | Unknown_because_of_unresolved_symbol sym -> + | Unknown_because_of_unresolved_value value -> (* For example: a move upon a (move upon a closure whose .cmx file is missing). *) Move_within_set_of_closures { @@ -308,7 +308,7 @@ let simplify_move_within_set_of_closures env r start_from = move_within_set_of_closures.start_from; move_to = move_within_set_of_closures.move_to; }, - ret r (A.value_unknown (Unresolved_symbol sym)) + ret r (A.value_unknown (Unresolved_value value)) | Ok (_value_closure, set_of_closures_var, set_of_closures_symbol, value_set_of_closures) -> let freshen = @@ -491,9 +491,9 @@ let rec simplify_project_var env r ~(project_var : Flambda.project_var) | Unknown -> Project_var { project_var with closure }, ret r (A.value_unknown Other) - | Unknown_because_of_unresolved_symbol symbol -> + | Unknown_because_of_unresolved_value value -> Project_var { project_var with closure }, - ret r (A.value_unknown (Unresolved_symbol symbol)) + ret r (A.value_unknown (Unresolved_value value)) | Wrong -> (* We must have the correct approximation of the value to ensure we take account of all freshenings. *) @@ -989,6 +989,7 @@ and simplify_named env r (tree : Flambda.named) : Flambda.named * R.t = begin match prim, args, args_approxs with | Pgetglobal _, _, _ -> Misc.fatal_error "Pgetglobal is forbidden in Inline_and_simplify" + (* CR-someday mshinwell: Optimise [Pfield_computed]. *) | Pfield field_index, [arg], [arg_approx] -> let projection : Projection.t = Field (field_index, arg) in begin match E.find_projection env ~projection with @@ -1437,7 +1438,7 @@ let constant_defining_value_approx | Flambda.Symbol sym -> begin match E.find_symbol_opt env sym with | Some approx -> approx - | None -> A.value_unresolved sym + | None -> A.value_unresolved (Symbol sym) end | Flambda.Const cst -> simplify_const cst) fields @@ -1466,7 +1467,7 @@ let constant_defining_value_approx | Project_closure (set_of_closures_symbol, closure_id) -> begin match E.find_symbol_opt env set_of_closures_symbol with | None -> - A.value_unresolved set_of_closures_symbol + A.value_unresolved (Symbol set_of_closures_symbol) | Some set_of_closures_approx -> let checked_approx = A.check_approx_for_set_of_closures set_of_closures_approx @@ -1479,8 +1480,8 @@ let constant_defining_value_approx A.value_closure value_set_of_closures closure_id | Unresolved sym -> A.value_unresolved sym | Unknown -> A.value_unknown Other - | Unknown_because_of_unresolved_symbol sym -> - A.value_unknown (Unresolved_symbol sym) + | Unknown_because_of_unresolved_value value -> + A.value_unknown (Unresolved_value value) | Wrong -> Misc.fatal_errorf "Wrong approximation for [Project_closure] \ when being used as a [constant_defining_value]: %a" @@ -1492,7 +1493,7 @@ let define_let_rec_symbol_approx env defs = (* First declare an empty version of the symbols *) let env = List.fold_left (fun env (symbol, _) -> - E.add_symbol env symbol (A.value_unresolved symbol)) + E.add_symbol env symbol (A.value_unresolved (Symbol symbol))) env defs in let rec loop times env = @@ -1552,8 +1553,8 @@ let simplify_constant_defining_value A.value_closure value_set_of_closures closure_id | Unresolved sym -> A.value_unresolved sym | Unknown -> A.value_unknown Other - | Unknown_because_of_unresolved_symbol sym -> - A.value_unknown (Unresolved_symbol sym) + | Unknown_because_of_unresolved_value value -> + A.value_unknown (Unresolved_value value) | Wrong -> Misc.fatal_errorf "Wrong approximation for [Project_closure] \ when being used as a [constant_defining_value]: %a" diff --git a/middle_end/inlining_cost.ml b/middle_end/inlining_cost.ml index 9c049eff..696a7646 100644 --- a/middle_end/inlining_cost.ml +++ b/middle_end/inlining_cost.ml @@ -27,8 +27,8 @@ let prim_size (prim : Lambda.primitive) args = | Pfield _ -> 1 | Psetfield (_, isptr, init) -> begin match init with - | Initialization -> 1 (* never causes a write barrier hit *) - | Assignment -> + | Root_initialization -> 1 (* never causes a write barrier hit *) + | Assignment | Heap_initialization -> match isptr with | Pointer -> 4 | Immediate -> 1 diff --git a/middle_end/inlining_decision.ml b/middle_end/inlining_decision.ml index 730419b2..d0dadee4 100755 --- a/middle_end/inlining_decision.ml +++ b/middle_end/inlining_decision.ml @@ -104,7 +104,7 @@ let inline env r ~lhs_of_application | T.Never_inline -> assert false | T.Can_inline_if_no_larger_than threshold -> threshold in - Don't_try_it (S.Not_inlined.Function_obviously_too_large threshold) + Don't_try_it (S.Not_inlined.Above_threshold threshold) else if not (toplevel && branch_depth = 0) && A.all_not_useful (E.find_list_exn env args) then (* When all of the arguments to the function being inlined are unknown, @@ -173,7 +173,7 @@ let inline env r ~lhs_of_application should already have been simplified (inside its declaration), so we also expect no gain from the code below that permits inlining inside the body. *) - Don't_try_it S.Not_inlined.Unspecialised + Don't_try_it S.Not_inlined.No_useful_approximations else begin (* There are useful approximations, so we should simplify. *) Try_it @@ -374,7 +374,7 @@ let specialise env r ~lhs_of_application | T.Never_inline -> assert false | T.Can_inline_if_no_larger_than threshold -> threshold in - Don't_try_it (S.Not_specialised.Function_obviously_too_large threshold) + Don't_try_it (S.Not_specialised.Above_threshold threshold) else if not (Var_within_closure.Map.is_empty (Lazy.force bound_vars)) then Don't_try_it S.Not_specialised.Not_closed else if not (Lazy.force recursive) then diff --git a/middle_end/inlining_stats_types.ml b/middle_end/inlining_stats_types.ml index 568c5d83..ce434f1d 100644 --- a/middle_end/inlining_stats_types.ml +++ b/middle_end/inlining_stats_types.ml @@ -73,9 +73,9 @@ end module Not_inlined = struct type t = | Classic_mode - | Function_obviously_too_large of int + | Above_threshold of int | Annotation - | Unspecialised + | No_useful_approximations | Unrolling_depth_exceeded | Self_call | Without_subfunctions of Wsb.t @@ -86,19 +86,20 @@ module Not_inlined = struct | Classic_mode -> Format.pp_print_text ppf "This function was prevented from inlining by `-Oclassic'." - | Function_obviously_too_large size -> + | Above_threshold size -> Format.pp_print_text ppf "This function was not inlined because \ - it was obviously too large"; + it was larger than the current size threshold"; Format.fprintf ppf "(%i)" size | Annotation -> Format.pp_print_text ppf "This function was not inlined because \ of an annotation." - | Unspecialised -> + | No_useful_approximations -> Format.pp_print_text ppf "This function was not inlined because \ - its parameters could not be specialised." + there was no useful information about any of its parameters, \ + and it was not particularly small." | Unrolling_depth_exceeded -> Format.pp_print_text ppf "This function was not inlined because \ @@ -118,9 +119,9 @@ module Not_inlined = struct let calculation ~depth ppf = function | Classic_mode - | Function_obviously_too_large _ + | Above_threshold _ | Annotation - | Unspecialised + | No_useful_approximations | Unrolling_depth_exceeded | Self_call -> () | Without_subfunctions wsb -> @@ -169,7 +170,7 @@ end module Not_specialised = struct type t = | Classic_mode - | Function_obviously_too_large of int + | Above_threshold of int | Annotation | Not_recursive | Not_closed @@ -183,10 +184,10 @@ module Not_specialised = struct Format.pp_print_text ppf "This function was prevented from specialising by \ `-Oclassic'." - | Function_obviously_too_large size -> + | Above_threshold size -> Format.pp_print_text ppf "This function was not specialised because \ - it was obviously too large"; + it was larger than the current size threshold"; Format.fprintf ppf "(%i)" size | Annotation -> Format.pp_print_text ppf @@ -220,7 +221,7 @@ module Not_specialised = struct let calculation ~depth ppf = function | Classic_mode - | Function_obviously_too_large _ + | Above_threshold _ | Annotation | Not_recursive | Not_closed diff --git a/middle_end/inlining_stats_types.mli b/middle_end/inlining_stats_types.mli index c0915228..1c0a20e1 100644 --- a/middle_end/inlining_stats_types.mli +++ b/middle_end/inlining_stats_types.mli @@ -32,9 +32,9 @@ end module Not_inlined : sig type t = | Classic_mode - | Function_obviously_too_large of int + | Above_threshold of int | Annotation - | Unspecialised + | No_useful_approximations | Unrolling_depth_exceeded | Self_call | Without_subfunctions of @@ -57,7 +57,7 @@ end module Not_specialised : sig type t = | Classic_mode - | Function_obviously_too_large of int + | Above_threshold of int | Annotation | Not_recursive | Not_closed diff --git a/middle_end/lift_constants.ml b/middle_end/lift_constants.ml index 6d137e19..4059e3cd 100644 --- a/middle_end/lift_constants.ml +++ b/middle_end/lift_constants.ml @@ -841,9 +841,15 @@ let replace_definitions_in_initialize_symbol_and_effects var_to_definition_tbl var in - match resolved with - | Symbol s -> Symbol s - | Const c -> Const c) + match named, resolved with + | Symbol s1, Symbol s2 -> + assert (s1 == s2); (* physical equality for speed *) + named; + | Const c1, Const c2 -> + assert (c1 == c2); + named + | _, Symbol s -> Symbol s + | _, Const c -> Const c) in (* This is safe because we only [replace] the current key during iteration (cf. https://github.com/ocaml/ocaml/pull/337) *) diff --git a/middle_end/middle_end.ml b/middle_end/middle_end.ml index c6646abf..901c96a6 100644 --- a/middle_end/middle_end.ml +++ b/middle_end/middle_end.ml @@ -91,11 +91,11 @@ let middle_end ppf ~source_provenance ~prefixname ~backend +-+ ("Inline_and_simplify", Inline_and_simplify.run ~never_inline:false ~backend ~prefixname ~round) - +-+ ("Ref_to_variables", - Ref_to_variables.eliminate_ref) +-+ ("Remove_unused_closure_vars 2", Remove_unused_closure_vars.remove_unused_closure_variables ~remove_direct_call_surrogates:false) + +-+ ("Ref_to_variables", + Ref_to_variables.eliminate_ref) +-+ ("Initialize_symbol_to_let_symbol", Initialize_symbol_to_let_symbol.run) in @@ -126,14 +126,14 @@ let middle_end ppf ~source_provenance ~prefixname ~backend Remove_unused_closure_vars.remove_unused_closure_variables ~remove_direct_call_surrogates:false) +-+ ("lift_lets 3", Lift_code.lift_lets) - +-+ ("Ref_to_variables", - Ref_to_variables.eliminate_ref) +-+ ("Inline_and_simplify noinline", Inline_and_simplify.run ~never_inline:true ~backend ~prefixname ~round) +-+ ("Remove_unused_closure_vars 3", Remove_unused_closure_vars.remove_unused_closure_variables ~remove_direct_call_surrogates:false) + +-+ ("Ref_to_variables", + Ref_to_variables.eliminate_ref) +-+ ("Initialize_symbol_to_let_symbol", Initialize_symbol_to_let_symbol.run) |> loop diff --git a/middle_end/simple_value_approx.ml b/middle_end/simple_value_approx.ml index 4d928466..43c7f92e 100644 --- a/middle_end/simple_value_approx.ml +++ b/middle_end/simple_value_approx.ml @@ -29,8 +29,12 @@ type value_string = { size : int; } +type unresolved_value = + | Set_of_closures_id of Set_of_closures_id.t + | Symbol of Symbol.t + type unknown_because_of = - | Unresolved_symbol of Symbol.t + | Unresolved_value of unresolved_value | Other type t = { @@ -54,7 +58,8 @@ and descr = | Value_bottom | Value_extern of Export_id.t | Value_symbol of Symbol.t - | Value_unresolved of Symbol.t (* No description was found for this symbol *) + | Value_unresolved of unresolved_value + (* No description was found for this value *) and value_closure = { set_of_closures : t; @@ -89,6 +94,12 @@ let print_value_set_of_closures ppf (Variable.Map.print Variable.Set.print) (Lazy.force invariant_params) Freshening.Project_var.print freshening +let print_unresolved_value ppf = function + | Set_of_closures_id set -> + Format.fprintf ppf "Set_of_closures_id %a" Set_of_closures_id.print set + | Symbol symbol -> + Format.fprintf ppf "Symbol %a" Symbol.print symbol + let rec print_descr ppf = function | Value_int i -> Format.pp_print_int ppf i | Value_char c -> Format.fprintf ppf "%c" c @@ -99,8 +110,8 @@ let rec print_descr ppf = function Format.fprintf ppf "[%i:@ @[<1>%a@]]" (Tag.to_int tag) p fields | Value_unknown reason -> begin match reason with - | Unresolved_symbol symbol -> - Format.fprintf ppf "?(due to unresolved symbol '%a')" Symbol.print symbol + | Unresolved_value value -> + Format.fprintf ppf "?(due to unresolved %a)" print_unresolved_value value | Other -> Format.fprintf ppf "?" end; | Value_bottom -> Format.fprintf ppf "bottom" @@ -111,8 +122,8 @@ let rec print_descr ppf = function print set_of_closures | Value_set_of_closures set_of_closures -> print_value_set_of_closures ppf set_of_closures - | Value_unresolved sym -> - Format.fprintf ppf "(unresolved %a)" Symbol.print sym + | Value_unresolved value -> + Format.fprintf ppf "(unresolved %a)" print_unresolved_value value | Value_float (Some f) -> Format.pp_print_float ppf f | Value_float None -> Format.pp_print_string ppf "float" | Value_string { contents; size } -> begin @@ -272,7 +283,7 @@ let value_extern ex = approx (Value_extern ex) let value_symbol sym = { (approx (Value_symbol sym)) with symbol = Some (sym, None) } let value_bottom = approx Value_bottom -let value_unresolved sym = approx (Value_unresolved sym) +let value_unresolved value = approx (Value_unresolved value) let value_string size contents = approx (Value_string {size; contents }) let value_mutable_float_array ~size = @@ -527,10 +538,10 @@ let get_field t ~field_index:i : get_field_result = Ok (value_unknown Other) | Value_unknown reason -> Ok (value_unknown reason) - | Value_unresolved sym -> + | Value_unresolved value -> (* We don't know anything, but we must remember that it comes from another compilation unit in case it contains a closure. *) - Ok (value_unresolved sym) + Ok (value_unknown (Unresolved_value value)) type checked_approx_for_block = | Wrong @@ -660,16 +671,16 @@ let freshen_and_check_closure_id type checked_approx_for_set_of_closures = | Wrong - | Unresolved of Symbol.t + | Unresolved of unresolved_value | Unknown - | Unknown_because_of_unresolved_symbol of Symbol.t + | Unknown_because_of_unresolved_value of unresolved_value | Ok of Variable.t option * value_set_of_closures let check_approx_for_set_of_closures t : checked_approx_for_set_of_closures = match t.descr with - | Value_unresolved symbol -> Unresolved symbol - | Value_unknown (Unresolved_symbol symbol) -> - Unknown_because_of_unresolved_symbol symbol + | Value_unresolved value -> Unresolved value + | Value_unknown (Unresolved_value value) -> + Unknown_because_of_unresolved_value value | Value_set_of_closures value_set_of_closures -> (* Note that [var] might be [None]; we might be reaching the set of closures via approximations only, with the variable originally bound @@ -690,13 +701,13 @@ let strict_check_approx_for_set_of_closures t match check_approx_for_set_of_closures t with | Ok (var, value_set_of_closures) -> Ok (var, value_set_of_closures) | Wrong | Unresolved _ - | Unknown | Unknown_because_of_unresolved_symbol _ -> Wrong + | Unknown | Unknown_because_of_unresolved_value _ -> Wrong type checked_approx_for_closure_allowing_unresolved = | Wrong - | Unresolved of Symbol.t + | Unresolved of unresolved_value | Unknown - | Unknown_because_of_unresolved_symbol of Symbol.t + | Unknown_because_of_unresolved_value of unresolved_value | Ok of value_closure * Variable.t option * Symbol.t option * value_set_of_closures @@ -719,8 +730,8 @@ let check_approx_for_closure_allowing_unresolved t | Value_symbol _ -> Wrong end - | Value_unknown (Unresolved_symbol symbol) -> - Unknown_because_of_unresolved_symbol symbol + | Value_unknown (Unresolved_value value) -> + Unknown_because_of_unresolved_value value | Value_unresolved symbol -> Unresolved symbol | Value_set_of_closures _ | Value_block _ | Value_int _ | Value_char _ | Value_constptr _ | Value_float _ | Value_boxed_int _ @@ -742,7 +753,7 @@ let check_approx_for_closure t : checked_approx_for_closure = value_set_of_closures) -> Ok (value_closure, set_of_closures_var, set_of_closures_symbol, value_set_of_closures) - | Wrong | Unknown | Unresolved _ | Unknown_because_of_unresolved_symbol _ -> + | Wrong | Unknown | Unresolved _ | Unknown_because_of_unresolved_value _ -> Wrong let approx_for_bound_var value_set_of_closures var = diff --git a/middle_end/simple_value_approx.mli b/middle_end/simple_value_approx.mli index 36501b05..ec33239c 100644 --- a/middle_end/simple_value_approx.mli +++ b/middle_end/simple_value_approx.mli @@ -30,8 +30,12 @@ type value_string = { size : int; } +type unresolved_value = + | Set_of_closures_id of Set_of_closures_id.t + | Symbol of Symbol.t + type unknown_because_of = - | Unresolved_symbol of Symbol.t + | Unresolved_value of unresolved_value | Other (** A value of type [t] corresponds to an "approximation" of the result of @@ -131,7 +135,8 @@ and descr = private | Value_bottom | Value_extern of Export_id.t | Value_symbol of Symbol.t - | Value_unresolved of Symbol.t (* No description was found for this symbol *) + | Value_unresolved of unresolved_value + (* No description was found for this value *) and value_closure = { set_of_closures : t; @@ -203,7 +208,7 @@ val value_block : Tag.t -> t array -> t val value_extern : Export_id.t -> t val value_symbol : Symbol.t -> t val value_bottom : t -val value_unresolved : Symbol.t -> t +val value_unresolved : unresolved_value -> t (** Construct a closure approximation given the approximation of the corresponding set of closures and the closure ID of the closure to @@ -366,9 +371,9 @@ val strict_check_approx_for_set_of_closures type checked_approx_for_set_of_closures = | Wrong - | Unresolved of Symbol.t + | Unresolved of unresolved_value | Unknown - | Unknown_because_of_unresolved_symbol of Symbol.t + | Unknown_because_of_unresolved_value of unresolved_value (* In the [Ok] case, there may not be a variable associated with the set of closures; it might be out of scope. *) | Ok of Variable.t option * value_set_of_closures @@ -392,9 +397,9 @@ val check_approx_for_closure : t -> checked_approx_for_closure type checked_approx_for_closure_allowing_unresolved = | Wrong - | Unresolved of Symbol.t + | Unresolved of unresolved_value | Unknown - | Unknown_because_of_unresolved_symbol of Symbol.t + | Unknown_because_of_unresolved_value of unresolved_value | Ok of value_closure * Variable.t option * Symbol.t option * value_set_of_closures diff --git a/ocamldoc/.depend b/ocamldoc/.depend index 9aaef1f9..c9e0a329 100644 --- a/ocamldoc/.depend +++ b/ocamldoc/.depend @@ -1,3 +1,11 @@ +generators/odoc_literate.cmo : odoc_info.cmi odoc_html.cmo odoc_gen.cmi \ + odoc_args.cmi +generators/odoc_literate.cmx : odoc_info.cmx odoc_html.cmx odoc_gen.cmx \ + odoc_args.cmx +generators/odoc_todo.cmo : odoc_module.cmo odoc_info.cmi odoc_html.cmo \ + odoc_gen.cmi odoc_args.cmi +generators/odoc_todo.cmx : odoc_module.cmx odoc_info.cmx odoc_html.cmx \ + odoc_gen.cmx odoc_args.cmx odoc.cmo : odoc_messages.cmo odoc_info.cmi odoc_global.cmi odoc_gen.cmi \ odoc_config.cmi odoc_args.cmi odoc_analyse.cmi odoc.cmx : odoc_messages.cmx odoc_info.cmx odoc_global.cmx odoc_gen.cmx \ @@ -170,10 +178,10 @@ odoc_misc.cmi : ../typing/types.cmi odoc_types.cmi ../parsing/longident.cmi \ ../parsing/asttypes.cmi odoc_module.cmo : ../typing/types.cmi odoc_value.cmo odoc_types.cmi \ odoc_type.cmo odoc_name.cmi odoc_extension.cmo odoc_exception.cmo \ - odoc_class.cmo + odoc_class.cmo ../utils/misc.cmi odoc_module.cmx : ../typing/types.cmx odoc_value.cmx odoc_types.cmx \ odoc_type.cmx odoc_name.cmx odoc_extension.cmx odoc_exception.cmx \ - odoc_class.cmx + odoc_class.cmx ../utils/misc.cmx odoc_name.cmo : ../typing/path.cmi odoc_misc.cmi ../typing/ident.cmi \ odoc_name.cmi odoc_name.cmx : ../typing/path.cmx odoc_misc.cmx ../typing/ident.cmx \ diff --git a/ocamldoc/Makefile b/ocamldoc/Makefile index 7b53a036..f69b8745 100644 --- a/ocamldoc/Makefile +++ b/ocamldoc/Makefile @@ -13,194 +13,240 @@ #* * #************************************************************************** -include ../config/Makefile -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc - -# Various commands and dir -########################## -ROOTDIR = .. -OCAMLC = $(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib -OCAMLOPT = $(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib -I $(ROOTDIR)/stdlib -OCAMLDEP = $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -OCAMLLEX = $(CAMLRUN) $(ROOTDIR)/boot/ocamllex -OCAMLLIB = $(LIBDIR) -OCAMLBIN = $(BINDIR) - -OCAMLPP=-pp './remove_DEBUG' +ROOTDIR = .. + +include $(ROOTDIR)/config/Makefile +OCAMLRUN ?= $(ROOTDIR)/boot/ocamlrun +OCAMLYACC ?= $(ROOTDIR)/boot/ocamlyacc + +STDLIBFLAGS = -nostdlib -I $(ROOTDIR)/stdlib +OCAMLC = $(OCAMLRUN) $(ROOTDIR)/ocamlc $(STDLIBFLAGS) +ifeq "$(UNIX_OR_WIN32)" "unix" +OCAMLOPT = $(OCAMLRUN) $(ROOTDIR)/ocamlopt $(STDLIBFLAGS) +else # Windows + ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" + FLEXLINK_ENV= + else + FLEXLINK_ENV=OCAML_FLEXLINK="$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe" + endif + OCAMLOPT = $(FLEXLINK_ENV) $(OCAMLRUN) $(ROOTDIR)/ocamlopt $(STDLIBFLAGS) +endif +OCAMLDEP = $(OCAMLRUN) $(ROOTDIR)/tools/ocamldep -slash +OCAMLLEX = $(OCAMLRUN) $(ROOTDIR)/boot/ocamllex +# TODO: figure out whether the DEBUG lines the following preprocessor removes +# are actually useful. +# If they are not, then the preprocessor logic (including the +# remove_DEBUG script and the debug target) could be removed. +# If they are, it may be better to be able to enable them at run-time +# rather than compile-time, e.g. through a -debug command-line option. +# In the following line, "sh" is useful under Windows. Without it, +# the ./remove_DEBUG command would be executed by cmd.exe which would not +# know how to handle it. +OCAMLPP=-pp 'sh ./remove_DEBUG' # For installation ############## + MKDIR=mkdir -p -CP=cp -f -OCAMLDOC=./ocamldoc -ifeq "$(TARGET)" "$(HOST)" - ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" - OCAMLDOC_RUN=$(CAMLRUN) -I ../otherlibs/unix -I ../otherlibs/str $(OCAMLDOC) +CP=cp +OCAMLDOC=ocamldoc + +# TODO: clarify whether the following really needs to be that complicated +ifeq "$(UNIX_OR_WIN32)" "unix" + ifeq "$(TARGET)" "$(HOST)" + ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" + OCAMLDOC_RUN=$(OCAMLRUN) -I $(ROOTDIR)/otherlibs/$(UNIXLIB) -I $(ROOTDIR)/otherlibs/str ./$(OCAMLDOC) + else + OCAMLDOC_RUN=./$(OCAMLDOC) + endif else - OCAMLDOC_RUN=$(OCAMLDOC) + OCAMLDOC_RUN=$(OCAMLRUN) ./$(OCAMLDOC) endif -else - OCAMLDOC_RUN=$(CAMLRUN) $(OCAMLDOC) +else # Windows + OCAMLDOC_RUN = CAML_LD_LIBRARY_PATH="../otherlibs/win32unix;../otherlibs/str" $(OCAMLRUN) ./$(OCAMLDOC) endif + OCAMLDOC_OPT=$(OCAMLDOC).opt OCAMLDOC_LIBCMA=odoc_info.cma OCAMLDOC_LIBCMI=odoc_info.cmi OCAMLDOC_LIBCMXA=odoc_info.cmxa OCAMLDOC_LIBA=odoc_info.$(A) -INSTALL_LIBDIR=$(DESTDIR)$(OCAMLLIB)/ocamldoc -INSTALL_CUSTOMDIR=$(INSTALL_LIBDIR)/custom -INSTALL_BINDIR=$(DESTDIR)$(OCAMLBIN) + +INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)/ocamldoc + +INSTALL_BINDIR=$(DESTDIR)$(BINDIR) + #MANO: man ocamldoc INSTALL_MANODIR=$(DESTDIR)$(MANDIR)/man3 INSTALL_MLIS=odoc_info.mli INSTALL_CMIS=$(INSTALL_MLIS:.mli=.cmi) +INSTALL_CMTS=$(INSTALL_MLIS:.mli=.cmt) $(INSTALL_MLIS:.mli=.cmti) ODOC_TEST=odoc_test.cmo - GENERATORS_CMOS= \ - generators/odoc_todo.cmo \ - generators/odoc_literate.cmo -true = $(GENERATORS_CMOS:.cmo=.cmxs) -false = -GENERATORS_CMXS := $($(NATDYNLINK)) - + generators/odoc_todo.cmo \ + generators/odoc_literate.cmo +ifeq "$(NATDYNLINK)" "true" +GENERATORS_CMXS = $(GENERATORS_CMOS:.cmo=.cmxs) +else +GENERATORS_CMXS = +endif # Compilation ############# -OCAMLSRCDIR=.. -INCLUDES_DEP=-I $(OCAMLSRCDIR)/parsing \ - -I $(OCAMLSRCDIR)/utils \ - -I $(OCAMLSRCDIR)/typing \ - -I $(OCAMLSRCDIR)/driver \ - -I $(OCAMLSRCDIR)/bytecomp \ - -I $(OCAMLSRCDIR)/toplevel/ - -INCLUDES_NODEP= -I $(OCAMLSRCDIR)/stdlib \ - -I $(OCAMLSRCDIR)/otherlibs/str \ - -I $(OCAMLSRCDIR)/otherlibs/dynlink \ - -I $(OCAMLSRCDIR)/otherlibs/$(UNIXLIB) \ - -I $(OCAMLSRCDIR)/otherlibs/num \ - -I $(OCAMLSRCDIR)/otherlibs/$(GRAPHLIB) + +INCLUDES_DEP=\ + -I $(ROOTDIR)/parsing \ + -I $(ROOTDIR)/utils \ + -I $(ROOTDIR)/typing \ + -I $(ROOTDIR)/driver \ + -I $(ROOTDIR)/bytecomp \ + -I $(ROOTDIR)/toplevel + +INCLUDES_NODEP=\ + -I $(ROOTDIR)/stdlib \ + -I $(ROOTDIR)/compilerlibs \ + -I $(ROOTDIR)/otherlibs/str \ + -I $(ROOTDIR)/otherlibs/dynlink \ + -I $(ROOTDIR)/otherlibs/$(UNIXLIB) \ + -I $(ROOTDIR)/otherlibs/num \ + -I $(ROOTDIR)/otherlibs/$(GRAPHLIB) INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP) -COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A -safe-string -strict-sequence -strict-formats +COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A -safe-string -strict-sequence -strict-formats -bin-annot LINKFLAGS=$(INCLUDES) -nostdlib -CMOFILES= odoc_config.cmo \ - odoc_messages.cmo\ - odoc_global.cmo\ - odoc_types.cmo\ - odoc_misc.cmo\ - odoc_text_parser.cmo\ - odoc_text_lexer.cmo\ - odoc_text.cmo\ - odoc_name.cmo\ - odoc_parameter.cmo\ - odoc_value.cmo\ - odoc_type.cmo\ - odoc_extension.cmo\ - odoc_exception.cmo\ - odoc_class.cmo\ - odoc_module.cmo\ - odoc_print.cmo \ - odoc_str.cmo\ - odoc_comments_global.cmo\ - odoc_parser.cmo\ - odoc_lexer.cmo\ - odoc_see_lexer.cmo\ - odoc_env.cmo\ - odoc_merge.cmo\ - odoc_sig.cmo\ - odoc_ast.cmo\ - odoc_control.cmo\ - odoc_inherit.cmo\ - odoc_search.cmo\ - odoc_scan.cmo\ - odoc_cross.cmo\ - odoc_comments.cmo\ - odoc_dep.cmo\ - odoc_analyse.cmo\ - odoc_info.cmo - - -CMXFILES= $(CMOFILES:.cmo=.cmx) -CMIFILES= $(CMOFILES:.cmo=.cmi) - -EXECMOFILES=$(CMOFILES) \ - odoc_dag2html.cmo \ - odoc_to_text.cmo \ - odoc_ocamlhtml.cmo \ - odoc_html.cmo \ - odoc_man.cmo \ - odoc_latex_style.cmo \ - odoc_latex.cmo \ - odoc_texi.cmo \ - odoc_dot.cmo \ - odoc_gen.cmo \ - odoc_args.cmo \ - odoc.cmo - -EXECMXFILES= $(EXECMOFILES:.cmo=.cmx) -EXECMIFILES= $(EXECMOFILES:.cmo=.cmi) - -LIBCMOFILES=$(CMOFILES) -LIBCMXFILES= $(LIBCMOFILES:.cmo=.cmx) -LIBCMIFILES= $(LIBCMOFILES:.cmo=.cmi) - -STDLIB_MLIS=../stdlib/*.mli \ +CMOFILES=\ + odoc_config.cmo \ + odoc_messages.cmo \ + odoc_global.cmo \ + odoc_types.cmo \ + odoc_misc.cmo \ + odoc_text_parser.cmo \ + odoc_text_lexer.cmo \ + odoc_text.cmo \ + odoc_name.cmo \ + odoc_parameter.cmo \ + odoc_value.cmo \ + odoc_type.cmo \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo \ + odoc_module.cmo \ + odoc_print.cmo \ + odoc_str.cmo \ + odoc_comments_global.cmo \ + odoc_parser.cmo \ + odoc_lexer.cmo \ + odoc_see_lexer.cmo \ + odoc_env.cmo \ + odoc_merge.cmo \ + odoc_sig.cmo \ + odoc_ast.cmo \ + odoc_control.cmo \ + odoc_inherit.cmo \ + odoc_search.cmo \ + odoc_scan.cmo \ + odoc_cross.cmo \ + odoc_comments.cmo \ + odoc_dep.cmo \ + odoc_analyse.cmo \ + odoc_info.cmo + +CMXFILES = $(CMOFILES:.cmo=.cmx) +CMIFILES = $(CMOFILES:.cmo=.cmi) + +EXECMOFILES=\ + $(CMOFILES) \ + odoc_dag2html.cmo \ + odoc_to_text.cmo \ + odoc_ocamlhtml.cmo \ + odoc_html.cmo \ + odoc_man.cmo \ + odoc_latex_style.cmo \ + odoc_latex.cmo \ + odoc_texi.cmo \ + odoc_dot.cmo \ + odoc_gen.cmo \ + odoc_args.cmo \ + odoc.cmo + +EXECMXFILES = $(EXECMOFILES:.cmo=.cmx) +EXECMIFILES = $(EXECMOFILES:.cmo=.cmi) + +LIBCMOFILES = $(CMOFILES) +LIBCMXFILES = $(LIBCMOFILES:.cmo=.cmx) +LIBCMIFILES = $(LIBCMOFILES:.cmo=.cmi) + +STDLIB_MLIS=\ + ../stdlib/*.mli \ ../parsing/*.mli \ - ../otherlibs/$(UNIXLIB)/unix.mli \ - ../otherlibs/str/str.mli \ - ../otherlibs/bigarray/bigarray.mli \ - ../otherlibs/num/num.mli + ../otherlibs/$(UNIXLIB)/unix.mli \ + ../otherlibs/str/str.mli \ + ../otherlibs/bigarray/bigarray.mli \ + ../otherlibs/num/num.mli -all: - $(MAKE) exe - $(MAKE) lib - $(MAKE) generators - $(MAKE) manpages +.PHONY: all +all: lib exe generators manpages +manpages: generators + +.PHONY: exe exe: $(OCAMLDOC) + +.PHONY: lib lib: $(OCAMLDOC_LIBCMA) $(OCAMLDOC_LIBCMI) $(ODOC_TEST) + +.PHONY: generators generators: $(GENERATORS_CMOS) -opt.opt: - $(MAKE) exeopt - $(MAKE) libopt - $(MAKE) generatorsopt +.PHONY: opt.opt +opt.opt: exeopt libopt generatorsopt +.PHONY: exeopt exeopt: $(OCAMLDOC_OPT) + +.PHONY: libopt libopt: $(OCAMLDOC_LIBCMXA) $(OCAMLDOC_LIBCMI) + +.PHONY: generatorsopt generatorsopt: $(GENERATORS_CMXS) +# TODO: the following debug target could be replaced by a DEBUG variable +.PHONY: debug debug: $(MAKE) OCAMLPP="" +OCAMLDOC_LIBRARIES = unix str dynlink ocamlcommon + +OCAMLDOC_BCLIBRARIES = $(OCAMLDOC_LIBRARIES:%=%.cma) +OCAMLDOC_NCLIBRARIES = $(OCAMLDOC_LIBRARIES:%=%.cmxa) + $(OCAMLDOC): $(EXECMOFILES) - $(OCAMLC) -o $@ -linkall unix.cma str.cma dynlink.cma \ - $(OCAMLSRCDIR)/compilerlibs/ocamlcommon.cma \ - $(LINKFLAGS) $(EXECMOFILES) + $(OCAMLC) -o $@ -linkall $(LINKFLAGS) $(OCAMLDOC_BCLIBRARIES) $^ + $(OCAMLDOC_OPT): $(EXECMXFILES) - $(OCAMLOPT) -o $@ -linkall unix.cmxa str.cmxa dynlink.cmxa \ - $(OCAMLSRCDIR)/compilerlibs/ocamlcommon.cmxa \ - $(LINKFLAGS) $(EXECMXFILES) + $(OCAMLOPT) -o $@ -linkall $(LINKFLAGS) $(OCAMLDOC_NCLIBRARIES) $^ $(OCAMLDOC_LIBCMA): $(LIBCMOFILES) - $(OCAMLC) -a -o $@ $(LINKFLAGS) \ - $(LIBCMOFILES) + $(OCAMLC) -a -o $@ $(LINKFLAGS) $^ + $(OCAMLDOC_LIBCMXA): $(LIBCMXFILES) - $(OCAMLOPT) -a -o $@ $(LINKFLAGS) \ - $(LIBCMXFILES) + $(OCAMLOPT) -a -o $@ $(LINKFLAGS) $^ +.PHONY: manpages manpages: stdlib_man/Pervasives.3o + +.PHONY: html_doc html_doc: stdlib_html/Pervasives.html -dot: $(EXECMOFILES) - $(OCAMLDOC_RUN) -dot -dot-reduce -o ocamldoc.dot $(INCLUDES) \ - odoc*.ml +.PHONY: dot +dot: ocamldoc.dot + +ocamldoc.dot: $(EXECMOFILES) + $(OCAMLDOC_RUN) -dot -dot-reduce -o $@ $(INCLUDES) odoc*.ml # Parsers and lexers dependencies : ################################### @@ -240,36 +286,50 @@ odoc_see_lexer.ml: odoc_see_lexer.mll $(OCAMLLEX) $< .mly.ml: - $(CAMLYACC) -v $< + $(OCAMLYACC) -v $< .mly.mli: - $(CAMLYACC) -v $< + $(OCAMLYACC) -v $< # Installation targets ###################### -install: dummy - if test -d "$(INSTALL_BINDIR)"; then : ; else $(MKDIR) "$(INSTALL_BINDIR)"; fi - if test -d "$(INSTALL_LIBDIR)"; then : ; else $(MKDIR) "$(INSTALL_LIBDIR)"; fi - if test -d "$(INSTALL_CUSTOMDIR)"; then : ; else $(MKDIR) "$(INSTALL_CUSTOMDIR)"; fi + +# TODO: it may be good to split the following rule in several ones, e.g. +# install-programs, install-doc, install-libs + +.PHONY: install +install: + $(MKDIR) "$(INSTALL_BINDIR)" + $(MKDIR) "$(INSTALL_LIBDIR)" + $(MKDIR) "$(INSTALL_MANODIR)" $(CP) $(OCAMLDOC) "$(INSTALL_BINDIR)/$(OCAMLDOC)$(EXE)" $(CP) ocamldoc.hva *.cmi $(OCAMLDOC_LIBCMA) "$(INSTALL_LIBDIR)" - $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) "$(INSTALL_LIBDIR)" - if test -d "$(INSTALL_MANODIR)"; then : ; else $(MKDIR) "$(INSTALL_MANODIR)"; fi + $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) $(INSTALL_CMTS) "$(INSTALL_LIBDIR)" if test -d stdlib_man; then $(CP) stdlib_man/* "$(INSTALL_MANODIR)"; else : ; fi +# Note: at the moment, $(INSTALL_MANODIR) is created even if the doc has +# not been built. This is not clean and should be changed. + +.PHONY: installopt installopt: if test -f $(OCAMLDOC_OPT); then $(MAKE) installopt_really ; fi +.PHONY: installopt_really installopt_really: - if test -d "$(INSTALL_BINDIR)"; then : ; else $(MKDIR) "$(INSTALL_BINDIR)"; fi - if test -d "$(INSTALL_LIBDIR)"; then : ; else $(MKDIR) "$(INSTALL_LIBDIR)"; fi + $(MKDIR) "$(INSTALL_BINDIR)" + $(MKDIR) "$(INSTALL_LIBDIR)" $(CP) $(OCAMLDOC_OPT) "$(INSTALL_BINDIR)/$(OCAMLDOC_OPT)$(EXE)" - $(CP) ocamldoc.hva *.cmx $(OCAMLDOC_LIBA) $(OCAMLDOC_LIBCMXA) "$(INSTALL_LIBDIR)" - $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) "$(INSTALL_LIBDIR)" + $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) $(INSTALL_CMTS) "$(INSTALL_LIBDIR)" + $(CP) ocamldoc.hva *.cmx $(OCAMLDOC_LIBA) $(OCAMLDOC_LIBCMXA) \ + "$(INSTALL_LIBDIR)" + +# TODO: also split into several rules # Testing : ########### -test: dummy + +.PHONY: test +test: $(MKDIR) $@ $(OCAMLDOC_RUN) -html -colorize-code -sort -d $@ $(INCLUDES) -dump $@/ocamldoc.odoc odoc*.ml odoc*.mli -v $(MKDIR) $@-custom @@ -277,30 +337,35 @@ test: dummy -g generators/odoc_literate.cmo -g generators/odoc_todo.cmo \ -load $@/ocamldoc.odoc -v -test_stdlib: dummy +.PHONY: test_stdlib +test_stdlib: $(MKDIR) $@ $(OCAMLDOC_RUN) -html -colorize-code -sort -d $@ $(INCLUDES) -dump $@/stdlib.odoc -keep-code \ ../stdlib/pervasives.ml ../stdlib/*.mli \ ../otherlibs/$(UNIXLIB)/unix.mli \ ../otherlibs/str/str.mli -test_stdlib_code: dummy +.PHONY: test_stdlib_code +test_stdlib_code: $(MKDIR) $@ $(OCAMLDOC_RUN) -html -colorize-code -sort -d $@ $(INCLUDES) -dump $@/stdlib.odoc -keep-code \ `ls ../stdlib/*.ml | grep -v Labels` \ ../otherlibs/$(UNIXLIB)/unix.ml \ ../otherlibs/str/str.ml -test_framed: dummy +.PHONY: test_framed +test_framed: $(MKDIR) $@ $(OCAMLDOC_RUN) -g odoc_fhtml.cmo -sort -colorize-code -d $@ $(INCLUDES) odoc*.ml odoc*.mli -test_latex: dummy +.PHONY: test_latex +test_latex: $(MKDIR) $@ $(OCAMLDOC_RUN) -latex -sort -o $@/test.tex -d $@ $(INCLUDES) odoc*.ml \ odoc*.mli test2.txt ../stdlib/*.mli ../otherlibs/unix/unix.mli -test_latex_simple: dummy +.PHONY: test_latex_simple +test_latex_simple: $(MKDIR) $@ $(OCAMLDOC_RUN) -latex -sort -o $@/test.tex -d $@ $(INCLUDES) \ -latextitle 6,subsection -latextitle 7,subsubection \ @@ -309,28 +374,28 @@ test_latex_simple: dummy ../otherlibs/$(UNIXLIB)/unix.mli \ ../stdlib/map.mli -test_man: dummy +.PHONY: test_man +test_man: $(MKDIR) $@ $(OCAMLDOC_RUN) -man -sort -d $@ $(INCLUDES) odoc*.ml odoc*.mli -test_texi: dummy +.PHONY: test_texi +test_texi: $(MKDIR) $@ $(OCAMLDOC_RUN) -texi -sort -d $@ $(INCLUDES) odoc*.ml odoc*.mli -stdlib_man/Pervasives.3o: $(STDLIB_MLIS) +stdlib_man/Pervasives.3o: $(OCAMLDOC) $(STDLIB_MLIS) $(MKDIR) stdlib_man $(OCAMLDOC_RUN) -man -d stdlib_man $(INCLUDES) \ - -t "OCaml library" -man-mini \ - $(STDLIB_MLIS) + -t "OCaml library" -man-mini $(STDLIB_MLIS) stdlib_html/Pervasives.html: $(STDLIB_MLIS) $(MKDIR) stdlib_html $(OCAMLDOC_RUN) -d stdlib_html -html $(INCLUDES) \ - -t "OCaml library" \ - $(STDLIB_MLIS) + -t "OCaml library" $^ - -autotest_stdlib: dummy +.PHONY: autotest_stdlib +autotest_stdlib: $(MKDIR) $@ $(OCAMLDOC_RUN) -g autotest/odoc_test.cmo\ $(INCLUDES) -keep-code \ @@ -341,24 +406,24 @@ autotest_stdlib: dummy # backup, clean and depend : ############################ -clean:: dummy - @rm -f *~ \#*\# - @rm -f $(OCAMLDOC) $(OCAMLDOC_OPT) *.cma *.cmxa *.cmo *.cmi *.cmx *.$(A) *.$(O) - @rm -f odoc_parser.output odoc_text_parser.output - @rm -f odoc_lexer.ml odoc_text_lexer.ml odoc_see_lexer.ml odoc_ocamlhtml.ml - @rm -f odoc_parser.ml odoc_parser.mli odoc_text_parser.ml odoc_text_parser.mli - @rm -rf stdlib_man - @rm -f generators/*.cm[aiox] generators/*.$(A) generators/*.$(O) generators/*.cmx[as] - -depend:: - $(CAMLYACC) odoc_text_parser.mly - $(CAMLYACC) odoc_parser.mly +.PHONY: clean +clean: + rm -f *~ \#*\# + rm -f $(OCAMLDOC) $(OCAMLDOC_OPT) *.cma *.cmxa *.cmo *.cmi *.cmx *.cmt *.cmti *.$(A) *.$(O) + rm -f odoc_parser.output odoc_text_parser.output + rm -f odoc_lexer.ml odoc_text_lexer.ml odoc_see_lexer.ml odoc_ocamlhtml.ml + rm -f odoc_parser.ml odoc_parser.mli odoc_text_parser.ml odoc_text_parser.mli + rm -rf stdlib_man + rm -f generators/*.cm[taiox] generators/*.$(A) generators/*.$(O) generators/*.cmx[as] + +.PHONY: depend +depend: + $(OCAMLYACC) odoc_text_parser.mly + $(OCAMLYACC) odoc_parser.mly $(OCAMLLEX) odoc_text_lexer.mll $(OCAMLLEX) odoc_lexer.mll $(OCAMLLEX) odoc_ocamlhtml.mll $(OCAMLLEX) odoc_see_lexer.mll - $(OCAMLDEP) $(INCLUDES_DEP) *.mll *.mly *.ml *.mli > .depend - -dummy: + $(OCAMLDEP) $(INCLUDES_DEP) *.mll *.mly *.ml *.mli generators/*.ml > .depend include .depend diff --git a/ocamldoc/Makefile.nt b/ocamldoc/Makefile.nt index 7bb17e25..46ed1c31 100644 --- a/ocamldoc/Makefile.nt +++ b/ocamldoc/Makefile.nt @@ -13,244 +13,4 @@ #* * #************************************************************************** -include ../config/Makefile -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc - -# Various commands and dir -########################## -ROOTDIR = .. -OCAMLC = $(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib -ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" - FLEXLINK_ENV= -else - FLEXLINK_ENV=OCAML_FLEXLINK="$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe" -endif -OCAMLOPT = $(FLEXLINK_ENV) $(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib \ - -I $(ROOTDIR)/stdlib -OCAMLDEP = $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -OCAMLLEX = $(CAMLRUN) $(ROOTDIR)/boot/ocamllex -OCAMLLIB = $(LIBDIR) -OCAMLBIN = $(BINDIR) - -OCAMLPP=-pp "grep -v DEBUG" - -# For installation -############## -MKDIR=mkdir -CP=cp -OCAMLDOC=ocamldoc -OCAMLDOC_RUN=$(CAMLRUN) $(OCAMLDOC) -OCAMLDOC_OPT=$(OCAMLDOC).opt -OCAMLDOC_LIBCMA=odoc_info.cma -OCAMLDOC_LIBCMI=odoc_info.cmi -OCAMLDOC_LIBCMXA=odoc_info.cmxa -OCAMLDOC_LIBA=odoc_info.$(A) -INSTALL_LIBDIR=$(DESTDIR)$(OCAMLLIB)/ocamldoc -INSTALL_CUSTOMDIR=$(INSTALL_LIBDIR)/custom -INSTALL_BINDIR=$(DESTDIR)$(OCAMLBIN) - -INSTALL_MLIS=odoc_info.mli -INSTALL_CMIS=$(INSTALL_MLIS:.mli=.cmi) - -# Compilation -############# -OCAMLSRCDIR=.. -INCLUDES_DEP=-I $(OCAMLSRCDIR)/parsing \ - -I $(OCAMLSRCDIR)/utils \ - -I $(OCAMLSRCDIR)/typing \ - -I $(OCAMLSRCDIR)/driver \ - -I $(OCAMLSRCDIR)/bytecomp \ - -I $(OCAMLSRCDIR)/toplevel/ - -INCLUDES_NODEP= -I $(OCAMLSRCDIR)/stdlib \ - -I $(OCAMLSRCDIR)/otherlibs/str \ - -I $(OCAMLSRCDIR)/otherlibs/dynlink \ - -I $(OCAMLSRCDIR)/otherlibs/$(UNIXLIB) \ - -I $(OCAMLSRCDIR)/otherlibs/num \ - -I $(OCAMLSRCDIR)/otherlibs/$(GRAPHLIB) - -INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP) - -COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A -safe-string -strict-sequence -strict-formats -LINKFLAGS=$(INCLUDES) -nostdlib - -CMOFILES= odoc_config.cmo \ - odoc_messages.cmo\ - odoc_global.cmo\ - odoc_types.cmo\ - odoc_misc.cmo\ - odoc_text_parser.cmo\ - odoc_text_lexer.cmo\ - odoc_text.cmo\ - odoc_name.cmo\ - odoc_parameter.cmo\ - odoc_value.cmo\ - odoc_type.cmo\ - odoc_extension.cmo\ - odoc_exception.cmo\ - odoc_class.cmo\ - odoc_module.cmo\ - odoc_print.cmo \ - odoc_str.cmo\ - odoc_comments_global.cmo\ - odoc_parser.cmo\ - odoc_lexer.cmo\ - odoc_see_lexer.cmo\ - odoc_env.cmo\ - odoc_merge.cmo\ - odoc_sig.cmo\ - odoc_ast.cmo\ - odoc_control.cmo\ - odoc_inherit.cmo\ - odoc_search.cmo\ - odoc_scan.cmo\ - odoc_cross.cmo\ - odoc_comments.cmo\ - odoc_dep.cmo\ - odoc_analyse.cmo\ - odoc_info.cmo - - -CMXFILES= $(CMOFILES:.cmo=.cmx) -CMIFILES= $(CMOFILES:.cmo=.cmi) - -EXECMOFILES=$(CMOFILES) \ - odoc_dag2html.cmo \ - odoc_to_text.cmo \ - odoc_ocamlhtml.cmo \ - odoc_html.cmo \ - odoc_man.cmo \ - odoc_latex_style.cmo \ - odoc_latex.cmo \ - odoc_texi.cmo \ - odoc_dot.cmo \ - odoc_gen.cmo \ - odoc_args.cmo \ - odoc.cmo - -EXECMXFILES= $(EXECMOFILES:.cmo=.cmx) -EXECMIFILES= $(EXECMOFILES:.cmo=.cmi) - -LIBCMOFILES=$(CMOFILES) -LIBCMXFILES= $(LIBCMOFILES:.cmo=.cmx) -LIBCMIFILES= $(LIBCMOFILES:.cmo=.cmi) - -all: - $(MAKEREC) exe - $(MAKEREC) lib - -exe: $(OCAMLDOC) -lib: $(OCAMLDOC_LIBCMA) $(OCAMLDOC_LIBCMI) - -opt.opt: exeopt libopt -exeopt: $(OCAMLDOC_OPT) -libopt: $(OCAMLDOC_LIBCMXA) $(OCAMLDOC_LIBCMI) - -debug: - $(MAKEREC) OCAMLPP="" - -$(OCAMLDOC): $(EXECMOFILES) - $(OCAMLC) -o $@ -linkall unix.cma str.cma dynlink.cma \ - $(OCAMLSRCDIR)/compilerlibs/ocamlcommon.cma \ - $(LINKFLAGS) $(EXECMOFILES) -$(OCAMLDOC_OPT): $(EXECMXFILES) - $(OCAMLOPT) -o $@ -linkall unix.cmxa str.cmxa dynlink.cmxa \ - $(OCAMLSRCDIR)/compilerlibs/ocamlcommon.cmxa \ - $(LINKFLAGS) $(EXECMXFILES) - -$(OCAMLDOC_LIBCMA): $(LIBCMOFILES) - $(OCAMLC) -a -o $@ $(LINKFLAGS) \ - $(LIBCMOFILES) -$(OCAMLDOC_LIBCMXA): $(LIBCMXFILES) - $(OCAMLOPT) -a -o $@ $(LINKFLAGS) \ - $(LIBCMXFILES) - -# Parsers and lexers dependencies : -################################### -odoc_text_parser.ml: odoc_text_parser.mly -odoc_text_parser.mli: odoc_text_parser.mly - -odoc_parser.ml: odoc_parser.mly -odoc_parser.mli:odoc_parser.mly - -odoc_text_lexer.ml: odoc_text_lexer.mll - -odoc_lexer.ml:odoc_lexer.mll - -odoc_ocamlhtml.ml: odoc_ocamlhtml.mll - -odoc_see_lexer.ml: odoc_see_lexer.mll - - -# generic rules : -################# - -.SUFFIXES: .mll .mly .ml .mli .cmo .cmi .cmx .cmxs - -.ml.cmo: - $(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $< - -.mli.cmi: - $(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $< - -.ml.cmx: - $(OCAMLOPT) $(OCAMLPP) $(COMPFLAGS) -c $< - -.ml.cmxs: - $(OCAMLOPT) -shared -o $@ $(OCAMLPP) $(COMPFLAGS) $< - -.mll.ml: - $(OCAMLLEX) $< - -.mly.ml: - $(CAMLYACC) -v $< - -.mly.mli: - $(CAMLYACC) -v $< - -# Installation targets -###################### -install: dummy - $(MKDIR) -p "$(INSTALL_BINDIR)" - $(MKDIR) -p "$(INSTALL_LIBDIR)" - $(CP) $(OCAMLDOC) "$(INSTALL_BINDIR)/$(OCAMLDOC)$(EXE)" - $(CP) ocamldoc.hva *.cmi $(OCAMLDOC_LIBCMA) "$(INSTALL_LIBDIR)" - $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) "$(INSTALL_LIBDIR)" - -installopt: - if test -f $(OCAMLDOC_OPT); then $(MAKEREC) installopt_really; fi - -installopt_really: - $(MKDIR) -p "$(INSTALL_BINDIR)" - $(MKDIR) -p "$(INSTALL_LIBDIR)" - $(CP) $(OCAMLDOC_OPT) "$(INSTALL_BINDIR)/$(OCAMLDOC_OPT)$(EXE)" - $(CP) ocamldoc.hva $(OCAMLDOC_LIBA) $(OCAMLDOC_LIBCMXA) \ - "$(INSTALL_LIBDIR)" - $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) "$(INSTALL_LIBDIR)" - - -# backup, clean and depend : -############################ - -clean:: dummy - @rm -f *~ \#*\# - @rm -f $(OCAMLDOC) $(OCAMLDOC_OPT) *.cma *.cmxa *.cmo *.cmi *.cmx *.$(A) *.$(O) - @rm -f odoc_parser.output odoc_text_parser.output - @rm -f odoc_lexer.ml odoc_text_lexer.ml odoc_see_lexer.ml odoc_ocamlhtml.ml - @rm -f odoc_parser.ml odoc_parser.mli odoc_text_parser.ml odoc_text_parser.mli - @rm -rf stdlib_man - @rm -f generators/*.cm[aiox] generators/*.$(A) generators/*.$(O) generators/*.cmx[as] - -depend:: - $(CAMLYACC) odoc_text_parser.mly - $(CAMLYACC) odoc_parser.mly - $(OCAMLLEX) odoc_text_lexer.mll - $(OCAMLLEX) odoc_lexer.mll - $(OCAMLLEX) odoc_ocamlhtml.mll - $(OCAMLLEX) odoc_see_lexer.mll - $(OCAMLDEP) -slash $(INCLUDES_DEP) *.mll *.mly *.ml *.mli > .depend - -dummy: - -include .depend +include Makefile diff --git a/ocamldoc/odoc_analyse.ml b/ocamldoc/odoc_analyse.ml index a166cd9b..86c1ea36 100644 --- a/ocamldoc/odoc_analyse.ml +++ b/ocamldoc/odoc_analyse.ml @@ -50,7 +50,7 @@ let initial_env () = let open_mod env m = let open Asttypes in let lid = {loc = Location.in_file "ocamldoc command line"; - txt = Longident.Lident m } in + txt = Longident.parse m } in snd (Typemod.type_open_ Override env lid.loc lid) in (* Open the list of modules given as arguments of the "-open" flag The list is reversed to open the modules in the left-to-right order *) @@ -230,15 +230,16 @@ let process_file sourcefile = with Odoc_text.Text_syntax (l, c, s) -> raise (Failure (Odoc_messages.text_parse_error l c s)) in + let m_info = + Some Odoc_types.{dummy_info with i_desc= Some txt } in let m = { Odoc_module.m_name = mod_name ; Odoc_module.m_type = Types.Mty_signature [] ; - Odoc_module.m_info = None ; + Odoc_module.m_info; Odoc_module.m_is_interface = true ; Odoc_module.m_file = file ; - Odoc_module.m_kind = Odoc_module.Module_struct - [Odoc_module.Element_module_comment txt] ; + Odoc_module.m_kind = Odoc_module.Module_struct [] ; Odoc_module.m_loc = { Odoc_types.loc_impl = None ; Odoc_types.loc_inter = Some (Location.in_file file) } ; diff --git a/ocamldoc/odoc_args.ml b/ocamldoc/odoc_args.ml index 039c8d70..4d825b6e 100644 --- a/ocamldoc/odoc_args.ml +++ b/ocamldoc/odoc_args.ml @@ -252,6 +252,8 @@ let default_options = Options.list @ Odoc_global.files := !Odoc_global.files @ [Odoc_global.Text_file s]), M.option_text ; "-warn-error", Arg.Set Odoc_global.warn_error, M.werr ; + "-show-missed-crossref", Arg.Set Odoc_global.show_missed_crossref, + M.show_missed_crossref; "-hide-warnings", Arg.Clear Odoc_config.print_warnings, M.hide_warnings ; "-o", Arg.String (fun s -> Odoc_global.out_file := s), M.out_file ; "-d", Arg.String (fun s -> Odoc_global.target_dir := s), M.target_dir ; diff --git a/ocamldoc/odoc_ast.ml b/ocamldoc/odoc_ast.ml index d987485c..511d9d11 100644 --- a/ocamldoc/odoc_ast.ml +++ b/ocamldoc/odoc_ast.ml @@ -331,7 +331,7 @@ module Analyser = in (* continue if the body is still a function *) match next_exp.exp_desc with - Texp_function (_, pat_exp_list, _) -> + Texp_function { cases = pat_exp_list ; _ } -> p :: (tt_analyse_function_parameters env current_comment_opt pat_exp_list) | _ -> (* something else ; no more parameter *) @@ -342,7 +342,7 @@ module Analyser = let tt_analyse_value env current_module_name comment_opt loc pat_exp rec_flag = let (pat, exp) = pat_exp in match (pat.pat_desc, exp.exp_desc) with - (Typedtree.Tpat_var (ident, _), Typedtree.Texp_function (_, pat_exp_list2, _partial)) -> + (Typedtree.Tpat_var (ident, _), Typedtree.Texp_function { cases = pat_exp_list2; _ }) -> (* a new function is defined *) let name_pre = Name.from_ident ident in let name = Name.parens_if_infix name_pre in @@ -431,7 +431,7 @@ module Analyser = *) let rec tt_analyse_method_expression env current_method_name comment_opt ?(first=true) exp = match exp.Typedtree.exp_desc with - Typedtree.Texp_function (_, pat_exp_list, _) -> + Typedtree.Texp_function { cases = pat_exp_list; _ } -> ( match pat_exp_list with [] -> @@ -1867,21 +1867,7 @@ module Analyser = let analyse_typed_tree source_file input_file (parsetree : Parsetree.structure) (typedtree : typedtree) = let (tree_structure, _) = typedtree in - let complete_source_file = - try - let curdir = Sys.getcwd () in - let (dirname, basename) = (Filename.dirname source_file, Filename.basename source_file) in - Sys.chdir dirname ; - let complete = Filename.concat (Sys.getcwd ()) basename in - Sys.chdir curdir ; - complete - with - Sys_error s -> - prerr_endline s ; - incr Odoc_global.errors ; - source_file - in - prepare_file complete_source_file input_file; + prepare_file source_file input_file; (* We create the t_module for this file. *) let mod_name = String.capitalize_ascii (Filename.basename (Filename.chop_extension source_file)) in let (len,info_opt) = My_ir.first_special !file_name !file in diff --git a/ocamldoc/odoc_cross.ml b/ocamldoc/odoc_cross.ml index 4847e105..a9909ac1 100644 --- a/ocamldoc/odoc_cross.ml +++ b/ocamldoc/odoc_cross.ml @@ -667,10 +667,71 @@ let not_found_of_kind kind name = | RK_const -> Odoc_messages.cross_const_not_found ) name +let query module_list name = + match get_known_elements name with + | [] -> + ( + try + let re = Str.regexp ("^"^(Str.quote name)^"$") in + let t = Odoc_search.find_section module_list re in + let v2 = (name, Some (RK_section t)) in + add_verified v2 ; + (name, Some (RK_section t)) + with + Not_found -> + (name, None) + ) + | ele :: _ -> + (* we look for the first element with this name *) + let (name, kind) = + match ele with + Odoc_search.Res_module m -> (m.m_name, RK_module) + | Odoc_search.Res_module_type mt -> (mt.mt_name, RK_module_type) + | Odoc_search.Res_class c -> (c.cl_name, RK_class) + | Odoc_search.Res_class_type ct -> (ct.clt_name, RK_class_type) + | Odoc_search.Res_value v -> (v.val_name, RK_value) + | Odoc_search.Res_type t -> (t.ty_name, RK_type) + | Odoc_search.Res_extension x -> (x.xt_name, RK_extension) + | Odoc_search.Res_exception e -> (e.ex_name, RK_exception) + | Odoc_search.Res_attribute a -> (a.att_value.val_name, RK_attribute) + | Odoc_search.Res_method m -> (m.met_value.val_name, RK_method) + | Odoc_search.Res_section _-> assert false + | Odoc_search.Res_recfield (t, f) -> + (Printf.sprintf "%s.%s" t.ty_name f.rf_name, RK_recfield) + | Odoc_search.Res_const (t, f) -> + (Printf.sprintf "%s.%s" t.ty_name f.vc_name, RK_const) + in + add_verified (name, Some kind) ; + (name, Some kind) + + +let rec search_within_ancestry + (finalize,initial_name,query as param) ?parent_name name = + let name = Odoc_name.normalize_name name in + let res = query name in + match res with + | (name, Some k) -> finalize (Some (name,k)) + | (_, None) -> + match parent_name with + | None -> + finalize None + (* *) + | Some p -> + let parent_name = + match Name.father p with + "" -> None + | s -> Some s + in + search_within_ancestry param + ?parent_name (Name.concat p initial_name) + +let search_within_ancestry finalize query ?parent_name name = + search_within_ancestry (finalize, name, query) ?parent_name name + + let rec assoc_comments_text_elements parent_name module_list t_ele = match t_ele with | Raw _ - | Code _ | CodePre _ | Latex _ | Verbatim _ -> t_ele @@ -689,63 +750,65 @@ let rec assoc_comments_text_elements parent_name module_list t_ele = | Title (n, l_opt, t) -> Title (n, l_opt, (assoc_comments_text parent_name module_list t)) | Link (s, t) -> Link (s, (assoc_comments_text parent_name module_list t)) | Ref (initial_name, None, text_option) -> - ( - let rec iter_parent ?parent_name name = - let name = Odoc_name.normalize_name name in - let res = - match get_known_elements name with - [] -> - ( - try - let re = Str.regexp ("^"^(Str.quote name)^"$") in - let t = Odoc_search.find_section module_list re in - let v2 = (name, Some (RK_section t)) in - add_verified v2 ; - (name, Some (RK_section t)) - with - Not_found -> - (name, None) - ) - | ele :: _ -> - (* we look for the first element with this name *) - let (name, kind) = - match ele with - Odoc_search.Res_module m -> (m.m_name, RK_module) - | Odoc_search.Res_module_type mt -> (mt.mt_name, RK_module_type) - | Odoc_search.Res_class c -> (c.cl_name, RK_class) - | Odoc_search.Res_class_type ct -> (ct.clt_name, RK_class_type) - | Odoc_search.Res_value v -> (v.val_name, RK_value) - | Odoc_search.Res_type t -> (t.ty_name, RK_type) - | Odoc_search.Res_extension x -> (x.xt_name, RK_extension) - | Odoc_search.Res_exception e -> (e.ex_name, RK_exception) - | Odoc_search.Res_attribute a -> (a.att_value.val_name, RK_attribute) - | Odoc_search.Res_method m -> (m.met_value.val_name, RK_method) - | Odoc_search.Res_section _-> assert false - | Odoc_search.Res_recfield (t, f) -> - (Printf.sprintf "%s.%s" t.ty_name f.rf_name, RK_recfield) - | Odoc_search.Res_const (t, f) -> - (Printf.sprintf "%s.%s" t.ty_name f.vc_name, RK_const) - in - add_verified (name, Some kind) ; - (name, Some kind) - in - match res with - | (name, Some k) -> Ref (name, Some k, text_option) - | (_, None) -> - match parent_name with - None -> - Odoc_global.pwarning (Odoc_messages.cross_element_not_found initial_name); - Ref (initial_name, None, text_option) - | Some p -> - let parent_name = - match Name.father p with - "" -> None - | s -> Some s - in - iter_parent ?parent_name (Name.concat p initial_name) - in - iter_parent ~parent_name initial_name - ) + let finalize = function + | Some (name,k) -> Ref (name, Some k, text_option) + | None -> + Odoc_global.pwarning + (Odoc_messages.cross_element_not_found initial_name); + Ref (initial_name, None, text_option) in + search_within_ancestry finalize (query module_list) ~parent_name initial_name + | Code s -> + if not !Odoc_global.show_missed_crossref then + t_ele + else (* Check if s could be turned into a valid cross-reference *) + let name = String.trim s in + begin + (* First, we ignore code fragments with more than one space-separated + words: "word1 word2" *) + try (ignore (String.index name ' '); t_ele) + with Not_found -> + if name = "" then t_ele + else + let first_char = name.[0] in + (* Then, we only consider code fragments which start with a + distinctly uppercase letter *) + if Char.uppercase_ascii first_char <> first_char || + Char.lowercase_ascii first_char = first_char then + t_ele + else + (* Some path analysis auxiliary functions *) + let path s = + String.split_on_char '.' s + in + let filter = + List.filter + (fun s -> s <> "" && s.[0] = Char.uppercase_ascii s.[0]) in + let rec is_prefix prefix full = + match prefix, full with + | [], _ -> true + | a :: pre, b :: f when a = b -> is_prefix pre f + | _ -> false in + let p = filter @@ path name and parent_p = path parent_name in + let is_path_suffix () = + is_prefix (List.rev @@ p) (List.rev @@ parent_p ) in + (* heuristic: + - if name = parent_name: we are using the name of an element + or module in its definition, no need of cross_reference + - if the path of name is a suffix of the parent path, we + are in the same module, maybe the same function. To decreace + the false positive rate, we stop here *) + if name = parent_name || is_path_suffix () then + t_ele + else + let finalize = function + | None -> t_ele + | Some _ -> + Odoc_global.pwarning @@ + Odoc_messages.code_could_be_cross_reference name parent_name; + t_ele in + search_within_ancestry finalize (query module_list) ~parent_name + name + end | Ref (initial_name, Some kind, text_option) -> ( let rec iter_parent ?parent_name name = diff --git a/ocamldoc/odoc_global.ml b/ocamldoc/odoc_global.ml index fa366eae..cd528bf2 100644 --- a/ocamldoc/odoc_global.ml +++ b/ocamldoc/odoc_global.ml @@ -28,6 +28,7 @@ let include_dirs = Clflags.include_dirs let errors = ref 0 let warn_error = ref false +let show_missed_crossref = ref false let pwarning s = if !Odoc_config.print_warnings then prerr_endline (Odoc_messages.warning^": "^s); diff --git a/ocamldoc/odoc_global.mli b/ocamldoc/odoc_global.mli index c4c38096..46bfc756 100644 --- a/ocamldoc/odoc_global.mli +++ b/ocamldoc/odoc_global.mli @@ -69,6 +69,9 @@ val errors : int ref (** Indicate if a warning is an error. *) val warn_error : bool ref +(** Show code fragments that could be transformed into a cross-reference. *) +val show_missed_crossref: bool ref + (** Print the given warning, adding it to the list of {!errors} if {!warn_error} is [true]. *) val pwarning : string -> unit diff --git a/ocamldoc/odoc_html.ml b/ocamldoc/odoc_html.ml index 0fe22af1..29e646ca 100644 --- a/ocamldoc/odoc_html.ml +++ b/ocamldoc/odoc_html.ml @@ -441,7 +441,7 @@ class virtual text = method html_of_Link b s t = bs b ""; self#html_of_text b t; bs b "" @@ -861,7 +861,7 @@ class html = ".indextable {border: 1px #ddd solid; border-collapse: collapse}"; ".indextable td, .indextable th {border: 1px #ddd solid; min-width: 80px}"; ".indextable td.module {background-color: #eee ; padding-left: 2px; padding-right: 2px}"; - ".indextable td.module a {color: 4E6272; text-decoration: none; display: block; width: 100%}"; + ".indextable td.module a {color: #4E6272; text-decoration: none; display: block; width: 100%}"; ".indextable td.module a:hover {text-decoration: underline; background-color: transparent}"; ".deprecated {color: #888; font-style: italic}" ; @@ -1291,9 +1291,13 @@ class html = ( match modu with None -> + (* first we close the current

 tag, since the following
+                  list of module elements is not preformatted *)
+               bs b "
"; bs b "
"; List.iter (self#html_of_module_element b father) eles; - bs b "
" + bs b ""; + bs b "\n
"
            | Some m ->
                let (html_file, _) = Naming.html_files m.m_name in
                bp b " .. " html_file
@@ -1402,9 +1406,13 @@ class html =
                (
                 match modu with
                   None ->
+                    (*close the current 
 tag, to avoid anarchic line breaks
+                      in the list of module elements *)
+                    bs b "
"; bs b "
"; List.iter (self#html_of_module_element b father) eles; - bs b "
" + bs b ""; + bs b "
";
                 | Some m ->
                     let (html_file, _) = Naming.html_files m.m_name in
                     bp b " .. " html_file
@@ -2564,7 +2572,10 @@ class html =
           );
         bs b "

\n"; - if not modu.m_text_only then self#html_of_module b ~with_link: false modu; + if not modu.m_text_only then + self#html_of_module b ~with_link: false modu + else + self#html_of_info ~indent:false b modu.m_info; (* parameters for functors *) self#html_of_module_parameter_list b diff --git a/ocamldoc/odoc_latex.ml b/ocamldoc/odoc_latex.ml index 37252d63..c9292b84 100644 --- a/ocamldoc/odoc_latex.ml +++ b/ocamldoc/odoc_latex.ml @@ -566,16 +566,18 @@ class latex = method latex_of_cstr_args ( (fmt,flush) as f) mod_name (args, ret) = match args, ret with - | Cstr_tuple [], None -> [] + | Cstr_tuple [], None -> [CodePre(flush())] | Cstr_tuple _ as l, None -> p fmt " of@ %s" (self#normal_cstr_args ~par:false mod_name l); [CodePre (flush())] - | Cstr_tuple _ as l, Some r -> - p fmt " :@ %s@ %s@ %s" - (self#normal_cstr_args ~par:false mod_name l) - "->" - (self#normal_type mod_name r); + | Cstr_tuple t as l, Some r -> + let res = self#normal_type mod_name r in + if t = [] then + p fmt " :@ %s" res + else + p fmt " :@ %s -> %s" (self#normal_cstr_args ~par:false mod_name l) res + ; [CodePre (flush())] | Cstr_record l, None -> p fmt " of@ "; @@ -700,17 +702,17 @@ class latex = p fmt2 "@[ | %s" (Name.simple x.xt_name); let l = self#latex_of_cstr_args f father (x.xt_args, x.xt_ret) in let c = - begin match x.xt_alias with - | None -> () + match x.xt_alias with + | None -> [] | Some xa -> p fmt2 " = %s" ( match xa.xa_xt with | None -> xa.xa_name | Some x -> x.xt_name - ) - end; - [CodePre (flush2 ())] in + ); + [CodePre (flush2 ())] + in Latex (self#make_label (self#extension_label x.xt_name)) :: l @ c @ (match x.xt_text with None -> [] @@ -744,16 +746,17 @@ class latex = p fmt2 "@[exception %s" s_name; let l = self#latex_of_cstr_args f father (e.ex_args, e.ex_ret) in let s = - (match e.ex_alias with - None -> () - | Some ea -> - Format.fprintf fmt " = %s" - ( - match ea.ea_ex with - None -> ea.ea_name - | Some e -> e.ex_name - ) - ); [CodePre (flush2 ())] in + match e.ex_alias with + None -> [] + | Some ea -> + Format.fprintf fmt " = %s" + ( + match ea.ea_ex with + None -> ea.ea_name + | Some e -> e.ex_name + ); + [CodePre (flush2 ())] + in merge_codepre (l @ s ) @ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @ (self#text_of_info e.ex_info) in @@ -1209,20 +1212,13 @@ class latex = method generate_for_top_module fmt m = let (first_t, rest_t) = self#first_and_rest_of_info m.m_info in let text = - if m.m_text_only then - [ Title (1, None, [Raw m.m_name] @ - (match first_t with - [] -> [] - | t -> (Raw " : ") :: t) - ) ; - ] - else - [ Title (1, None, - [ Raw (Odoc_messages.modul^" ") ; Code m.m_name ] @ - (match first_t with - [] -> [] - | t -> (Raw " : ") :: t)) ; - ] + let title = + if m.m_text_only then [Raw m.m_name] + else [ Raw (Odoc_messages.modul^" ") ; Code m.m_name ] in + let subtitle = match first_t with + | [] -> [] + | t -> (Raw " : ") :: t in + [ Title (1, None, title @ subtitle ) ] in self#latex_of_text fmt text; self#latex_for_module_label fmt m; diff --git a/ocamldoc/odoc_messages.ml b/ocamldoc/odoc_messages.ml index 762e2666..c4619886 100644 --- a/ocamldoc/odoc_messages.ml +++ b/ocamldoc/odoc_messages.ml @@ -39,6 +39,7 @@ let add_load_dir = " Add the given directory to the search path for custom\ "\t\tgenerators" let load_file = " Load file defining a new documentation generator" let werr = " Treat ocamldoc warnings as errors" +let show_missed_crossref = " Show missed cross-reference opportunities" let hide_warnings = " do not print ocamldoc warnings" let target_dir = " Generate files in directory , rather than in current\n"^ "\t\tdirectory (for man and HTML generators)" @@ -250,7 +251,9 @@ let errors_occured n = (string_of_int n)^" error(s) encountered" let parse_error = "Parse error" let text_parse_error l c s = let lines = Str.split (Str.regexp_string "\n") s in - (List.nth lines l) ^ "\n" ^ (String.make c ' ') ^ "^" + "Error parsing text:\n" + ^ (List.nth lines l) ^ "\n" + ^ (String.make c ' ') ^ "^" let file_not_found_in_paths paths name = Printf.sprintf "No file %s found in the load paths: \n%s" @@ -321,6 +324,12 @@ let cross_type_not_found n = "Type "^n^" not found" let cross_recfield_not_found n = Printf.sprintf "Record field %s not found" n let cross_const_not_found n = Printf.sprintf "Constructor %s not found" n +let code_could_be_cross_reference n parent = + Printf.sprintf "Code element [%s] in %s corresponds to a known \ + cross-referenceable element, it might be worthwhile to replace it \ + with {!%s}" n parent n + + let object_end = "object ... end" let struct_end = "struct ... end" let sig_end = "sig ... end" diff --git a/ocamldoc/odoc_module.ml b/ocamldoc/odoc_module.ml index f986a4fd..afd31020 100644 --- a/ocamldoc/odoc_module.ml +++ b/ocamldoc/odoc_module.ml @@ -219,61 +219,12 @@ let included_modules l = [] l -(** Returns the list of elements of a module. - @param trans indicates if, for aliased modules, we must perform a transitive search.*) -let rec module_elements ?(trans=true) m = - let rec iter_kind = function - Module_struct l -> - print_DEBUG "Odoc_module.module_element: Module_struct"; - l - | Module_alias ma -> - print_DEBUG "Odoc_module.module_element: Module_alias"; - if trans then - match ma.ma_module with - None -> [] - | Some (Mod m) -> module_elements m - | Some (Modtype mt) -> module_type_elements mt - else - [] - | Module_functor (_, k) - | Module_apply (k, _) -> - print_DEBUG "Odoc_module.module_element: Module_functor ou Module_apply"; - iter_kind k - | Module_with (tk,_) -> - print_DEBUG "Odoc_module.module_element: Module_with"; - module_type_elements ~trans: trans - { mt_name = "" ; mt_info = None ; mt_type = None ; - mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ; - mt_loc = Odoc_types.dummy_loc ; - } - | Module_constraint (k, _tk) -> - print_DEBUG "Odoc_module.module_element: Module_constraint"; - (* FIXME : use k or tk ? *) - module_elements ~trans: trans - { m_name = "" ; - m_info = None ; - m_type = Types.Mty_signature [] ; - m_is_interface = false ; m_file = "" ; m_kind = k ; - m_loc = Odoc_types.dummy_loc ; - m_top_deps = [] ; - m_code = None ; - m_code_intf = None ; - m_text_only = false ; - } - | Module_typeof _ -> [] - | Module_unpack _ -> [] -(* - module_type_elements ~trans: trans - { mt_name = "" ; mt_info = None ; mt_type = None ; - mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ; - mt_loc = Odoc_types.dummy_loc } -*) - in - iter_kind m.m_kind +module S = Misc.StringSet + (** Returns the list of elements of a module type. @param trans indicates if, for aliased modules, we must perform a transitive search.*) -and module_type_elements ?(trans=true) mt = +let rec module_type_elements ?(trans=true) mt = let rec iter_kind = function | None -> [] | Some (Module_type_struct l) -> l @@ -294,6 +245,68 @@ and module_type_elements ?(trans=true) mt = in iter_kind mt.mt_kind +(** Returns the list of elements of a module. + @param trans indicates if, for aliased modules, we must perform a transitive search. +*) +let module_elements ?(trans=true) m = +(* visited is used to guard against aliases loop + (e.g [module rec M:sig end=M] induced loop. +*) + let rec module_elements visited ?(trans=true) m = + let rec iter_kind = function + Module_struct l -> + print_DEBUG "Odoc_module.module_elements: Module_struct"; + l + | Module_alias ma -> + print_DEBUG "Odoc_module.module_elements: Module_alias"; + if trans then + match ma.ma_module with + None -> [] + | Some (Mod m') -> + if S.mem m'.m_name visited then + [] + else + module_elements (S.add m'.m_name visited) m' + | Some (Modtype mt) -> module_type_elements mt + else + [] + | Module_functor (_, k) + | Module_apply (k, _) -> + print_DEBUG "Odoc_module.module_elements: Module_functor ou Module_apply"; + iter_kind k + | Module_with (tk,_) -> + print_DEBUG "Odoc_module.module_elements: Module_with"; + module_type_elements ~trans: trans + { mt_name = "" ; mt_info = None ; mt_type = None ; + mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ; + mt_loc = Odoc_types.dummy_loc ; + } + | Module_constraint (k, _tk) -> + print_DEBUG "Odoc_module.module_elements: Module_constraint"; + (* FIXME : use k or tk ? *) + module_elements visited ~trans: trans + { m_name = "" ; + m_info = None ; + m_type = Types.Mty_signature [] ; + m_is_interface = false ; m_file = "" ; m_kind = k ; + m_loc = Odoc_types.dummy_loc ; + m_top_deps = [] ; + m_code = None ; + m_code_intf = None ; + m_text_only = false ; + } + | Module_typeof _ -> [] + | Module_unpack _ -> [] +(* + module_type_elements ~trans: trans + { mt_name = "" ; mt_info = None ; mt_type = None ; + mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ; + mt_loc = Odoc_types.dummy_loc } +*) + in + iter_kind m.m_kind in + module_elements S.empty ~trans m + (** Returns the list of values of a module. @param trans indicates if, for aliased modules, we must perform a transitive search.*) let module_values ?(trans=true) m = values (module_elements ~trans m) @@ -459,20 +472,22 @@ let rec module_type_is_functor mt = (** The module is a functor if is defined as a functor or if it is an alias for a functor. *) let module_is_functor m = - let rec iter = function + let rec iter visited = function Module_functor _ -> true | Module_alias ma -> ( - match ma.ma_module with - None -> false - | Some (Mod mo) -> iter mo.m_kind - | Some (Modtype mt) -> module_type_is_functor mt + not (S.mem ma.ma_name visited) + && + match ma.ma_module with + None -> false + | Some (Mod mo) -> iter (S.add ma.ma_name visited) mo.m_kind + | Some (Modtype mt) -> module_type_is_functor mt ) | Module_constraint (k, _) -> - iter k + iter visited k | _ -> false in - iter m.m_kind + iter S.empty m.m_kind (** Returns the list of values of a module type. @param trans indicates if, for aliased modules, we must perform a transitive search.*) diff --git a/ocamldoc/odoc_sig.ml b/ocamldoc/odoc_sig.ml index ff1e9a57..5bc67b80 100644 --- a/ocamldoc/odoc_sig.ml +++ b/ocamldoc/odoc_sig.ml @@ -282,15 +282,15 @@ module Analyser = | Ptyp_object (fields, _) -> let rec f = function | [] -> [] - | ("",_,_) :: _ -> + | ({txt=""},_,_) :: _ -> (* Fields with no name have been eliminated previously. *) assert false - | (name, _atts, ct) :: [] -> + | ({txt=name}, _atts, ct) :: [] -> let pos = Loc.ptyp_end ct in let (_,comment_opt) = just_after_special pos pos_end in [name, comment_opt] - | (name, _atts, ct) :: ((_name2, _atts2, ct2) as ele2) :: q -> + | ({txt=name}, _atts, ct) :: ((_name2, _atts2, ct2) as ele2) :: q -> let pos = Loc.ptyp_end ct in let pos2 = Loc.ptyp_start ct2 in let (_,comment_opt) = just_after_special pos pos2 in @@ -298,7 +298,7 @@ module Analyser = in let is_named_field field = match field with - | ("",_,_) -> false + | ({txt=""},_,_) -> false | _ -> true in (0, f @@ List.filter is_named_field fields) @@ -525,7 +525,7 @@ module Analyser = let loc = item.Parsetree.pctf_loc in match item.Parsetree.pctf_desc with - | Parsetree.Pctf_val (name, mutable_flag, virtual_flag, _) -> + | Parsetree.Pctf_val ({txt=name}, mutable_flag, virtual_flag, _) -> (* of (string * mutable_flag * core_type option * Location.t)*) let (comment_opt, eles_comments) = get_comments_in_class last_pos (Loc.start loc) in @@ -563,7 +563,7 @@ module Analyser = let (inher_l, eles) = f (pos_end + maybe_more) q in (inher_l, eles_comments @ ((Class_attribute att) :: eles)) - | Parsetree.Pctf_method (name, private_flag, virtual_flag, _) -> + | Parsetree.Pctf_method ({txt=name}, private_flag, virtual_flag, _) -> (* of (string * private_flag * virtual_flag * core_type) *) let (comment_opt, eles_comments) = get_comments_in_class last_pos (Loc.start loc) in @@ -1619,21 +1619,7 @@ module Analyser = let analyse_signature source_file input_file (ast : Parsetree.signature) (signat : Types.signature) = - let complete_source_file = - try - let curdir = Sys.getcwd () in - let (dirname, basename) = (Filename.dirname source_file, Filename.basename source_file) in - Sys.chdir dirname ; - let complete = Filename.concat (Sys.getcwd ()) basename in - Sys.chdir curdir ; - complete - with - Sys_error s -> - prerr_endline s ; - incr Odoc_global.errors ; - source_file - in - prepare_file complete_source_file input_file; + prepare_file source_file input_file; (* We create the t_module for this file. *) let mod_name = String.capitalize_ascii (Filename.basename (try Filename.chop_extension source_file with _ -> source_file)) diff --git a/otherlibs/Makefile b/otherlibs/Makefile index 4758bf59..05a093fd 100644 --- a/otherlibs/Makefile +++ b/otherlibs/Makefile @@ -84,7 +84,8 @@ install:: cp dll$(CLIBNAME)$(EXT_DLL) "$(INSTALL_STUBLIBDIR)/"; fi cp lib$(CLIBNAME).$(A) "$(INSTALL_LIBDIR)/" cd "$(INSTALL_LIBDIR)"; $(RANLIB) lib$(CLIBNAME).$(A) - cp $(LIBNAME).cma $(CMIFILES) $(CMIFILES:.cmi=.mli) "$(INSTALL_LIBDIR)/" + cp $(LIBNAME).cma $(CMIFILES) $(CMIFILES:.cmi=.mli) \ + $(CMIFILES:.cmi=.cmti) "$(INSTALL_LIBDIR)/" if test -n "$(HEADERS)"; then \ cp $(HEADERS) "$(INSTALL_LIBDIR)/caml/"; fi diff --git a/otherlibs/bigarray/.depend b/otherlibs/bigarray/.depend index 5bf15bc9..7d75fc25 100644 --- a/otherlibs/bigarray/.depend +++ b/otherlibs/bigarray/.depend @@ -1,6 +1,6 @@ bigarray_stubs.o: bigarray_stubs.c ../../byterun/caml/alloc.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \ + ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \ bigarray.h ../../byterun/caml/custom.h ../../byterun/caml/fail.h \ ../../byterun/caml/intext.h ../../byterun/caml/io.h \ @@ -8,14 +8,14 @@ bigarray_stubs.o: bigarray_stubs.c ../../byterun/caml/alloc.h \ ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ ../../byterun/caml/address_class.h ../../byterun/caml/signals.h -mmap_unix.o: mmap_unix.c bigarray.h ../../byterun/caml/config.h \ - ../../byterun/caml/../../config/m.h \ +mmap_unix.o: mmap_unix.c bigarray.h ../../byterun/caml/compatibility.h \ + ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \ ../../byterun/caml/misc.h ../../byterun/caml/custom.h \ ../../byterun/caml/fail.h ../../byterun/caml/io.h \ ../../byterun/caml/sys.h ../../byterun/caml/signals.h -mmap_win32.o: mmap_win32.c bigarray.h ../../byterun/caml/config.h \ - ../../byterun/caml/../../config/m.h \ +mmap_win32.o: mmap_win32.c bigarray.h ../../byterun/caml/compatibility.h \ + ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \ ../../byterun/caml/misc.h ../../byterun/caml/alloc.h \ ../../byterun/caml/custom.h ../../byterun/caml/fail.h \ diff --git a/otherlibs/bigarray/Makefile b/otherlibs/bigarray/Makefile index 7b95b517..5044c724 100644 --- a/otherlibs/bigarray/Makefile +++ b/otherlibs/bigarray/Makefile @@ -13,10 +13,25 @@ #* * #************************************************************************** -include Makefile.shared +LIBNAME=bigarray +EXTRACFLAGS=-I../$(UNIXLIB) -DIN_OCAML_BIGARRAY +EXTRACAMLFLAGS=-I ../$(UNIXLIB) +COBJS=bigarray_stubs.$(O) mmap_$(UNIX_OR_WIN32).$(O) +CAMLOBJS=bigarray.cmo +HEADERS=bigarray.h + +include ../Makefile depend: $(CC) -MM $(CFLAGS) *.c > .depend - $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend + $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend + +ifeq "$(TOOLCHAIN)" "msvc" +.depend.nt: .depend + sed -e 's/\.o/.$(O)/g' $< > $@ + +include .depend.nt +else include .depend +endif diff --git a/otherlibs/bigarray/Makefile.nt b/otherlibs/bigarray/Makefile.nt index 2871177a..ed9900bb 100644 --- a/otherlibs/bigarray/Makefile.nt +++ b/otherlibs/bigarray/Makefile.nt @@ -13,12 +13,4 @@ #* * #************************************************************************** -# It would be better to move that to config/Makefile.* -UNIX_OR_WIN32=win32 - include Makefile - -.depend.nt: .depend - sed -e 's/\.o/.$(O)/g' .depend > .depend.nt - -include .depend.nt diff --git a/otherlibs/bigarray/bigarray.ml b/otherlibs/bigarray/bigarray.ml index 425dde11..8d697150 100644 --- a/otherlibs/bigarray/bigarray.ml +++ b/otherlibs/bigarray/bigarray.ml @@ -137,6 +137,26 @@ module Genarray = struct map_internal fd kind layout shared dims pos end +module Array0 = struct + type ('a, 'b, 'c) t = ('a, 'b, 'c) Genarray.t + let create kind layout = + Genarray.create kind layout [||] + let get arr = Genarray.get arr [||] + let set arr = Genarray.set arr [||] + external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind" + external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout" + + let size_in_bytes arr = kind_size_in_bytes (kind arr) + + external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" + external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" + + let of_value kind layout v = + let a = create kind layout in + set a v; + a +end + module Array1 = struct type ('a, 'b, 'c) t = ('a, 'b, 'c) Genarray.t let create kind layout dim = @@ -154,6 +174,10 @@ module Array1 = struct (kind_size_in_bytes (kind arr)) * (dim arr) external sub: ('a, 'b, 'c) t -> int -> int -> ('a, 'b, 'c) t = "caml_ba_sub" + let slice (type t) (a : (_, _, t) Genarray.t) n = + match layout a with + | C_layout -> (Genarray.slice_left a [|n|] : (_, _, t) Genarray.t) + | Fortran_layout -> (Genarray.slice_right a [|n|]: (_, _, t) Genarray.t) external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" let of_array (type t) kind (layout: t layout) data = @@ -277,12 +301,17 @@ module Array3 = struct Genarray.map_file fd ?pos kind layout shared [|dim1;dim2;dim3|] end +external genarray_of_array0: ('a, 'b, 'c) Array0.t -> ('a, 'b, 'c) Genarray.t + = "%identity" external genarray_of_array1: ('a, 'b, 'c) Array1.t -> ('a, 'b, 'c) Genarray.t = "%identity" external genarray_of_array2: ('a, 'b, 'c) Array2.t -> ('a, 'b, 'c) Genarray.t = "%identity" external genarray_of_array3: ('a, 'b, 'c) Array3.t -> ('a, 'b, 'c) Genarray.t = "%identity" +let array0_of_genarray a = + if Genarray.num_dims a = 0 then a + else invalid_arg "Bigarray.array0_of_genarray" let array1_of_genarray a = if Genarray.num_dims a = 1 then a else invalid_arg "Bigarray.array1_of_genarray" @@ -296,6 +325,7 @@ let array3_of_genarray a = external reshape: ('a, 'b, 'c) Genarray.t -> int array -> ('a, 'b, 'c) Genarray.t = "caml_ba_reshape" +let reshape_0 a = reshape a [||] let reshape_1 a dim1 = reshape a [|dim1|] let reshape_2 a dim1 dim2 = reshape a [|dim1;dim2|] let reshape_3 a dim1 dim2 dim3 = reshape a [|dim1;dim2;dim3|] diff --git a/otherlibs/bigarray/bigarray.mli b/otherlibs/bigarray/bigarray.mli index c805d518..683e1682 100644 --- a/otherlibs/bigarray/bigarray.mli +++ b/otherlibs/bigarray/bigarray.mli @@ -49,7 +49,7 @@ ({!Bigarray.int16_signed_elt} or {!Bigarray.int16_unsigned_elt}), - OCaml integers (signed, 31 bits on 32-bit architectures, 63 bits on 64-bit architectures) ({!Bigarray.int_elt}), -- 32-bit signed integer ({!Bigarray.int32_elt}), +- 32-bit signed integers ({!Bigarray.int32_elt}), - 64-bit signed integers ({!Bigarray.int64_elt}), - platform-native signed integers (32 bits on 32-bit architectures, 64 bits on 64-bit architectures) ({!Bigarray.nativeint_elt}). @@ -226,7 +226,7 @@ module Genarray : sig type ('a, 'b, 'c) t (** The type [Genarray.t] is the type of big arrays with variable - numbers of dimensions. Any number of dimensions between 1 and 16 + numbers of dimensions. Any number of dimensions between 0 and 16 is supported. The three type parameters to [Genarray.t] identify the array element @@ -264,7 +264,7 @@ module Genarray : the initial values of array elements is unspecified. [Genarray.create] raises [Invalid_argument] if the number of dimensions - is not in the range 1 to 16 inclusive, or if one of the dimensions + is not in the range 0 to 16 inclusive, or if one of the dimensions is negative. *) external num_dims: ('a, 'b, 'c) t -> int = "caml_ba_num_dims" @@ -486,12 +486,60 @@ module Genarray : end +(** {6 Zero-dimensional arrays} *) + +(** Zero-dimensional arrays. The [Array0] structure provides operations + similar to those of {!Bigarray.Genarray}, but specialized to the case + of zero-dimensional arrays that only contain a single scalar value. + Statically knowing the number of dimensions of the array allows + faster operations, and more precise static type-checking. + @since 4.05.0 *) +module Array0 : sig + type ('a, 'b, 'c) t + (** The type of zero-dimensional big arrays whose elements have + OCaml type ['a], representation kind ['b], and memory layout ['c]. *) + + val create: ('a, 'b) kind -> 'c layout -> ('a, 'b, 'c) t + (** [Array0.create kind layout] returns a new bigarray of zero dimension. + [kind] and [layout] determine the array element kind and the array + layout as described for {!Genarray.create}. *) + + external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind" + (** Return the kind of the given big array. *) + + external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout" + (** Return the layout of the given big array. *) + + val size_in_bytes : ('a, 'b, 'c) t -> int + (** [size_in_bytes a] is [a]'s {!kind_size_in_bytes}. *) + + val get: ('a, 'b, 'c) t -> 'a + (** [Array0.get a] returns the only element in [a]. *) + + val set: ('a, 'b, 'c) t -> 'a -> unit + (** [Array0.set a x v] stores the value [v] in [a]. *) + + external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" + (** Copy the first big array to the second big array. + See {!Genarray.blit} for more details. *) + + external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" + (** Fill the given big array with the given value. + See {!Genarray.fill} for more details. *) + + val of_value: ('a, 'b) kind -> 'c layout -> 'a -> ('a, 'b, 'c) t + (** Build a zero-dimensional big array initialized from the + given value. *) + +end + + (** {6 One-dimensional arrays} *) (** One-dimensional arrays. The [Array1] structure provides operations similar to those of {!Bigarray.Genarray}, but specialized to the case of one-dimensional arrays. - (The [Array2] and [Array3] structures below provide operations + (The {!Array2} and {!Array3} structures below provide operations specialized for two- and three-dimensional arrays.) Statically knowing the number of dimensions of the array allows faster operations, and more precise static type-checking. *) @@ -504,7 +552,7 @@ module Array1 : sig (** [Array1.create kind layout dim] returns a new bigarray of one dimension, whose size is [dim]. [kind] and [layout] determine the array element kind and the array layout - as described for [Genarray.create]. *) + as described for {!Genarray.create}. *) external dim: ('a, 'b, 'c) t -> int = "%caml_ba_dim_1" (** Return the size (dimension) of the given one-dimensional @@ -540,16 +588,23 @@ module Array1 : sig external sub: ('a, 'b, 'c) t -> int -> int -> ('a, 'b, 'c) t = "caml_ba_sub" (** Extract a sub-array of the given one-dimensional big array. - See [Genarray.sub_left] for more details. *) + See {!Genarray.sub_left} for more details. *) + + val slice: ('a, 'b, 'c) t -> int -> ('a, 'b, 'c) Array0.t + (** Extract a scalar (zero-dimensional slice) of the given one-dimensional + big array. The integer parameter is the index of the scalar to + extract. See {!Bigarray.Genarray.slice_left} and + {!Bigarray.Genarray.slice_right} for more details. + @since 4.05.0 *) external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" (** Copy the first big array to the second big array. - See [Genarray.blit] for more details. *) + See {!Genarray.blit} for more details. *) external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" (** Fill the given big array with the given value. - See [Genarray.fill] for more details. *) + See {!Genarray.fill} for more details. *) val of_array: ('a, 'b) kind -> 'c layout -> 'a array -> ('a, 'b, 'c) t (** Build a one-dimensional big array initialized from the @@ -819,6 +874,11 @@ end (** {6 Coercions between generic big arrays and fixed-dimension big arrays} *) +external genarray_of_array0 : + ('a, 'b, 'c) Array0.t -> ('a, 'b, 'c) Genarray.t = "%identity" +(** Return the generic big array corresponding to the given zero-dimensional + big array. @since 4.05.0 *) + external genarray_of_array1 : ('a, 'b, 'c) Array1.t -> ('a, 'b, 'c) Genarray.t = "%identity" (** Return the generic big array corresponding to the given one-dimensional @@ -834,6 +894,12 @@ external genarray_of_array3 : (** Return the generic big array corresponding to the given three-dimensional big array. *) +val array0_of_genarray : ('a, 'b, 'c) Genarray.t -> ('a, 'b, 'c) Array0.t +(** Return the zero-dimensional big array corresponding to the given + generic big array. Raise [Invalid_argument] if the generic big array + does not have exactly zero dimension. + @since 4.05.0 *) + val array1_of_genarray : ('a, 'b, 'c) Genarray.t -> ('a, 'b, 'c) Array1.t (** Return the one-dimensional big array corresponding to the given generic big array. Raise [Invalid_argument] if the generic big array @@ -868,6 +934,11 @@ val reshape : ('a, 'b, 'c) Genarray.t -> int array -> ('a, 'b, 'c) Genarray.t of the dimensions of [b] must be equal to [i1 * ... * iN]. Otherwise, [Invalid_argument] is raised. *) +val reshape_0 : ('a, 'b, 'c) Genarray.t -> ('a, 'b, 'c) Array0.t +(** Specialized version of {!Bigarray.reshape} for reshaping to + zero-dimensional arrays. + @since 4.05.0 *) + val reshape_1 : ('a, 'b, 'c) Genarray.t -> int -> ('a, 'b, 'c) Array1.t (** Specialized version of {!Bigarray.reshape} for reshaping to one-dimensional arrays. *) diff --git a/otherlibs/bigarray/bigarray_stubs.c b/otherlibs/bigarray/bigarray_stubs.c index b0619cd7..cb38bef7 100644 --- a/otherlibs/bigarray/bigarray_stubs.c +++ b/otherlibs/bigarray/bigarray_stubs.c @@ -146,7 +146,7 @@ caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim) struct caml_ba_array * b; intnat dimcopy[CAML_BA_MAX_NUM_DIMS]; - Assert(num_dims >= 1 && num_dims <= CAML_BA_MAX_NUM_DIMS); + Assert(num_dims >= 0 && num_dims <= CAML_BA_MAX_NUM_DIMS); Assert((flags & CAML_BA_KIND_MASK) <= CAML_BA_CHAR); for (i = 0; i < num_dims; i++) dimcopy[i] = dim[i]; size = 0; @@ -202,7 +202,8 @@ CAMLprim value caml_ba_create(value vkind, value vlayout, value vdim) int i, flags; num_dims = Wosize_val(vdim); - if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS) + /* here num_dims is unsigned (mlsize_t) so no need to check (num_dims >= 0) */ + if (num_dims > CAML_BA_MAX_NUM_DIMS) caml_invalid_argument("Bigarray.create: bad number of dimensions"); for (i = 0; i < num_dims; i++) { dim[i] = Long_val(Field(vdim, i)); @@ -1048,9 +1049,9 @@ CAMLprim value caml_ba_slice(value vb, value vind) intnat * sub_dims; char * sub_data; - /* Check number of indices < number of dimensions of array */ + /* Check number of indices <= number of dimensions of array */ num_inds = Wosize_val(vind); - if (num_inds >= b->num_dims) + if (num_inds > b->num_dims) caml_invalid_argument("Bigarray.slice: too many indices"); /* Compute offset and check bounds */ if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { @@ -1090,7 +1091,8 @@ CAMLprim value caml_ba_change_layout(value vb, value vlayout) /* if the layout is different, change the flags and reverse the dimensions */ if (Caml_ba_layout_val(vlayout) != (b->flags & CAML_BA_LAYOUT_MASK)) { /* change the flags to reflect the new layout */ - int flags = (b->flags & CAML_BA_KIND_MASK) | Caml_ba_layout_val(vlayout); + int flags = (b->flags & (CAML_BA_KIND_MASK | CAML_BA_MANAGED_MASK)) + | Caml_ba_layout_val(vlayout); /* reverse the dimensions */ intnat new_dim[CAML_BA_MAX_NUM_DIMS]; unsigned int i; @@ -1099,8 +1101,8 @@ CAMLprim value caml_ba_change_layout(value vb, value vlayout) caml_ba_update_proxy(b, Caml_ba_array_val(res)); CAMLreturn(res); } else { - /* otherwise, do nothing */ - CAMLreturn(vb); + /* otherwise, do nothing */ + CAMLreturn(vb); } #undef b } @@ -1299,7 +1301,8 @@ CAMLprim value caml_ba_reshape(value vb, value vdim) int i; num_dims = Wosize_val(vdim); - if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS) + /* here num_dims is unsigned (mlsize_t) so no need to check (num_dims >= 0) */ + if (num_dims > CAML_BA_MAX_NUM_DIMS) caml_invalid_argument("Bigarray.reshape: bad number of dimensions"); num_elts = 1; for (i = 0; i < num_dims; i++) { diff --git a/otherlibs/dynlink/Makefile b/otherlibs/dynlink/Makefile index 35b40f6e..8c8c3ae4 100644 --- a/otherlibs/dynlink/Makefile +++ b/otherlibs/dynlink/Makefile @@ -45,7 +45,8 @@ COMPILEROBJS=\ ../../utils/terminfo.cmo ../../utils/warnings.cmo \ ../../parsing/asttypes.cmi \ ../../parsing/location.cmo ../../parsing/longident.cmo \ - ../../parsing/docstrings.cmo ../../parsing/ast_helper.cmo \ + ../../parsing/docstrings.cmo ../../parsing/syntaxerr.cmo \ + ../../parsing/ast_helper.cmo \ ../../parsing/ast_mapper.cmo ../../parsing/ast_iterator.cmo \ ../../parsing/attr_helper.cmo \ ../../parsing/builtin_attributes.cmo \ @@ -89,7 +90,7 @@ extract_crc: dynlink.cma extract_crc.cmo INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) install: - cp dynlink.cmi dynlink.cma dynlink.mli "$(INSTALL_LIBDIR)" + cp dynlink.cmi dynlink.cmti dynlink.cma dynlink.mli "$(INSTALL_LIBDIR)" cp extract_crc "$(INSTALL_LIBDIR)/extract_crc$(EXE)" installopt: diff --git a/otherlibs/dynlink/natdynlink.ml b/otherlibs/dynlink/natdynlink.ml index 685b306b..de237728 100644 --- a/otherlibs/dynlink/natdynlink.ml +++ b/otherlibs/dynlink/natdynlink.ml @@ -16,11 +16,20 @@ (* Dynamic loading of .cmx files *) +open Cmx_format + type handle -external ndl_open: string -> bool -> handle * bytes = "caml_natdynlink_open" +type global_map = { + name : string; + crc_intf : Digest.t; + crc_impl : Digest.t; + syms : string list +} + +external ndl_open: string -> bool -> handle * dynheader = "caml_natdynlink_open" external ndl_run: handle -> string -> unit = "caml_natdynlink_run" -external ndl_getmap: unit -> bytes = "caml_natdynlink_getmap" +external ndl_getmap: unit -> global_map list = "caml_natdynlink_getmap" external ndl_globals_inited: unit -> int = "caml_natdynlink_globals_inited" type linking_error = @@ -41,8 +50,6 @@ type error = exception Error of error -open Cmx_format - (* Copied from config.ml to avoid dependencies *) let cmxs_magic_number = "Caml2007D002" @@ -54,11 +61,10 @@ let read_file filename priv = let dll = dll_filename filename in if not (Sys.file_exists dll) then raise (Error (File_not_found dll)); - let (handle,data) as res = ndl_open dll (not priv) in - if Obj.tag (Obj.repr res) = Obj.string_tag - then raise (Error (Cannot_open_dll (Obj.magic res))); + let (handle,header) = try + ndl_open dll (not priv) + with Failure s -> raise (Error (Cannot_open_dll s)) in - let header : dynheader = Marshal.from_bytes data 0 in if header.dynu_magic <> cmxs_magic_number then raise(Error(Not_a_bytecode_file dll)); (dll, handle, header.dynu_units) @@ -90,13 +96,12 @@ let allow_extension = ref true let inited = ref false let default_available_units () = - let map : (string*Digest.t*Digest.t*string list) list = - Marshal.from_bytes (ndl_getmap ()) 0 in + let map = ndl_getmap () in let exe = Sys.executable_name in let rank = ref 0 in global_state := List.fold_left - (fun st (name,crc_intf,crc_impl,syms) -> + (fun st {name;crc_intf;crc_impl;syms} -> rank := !rank + List.length syms; { ifaces = StrMap.add name (crc_intf,exe) st.ifaces; diff --git a/otherlibs/graph/dump_img.c b/otherlibs/graph/dump_img.c index 38fab8be..6d9be709 100644 --- a/otherlibs/graph/dump_img.c +++ b/otherlibs/graph/dump_img.c @@ -28,10 +28,10 @@ value caml_gr_dump_image(value image) caml_gr_check_open(); width = Width_im(image); height = Height_im(image); - m = alloc(height, 0); + m = caml_alloc(height, 0); for (i = 0; i < height; i++) { - value v = alloc(width, 0); - modify(&Field(m, i), v); + value v = caml_alloc(width, 0); + caml_modify(&Field(m, i), v); } idata = diff --git a/otherlibs/graph/events.c b/otherlibs/graph/events.c index 164c3601..37146c9d 100644 --- a/otherlibs/graph/events.c +++ b/otherlibs/graph/events.c @@ -146,7 +146,7 @@ void caml_gr_handle_event(XEvent * event) static value caml_gr_wait_allocate_result(int mouse_x, int mouse_y, int button, int keypressed, int key) { - value res = alloc_small(5, 0); + value res = caml_alloc_small(5, 0); Field(res, 0) = Val_int(mouse_x); Field(res, 1) = Val_int(mouse_y == -1 ? -1 : Wcvt(mouse_y)); Field(res, 2) = Val_bool(button); @@ -237,9 +237,9 @@ static value caml_gr_wait_event_blocking(long mask) /* No event available: block on input socket until one is */ FD_ZERO(&readfds); FD_SET(ConnectionNumber(caml_gr_display), &readfds); - enter_blocking_section(); + caml_enter_blocking_section(); select(FD_SETSIZE, &readfds, NULL, NULL, NULL); - leave_blocking_section(); + caml_leave_blocking_section(); caml_gr_check_open(); /* in case another thread closed the display */ } } diff --git a/otherlibs/graph/fill.c b/otherlibs/graph/fill.c index dc7baf0f..0eb307f9 100644 --- a/otherlibs/graph/fill.c +++ b/otherlibs/graph/fill.c @@ -57,7 +57,7 @@ value caml_gr_fill_poly(value array) npoints, Complex, CoordModeOrigin); XFlush(caml_gr_display); } - stat_free((char *) points); + caml_stat_free((char *) points); return Val_unit; } diff --git a/otherlibs/graph/graphics.mli b/otherlibs/graph/graphics.mli index c32ff39e..e364f6e0 100644 --- a/otherlibs/graph/graphics.mli +++ b/otherlibs/graph/graphics.mli @@ -48,7 +48,10 @@ external size_y : unit -> int = "caml_gr_size_y" (** Return the size of the graphics window. Coordinates of the screen pixels range over [0 .. size_x()-1] and [0 .. size_y()-1]. Drawings outside of this rectangle are clipped, without causing - an error. The origin (0,0) is at the lower left corner. *) + an error. The origin (0,0) is at the lower left corner. + Some implementation (e.g. X Windows) represent coordinates by + 16-bit integers, hence wrong clipping may occur with coordinates + below [-32768] or above [32676]. *) (** {6 Colors} *) @@ -303,7 +306,7 @@ external wait_next_event : event list -> status = "caml_gr_wait_event" graphics window, the [mouse_x] and [mouse_y] fields of the event are outside the range [0..size_x()-1, 0..size_y()-1]. Keypresses are queued, and dequeued one by one when the [Key_pressed] - event is specified. *) + event is specified and the [Poll] event is not specified. *) val loop_at_exit : event list -> (status -> unit) -> unit (** Loop before exiting the program, the list given as argument is the diff --git a/otherlibs/graph/image.c b/otherlibs/graph/image.c index ffd6a95e..1d72e0da 100644 --- a/otherlibs/graph/image.c +++ b/otherlibs/graph/image.c @@ -38,7 +38,7 @@ static struct custom_operations image_ops = { value caml_gr_new_image(int w, int h) { - value res = alloc_custom(&image_ops, sizeof(struct grimage), + value res = caml_alloc_custom(&image_ops, sizeof(struct grimage), w * h, Max_image_mem); Width_im(res) = w; Height_im(res) = h; diff --git a/otherlibs/graph/open.c b/otherlibs/graph/open.c index eb94fc78..8f6ee07f 100644 --- a/otherlibs/graph/open.c +++ b/otherlibs/graph/open.c @@ -234,7 +234,7 @@ value caml_gr_id_of_window(Window win) char tmp[256]; sprintf(tmp, "%lu", (unsigned long)win); - return copy_string( tmp ); + return caml_copy_string( tmp ); } value caml_gr_window_id(void) @@ -245,7 +245,7 @@ value caml_gr_window_id(void) value caml_gr_set_window_title(value n) { - if (window_name != NULL) stat_free(window_name); + if (window_name != NULL) caml_stat_free(window_name); window_name = caml_strdup(String_val(n)); if (caml_gr_initialized) { XStoreName(caml_gr_display, caml_gr_window.win, window_name); @@ -373,11 +373,11 @@ void caml_gr_fail(char *fmt, char *arg) if (graphic_failure_exn == NULL) { graphic_failure_exn = caml_named_value("Graphics.Graphic_failure"); if (graphic_failure_exn == NULL) - invalid_argument("Exception Graphics.Graphic_failure not initialized," + caml_invalid_argument("Exception Graphics.Graphic_failure not initialized," " must link graphics.cma"); } sprintf(buffer, fmt, arg); - raise_with_string(*graphic_failure_exn, buffer); + caml_raise_with_string(*graphic_failure_exn, buffer); } void caml_gr_check_open(void) diff --git a/otherlibs/graph/text.c b/otherlibs/graph/text.c index 3fccaa01..7328967d 100644 --- a/otherlibs/graph/text.c +++ b/otherlibs/graph/text.c @@ -68,7 +68,7 @@ value caml_gr_draw_char(value chr) value caml_gr_draw_string(value str) { caml_gr_check_open(); - caml_gr_draw_text(String_val(str), string_length(str)); + caml_gr_draw_text(String_val(str), caml_string_length(str)); return Val_unit; } @@ -78,8 +78,8 @@ value caml_gr_text_size(value str) value res; caml_gr_check_open(); if (caml_gr_font == NULL) caml_gr_get_font(DEFAULT_FONT); - width = XTextWidth(caml_gr_font, String_val(str), string_length(str)); - res = alloc_small(2, 0); + width = XTextWidth(caml_gr_font, String_val(str), caml_string_length(str)); + res = caml_alloc_small(2, 0); Field(res, 0) = Val_int(width); Field(res, 1) = Val_int(caml_gr_font->ascent + caml_gr_font->descent); return res; diff --git a/otherlibs/num/Makefile b/otherlibs/num/Makefile index 7b95b517..ccd077d3 100644 --- a/otherlibs/num/Makefile +++ b/otherlibs/num/Makefile @@ -13,10 +13,36 @@ #* * #************************************************************************** -include Makefile.shared +# Makefile for the "num" (exact rational arithmetic) library +LIBNAME=nums +EXTRACFLAGS=-DBNG_ARCH_$(BNG_ARCH) -DBNG_ASM_LEVEL=$(BNG_ASM_LEVEL) +CAMLOBJS=int_misc.cmo nat.cmo big_int.cmo arith_flags.cmo \ + ratio.cmo num.cmo arith_status.cmo +CMIFILES=big_int.cmi nat.cmi num.cmi ratio.cmi arith_status.cmi +COBJS=bng.$(O) nat_stubs.$(O) + +include ../Makefile + +clean:: + rm -f *~ + +bng.$(O): bng.h bng_digit.c \ + bng_amd64.c bng_ia32.c bng_ppc.c bng_sparc.c + +# At the moment, the following rule only works with gcc +# It is not a big deal since the .depend file it produces is stored +# in the repository depend: $(CC) -MM $(CFLAGS) *.c > .depend - $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend + $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend + +ifeq "$(TOOLCHAIN)" "msvc" + +.depend.nt: .depend + sed -e 's/\.o/.$(O)/g' $< > $@ +include .depend.nt +else include .depend +endif diff --git a/otherlibs/num/Makefile.nt b/otherlibs/num/Makefile.nt index 1c47f07b..ed9900bb 100644 --- a/otherlibs/num/Makefile.nt +++ b/otherlibs/num/Makefile.nt @@ -13,9 +13,4 @@ #* * #************************************************************************** -include Makefile.shared - -depend: - sed -e 's/\.o/.$(O)/g' .depend > .depend.nt - -include .depend.nt +include Makefile diff --git a/otherlibs/num/big_int.ml b/otherlibs/num/big_int.ml index efe376ca..45cea9ca 100644 --- a/otherlibs/num/big_int.ml +++ b/otherlibs/num/big_int.ml @@ -336,6 +336,9 @@ let int_of_big_int bi = if eq_big_int bi monster_big_int then monster_int else failwith "int_of_big_int";; +let int_of_big_int_opt bi = + try Some (int_of_big_int bi) with Failure _ -> None + let big_int_of_nativeint i = if i = 0n then zero_big_int @@ -359,6 +362,9 @@ let nativeint_of_big_int bi = then Nativeint.neg i else failwith "nativeint_of_big_int" +let nativeint_of_big_int_opt bi = + try Some (nativeint_of_big_int bi) with Failure _ -> None + let big_int_of_int32 i = big_int_of_nativeint (Nativeint.of_int32 i) let int32_of_big_int bi = @@ -367,6 +373,9 @@ let int32_of_big_int bi = then Nativeint.to_int32 i else failwith "int32_of_big_int" +let int32_of_big_int_opt bi = + try Some (int32_of_big_int bi) with Failure _ -> None + let big_int_of_int64 i = if Sys.word_size = 64 then big_int_of_nativeint (Int64.to_nativeint i) @@ -406,6 +415,9 @@ let int64_of_big_int bi = else failwith "int64_of_big_int" end +let int64_of_big_int_opt bi = + try Some (int64_of_big_int bi) with Failure _ -> None + (* Coercion with nat type *) let nat_of_big_int bi = if bi.sign = -1 @@ -460,6 +472,9 @@ let sys_big_int_of_string s ofs len = let big_int_of_string s = sys_big_int_of_string s 0 (String.length s) +let big_int_of_string_opt s = + try Some (big_int_of_string s) with Failure _ -> None + let power_base_nat base nat off len = if base = 0 then nat_of_int 0 else if is_zero_nat nat off len || base = 1 then nat_of_int 1 else diff --git a/otherlibs/num/big_int.mli b/otherlibs/num/big_int.mli index f5b2800f..07c40729 100644 --- a/otherlibs/num/big_int.mli +++ b/otherlibs/num/big_int.mli @@ -141,6 +141,16 @@ val big_int_of_string : string -> big_int (** Convert a string to a big integer, in decimal. The string consists of an optional [-] or [+] sign, followed by one or several decimal digits. *) +(* TODO: document error condition. *) + +val big_int_of_string_opt: string -> big_int option +(** Convert a string to a big integer, in decimal. + The string consists of an optional [-] or [+] sign, + followed by one or several decimal digits. Other the function + returns [None]. + @since 4.05 +*) + (** {6 Conversions to and from other numerical types} *) @@ -161,6 +171,13 @@ val int_of_big_int : big_int -> int Raises [Failure "int_of_big_int"] if the big integer is not representable as a small integer. *) +val int_of_big_int_opt: big_int -> int option +(** Convert a big integer to a small integer (type [int]). Return + [None] if the big integer is not representable as a small + integer. + @since 4.05 +*) + val big_int_of_int32 : int32 -> big_int (** Convert a 32-bit integer to a big integer. *) @@ -175,16 +192,35 @@ val int32_of_big_int : big_int -> int32 Raises [Failure] if the big integer is outside the range \[-2{^31}, 2{^31}-1\]. *) +val int32_of_big_int_opt: big_int -> int32 option +(** Convert a big integer to a 32-bit integer. Return [None] if the + big integer is outside the range \[-2{^31}, 2{^31}-1\]. + @since 4.05 +*) + val nativeint_of_big_int : big_int -> nativeint (** Convert a big integer to a native integer. Raises [Failure] if the big integer is outside the range [[Nativeint.min_int, Nativeint.max_int]]. *) +val nativeint_of_big_int_opt: big_int -> nativeint option +(** Convert a big integer to a native integer. Return [None] if the + big integer is outside the range [[Nativeint.min_int, + Nativeint.max_int]]; + @since 4.05 +*) + val int64_of_big_int : big_int -> int64 (** Convert a big integer to a 64-bit integer. Raises [Failure] if the big integer is outside the range \[-2{^63}, 2{^63}-1\]. *) +val int64_of_big_int_opt: big_int -> int64 option +(** Convert a big integer to a 64-bit integer. Return [None] if the + big integer is outside the range \[-2{^63}, 2{^63}-1\]. + @since 4.05 +*) + val float_of_big_int : big_int -> float (** Returns a floating-point number approximating the given big integer. *) @@ -237,4 +273,4 @@ val round_futur_last_digit : bytes -> int -> int -> bool val approx_big_int: int -> big_int -> string val round_big_int_to_float: big_int -> bool -> float -(* @since 4.03.0 *) +(** @since 4.03.0 *) diff --git a/otherlibs/num/nat_stubs.c b/otherlibs/num/nat_stubs.c index f85d7c13..5a07a801 100644 --- a/otherlibs/num/nat_stubs.c +++ b/otherlibs/num/nat_stubs.c @@ -46,7 +46,7 @@ static struct custom_operations nat_operations = { CAMLprim value initialize_nat(value unit) { bng_init(); - register_custom_operations(&nat_operations); + caml_register_custom_operations(&nat_operations); return Val_unit; } @@ -54,7 +54,7 @@ CAMLprim value create_nat(value size) { mlsize_t sz = Long_val(size); - return alloc_custom(&nat_operations, sz * sizeof(value), 0, 1); + return caml_alloc_custom(&nat_operations, sz * sizeof(value), 0, 1); } CAMLprim value length_nat(value nat) @@ -335,7 +335,7 @@ CAMLprim value lxor_digit_nat(value nat1, value ofs1, value nat2, value ofs2) - 32-bit word: number of 32-bit words in nat - N 32-bit words (big-endian format) For little-endian platforms, the memory layout between 32-bit and 64-bit - machines is identical, so we can write the nat using serialize_block_4. + machines is identical, so we can write the nat using caml_serialize_block_4. For big-endian 64-bit platforms, we need to swap the two 32-bit halves of 64-bit words to obtain the correct behavior. */ @@ -348,19 +348,19 @@ static void serialize_nat(value nat, #ifdef ARCH_SIXTYFOUR len = len * 2; /* two 32-bit words per 64-bit digit */ if (len >= ((mlsize_t)1 << 32)) - failwith("output_value: nat too big"); + caml_failwith("output_value: nat too big"); #endif - serialize_int_4((int32_t) len); + caml_serialize_int_4((int32_t) len); #if defined(ARCH_SIXTYFOUR) && defined(ARCH_BIG_ENDIAN) { int32_t * p; mlsize_t i; for (i = len, p = Data_custom_val(nat); i > 0; i -= 2, p += 2) { - serialize_int_4(p[1]); /* low 32 bits of 64-bit digit */ - serialize_int_4(p[0]); /* high 32 bits of 64-bit digit */ + caml_serialize_int_4(p[1]); /* low 32 bits of 64-bit digit */ + caml_serialize_int_4(p[0]); /* high 32 bits of 64-bit digit */ } } #else - serialize_block_4(Data_custom_val(nat), len); + caml_serialize_block_4(Data_custom_val(nat), len); #endif *wsize_32 = len * 4; *wsize_64 = len * 4; @@ -370,22 +370,22 @@ static uintnat deserialize_nat(void * dst) { mlsize_t len; - len = deserialize_uint_4(); + len = caml_deserialize_uint_4(); #if defined(ARCH_SIXTYFOUR) && defined(ARCH_BIG_ENDIAN) { uint32_t * p; mlsize_t i; for (i = len, p = dst; i > 1; i -= 2, p += 2) { - p[1] = deserialize_uint_4(); /* low 32 bits of 64-bit digit */ - p[0] = deserialize_uint_4(); /* high 32 bits of 64-bit digit */ + p[1] = caml_deserialize_uint_4(); /* low 32 bits of 64-bit digit */ + p[0] = caml_deserialize_uint_4(); /* high 32 bits of 64-bit digit */ } if (i > 0){ - p[1] = deserialize_uint_4(); /* low 32 bits of 64-bit digit */ + p[1] = caml_deserialize_uint_4(); /* low 32 bits of 64-bit digit */ p[0] = 0; /* high 32 bits of 64-bit digit */ ++ len; } } #else - deserialize_block_4(dst, len); + caml_deserialize_block_4(dst, len); #if defined(ARCH_SIXTYFOUR) if (len & 1){ ((uint32_t *) dst)[len] = 0; diff --git a/otherlibs/num/num.ml b/otherlibs/num/num.ml index d3d76eac..46b70a13 100644 --- a/otherlibs/num/num.ml +++ b/otherlibs/num/num.ml @@ -354,6 +354,11 @@ let int_of_num = function | Big_int bi -> int_of_big_int bi | Ratio r -> int_of_ratio r +let int_of_num_opt = function + Int i -> Some i +| Big_int bi -> int_of_big_int_opt bi +| Ratio r -> (try Some (int_of_ratio r) with Failure _ -> None) + and num_of_int i = if i = monster_int then Big_int (big_int_of_int i) @@ -370,12 +375,18 @@ and num_of_nat nat = then Int (nth_digit_nat nat 0) else Big_int (big_int_of_nat nat) +let nat_of_num_opt x = + try Some (nat_of_num x) with Failure _ -> None + (* Coercion with big_int type *) let big_int_of_num = function Int i -> big_int_of_int i | Big_int bi -> bi | Ratio r -> big_int_of_ratio r +let big_int_of_num_opt x = + try Some (big_int_of_num x) with Failure _ -> None + let string_of_big_int_for_num bi = if !approx_printing_flag then approx_big_int !floating_precision bi @@ -389,6 +400,7 @@ let string_of_normalized_num = function | Ratio r -> string_of_ratio r let string_of_num n = string_of_normalized_num (cautious_normalize_num_when_printing n) + let num_of_string s = try let flag = !normalize_ratio_flag in @@ -401,6 +413,9 @@ let num_of_string s = with Failure _ -> failwith "num_of_string" +let num_of_string_opt s = + try Some (num_of_string s) with Failure _ -> None + (* Coercion with float type *) let float_of_num = function Int i -> float i diff --git a/otherlibs/num/num.mli b/otherlibs/num/num.mli index 3b414a3d..4d3793b9 100644 --- a/otherlibs/num/num.mli +++ b/otherlibs/num/num.mli @@ -159,14 +159,33 @@ val num_of_string : string -> num Raise [Failure "num_of_string"] if the given string is not a valid representation of an integer *) +val num_of_string_opt: string -> num option +(** Convert a string to a number. + Return [None] if the given string is not + a valid representation of an integer. + + @since 4.05 +*) + (** {6 Coercions between numerical types} *) +(* TODO: document the functions below (truncating behavior and error conditions). *) + val int_of_num : num -> int +val int_of_num_opt: num -> int option +(** @since 4.05.0 *) + val num_of_int : int -> num val nat_of_num : num -> nat +val nat_of_num_opt: num -> nat option +(** @since 4.05.0 *) + val num_of_nat : nat -> num val num_of_big_int : big_int -> num val big_int_of_num : num -> big_int +val big_int_of_num_opt: num -> big_int option +(** @since 4.05.0 *) + val ratio_of_num : num -> ratio val num_of_ratio : ratio -> num val float_of_num : num -> float diff --git a/otherlibs/raw_spacetime_lib/.depend b/otherlibs/raw_spacetime_lib/.depend index ddc792f7..098efdb2 100644 --- a/otherlibs/raw_spacetime_lib/.depend +++ b/otherlibs/raw_spacetime_lib/.depend @@ -40,3 +40,12 @@ raw_spacetime_lib.cmi : raw_spacetime_lib.cmo : raw_spacetime_lib.cmi raw_spacetime_lib.cmx : raw_spacetime_lib.cmi raw_spacetime_lib.cmi : +raw_spacetime_lib.cmo : raw_spacetime_lib.cmi +raw_spacetime_lib.cmx : raw_spacetime_lib.cmi +raw_spacetime_lib.cmi : +raw_spacetime_lib.cmo : raw_spacetime_lib.cmi +raw_spacetime_lib.cmx : raw_spacetime_lib.cmi +raw_spacetime_lib.cmi : +raw_spacetime_lib.cmo : raw_spacetime_lib.cmi +raw_spacetime_lib.cmx : raw_spacetime_lib.cmi +raw_spacetime_lib.cmi : diff --git a/otherlibs/raw_spacetime_lib/Makefile b/otherlibs/raw_spacetime_lib/Makefile index 3dd7a322..7e4bf2c7 100644 --- a/otherlibs/raw_spacetime_lib/Makefile +++ b/otherlibs/raw_spacetime_lib/Makefile @@ -13,13 +13,71 @@ #* * #************************************************************************** -# Common Makefile for otherlibs on the Unix ports +# Makefile for Raw_spacetime_lib +ROOTDIR=../.. +include $(ROOTDIR)/config/Makefile + +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib CAMLOPT=$(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib \ -I $(ROOTDIR)/stdlib CFLAGS=-I$(ROOTDIR)/byterun $(SHAREDCCCOMPOPTS) $(EXTRACFLAGS) -include Makefile.shared -# Note .. is the current directory (this makefile is included from -# a subdirectory) +# The remainder of this file could probably be simplified by including +# ../Makefile. + +LIBNAME=raw_spacetime_lib +CAMLOBJS=raw_spacetime_lib.cmo + +CC=$(BYTECC) +COMPFLAGS=-w +33..39 -warn-error A -bin-annot -g -safe-string $(EXTRACAMLFLAGS) + +CMIFILES=$(CAMLOBJS:.cmo=.cmi) +CAMLOBJS_NAT=$(CAMLOBJS:.cmo=.cmx) + +all: $(LIBNAME).cma $(CMIFILES) + +allopt: $(LIBNAME).cmxa $(LIBNAME).$(CMXS) $(CMIFILES) + +$(LIBNAME).cma: $(CAMLOBJS) + $(CAMLC) -a -o $(LIBNAME).cma -linkall $(CAMLOBJS) + +$(LIBNAME).cmxa: $(CAMLOBJS_NAT) + $(CAMLOPT) -a -o $(LIBNAME).cmxa -linkall $(CAMLOBJS_NAT) + +$(LIBNAME).cmxs: $(LIBNAME).cmxa + $(CAMLOPT) -shared -o $(LIBNAME).cmxs -I . $(LIBNAME).cmxa + +INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) + +install:: + cp $(LIBNAME).cma $(CMIFILES) $(CMIFILES:.cmi=.mli) $(INSTALL_LIBDIR) + +installopt: + cp $(CAMLOBJS_NAT) $(LIBNAME).cmxa $(LIBNAME).$(A) $(INSTALL_LIBDIR)/ + if test -f $(LIBNAME).cmxs; then \ + cp $(LIBNAME).cmxs $(INSTALL_LIBDIR)/; \ + fi + +partialclean: + rm -f *.cm* + +clean:: partialclean + rm -f *.a *.o + +.SUFFIXES: .ml .mli .cmi .cmo .cmx + +.mli.cmi: + $(CAMLC) -c $(COMPFLAGS) $< + +.ml.cmo: + $(CAMLC) -c $(COMPFLAGS) $< + +.ml.cmx: + $(CAMLOPT) -c $(COMPFLAGS) $< + +depend: + $(CAMLRUN) $(ROOTDIR)/tools/ocamldep *.mli *.ml >> .depend + +include .depend diff --git a/otherlibs/raw_spacetime_lib/Makefile.nt b/otherlibs/raw_spacetime_lib/Makefile.nt index f8fdaccd..16e27354 100644 --- a/otherlibs/raw_spacetime_lib/Makefile.nt +++ b/otherlibs/raw_spacetime_lib/Makefile.nt @@ -13,11 +13,4 @@ #* * #************************************************************************** -# Common Makefile for otherlibs on the Win32/MinGW ports - include Makefile - -# The Unix version now works fine under Windows - -# Note .. is the current directory (this makefile is included from -# a subdirectory) diff --git a/otherlibs/raw_spacetime_lib/Makefile.shared b/otherlibs/raw_spacetime_lib/Makefile.shared deleted file mode 100644 index a43fe4d2..00000000 --- a/otherlibs/raw_spacetime_lib/Makefile.shared +++ /dev/null @@ -1,74 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Mark Shinwell and Leo White, Jane Street Europe * -#* * -#* Copyright 2015--2016 Jane Street Group LLC * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -# Makefile for Raw_spacetime_lib - -ROOTDIR=../.. -include $(ROOTDIR)/config/Makefile -CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun - -LIBNAME=raw_spacetime_lib -CAMLOBJS=raw_spacetime_lib.cmo - -CC=$(BYTECC) -COMPFLAGS=-w +33..39 -warn-error A -bin-annot -g -safe-string $(EXTRACAMLFLAGS) - -CMIFILES=$(CAMLOBJS:.cmo=.cmi) -CAMLOBJS_NAT=$(CAMLOBJS:.cmo=.cmx) - -all: $(LIBNAME).cma $(CMIFILES) - -allopt: $(LIBNAME).cmxa $(LIBNAME).$(CMXS) $(CMIFILES) - -$(LIBNAME).cma: $(CAMLOBJS) - $(CAMLC) -a -o $(LIBNAME).cma -linkall $(CAMLOBJS) - -$(LIBNAME).cmxa: $(CAMLOBJS_NAT) - $(CAMLOPT) -a -o $(LIBNAME).cmxa -linkall $(CAMLOBJS_NAT) - -$(LIBNAME).cmxs: $(LIBNAME).cmxa - $(CAMLOPT) -shared -o $(LIBNAME).cmxs -I . $(LIBNAME).cmxa - -INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) - -install:: - cp $(LIBNAME).cma $(CMIFILES) $(CMIFILES:.cmi=.mli) $(INSTALL_LIBDIR) - -installopt: - cp $(CAMLOBJS_NAT) $(LIBNAME).cmxa $(LIBNAME).$(A) $(INSTALL_LIBDIR)/ - if test -f $(LIBNAME).cmxs; then \ - cp $(LIBNAME).cmxs $(INSTALL_LIBDIR)/; \ - fi - -partialclean: - rm -f *.cm* - -clean:: partialclean - rm -f *.a *.o - -.SUFFIXES: .ml .mli .cmi .cmo .cmx - -.mli.cmi: - $(CAMLC) -c $(COMPFLAGS) $< - -.ml.cmo: - $(CAMLC) -c $(COMPFLAGS) $< - -.ml.cmx: - $(CAMLOPT) -c $(COMPFLAGS) $< - -depend: - $(CAMLRUN) ../../tools/ocamldep *.mli *.ml >> .depend - -include .depend diff --git a/otherlibs/str/.depend b/otherlibs/str/.depend index 6625198e..6c0795d8 100644 --- a/otherlibs/str/.depend +++ b/otherlibs/str/.depend @@ -1,5 +1,6 @@ strstubs.o: strstubs.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \ + ../../byterun/caml/../../config/m.h \ ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ ../../byterun/caml/alloc.h ../../byterun/caml/memory.h \ ../../byterun/caml/fail.h diff --git a/otherlibs/str/Makefile b/otherlibs/str/Makefile index 7ab2f11f..1e5d4bb2 100644 --- a/otherlibs/str/Makefile +++ b/otherlibs/str/Makefile @@ -13,4 +13,28 @@ #* * #************************************************************************** -include Makefile.shared +# Makefile for the str library + +LIBNAME=str +COBJS=strstubs.$(O) +CLIBNAME=camlstr +CAMLOBJS=str.cmo + +include ../Makefile + +str.cmo: str.cmi +str.cmx: str.cmi + +depend: + $(CC) -MM $(CFLAGS) *.c > .depend + $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend + +ifeq "$(TOOLCHAIN)" "msvc" + +.depend.nt: .depend + sed -e 's/\.o/.$(O)/g' $< > $@ + +include .depend.nt +else +include .depend +endif diff --git a/otherlibs/str/Makefile.nt b/otherlibs/str/Makefile.nt index 202a3cb8..ed9900bb 100644 --- a/otherlibs/str/Makefile.nt +++ b/otherlibs/str/Makefile.nt @@ -13,9 +13,4 @@ #* * #************************************************************************** -include Makefile.shared - -.depend.nt: .depend - sed -e 's/\.o/.$(O)/g' .depend > .depend.nt - -include .depend.nt +include Makefile diff --git a/otherlibs/str/str.ml b/otherlibs/str/str.ml index 63c19715..6242be7f 100644 --- a/otherlibs/str/str.ml +++ b/otherlibs/str/str.ml @@ -13,7 +13,7 @@ (* *) (**************************************************************************) -(* In this module, [@ocaml.warnerror "-3"] is used in several places +(* In this module, [@ocaml.warning "-3"] is used in several places that use deprecated functions to preserve legacy behavior. It overrides -w @3 given on the command line. *) @@ -96,7 +96,7 @@ module Charset = let fold_case s = (let r = make_empty() in iter (fun c -> add r (Char.lowercase c); add r (Char.uppercase c)) s; - r)[@ocaml.warnerror "-3"] + r)[@ocaml.warning "-3"] end @@ -219,7 +219,7 @@ let charclass_of_regexp fold_case re = let fold_case_table = (let t = Bytes.create 256 in for i = 0 to 255 do Bytes.set t i (Char.lowercase(Char.chr i)) done; - Bytes.to_string t)[@ocaml.warnerror "-3"] + Bytes.to_string t)[@ocaml.warning "-3"] module StringMap = Map.Make(struct type t = string let compare (x:t) y = compare x y end) @@ -248,7 +248,7 @@ let compile fold_case re = incr progpos in (* Reserve an instruction slot and return its position *) let emit_hole () = - let p = !progpos in incr progpos; p in + let p = !progpos in emit_instr op_CHAR 0; p in (* Fill a reserved instruction slot with a GOTO or PUSHBACK instruction *) let patch_instr pos opc dest = (!prog).(pos) <- (instr opc (displ dest pos)) in @@ -276,7 +276,7 @@ let compile fold_case re = Char c -> if fold_case then emit_instr op_CHARNORM (Char.code (Char.lowercase c)) - [@ocaml.warnerror "-3"] + [@ocaml.warning "-3"] else emit_instr op_CHAR (Char.code c) | String s -> @@ -285,7 +285,7 @@ let compile fold_case re = | 1 -> if fold_case then emit_instr op_CHARNORM (Char.code (Char.lowercase s.[0])) - [@ocaml.warnerror "-3"] + [@ocaml.warning "-3"] else emit_instr op_CHAR (Char.code s.[0]) | _ -> @@ -299,7 +299,7 @@ let compile fold_case re = with Not_found -> if fold_case then emit_instr op_STRINGNORM (cpool_index (String.lowercase s)) - [@ocaml.warnerror "-3"] + [@ocaml.warning "-3"] else emit_instr op_STRING (cpool_index s) end diff --git a/otherlibs/str/strstubs.c b/otherlibs/str/strstubs.c index 4efa1ed6..505b927e 100644 --- a/otherlibs/str/strstubs.c +++ b/otherlibs/str/strstubs.c @@ -13,7 +13,6 @@ /* */ /**************************************************************************/ -#define CAML_NAME_SPACE #include #include #include diff --git a/otherlibs/systhreads/Makefile b/otherlibs/systhreads/Makefile index 87e071a6..49130bd2 100644 --- a/otherlibs/systhreads/Makefile +++ b/otherlibs/systhreads/Makefile @@ -13,16 +13,24 @@ #* * #************************************************************************** -include ../../config/Makefile -CAMLRUN ?= ../../boot/ocamlrun -CAMLYACC ?= ../../boot/ocamlyacc - ROOTDIR=../.. -CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib \ - -I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/unix -CAMLOPT=$(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib \ - -I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/unix -MKLIB=$(CAMLRUN) ../../tools/ocamlmklib + +include $(ROOTDIR)/config/Makefile + +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun +CAMLYACC ?= $(ROOTDIR)/boot/ocamlyacc + +ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" +export OCAML_FLEXLINK:= +else +export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe +endif + +LIBS = -nostdlib -I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/$(UNIXLIB) + +CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc $(LIBS) +CAMLOPT=$(CAMLRUN) $(ROOTDIR)/ocamlopt $(LIBS) +MKLIB=$(CAMLRUN) $(ROOTDIR)/tools/ocamlmklib COMPFLAGS=-w +33..39 -warn-error A -g -bin-annot -safe-string ifeq "$(FLAMBDA)" "true" OPTCOMPFLAGS=-O3 @@ -30,79 +38,104 @@ else OPTCOMPFLAGS= endif -BYTECODE_C_OBJS=st_stubs_b.o -NATIVECODE_C_OBJS=st_stubs_n.o +LIBNAME=threads -THREAD_OBJS= thread.cmo mutex.cmo condition.cmo event.cmo threadUnix.cmo +ifeq "$(UNIX_OR_WIN32)" "unix" +HEADER = st_posix.h +else # Windows +HEADER = st_win32.h +endif -all: libthreads.a threads.cma +BYTECODE_C_OBJS=st_stubs_b.$(O) +NATIVECODE_C_OBJS=st_stubs_n.$(O) -allopt: libthreadsnat.a threads.cmxa +THREADS_SOURCES = thread.ml mutex.ml condition.ml event.ml threadUnix.ml -libthreads.a: $(BYTECODE_C_OBJS) - $(MKLIB) -o threads $(BYTECODE_C_OBJS) $(PTHREAD_LINK) +THREADS_BCOBJS = $(THREADS_SOURCES:.ml=.cmo) +THREADS_NCOBJS = $(THREADS_SOURCES:.ml=.cmx) -st_stubs_b.o: st_stubs.c st_posix.h - $(BYTECC) -I../../byterun $(BYTECCCOMPOPTS) $(SHAREDCCCOMPOPTS) \ - -c st_stubs.c - mv st_stubs.o st_stubs_b.o +MLIFILES=thread.mli mutex.mli condition.mli event.mli threadUnix.mli +CMIFILES=$(MLIFILES:.mli=.cmi) -# Dynamic linking with -lpthread is risky on many platforms, so -# do not create a shared object for libthreadsnat. -libthreadsnat.a: $(NATIVECODE_C_OBJS) - $(AR) rc libthreadsnat.a $(NATIVECODE_C_OBJS) +all: lib$(LIBNAME).$(A) $(LIBNAME).cma $(CMIFILES) -st_stubs_n.o: st_stubs.c st_posix.h - $(NATIVECC) -I../../asmrun -I../../byterun $(NATIVECCCOMPOPTS) \ - $(SHAREDCCCOMPOPTS) -DNATIVE_CODE -DTARGET_$(ARCH) \ - -DMODEL_$(MODEL) -DSYS_$(SYSTEM) -c st_stubs.c - mv st_stubs.o st_stubs_n.o +allopt: lib$(LIBNAME)nat.$(A) $(LIBNAME).cmxa $(CMIFILES) -threads.cma: $(THREAD_OBJS) - $(MKLIB) -ocamlc '$(CAMLC)' -o threads $(THREAD_OBJS) \ - -cclib -lunix $(PTHREAD_CAML_LINK) +lib$(LIBNAME).$(A): $(BYTECODE_C_OBJS) + $(MKLIB) -o $(LIBNAME) $(BYTECODE_C_OBJS) $(PTHREAD_LINK) + +lib$(LIBNAME)nat.$(A): $(NATIVECODE_C_OBJS) + $(MKLIB) -o $(LIBNAME)nat $^ + +$(LIBNAME).cma: $(THREADS_BCOBJS) +ifeq "$(UNIX_OR_WIN32)" "unix" + $(MKLIB) -o $(LIBNAME) -ocamlc '$(CAMLC)' -cclib -lunix -linkall $(PTHREAD_CAML_LINK) $^ +# TODO: Figure out why -cclib -lunix is used here. +# It may be because of the threadsUnix module which is deprecated. +# It may hence be good to figure out whether this module shouldn't be +# removed, and then -cclib -lunix arguments. +else # Windows + $(MKLIB) -o $(LIBNAME) -ocamlc "$(CAMLC)" -linkall $(PTHREAD_CAML_LINK) $^ +endif # See remark above: force static linking of libthreadsnat.a -threads.cmxa: $(THREAD_OBJS:.cmo=.cmx) - $(CAMLOPT) -a -o threads.cmxa $(THREAD_OBJS:.cmo=.cmx) \ - -cclib -lthreadsnat $(PTHREAD_CAML_LINK) +$(LIBNAME).cmxa: $(THREADS_NCOBJS) + $(CAMLOPT) -linkall -a -cclib -lthreadsnat $(PTHREAD_CAML_LINK) -o $@ $^ # Note: I removed "-cclib -lunix" from the line above. # Indeed, if we link threads.cmxa, then we must also link unix.cmxa, # which itself will pass -lunix to the C linker. It seems more # modular to me this way. -- Alain +# The following lines produce two object files st_stubs_b.$(O) and +# st_stubs_n.$(O) from the same source file st_stubs.c (it is compiled +# twice, each time with different of options). +# Since the source and object file have a different basename, the name of +# the object file to produce must be given to the C compiler. +# For gcc this is done with the -ofoo.$(O) option. +# For msvc it's the /Fofoo.$(O) option. + +ifeq "$(TOOLCHAIN)" "msvc" + CCOUTPUT=/Fo +else + CCOUTPUT=-o +endif -$(THREAD_OBJS:.cmo=.cmx): ../../ocamlopt +st_stubs_b.$(O): st_stubs.c $(HEADER) + $(BYTECC) -I$(ROOTDIR)/byterun $(BYTECCCOMPOPTS) $(SHAREDCCCOMPOPTS) \ + $(CCOUTPUT)$@ -c $< + +st_stubs_n.$(O): st_stubs.c $(HEADER) + $(NATIVECC) -I$(ROOTDIR)/asmrun -I$(ROOTDIR)/byterun \ + $(NATIVECCCOMPOPTS) $(SHAREDCCCOMPOPTS) -DNATIVE_CODE \ + -DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) \ + $(CCOUTPUT)$@ -c $< partialclean: rm -f *.cm* clean: partialclean - rm -f *.o *.a *.so + rm -f dllthreads*$(EXT_DLL) *.$(A) *.$(O) INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) +THREADS_LIBDIR=$(INSTALL_LIBDIR)/$(LIBNAME) INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR) install: - if test -f dllthreads.so; then \ - cp dllthreads.so $(INSTALL_STUBLIBDIR)/dllthreads.so; fi - cp libthreads.a $(INSTALL_LIBDIR)/libthreads.a - cd $(INSTALL_LIBDIR); $(RANLIB) libthreads.a - if test -d $(INSTALL_LIBDIR)/threads; then :; \ - else mkdir $(INSTALL_LIBDIR)/threads; fi - cp $(THREAD_OBJS:.cmo=.cmi) threads.cma $(INSTALL_LIBDIR)/threads - rm -f $(INSTALL_LIBDIR)/threads/stdlib.cma - cp thread.mli mutex.mli condition.mli event.mli threadUnix.mli \ - $(INSTALL_LIBDIR) - cp threads.h $(INSTALL_LIBDIR)/caml/threads.h + if test -f dllthreads$(EXT_DLL); then \ + cp dllthreads$(EXT_DLL) "$(INSTALL_STUBLIBDIR)/dllthreads$(EXT_DLL)"; fi + cp libthreads.$(A) "$(INSTALL_LIBDIR)" + cd "$(INSTALL_LIBDIR)"; $(RANLIB) libthreads.$(A) + mkdir -p "$(THREADS_LIBDIR)" + cp $(CMIFILES) $(CMIFILES:.cmi=.cmti) threads.cma "$(THREADS_LIBDIR)" + cp $(MLIFILES) "$(INSTALL_LIBDIR)" + cp threads.h "$(INSTALL_LIBDIR)/caml" installopt: - cp libthreadsnat.a $(INSTALL_LIBDIR)/libthreadsnat.a - cd $(INSTALL_LIBDIR); $(RANLIB) libthreadsnat.a - cp $(THREAD_OBJS:.cmo=.cmx) threads.cmxa threads.a \ - $(INSTALL_LIBDIR)/threads - cd $(INSTALL_LIBDIR)/threads && $(RANLIB) threads.a + cp libthreadsnat.$(A) "$(INSTALL_LIBDIR)" + cd "$(INSTALL_LIBDIR)"; $(RANLIB) libthreadsnat.$(A) + cp $(THREADS_NCOBJS) threads.cmxa threads.$(A) "$(THREADS_LIBDIR)" + cd "$(THREADS_LIBDIR)" && $(RANLIB) threads.$(A) .SUFFIXES: .ml .mli .cmo .cmi .cmx @@ -115,8 +148,12 @@ installopt: .ml.cmx: $(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< +ifeq "$(UNIX_OR_WIN32)" "unix" depend: $(GENFILES) -$(CC) -MM -I../../byterun *.c > .depend $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend +else # Windows +depend: +endif include .depend diff --git a/otherlibs/systhreads/Makefile.nt b/otherlibs/systhreads/Makefile.nt index e1dd2c36..ed9900bb 100644 --- a/otherlibs/systhreads/Makefile.nt +++ b/otherlibs/systhreads/Makefile.nt @@ -13,106 +13,4 @@ #* * #************************************************************************** -include ../../config/Makefile -CAMLRUN ?= ../../boot/ocamlrun -CAMLYACC ?= ../../boot/ocamlyacc - -# Compilation options -CAMLC=$(CAMLRUN) ../../ocamlc -I ../../stdlib -I ../win32unix -CAMLOPT=$(CAMLRUN) ../../ocamlopt -I ../../stdlib -I ../win32unix -COMPFLAGS=-w +33 -warn-error A -g -ifeq "$(FLAMBDA)" "true" -OPTCOMPFLAGS=-O3 -else -OPTCOMPFLAGS= -endif -MKLIB=$(CAMLRUN) ../../tools/ocamlmklib -CFLAGS=-I../../byterun $(EXTRACFLAGS) - -ifeq "$(wildcard ../../flexdll/Makefile)" "" - export OCAML_FLEXLINK:= -else - export OCAML_FLEXLINK:=../../boot/ocamlrun ../../flexdll/flexlink.exe -endif - -THREAD_OBJS=thread.cmo mutex.cmo condition.cmo event.cmo threadUnix.cmo -CMIFILES=$(THREAD_OBJS:.cmo=.cmi) -COBJS=st_stubs_b.$(O) -COBJS_NAT=st_stubs_n.$(O) - -LIBNAME=threads - -all: lib$(LIBNAME).$(A) $(LIBNAME).cma $(CMIFILES) - -allopt: lib$(LIBNAME).$(A) $(LIBNAME).cmxa $(LIBNAME).cmxs $(CMIFILES) - -$(LIBNAME).cma: $(THREAD_OBJS) - $(MKLIB) -o $(LIBNAME) -ocamlc "$(CAMLRUN) ../../ocamlc" \ - -linkall $(THREAD_OBJS) $(LINKOPTS) - -lib$(LIBNAME).$(A): $(COBJS) - $(MKLIB) -o $(LIBNAME) $(COBJS) $(LDOPTS) - -st_stubs_b.$(O): st_stubs.c st_win32.h - $(BYTECC) $(BYTECCCOMPOPTS) $(CFLAGS) -c st_stubs.c - mv st_stubs.$(O) st_stubs_b.$(O) - - - -$(LIBNAME).cmxa: $(THREAD_OBJS:.cmo=.cmx) - $(MKLIB) -o $(LIBNAME)nat \ - -ocamlopt "$(CAMLRUN) ../../ocamlopt" -linkall \ - $(THREAD_OBJS:.cmo=.cmx) $(LINKOPTS) - mv $(LIBNAME)nat.cmxa $(LIBNAME).cmxa - mv $(LIBNAME)nat.$(A) $(LIBNAME).$(A) - -$(LIBNAME).cmxs: $(LIBNAME).cmxa lib$(LIBNAME)nat.$(A) - $(CAMLOPT) -shared -o $(LIBNAME).cmxs -I . $(LIBNAME).cmxa -linkall - -lib$(LIBNAME)nat.$(A): $(COBJS_NAT) - $(MKLIB) -o $(LIBNAME)nat $(COBJS_NAT) $(LDOPTS) - -st_stubs_n.$(O): st_stubs.c st_win32.h - $(NATIVECC) -DNATIVE_CODE -I../../asmrun -I../../byterun \ - $(NATIVECCCOMPOPTS) -c st_stubs.c - mv st_stubs.$(O) st_stubs_n.$(O) - -$(THREAD_OBJS:.cmo=.cmx): ../../ocamlopt - -partialclean: - rm -f *.cm* - -clean: partialclean - rm -f *.dll *.$(A) *.$(O) - -INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) -INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR) - -install: - cp dllthreads.dll "$(INSTALL_STUBLIBDIR)/dllthreads.dll" - cp libthreads.$(A) "$(INSTALL_LIBDIR)/libthreads.$(A)" - mkdir -p "$(INSTALL_LIBDIR)/threads" - cp $(CMIFILES) threads.cma "$(INSTALL_LIBDIR)/threads" - rm -f "$(INSTALL_LIBDIR)/threads/stdlib.cma" - cp threads.h "$(INSTALL_LIBDIR)/caml/threads.h" - -installopt: - cp libthreadsnat.$(A) "$(INSTALL_LIBDIR)/libthreadsnat.$(A)" - cp $(THREAD_OBJS:.cmo=.cmx) threads.cmxa threads.$(A) \ - "$(INSTALL_LIBDIR)/threads" - cp threads.cmxs "$(INSTALL_LIBDIR)/threads" - -.SUFFIXES: .ml .mli .cmo .cmi .cmx - -.mli.cmi: - $(CAMLC) -c $(COMPFLAGS) $< - -.ml.cmo: - $(CAMLC) -c -g $(COMPFLAGS) $< - -.ml.cmx: - $(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< - -depend: - -include .depend +include Makefile diff --git a/otherlibs/systhreads/condition.mli b/otherlibs/systhreads/condition.mli index decf6dce..36c71fc8 100644 --- a/otherlibs/systhreads/condition.mli +++ b/otherlibs/systhreads/condition.mli @@ -27,7 +27,7 @@ Condition.wait c m done; (* Modify D *) - if (* the predicate P over D is now satified *) then Condition.signal c; + if (* the predicate P over D is now satisfied *) then Condition.signal c; Mutex.unlock m ]} *) diff --git a/otherlibs/systhreads/st_posix.h b/otherlibs/systhreads/st_posix.h index 4e4ee19b..a751ff32 100644 --- a/otherlibs/systhreads/st_posix.h +++ b/otherlibs/systhreads/st_posix.h @@ -304,15 +304,15 @@ static void st_check_error(int retcode, char * msg) value str; if (retcode == 0) return; - if (retcode == ENOMEM) raise_out_of_memory(); + if (retcode == ENOMEM) caml_raise_out_of_memory(); err = strerror(retcode); msglen = strlen(msg); errlen = strlen(err); - str = alloc_string(msglen + 2 + errlen); + str = caml_alloc_string(msglen + 2 + errlen); memmove (&Byte(str, 0), msg, msglen); memmove (&Byte(str, msglen), ": ", 2); memmove (&Byte(str, msglen + 2), err, errlen); - raise_sys_error(str); + caml_raise_sys_error(str); } /* Variable used to stop the "tick" thread */ @@ -383,7 +383,7 @@ static value st_encode_sigset(sigset_t * set) Begin_root(res) for (i = 1; i < NSIG; i++) if (sigismember(set, i) > 0) { - value newcons = alloc_small(2, 0); + value newcons = caml_alloc_small(2, 0); Field(newcons, 0) = Val_int(caml_rev_convert_signal_number(i)); Field(newcons, 1) = res; res = newcons; @@ -402,9 +402,9 @@ value caml_thread_sigmask(value cmd, value sigs) /* ML */ how = sigmask_cmd[Int_val(cmd)]; st_decode_sigset(sigs, &set); - enter_blocking_section(); + caml_enter_blocking_section(); retcode = pthread_sigmask(how, &set, &oldset); - leave_blocking_section(); + caml_leave_blocking_section(); st_check_error(retcode, "Thread.sigmask"); return st_encode_sigset(&oldset); } @@ -416,13 +416,13 @@ value caml_wait_signal(value sigs) /* ML */ int retcode, signo; st_decode_sigset(sigs, &set); - enter_blocking_section(); + caml_enter_blocking_section(); retcode = sigwait(&set, &signo); - leave_blocking_section(); + caml_leave_blocking_section(); st_check_error(retcode, "Thread.wait_signal"); return Val_int(caml_rev_convert_signal_number(signo)); #else - invalid_argument("Thread.wait_signal not implemented"); + caml_invalid_argument("Thread.wait_signal not implemented"); return Val_int(0); /* not reached */ #endif } diff --git a/otherlibs/systhreads/st_stubs.c b/otherlibs/systhreads/st_stubs.c index 9c91e00c..cd7daa7c 100644 --- a/otherlibs/systhreads/st_stubs.c +++ b/otherlibs/systhreads/st_stubs.c @@ -36,7 +36,7 @@ #include "threads.h" #if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "../../asmrun/spacetime.h" +#include "caml/spacetime.h" #endif /* Initial size of bytecode stack when a thread is created (4 Ko) */ @@ -88,14 +88,14 @@ struct caml_thread_struct { value * stack_low; /* The execution stack for this thread */ value * stack_high; value * stack_threshold; - value * sp; /* Saved value of extern_sp for this thread */ - value * trapsp; /* Saved value of trapsp for this thread */ - struct caml__roots_block * local_roots; /* Saved value of local_roots */ - struct longjmp_buffer * external_raise; /* Saved external_raise */ + value * sp; /* Saved value of caml_extern_sp for this thread */ + value * trapsp; /* Saved value of caml_trapsp for this thread */ + struct caml__roots_block * local_roots; /* Saved value of caml_local_roots */ + struct longjmp_buffer * external_raise; /* Saved caml_external_raise */ #endif - int backtrace_pos; /* Saved backtrace_pos */ - backtrace_slot * backtrace_buffer; /* Saved backtrace_buffer */ - value backtrace_last_exn; /* Saved backtrace_last_exn (root) */ + int backtrace_pos; /* Saved caml_backtrace_pos */ + backtrace_slot * backtrace_buffer; /* Saved caml_backtrace_buffer */ + value backtrace_last_exn; /* Saved caml_backtrace_last_exn (root) */ }; typedef struct caml_thread_struct * caml_thread_t; @@ -152,10 +152,10 @@ static void caml_thread_scan_roots(scanning_action action) if (th != curr_thread) { #ifdef NATIVE_CODE if (th->bottom_of_stack != NULL) - do_local_roots(action, th->bottom_of_stack, th->last_retaddr, + caml_do_local_roots(action, th->bottom_of_stack, th->last_retaddr, th->gc_regs, th->local_roots); #else - do_local_roots(action, th->sp, th->stack_high, th->local_roots); + caml_do_local_roots(action, th->sp, th->stack_high, th->local_roots); #endif } th = th->next; @@ -169,11 +169,12 @@ static void caml_thread_scan_roots(scanning_action action) static inline void caml_thread_save_runtime_state(void) { #ifdef NATIVE_CODE + curr_thread->top_of_stack = caml_top_of_stack; curr_thread->bottom_of_stack = caml_bottom_of_stack; curr_thread->last_retaddr = caml_last_return_address; curr_thread->gc_regs = caml_gc_regs; curr_thread->exception_pointer = caml_exception_pointer; - curr_thread->local_roots = local_roots; + curr_thread->local_roots = caml_local_roots; #ifdef WITH_SPACETIME curr_thread->spacetime_trie_node_ptr = caml_spacetime_trie_node_ptr; @@ -181,27 +182,28 @@ static inline void caml_thread_save_runtime_state(void) = caml_spacetime_finaliser_trie_root; #endif #else - curr_thread->stack_low = stack_low; - curr_thread->stack_high = stack_high; - curr_thread->stack_threshold = stack_threshold; - curr_thread->sp = extern_sp; - curr_thread->trapsp = trapsp; - curr_thread->local_roots = local_roots; - curr_thread->external_raise = external_raise; + curr_thread->stack_low = caml_stack_low; + curr_thread->stack_high = caml_stack_high; + curr_thread->stack_threshold = caml_stack_threshold; + curr_thread->sp = caml_extern_sp; + curr_thread->trapsp = caml_trapsp; + curr_thread->local_roots = caml_local_roots; + curr_thread->external_raise = caml_external_raise; #endif - curr_thread->backtrace_pos = backtrace_pos; - curr_thread->backtrace_buffer = backtrace_buffer; - curr_thread->backtrace_last_exn = backtrace_last_exn; + curr_thread->backtrace_pos = caml_backtrace_pos; + curr_thread->backtrace_buffer = caml_backtrace_buffer; + curr_thread->backtrace_last_exn = caml_backtrace_last_exn; } static inline void caml_thread_restore_runtime_state(void) { #ifdef NATIVE_CODE + caml_top_of_stack = curr_thread->top_of_stack; caml_bottom_of_stack= curr_thread->bottom_of_stack; caml_last_return_address = curr_thread->last_retaddr; caml_gc_regs = curr_thread->gc_regs; caml_exception_pointer = curr_thread->exception_pointer; - local_roots = curr_thread->local_roots; + caml_local_roots = curr_thread->local_roots; #ifdef WITH_SPACETIME caml_spacetime_trie_node_ptr = curr_thread->spacetime_trie_node_ptr; @@ -209,20 +211,20 @@ static inline void caml_thread_restore_runtime_state(void) = curr_thread->spacetime_finaliser_trie_root; #endif #else - stack_low = curr_thread->stack_low; - stack_high = curr_thread->stack_high; - stack_threshold = curr_thread->stack_threshold; - extern_sp = curr_thread->sp; - trapsp = curr_thread->trapsp; - local_roots = curr_thread->local_roots; - external_raise = curr_thread->external_raise; + caml_stack_low = curr_thread->stack_low; + caml_stack_high = curr_thread->stack_high; + caml_stack_threshold = curr_thread->stack_threshold; + caml_extern_sp = curr_thread->sp; + caml_trapsp = curr_thread->trapsp; + caml_local_roots = curr_thread->local_roots; + caml_external_raise = curr_thread->external_raise; #endif - backtrace_pos = curr_thread->backtrace_pos; - backtrace_buffer = curr_thread->backtrace_buffer; - backtrace_last_exn = curr_thread->backtrace_last_exn; + caml_backtrace_pos = curr_thread->backtrace_pos; + caml_backtrace_buffer = curr_thread->backtrace_buffer; + caml_backtrace_last_exn = curr_thread->backtrace_last_exn; } -/* Hooks for enter_blocking_section and leave_blocking_section */ +/* Hooks for caml_enter_blocking_section and caml_leave_blocking_section */ static void caml_thread_enter_blocking_section(void) @@ -259,7 +261,10 @@ static int caml_thread_try_leave_blocking_section(void) static void caml_io_mutex_free(struct channel *chan) { st_mutex mutex = chan->mutex; - if (mutex != NULL) st_mutex_destroy(mutex); + if (mutex != NULL) { + st_mutex_destroy(mutex); + chan->mutex = NULL; + } } static void caml_io_mutex_lock(struct channel *chan) @@ -276,7 +281,7 @@ static void caml_io_mutex_lock(struct channel *chan) return; } /* If unsuccessful, block on mutex */ - enter_blocking_section(); + caml_enter_blocking_section(); st_mutex_lock(mutex); /* Problem: if a signal occurs at this point, and the signal handler raises an exception, we will not @@ -284,7 +289,7 @@ static void caml_io_mutex_lock(struct channel *chan) before locking the mutex is also incorrect, since we could then unlock a mutex that is unlocked or locked by someone else. */ st_tls_set(last_channel_locked_key, (void *) chan); - leave_blocking_section(); + caml_leave_blocking_section(); } static void caml_io_mutex_unlock(struct channel *chan) @@ -313,7 +318,9 @@ static uintnat caml_thread_stack_usage(void) th != curr_thread; th = th->next) { #ifdef NATIVE_CODE - sz += (value *) th->top_of_stack - (value *) th->bottom_of_stack; + if(th->top_of_stack != NULL && th->bottom_of_stack != NULL && + th->top_of_stack > th->bottom_of_stack) + sz += (value *) th->top_of_stack - (value *) th->bottom_of_stack; #else sz += th->stack_high - th->sp; #endif @@ -380,7 +387,7 @@ static value caml_thread_new_descriptor(value clos) /* Create and initialize the termination semaphore */ mu = caml_threadstatus_new(); /* Create a descriptor for the new thread */ - descr = alloc_small(3, 0); + descr = caml_alloc_small(3, 0); Ident(descr) = Val_long(thread_next_ident); Start_closure(descr) = clos; Terminated(descr) = mu; @@ -401,11 +408,11 @@ static void caml_thread_remove_info(caml_thread_t th) th->next->prev = th->prev; th->prev->next = th->next; #ifndef NATIVE_CODE - stat_free(th->stack_low); + caml_stat_free(th->stack_low); #endif if (th->backtrace_buffer != NULL) free(th->backtrace_buffer); #ifndef WITH_SPACETIME - stat_free(th); + caml_stat_free(th); /* CR-soon mshinwell: consider what to do about the Spacetime trace. Could perhaps have a hook to save a snapshot on thread termination. For the moment we can't even free [th], since it contains the trie @@ -425,7 +432,7 @@ static void caml_thread_reinitialize(void) thr = curr_thread->next; while (thr != curr_thread) { next = thr->next; - stat_free(thr); + caml_stat_free(thr); thr = next; } curr_thread->next = curr_thread; @@ -433,7 +440,7 @@ static void caml_thread_reinitialize(void) all_threads = curr_thread; /* Reinitialize the master lock machinery, just in case the fork happened while other threads were doing - leave_blocking_section */ + caml_leave_blocking_section */ st_masterlock_init(&caml_master_lock); /* Tick thread is not currently running in child process, will be re-created at next Thread.create */ @@ -474,15 +481,15 @@ CAMLprim value caml_thread_initialize(value unit) /* ML */ curr_thread->exit_buf = &caml_termination_jmpbuf; #endif /* The stack-related fields will be filled in at the next - enter_blocking_section */ + caml_enter_blocking_section */ /* Associate the thread descriptor with the thread */ st_tls_set(thread_descriptor_key, (void *) curr_thread); /* Set up the hooks */ - prev_scan_roots_hook = scan_roots_hook; - scan_roots_hook = caml_thread_scan_roots; - enter_blocking_section_hook = caml_thread_enter_blocking_section; - leave_blocking_section_hook = caml_thread_leave_blocking_section; - try_leave_blocking_section_hook = caml_thread_try_leave_blocking_section; + prev_scan_roots_hook = caml_scan_roots_hook; + caml_scan_roots_hook = caml_thread_scan_roots; + caml_enter_blocking_section_hook = caml_thread_enter_blocking_section; + caml_leave_blocking_section_hook = caml_thread_leave_blocking_section; + caml_try_leave_blocking_section_hook = caml_thread_try_leave_blocking_section; #ifdef NATIVE_CODE caml_termination_hook = st_thread_exit; #endif @@ -544,7 +551,7 @@ static ST_THREAD_FUNCTION caml_thread_start(void * arg) /* Associate the thread descriptor with the thread */ st_tls_set(thread_descriptor_key, (void *) th); /* Acquire the global mutex */ - leave_blocking_section(); + caml_leave_blocking_section(); #ifdef NATIVE_CODE /* Record top of stack (approximative) */ th->top_of_stack = &tos; @@ -554,8 +561,8 @@ static ST_THREAD_FUNCTION caml_thread_start(void * arg) #endif /* Callback the closure */ clos = Start_closure(th->descr); - modify(&(Start_closure(th->descr)), Val_unit); - callback_exn(clos, Val_unit); + caml_modify(&(Start_closure(th->descr)), Val_unit); + caml_callback_exn(clos, Val_unit); caml_thread_stop(); #ifdef NATIVE_CODE } @@ -630,7 +637,7 @@ CAMLexport int caml_c_thread_register(void) /* Release the master lock */ st_masterlock_release(&caml_master_lock); /* Now we can re-enter the run-time system and heap-allocate the descriptor */ - leave_blocking_section(); + caml_leave_blocking_section(); th->descr = caml_thread_new_descriptor(Val_unit); /* no closure */ /* Create the tick thread if not already done. */ if (! caml_tick_thread_running) { @@ -638,7 +645,7 @@ CAMLexport int caml_c_thread_register(void) if (err == 0) caml_tick_thread_running = 1; } /* Exit the run-time system */ - enter_blocking_section(); + caml_enter_blocking_section(); return 1; } @@ -665,7 +672,7 @@ CAMLexport int caml_c_thread_unregister(void) CAMLprim value caml_thread_self(value unit) /* ML */ { - if (curr_thread == NULL) invalid_argument("Thread.self: not initialized"); + if (curr_thread == NULL) caml_invalid_argument("Thread.self: not initialized"); return curr_thread->descr; } @@ -680,11 +687,11 @@ CAMLprim value caml_thread_id(value th) /* ML */ CAMLprim value caml_thread_uncaught_exception(value exn) /* ML */ { - char * msg = format_caml_exception(exn); + char * msg = caml_format_exception(exn); fprintf(stderr, "Thread %d killed on uncaught exception %s\n", Int_val(Ident(curr_thread->descr)), msg); free(msg); - if (caml_backtrace_active) print_exception_backtrace(); + if (caml_backtrace_active) caml_print_exception_backtrace(); fflush(stderr); return Val_unit; } @@ -695,7 +702,7 @@ CAMLprim value caml_thread_exit(value unit) /* ML */ { struct longjmp_buffer * exit_buf = NULL; - if (curr_thread == NULL) invalid_argument("Thread.exit: not initialized"); + if (curr_thread == NULL) caml_invalid_argument("Thread.exit: not initialized"); /* In native code, we cannot call pthread_exit here because on some systems this raises a C++ exception, and ocamlopt-generated stack @@ -724,9 +731,9 @@ CAMLprim value caml_thread_exit(value unit) /* ML */ CAMLprim value caml_thread_yield(value unit) /* ML */ { if (st_masterlock_waiters(&caml_master_lock) == 0) return Val_unit; - enter_blocking_section(); + caml_enter_blocking_section(); st_thread_yield(); - leave_blocking_section(); + caml_leave_blocking_section(); return Val_unit; } @@ -742,7 +749,6 @@ CAMLprim value caml_thread_join(value th) /* ML */ /* Mutex operations */ #define Mutex_val(v) (* ((st_mutex *) Data_custom_val(v))) -#define Max_mutex_number 5000 static void caml_mutex_finalize(value wrapper) { @@ -775,8 +781,8 @@ CAMLprim value caml_mutex_new(value unit) /* ML */ st_mutex mut = NULL; /* suppress warning */ value wrapper; st_check_error(st_mutex_create(&mut), "Mutex.create"); - wrapper = alloc_custom(&caml_mutex_ops, sizeof(st_mutex *), - 1, Max_mutex_number); + wrapper = caml_alloc_custom(&caml_mutex_ops, sizeof(st_mutex *), + 0, 1); Mutex_val(wrapper) = mut; return wrapper; } @@ -790,9 +796,9 @@ CAMLprim value caml_mutex_lock(value wrapper) /* ML */ if (st_mutex_trylock(mut) == PREVIOUSLY_UNLOCKED) return Val_unit; /* If unsuccessful, block on mutex */ Begin_root(wrapper) /* prevent the deallocation of mutex */ - enter_blocking_section(); + caml_enter_blocking_section(); retcode = st_mutex_lock(mut); - leave_blocking_section(); + caml_leave_blocking_section(); End_roots(); st_check_error(retcode, "Mutex.lock"); return Val_unit; @@ -821,7 +827,6 @@ CAMLprim value caml_mutex_try_lock(value wrapper) /* ML */ /* Conditions operations */ #define Condition_val(v) (* (st_condvar *) Data_custom_val(v)) -#define Max_condition_number 5000 static void caml_condition_finalize(value wrapper) { @@ -855,8 +860,8 @@ CAMLprim value caml_condition_new(value unit) /* ML */ st_condvar cond = NULL; /* suppress warning */ value wrapper; st_check_error(st_condvar_create(&cond), "Condition.create"); - wrapper = alloc_custom(&caml_condition_ops, sizeof(st_condvar *), - 1, Max_condition_number); + wrapper = caml_alloc_custom(&caml_condition_ops, sizeof(st_condvar *), + 0, 1); Condition_val(wrapper) = cond; return wrapper; } @@ -868,9 +873,9 @@ CAMLprim value caml_condition_wait(value wcond, value wmut) /* ML */ st_retcode retcode; Begin_roots2(wcond, wmut) /* prevent deallocation of cond and mutex */ - enter_blocking_section(); + caml_enter_blocking_section(); retcode = st_condvar_wait(cond, mut); - leave_blocking_section(); + caml_leave_blocking_section(); End_roots(); st_check_error(retcode, "Condition.wait"); return Val_unit; @@ -893,7 +898,6 @@ CAMLprim value caml_condition_broadcast(value wrapper) /* ML */ /* Thread status blocks */ #define Threadstatus_val(v) (* ((st_event *) Data_custom_val(v))) -#define Max_threadstatus_number 500 static void caml_threadstatus_finalize(value wrapper) { @@ -922,8 +926,8 @@ static value caml_threadstatus_new (void) st_event ts = NULL; /* suppress warning */ value wrapper; st_check_error(st_event_create(&ts), "Thread.create"); - wrapper = alloc_custom(&caml_threadstatus_ops, sizeof(st_event *), - 1, Max_threadstatus_number); + wrapper = caml_alloc_custom(&caml_threadstatus_ops, sizeof(st_event *), + 0, 1); Threadstatus_val(wrapper) = ts; return wrapper; } @@ -939,9 +943,9 @@ static st_retcode caml_threadstatus_wait (value wrapper) st_retcode retcode; Begin_roots1(wrapper) /* prevent deallocation of ts */ - enter_blocking_section(); + caml_enter_blocking_section(); retcode = st_event_wait(ts); - leave_blocking_section(); + caml_leave_blocking_section(); End_roots(); return retcode; } diff --git a/otherlibs/systhreads/st_win32.h b/otherlibs/systhreads/st_win32.h index 37f88df5..fa447a9c 100644 --- a/otherlibs/systhreads/st_win32.h +++ b/otherlibs/systhreads/st_win32.h @@ -15,6 +15,7 @@ /* Win32 implementation of the "st" interface */ +#undef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #include #include @@ -365,7 +366,7 @@ static void st_check_error(DWORD retcode, char * msg) value str; if (retcode == 0) return; - if (retcode == ERROR_NOT_ENOUGH_MEMORY) raise_out_of_memory(); + if (retcode == ERROR_NOT_ENOUGH_MEMORY) caml_raise_out_of_memory(); if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, retcode, @@ -377,11 +378,11 @@ static void st_check_error(DWORD retcode, char * msg) } msglen = strlen(msg); errlen = strlen(err); - str = alloc_string(msglen + 2 + errlen); + str = caml_alloc_string(msglen + 2 + errlen); memmove (&Byte(str, 0), msg, msglen); memmove (&Byte(str, msglen), ": ", 2); memmove (&Byte(str, msglen + 2), err, errlen); - raise_sys_error(str); + caml_raise_sys_error(str); } /* Variable used to stop the "tick" thread */ @@ -412,12 +413,12 @@ static DWORD st_atfork(void (*fn)(void)) value caml_thread_sigmask(value cmd, value sigs) /* ML */ { - invalid_argument("Thread.sigmask not implemented"); + caml_invalid_argument("Thread.sigmask not implemented"); return Val_int(0); /* not reached */ } value caml_wait_signal(value sigs) /* ML */ { - invalid_argument("Thread.wait_signal not implemented"); + caml_invalid_argument("Thread.wait_signal not implemented"); return Val_int(0); /* not reached */ } diff --git a/otherlibs/systhreads/thread.mli b/otherlibs/systhreads/thread.mli index e5581a2f..9b8a1267 100644 --- a/otherlibs/systhreads/thread.mli +++ b/otherlibs/systhreads/thread.mli @@ -83,7 +83,7 @@ val select : Unix.file_descr list -> Unix.file_descr list -> Unix.file_descr list -> float -> Unix.file_descr list * Unix.file_descr list * Unix.file_descr list -(** Suspend the execution of the calling thead until input/output +(** Suspend the execution of the calling thread until input/output becomes possible on the given Unix file descriptors. The arguments and results have the same meaning as for [Unix.select]. diff --git a/otherlibs/systhreads/threadUnix.mli b/otherlibs/systhreads/threadUnix.mli index 7829884e..9e8d927e 100644 --- a/otherlibs/systhreads/threadUnix.mli +++ b/otherlibs/systhreads/threadUnix.mli @@ -64,7 +64,7 @@ val select : (** {6 Pipes and redirections} *) -val pipe : unit -> Unix.file_descr * Unix.file_descr +val pipe : ?cloexec:bool -> unit -> Unix.file_descr * Unix.file_descr val open_process_in: string -> in_channel val open_process_out: string -> out_channel val open_process: string -> in_channel * out_channel @@ -75,9 +75,11 @@ val sleep : int -> unit (** {6 Sockets} *) -val socket : Unix.socket_domain -> - Unix.socket_type -> int -> Unix.file_descr -val accept : Unix.file_descr -> Unix.file_descr * Unix.sockaddr +val socket : + ?cloexec:bool -> Unix.socket_domain -> Unix.socket_type -> int -> + Unix.file_descr +val accept : + ?cloexec:bool -> Unix.file_descr -> Unix.file_descr * Unix.sockaddr val connect : Unix.file_descr -> Unix.sockaddr -> unit val recv : Unix.file_descr -> bytes -> int -> int -> Unix.msg_flag list -> int diff --git a/otherlibs/threads/.depend b/otherlibs/threads/.depend index 741d4253..f25df2a0 100644 --- a/otherlibs/threads/.depend +++ b/otherlibs/threads/.depend @@ -1,6 +1,6 @@ scheduler.o: scheduler.c ../../byterun/caml/alloc.h \ - ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/misc.h ../../byterun/caml/config.h \ + ../../byterun/caml/../../config/m.h \ ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \ ../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \ ../../byterun/caml/callback.h ../../byterun/caml/fail.h \ diff --git a/otherlibs/threads/Makefile b/otherlibs/threads/Makefile index dbe02504..a2a20e61 100644 --- a/otherlibs/threads/Makefile +++ b/otherlibs/threads/Makefile @@ -107,6 +107,8 @@ clean: partialclean INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR) +CMIFILES=thread.cmi mutex.cmi condition.cmi event.cmi threadUnix.cmi + install: if test -f dllvmthreads.so; then \ cp dllvmthreads.so $(INSTALL_STUBLIBDIR)/.; \ @@ -114,10 +116,8 @@ install: mkdir -p $(INSTALL_LIBDIR)/vmthreads cp libvmthreads.a $(INSTALL_LIBDIR)/vmthreads/libvmthreads.a cd $(INSTALL_LIBDIR)/vmthreads; $(RANLIB) libvmthreads.a - cp thread.cmi mutex.cmi condition.cmi event.cmi threadUnix.cmi \ + cp $(CMIFILES) $(CMIFILES:.cmi=.mli) $(CMIFILES:.cmi=.cmti) \ threads.cma stdlib.cma unix.cma $(INSTALL_LIBDIR)/vmthreads - cp thread.mli mutex.mli condition.mli event.mli threadUnix.mli \ - $(INSTALL_LIBDIR)/vmthreads installopt: diff --git a/otherlibs/threads/condition.mli b/otherlibs/threads/condition.mli index 2e1ee777..2557fe78 100644 --- a/otherlibs/threads/condition.mli +++ b/otherlibs/threads/condition.mli @@ -27,7 +27,7 @@ Condition.wait c m done; (* Modify D *) - if (* the predicate P over D is now satified *) then Condition.signal c; + if (* the predicate P over D is now satisfied *) then Condition.signal c; Mutex.unlock m ]} *) diff --git a/otherlibs/threads/pervasives.ml b/otherlibs/threads/pervasives.ml index fe3767d3..97cb52bc 100644 --- a/otherlibs/threads/pervasives.ml +++ b/otherlibs/threads/pervasives.ml @@ -246,10 +246,21 @@ let bool_of_string = function | "false" -> false | _ -> invalid_arg "bool_of_string" +let bool_of_string_opt = function + | "true" -> Some true + | "false" -> Some false + | _ -> None + let string_of_int n = format_int "%d" n external int_of_string : string -> int = "caml_int_of_string" + +let int_of_string_opt s = + (* TODO: provide this directly as a non-raising primitive. *) + try Some (int_of_string s) + with Failure _ -> None + external string_get : string -> int -> char = "%string_safe_get" let valid_float_lexem s = @@ -267,6 +278,11 @@ let string_of_float f = valid_float_lexem (format_float "%.12g" f);; external float_of_string : string -> float = "caml_float_of_string" +let float_of_string_opt s = + (* TODO: provide this directly as a non-raising primitive. *) + try Some (float_of_string s) + with Failure _ -> None + (* List operations -- more in module List *) let rec ( @ ) l1 l2 = @@ -563,7 +579,9 @@ let prerr_newline () = output_char stderr '\n'; flush stderr let read_line () = flush stdout; input_line stdin let read_int () = int_of_string(read_line()) +let read_int_opt () = int_of_string_opt(read_line()) let read_float () = float_of_string(read_line()) +let read_float_opt () = float_of_string_opt(read_line()) (* Operations on large files *) diff --git a/otherlibs/threads/scheduler.c b/otherlibs/threads/scheduler.c index f10bd4e7..fff4b177 100644 --- a/otherlibs/threads/scheduler.c +++ b/otherlibs/threads/scheduler.c @@ -128,7 +128,7 @@ static caml_thread_t curr_thread = NULL; /* Identifier for next thread creation */ static value next_ident = Val_int(0); -#define Assign(dst,src) modify((value *)&(dst), (value)(src)) +#define Assign(dst,src) caml_modify((value *)&(dst), (value)(src)) /* Scan the stacks of the other threads */ @@ -144,7 +144,7 @@ static void thread_scan_roots(scanning_action action) /* Don't scan curr_thread->sp, this has already been done. Don't scan local roots either, for the same reason. */ for (th = start->next; th != start; th = th->next) { - do_local_roots(action, th->sp, th->stack_high, NULL); + caml_do_local_roots(action, th->sp, th->stack_high, NULL); } /* Hook */ if (prev_scan_roots_hook != NULL) (*prev_scan_roots_hook)(action); @@ -163,20 +163,20 @@ value thread_initialize(value unit) /* ML */ if (curr_thread != NULL) return Val_unit; /* Create a descriptor for the current thread */ curr_thread = - (caml_thread_t) alloc_shr(sizeof(struct caml_thread_struct) + (caml_thread_t) caml_alloc_shr(sizeof(struct caml_thread_struct) / sizeof(value), 0); curr_thread->ident = next_ident; next_ident = Val_int(Int_val(next_ident) + 1); curr_thread->next = curr_thread; curr_thread->prev = curr_thread; - curr_thread->stack_low = stack_low; - curr_thread->stack_high = stack_high; - curr_thread->stack_threshold = stack_threshold; - curr_thread->sp = extern_sp; - curr_thread->trapsp = trapsp; - curr_thread->backtrace_pos = Val_int(backtrace_pos); - curr_thread->backtrace_buffer = backtrace_buffer; - caml_initialize (&curr_thread->backtrace_last_exn, backtrace_last_exn); + curr_thread->stack_low = caml_stack_low; + curr_thread->stack_high = caml_stack_high; + curr_thread->stack_threshold = caml_stack_threshold; + curr_thread->sp = caml_extern_sp; + curr_thread->trapsp = caml_trapsp; + curr_thread->backtrace_pos = Val_int(caml_backtrace_pos); + curr_thread->backtrace_buffer = caml_backtrace_buffer; + caml_initialize (&curr_thread->backtrace_last_exn, caml_backtrace_last_exn); curr_thread->status = RUNNABLE; curr_thread->fd = Val_int(0); curr_thread->readfds = NO_FDS; @@ -187,8 +187,8 @@ value thread_initialize(value unit) /* ML */ curr_thread->waitpid = NO_WAITPID; curr_thread->retval = Val_unit; /* Initialize GC */ - prev_scan_roots_hook = scan_roots_hook; - scan_roots_hook = thread_scan_roots; + prev_scan_roots_hook = caml_scan_roots_hook; + caml_scan_roots_hook = thread_scan_roots; /* Set standard file descriptors to non-blocking mode */ stdin_initial_status = fcntl(0, F_GETFL); stdout_initial_status = fcntl(1, F_GETFL); @@ -224,7 +224,7 @@ value thread_new(value clos) /* ML */ caml_thread_t th; /* Allocate the thread and its stack */ Begin_root(clos); - th = (caml_thread_t) alloc_shr(sizeof(struct caml_thread_struct) + th = (caml_thread_t) caml_alloc_shr(sizeof(struct caml_thread_struct) / sizeof(value), 0); End_roots(); th->ident = next_ident; @@ -303,17 +303,17 @@ static value schedule_thread(void) int need_select, need_wait; /* Don't allow preemption during a callback */ - if (callback_depth > 1) return curr_thread->retval; + if (caml_callback_depth > 1) return curr_thread->retval; /* Save the status of the current thread */ - curr_thread->stack_low = stack_low; - curr_thread->stack_high = stack_high; - curr_thread->stack_threshold = stack_threshold; - curr_thread->sp = extern_sp; - curr_thread->trapsp = trapsp; - curr_thread->backtrace_pos = Val_int(backtrace_pos); - curr_thread->backtrace_buffer = backtrace_buffer; - caml_modify (&curr_thread->backtrace_last_exn, backtrace_last_exn); + curr_thread->stack_low = caml_stack_low; + curr_thread->stack_high = caml_stack_high; + curr_thread->stack_threshold = caml_stack_threshold; + curr_thread->sp = caml_extern_sp; + curr_thread->trapsp = caml_trapsp; + curr_thread->backtrace_pos = Val_int(caml_backtrace_pos); + curr_thread->backtrace_buffer = caml_backtrace_buffer; + caml_modify (&curr_thread->backtrace_last_exn, caml_backtrace_last_exn); try_again: /* Find if a thread is runnable. @@ -403,9 +403,9 @@ try_again: else { delay_ptr = NULL; } - enter_blocking_section(); + caml_enter_blocking_section(); retcode = select(FD_SETSIZE, &readfds, &writefds, &exceptfds, delay_ptr); - leave_blocking_section(); + caml_leave_blocking_section(); if (retcode == -1) switch (errno) { case EINTR: @@ -430,7 +430,7 @@ try_again: retcode = FD_SETSIZE; break; default: - sys_error(NO_ARG); + caml_sys_error(NO_ARG); } if (retcode > 0) { /* Some descriptors are ready. @@ -462,7 +462,7 @@ try_again: w = inter_fdlist_set(th->writefds, &writefds, &retcode); e = inter_fdlist_set(th->exceptfds, &exceptfds, &retcode); if (r != NO_FDS || w != NO_FDS || e != NO_FDS) { - value retval = alloc_small(3, TAG_RESUMED_SELECT); + value retval = caml_alloc_small(3, TAG_RESUMED_SELECT); Field(retval, 0) = r; Field(retval, 1) = w; Field(retval, 2) = e; @@ -487,7 +487,7 @@ try_again: } /* If we haven't something to run at that point, we're in big trouble. */ - if (run_thread == NULL) invalid_argument("Thread: deadlock"); + if (run_thread == NULL) caml_invalid_argument("Thread: deadlock"); /* Free everything the thread was waiting on */ Assign(run_thread->readfds, NO_FDS); @@ -499,14 +499,14 @@ try_again: /* Activate the thread */ curr_thread = run_thread; - stack_low = curr_thread->stack_low; - stack_high = curr_thread->stack_high; - stack_threshold = curr_thread->stack_threshold; - extern_sp = curr_thread->sp; - trapsp = curr_thread->trapsp; - backtrace_pos = Int_val(curr_thread->backtrace_pos); - backtrace_buffer = curr_thread->backtrace_buffer; - backtrace_last_exn = curr_thread->backtrace_last_exn; + caml_stack_low = curr_thread->stack_low; + caml_stack_high = curr_thread->stack_high; + caml_stack_threshold = curr_thread->stack_threshold; + caml_extern_sp = curr_thread->sp; + caml_trapsp = curr_thread->trapsp; + caml_backtrace_pos = Int_val(curr_thread->backtrace_pos); + caml_backtrace_buffer = curr_thread->backtrace_buffer; + caml_backtrace_last_exn = curr_thread->backtrace_last_exn; return curr_thread->retval; } @@ -515,7 +515,7 @@ try_again: static void check_callback(void) { - if (callback_depth > 1) + if (caml_callback_depth > 1) caml_fatal_error("Thread: deadlock during callback"); } @@ -537,20 +537,20 @@ static void thread_reschedule(void) Assert(curr_thread != NULL); /* Pop accu from event frame, making it look like a C_CALL frame followed by a RETURN frame */ - accu = *extern_sp++; + accu = *caml_extern_sp++; /* Reschedule */ Assign(curr_thread->retval, accu); accu = schedule_thread(); /* Push accu below C_CALL frame so that it looks like an event frame */ - *--extern_sp = accu; + *--caml_extern_sp = accu; } /* Request a re-scheduling as soon as possible */ value thread_request_reschedule(value unit) /* ML */ { - async_action_hook = thread_reschedule; - something_to_do = 1; + caml_async_action_hook = thread_reschedule; + caml_something_to_do = 1; return Val_unit; } @@ -574,7 +574,7 @@ static value thread_wait_rw(int kind, value fd) if (curr_thread == NULL) return RESUMED_WAKEUP; /* As a special case, if we're in a callback, don't fail but block the whole process till I/O is possible */ - if (callback_depth > 1) { + if (caml_callback_depth > 1) { fd_set fds; FD_ZERO(&fds); FD_SET(Int_val(fd), &fds); @@ -609,7 +609,7 @@ static value thread_wait_timed_rw(int kind, value arg) check_callback(); curr_thread->fd = Field(arg, 0); date = timeofday() + Double_val(Field(arg, 1)); - Assign(curr_thread->delay, copy_double(date)); + Assign(curr_thread->delay, caml_copy_double(date)); curr_thread->status = kind | BLOCKED_DELAY; return schedule_thread(); } @@ -636,7 +636,7 @@ value thread_select(value arg) /* ML */ date = Double_val(Field(arg, 3)); if (date >= 0.0) { date += timeofday(); - Assign(curr_thread->delay, copy_double(date)); + Assign(curr_thread->delay, caml_copy_double(date)); curr_thread->status = BLOCKED_SELECT | BLOCKED_DELAY; } else { curr_thread->status = BLOCKED_SELECT; @@ -676,7 +676,7 @@ value thread_delay(value time) /* ML */ Assert(curr_thread != NULL); check_callback(); curr_thread->status = BLOCKED_DELAY; - Assign(curr_thread->delay, copy_double(date)); + Assign(curr_thread->delay, caml_copy_double(date)); return schedule_thread(); } @@ -714,9 +714,9 @@ value thread_wakeup(value thread) /* ML */ Assign(th->retval, RESUMED_WAKEUP); break; case KILLED: - failwith("Thread.wakeup: killed thread"); + caml_failwith("Thread.wakeup: killed thread"); default: - failwith("Thread.wakeup: thread not suspended"); + caml_failwith("Thread.wakeup: thread not suspended"); } return Val_unit; } @@ -735,9 +735,9 @@ value thread_kill(value thread) /* ML */ { value retval = Val_unit; caml_thread_t th = (caml_thread_t) thread; - if (th->status == KILLED) failwith("Thread.kill: killed thread"); + if (th->status == KILLED) caml_failwith("Thread.kill: killed thread"); /* Don't paint ourselves in a corner */ - if (th == th->next) failwith("Thread.kill: cannot kill the last thread"); + if (th == th->next) caml_failwith("Thread.kill: cannot kill the last thread"); /* This thread is no longer waiting on anything */ th->status = KILLED; /* If this is the current thread, activate another one */ @@ -751,7 +751,7 @@ value thread_kill(value thread) /* ML */ Assign(th->prev->next, th->next); Assign(th->next->prev, th->prev); /* Free its resources */ - stat_free((char *) th->stack_low); + caml_stat_free((char *) th->stack_low); th->stack_low = NULL; th->stack_high = NULL; th->stack_threshold = NULL; @@ -768,11 +768,11 @@ value thread_kill(value thread) /* ML */ value thread_uncaught_exception(value exn) /* ML */ { - char * msg = format_caml_exception(exn); + char * msg = caml_format_exception(exn); fprintf(stderr, "Thread %d killed on uncaught exception %s\n", Int_val(curr_thread->ident), msg); free(msg); - if (backtrace_active) print_exception_backtrace(); + if (caml_backtrace_active) caml_print_exception_backtrace(); fflush(stderr); return Val_unit; } @@ -800,7 +800,7 @@ static value inter_fdlist_set(value fdl, fd_set *set, int *count) for (res = NO_FDS; fdl != NO_FDS; fdl = Field(fdl, 1)) { int fd = Int_val(Field(fdl, 0)); if (FD_ISSET(fd, set)) { - cons = alloc_small(2, 0); + cons = caml_alloc_small(2, 0); Field(cons, 0) = Val_int(fd); Field(cons, 1) = res; res = cons; @@ -849,19 +849,19 @@ static value alloc_process_status(int pid, int status) value st, res; if (WIFEXITED(status)) { - st = alloc_small(1, TAG_WEXITED); + st = caml_alloc_small(1, TAG_WEXITED); Field(st, 0) = Val_int(WEXITSTATUS(status)); } else if (WIFSTOPPED(status)) { - st = alloc_small(1, TAG_WSTOPPED); + st = caml_alloc_small(1, TAG_WSTOPPED); Field(st, 0) = Val_int(WSTOPSIG(status)); } else { - st = alloc_small(1, TAG_WSIGNALED); + st = caml_alloc_small(1, TAG_WSIGNALED); Field(st, 0) = Val_int(WTERMSIG(status)); } Begin_root(st); - res = alloc_small(2, TAG_RESUMED_WAIT); + res = caml_alloc_small(2, TAG_RESUMED_WAIT); Field(res, 0) = Val_int(pid); Field(res, 1) = st; End_roots(); diff --git a/otherlibs/threads/thread.mli b/otherlibs/threads/thread.mli index 8369bbae..bf0c3804 100644 --- a/otherlibs/threads/thread.mli +++ b/otherlibs/threads/thread.mli @@ -82,7 +82,7 @@ val select : Unix.file_descr list -> Unix.file_descr list -> Unix.file_descr list -> float -> Unix.file_descr list * Unix.file_descr list * Unix.file_descr list -(** Suspend the execution of the calling thead until input/output +(** Suspend the execution of the calling thread until input/output becomes possible on the given Unix file descriptors. The arguments and results have the same meaning as for {!Unix.select}. *) @@ -125,7 +125,7 @@ val critical_section : bool ref (the timer interrupt that transfers control from thread to thread), causing the current thread to run uninterrupted until [critical_section] is reset to [false] or the current thread - explicitely relinquishes control using [sleep], [delay], + explicitly relinquishes control using [sleep], [delay], [wait_inchan] or [wait_descr]. *) val sleep : unit -> unit diff --git a/otherlibs/threads/threadUnix.mli b/otherlibs/threads/threadUnix.mli index 1bc9dea1..2b03ac9b 100644 --- a/otherlibs/threads/threadUnix.mli +++ b/otherlibs/threads/threadUnix.mli @@ -62,7 +62,7 @@ val select : (** {6 Pipes and redirections} *) -val pipe : unit -> Unix.file_descr * Unix.file_descr +val pipe : ?cloexec:bool -> unit -> Unix.file_descr * Unix.file_descr val open_process_in : string -> in_channel val open_process_out : string -> out_channel val open_process : string -> in_channel * out_channel @@ -75,11 +75,14 @@ val sleep : int -> unit (** {6 Sockets} *) -val socket : Unix.socket_domain -> Unix.socket_type -> int -> Unix.file_descr +val socket : + ?cloexec:bool -> Unix.socket_domain -> Unix.socket_type -> int -> + Unix.file_descr val socketpair : - Unix.socket_domain -> Unix.socket_type -> int -> + ?cloexec:bool -> Unix.socket_domain -> Unix.socket_type -> int -> Unix.file_descr * Unix.file_descr -val accept : Unix.file_descr -> Unix.file_descr * Unix.sockaddr +val accept : + ?cloexec:bool -> Unix.file_descr -> Unix.file_descr * Unix.sockaddr val connect : Unix.file_descr -> Unix.sockaddr -> unit val recv : Unix.file_descr -> bytes -> int -> int -> Unix.msg_flag list -> int diff --git a/otherlibs/threads/unix.ml b/otherlibs/threads/unix.ml index 491aeda1..9701cbd0 100644 --- a/otherlibs/threads/unix.ml +++ b/otherlibs/threads/unix.ml @@ -199,6 +199,7 @@ type open_flag = | O_RSYNC | O_SHARE_DELETE | O_CLOEXEC + | O_KEEPEXEC type file_perm = int @@ -330,8 +331,9 @@ external fchown : file_descr -> int -> int -> unit = "unix_fchown" external umask : int -> int = "unix_umask" external access : string -> access_permission list -> unit = "unix_access" -external dup : file_descr -> file_descr = "unix_dup" -external dup2 : file_descr -> file_descr -> unit = "unix_dup2" +external dup : ?cloexec: bool -> file_descr -> file_descr = "unix_dup" +external dup2 : + ?cloexec: bool -> file_descr -> file_descr -> unit = "unix_dup2" external set_nonblock : file_descr -> unit = "unix_set_nonblock" external clear_nonblock : file_descr -> unit = "unix_clear_nonblock" external set_close_on_exec : file_descr -> unit = "unix_set_close_on_exec" @@ -350,10 +352,11 @@ external readdir : dir_handle -> string = "unix_readdir" external rewinddir : dir_handle -> unit = "unix_rewinddir" external closedir : dir_handle -> unit = "unix_closedir" -external _pipe : unit -> file_descr * file_descr = "unix_pipe" +external _pipe : + ?cloexec: bool -> unit -> file_descr * file_descr = "unix_pipe" -let pipe() = - let (out_fd, in_fd as fd_pair) = _pipe() in +let pipe ?cloexec () = + let (out_fd, in_fd as fd_pair) = _pipe ?cloexec () in set_nonblock in_fd; set_nonblock out_fd; fd_pair @@ -558,28 +561,31 @@ type msg_flag = | MSG_DONTROUTE | MSG_PEEK -external _socket : socket_domain -> socket_type -> int -> file_descr - = "unix_socket" +external _socket : + ?cloexec: bool -> socket_domain -> socket_type -> int -> file_descr + = "unix_socket" external _socketpair : - socket_domain -> socket_type -> int -> file_descr * file_descr - = "unix_socketpair" + ?cloexec: bool -> socket_domain -> socket_type -> int -> + file_descr * file_descr + = "unix_socketpair" -let socket dom typ proto = - let s = _socket dom typ proto in +let socket ?cloexec dom typ proto = + let s = _socket ?cloexec dom typ proto in set_nonblock s; s -let socketpair dom typ proto = - let (s1, s2 as spair) = _socketpair dom typ proto in +let socketpair ?cloexec dom typ proto = + let (s1, s2 as spair) = _socketpair ?cloexec dom typ proto in set_nonblock s1; set_nonblock s2; spair -external _accept : file_descr -> file_descr * sockaddr = "unix_accept" +external _accept : + ?cloexec: bool -> file_descr -> file_descr * sockaddr = "unix_accept" -let rec accept req = +let rec accept ?cloexec req = wait_read req; try - let (s, caller as result) = _accept req in + let (s, caller as result) = _accept ?cloexec req in set_nonblock s; result with Unix_error((EAGAIN | EWOULDBLOCK), _, _) -> accept req @@ -937,6 +943,10 @@ external setsid : unit -> int = "unix_setsid" (* High-level process management (system, popen) *) +let rec waitpid_non_intr pid = + try waitpid [] pid + with Unix_error (EINTR, _, _) -> waitpid_non_intr pid + let system cmd = match fork() with 0 -> begin try @@ -944,31 +954,25 @@ let system cmd = with _ -> exit 127 end - | id -> snd(waitpid [] id) - -let rec safe_dup fd = - let new_fd = dup fd in - if new_fd >= 3 then - new_fd - else begin - let res = safe_dup fd in - close new_fd; + | id -> snd(waitpid_non_intr id) + +(* Make sure [fd] is not one of the standard descriptors 0, 1, 2, + by duplicating it if needed. *) + +let rec file_descr_not_standard fd = + if fd >= 3 then fd else begin + let res = file_descr_not_standard (dup fd) in + close fd; res end -let safe_close fd = - try close fd with Unix_error(_,_,_) -> () - let perform_redirections new_stdin new_stdout new_stderr = - let newnewstdin = safe_dup new_stdin in - let newnewstdout = safe_dup new_stdout in - let newnewstderr = safe_dup new_stderr in - safe_close new_stdin; - safe_close new_stdout; - safe_close new_stderr; - dup2 newnewstdin stdin; close newnewstdin; - dup2 newnewstdout stdout; close newnewstdout; - dup2 newnewstderr stderr; close newnewstderr + let new_stdin = file_descr_not_standard new_stdin in + let new_stdout = file_descr_not_standard new_stdout in + let new_stderr = file_descr_not_standard new_stderr in + dup2 ~cloexec:false new_stdin stdin; close new_stdin; + dup2 ~cloexec:false new_stdout stdout; close new_stdout; + dup2 ~cloexec:false new_stderr stderr; close new_stderr let create_process cmd args new_stdin new_stdout new_stderr = match fork() with @@ -1000,65 +1004,127 @@ type popen_process = let popen_processes = (Hashtbl.create 7 : (popen_process, int) Hashtbl.t) -let open_proc cmd proc input output toclose = +let open_proc cmd envopt proc input output error = match fork() with - 0 -> if input <> stdin then begin dup2 input stdin; close input end; - if output <> stdout then begin dup2 output stdout; close output end; - List.iter close toclose; - begin try execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |] - with _ -> exit 127 + 0 -> begin try + perform_redirections input output error; + let shell = "/bin/sh" in + let argv = [| shell; "-c"; cmd |] in + match envopt with + | Some env -> execve shell argv env + | None -> execv shell argv + with _ -> + exit 127 end | id -> Hashtbl.add popen_processes proc id let open_process_in cmd = - let (in_read, in_write) = pipe() in + let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in - open_proc cmd (Process_in inchan) stdin in_write [in_read]; - close in_write; - inchan + try + open_proc cmd None (Process_in inchan) stdin in_write stderr; + close in_write; + inchan + with e -> + close_in inchan; + close in_write; + raise e let open_process_out cmd = - let (out_read, out_write) = pipe() in + let (out_read, out_write) = pipe ~cloexec:true () in let outchan = out_channel_of_descr out_write in - open_proc cmd (Process_out outchan) out_read stdout [out_write]; - close out_read; - outchan + try + open_proc cmd None (Process_out outchan) out_read stdout stderr; + close out_read; + outchan + with e -> + close_out outchan; + close out_read; + raise e let open_process cmd = - let (in_read, in_write) = pipe() in - let (out_read, out_write) = pipe() in + let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in - let outchan = out_channel_of_descr out_write in - open_proc cmd (Process(inchan, outchan)) out_read in_write - [in_read; out_write]; - close out_read; - close in_write; - (inchan, outchan) - -let open_proc_full cmd env proc input output error toclose = - match fork() with - 0 -> dup2 input stdin; close input; - dup2 output stdout; close output; - dup2 error stderr; close error; - List.iter close toclose; - begin try execve "/bin/sh" [| "/bin/sh"; "-c"; cmd |] env - with _ -> exit 127 - end - | id -> Hashtbl.add popen_processes proc id + try + let (out_read, out_write) = pipe ~cloexec:true () in + let outchan = out_channel_of_descr out_write in + try + open_proc cmd None (Process(inchan, outchan)) out_read in_write stderr; + close out_read; + close in_write; + (inchan, outchan) + with e -> + close_out outchan; + close out_read; + raise e + with e -> + close_in inchan; + close in_write; + raise e let open_process_full cmd env = - let (in_read, in_write) = pipe() in - let (out_read, out_write) = pipe() in - let (err_read, err_write) = pipe() in + let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in - let outchan = out_channel_of_descr out_write in - let errchan = in_channel_of_descr err_read in - open_proc_full cmd env (Process_full(inchan, outchan, errchan)) - out_read in_write err_write [in_read; out_write; err_read]; - close out_read; - close in_write; - close err_write; - (inchan, outchan, errchan) + try + let (out_read, out_write) = pipe ~cloexec:true () in + let outchan = out_channel_of_descr out_write in + try + let (err_read, err_write) = pipe ~cloexec:true () in + let errchan = in_channel_of_descr err_read in + try + open_proc cmd (Some env) (Process_full(inchan, outchan, errchan)) + out_read in_write err_write; + close out_read; + close in_write; + close err_write; + (inchan, outchan, errchan) + with e -> + close_in errchan; + close err_write; + raise e + with e -> + close_out outchan; + close out_read; + raise e + with e -> + close_in inchan; + close in_write; + raise e + +let find_proc_id fun_name proc = + try + let pid = Hashtbl.find popen_processes proc in + Hashtbl.remove popen_processes proc; + pid + with Not_found -> + raise(Unix_error(EBADF, fun_name, "")) + +let close_process_in inchan = + let pid = find_proc_id "close_process_in" (Process_in inchan) in + close_in inchan; + snd(waitpid_non_intr pid) + +let close_process_out outchan = + let pid = find_proc_id "close_process_out" (Process_out outchan) in + (* The application may have closed [outchan] already to signal + end-of-input to the process. *) + begin try close_out outchan with Sys_error _ -> () end; + snd(waitpid_non_intr pid) + +let close_process (inchan, outchan) = + let pid = find_proc_id "close_process" (Process(inchan, outchan)) in + close_in inchan; + begin try close_out outchan with Sys_error _ -> () end; + snd(waitpid_non_intr pid) + +let close_process_full (inchan, outchan, errchan) = + let pid = + find_proc_id "close_process_full" + (Process_full(inchan, outchan, errchan)) in + close_in inchan; + begin try close_out outchan with Sys_error _ -> () end; + close_in errchan; + snd(waitpid_non_intr pid) let find_proc_id fun_name proc = try @@ -1101,7 +1167,7 @@ let close_process_full (inchan, outchan, errchan) = let open_connection sockaddr = let sock = - socket (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in + socket ~cloexec:true (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in try connect sock sockaddr; (in_channel_of_descr sock, out_channel_of_descr sock) @@ -1111,25 +1177,29 @@ let open_connection sockaddr = let shutdown_connection inchan = shutdown (descr_of_in_channel inchan) SHUTDOWN_SEND +let rec accept_non_intr s = + try accept ~cloexec:true s + with Unix_error (EINTR, _, _) -> accept_non_intr s + let establish_server server_fun sockaddr = let sock = - socket (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in + socket ~cloexec:true (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in setsockopt sock SO_REUSEADDR true; bind sock sockaddr; listen sock 5; while true do - let (s, caller) = accept sock in + let (s, caller) = accept_non_intr sock in (* The "double fork" trick, the process which calls server_fun will not leave a zombie process *) match fork() with 0 -> if fork() <> 0 then exit 0; (* The son exits, the grandson works *) + close sock; let inchan = in_channel_of_descr s in let outchan = out_channel_of_descr s in server_fun inchan outchan; - close_out outchan; - (* The file descriptor was already closed by close_out. - close_in inchan; - *) + (* Do not close inchan nor outchan, as the server_fun could + have done it already, and we are about to exit anyway + (PR#3794) *) exit 0 - | id -> close s; ignore(waitpid [] id) (* Reclaim the son *) + | id -> close s; ignore(waitpid_non_intr id) (* Reclaim the son *) done diff --git a/otherlibs/unix/.depend b/otherlibs/unix/.depend index 0076ca6d..2d9d23d3 100644 --- a/otherlibs/unix/.depend +++ b/otherlibs/unix/.depend @@ -106,7 +106,7 @@ execvp.o: execvp.c ../../byterun/caml/mlvalues.h \ ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \ ../../byterun/caml/../../config/m.h \ ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h unixsupport.h + ../../byterun/caml/memory.h ../../byterun/caml/osdeps.h unixsupport.h exit.o: exit.c ../../byterun/caml/mlvalues.h \ ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \ ../../byterun/caml/../../config/m.h \ diff --git a/otherlibs/unix/Makefile b/otherlibs/unix/Makefile index ce3fb748..39ef5917 100644 --- a/otherlibs/unix/Makefile +++ b/otherlibs/unix/Makefile @@ -19,6 +19,9 @@ LIBNAME=unix EXTRACAMLFLAGS=-nolabels +# dllunix.so particularly requires libm for modf symbols +LDOPTS=$(NATIVECCLIBS) + COBJS=accept.o access.o addrofstr.o alarm.o bind.o chdir.o chmod.o \ chown.o chroot.o close.o closedir.o connect.o cst2constr.o cstringv.o \ dup.o dup2.o envir.o errmsg.o execv.o execve.o execvp.o exit.o \ diff --git a/otherlibs/unix/accept.c b/otherlibs/unix/accept.c index d2217496..d02cc09a 100644 --- a/otherlibs/unix/accept.c +++ b/otherlibs/unix/accept.c @@ -13,6 +13,7 @@ /* */ /**************************************************************************/ +#define _GNU_SOURCE #include #include #include @@ -24,22 +25,31 @@ #include "socketaddr.h" -CAMLprim value unix_accept(value sock) +CAMLprim value unix_accept(value cloexec, value sock) { int retcode; value res; value a; union sock_addr_union addr; socklen_param_type addr_len; + int clo = unix_cloexec_p(cloexec); addr_len = sizeof(addr); - enter_blocking_section(); + caml_enter_blocking_section(); +#if defined(HAS_ACCEPT4) && defined(SOCK_CLOEXEC) + retcode = accept4(Int_val(sock), &addr.s_gen, &addr_len, + clo ? SOCK_CLOEXEC : 0); +#else retcode = accept(Int_val(sock), &addr.s_gen, &addr_len); - leave_blocking_section(); +#endif + caml_leave_blocking_section(); if (retcode == -1) uerror("accept", Nothing); +#if !(defined(HAS_ACCEPT4) && defined(SOCK_CLOEXEC)) + if (clo) unix_set_cloexec(retcode, "accept", Nothing); +#endif a = alloc_sockaddr(&addr, addr_len, retcode); Begin_root (a); - res = alloc_small(2, 0); + res = caml_alloc_small(2, 0); Field(res, 0) = Val_int(retcode); Field(res, 1) = a; End_roots(); @@ -48,7 +58,7 @@ CAMLprim value unix_accept(value sock) #else -CAMLprim value unix_accept(value sock) -{ invalid_argument("accept not implemented"); } +CAMLprim value unix_accept(value cloexec, value sock) +{ caml_invalid_argument("accept not implemented"); } #endif diff --git a/otherlibs/unix/access.c b/otherlibs/unix/access.c index 25401c5c..0df09ed2 100644 --- a/otherlibs/unix/access.c +++ b/otherlibs/unix/access.c @@ -24,22 +24,26 @@ #else # ifndef _WIN32 # include -# ifndef R_OK +# endif +# ifndef R_OK # define R_OK 4/* test for read permission */ # define W_OK 2/* test for write permission */ # define X_OK 1/* test for execute (search) permission */ # define F_OK 0/* test for presence of file */ -# endif -# else -# define R_OK 4/* test for read permission */ -# define W_OK 2/* test for write permission */ -# define X_OK 4/* test for execute permission - not implemented in Win32 */ -# define F_OK 0/* test for presence of file */ # endif #endif static int access_permission_table[] = { - R_OK, W_OK, X_OK, F_OK + R_OK, + W_OK, +#ifdef _WIN32 + /* Since there is no concept of execute permission on Windows, + we fall b+ack to the read permission */ + R_OK, +#else + X_OK, +#endif + F_OK }; CAMLprim value unix_access(value path, value perms) @@ -49,7 +53,7 @@ CAMLprim value unix_access(value path, value perms) int ret, cv_flags; caml_unix_check_path(path, "access"); - cv_flags = convert_flag_list(perms, access_permission_table); + cv_flags = caml_convert_flag_list(perms, access_permission_table); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = access(p, cv_flags); diff --git a/otherlibs/unix/addrofstr.c b/otherlibs/unix/addrofstr.c index 72f0ebd3..2325cb9e 100644 --- a/otherlibs/unix/addrofstr.c +++ b/otherlibs/unix/addrofstr.c @@ -24,7 +24,7 @@ CAMLprim value unix_inet_addr_of_string(value s) { - if (! caml_string_is_c_safe(s)) failwith("inet_addr_of_string"); + if (! caml_string_is_c_safe(s)) caml_failwith("inet_addr_of_string"); #if defined(HAS_IPV6) #ifdef _WIN32 { @@ -37,7 +37,7 @@ CAMLprim value unix_inet_addr_of_string(value s) hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; retcode = getaddrinfo(String_val(s), NULL, &hints, &res); - if (retcode != 0) failwith("inet_addr_of_string"); + if (retcode != 0) caml_failwith("inet_addr_of_string"); switch (res->ai_addr->sa_family) { case AF_INET: { @@ -54,7 +54,7 @@ CAMLprim value unix_inet_addr_of_string(value s) default: { freeaddrinfo(res); - failwith("inet_addr_of_string"); + caml_failwith("inet_addr_of_string"); } } freeaddrinfo(res); @@ -69,21 +69,21 @@ CAMLprim value unix_inet_addr_of_string(value s) else if (inet_pton(AF_INET6, String_val(s), &address6) > 0) return alloc_inet6_addr(&address6); else - failwith("inet_addr_of_string"); + caml_failwith("inet_addr_of_string"); } #endif #elif defined(HAS_INET_ATON) { struct in_addr address; if (inet_aton(String_val(s), &address) == 0) - failwith("inet_addr_of_string"); + caml_failwith("inet_addr_of_string"); return alloc_inet_addr(&address); } #else { struct in_addr address; address.s_addr = inet_addr(String_val(s)); - if (address.s_addr == (uint32_t) -1) failwith("inet_addr_of_string"); + if (address.s_addr == (uint32_t) -1) caml_failwith("inet_addr_of_string"); return alloc_inet_addr(&address); } #endif @@ -92,6 +92,6 @@ CAMLprim value unix_inet_addr_of_string(value s) #else CAMLprim value unix_inet_addr_of_string(value s) -{ invalid_argument("inet_addr_of_string not implemented"); } +{ caml_invalid_argument("inet_addr_of_string not implemented"); } #endif diff --git a/otherlibs/unix/bind.c b/otherlibs/unix/bind.c index 8849e6a9..73b24b06 100644 --- a/otherlibs/unix/bind.c +++ b/otherlibs/unix/bind.c @@ -36,6 +36,6 @@ CAMLprim value unix_bind(value socket, value address) #else CAMLprim value unix_bind(value socket, value address) -{ invalid_argument("bind not implemented"); } +{ caml_invalid_argument("bind not implemented"); } #endif diff --git a/otherlibs/unix/connect.c b/otherlibs/unix/connect.c index 4e79efa0..8569ab41 100644 --- a/otherlibs/unix/connect.c +++ b/otherlibs/unix/connect.c @@ -29,9 +29,9 @@ CAMLprim value unix_connect(value socket, value address) socklen_param_type addr_len; get_sockaddr(address, &addr, &addr_len); - enter_blocking_section(); + caml_enter_blocking_section(); retcode = connect(Int_val(socket), &addr.s_gen, addr_len); - leave_blocking_section(); + caml_leave_blocking_section(); if (retcode == -1) uerror("connect", Nothing); return Val_unit; } @@ -39,6 +39,6 @@ CAMLprim value unix_connect(value socket, value address) #else CAMLprim value unix_connect(value socket, value address) -{ invalid_argument("connect not implemented"); } +{ caml_invalid_argument("connect not implemented"); } #endif diff --git a/otherlibs/unix/dup.c b/otherlibs/unix/dup.c index 018eafa8..c9294e6e 100644 --- a/otherlibs/unix/dup.c +++ b/otherlibs/unix/dup.c @@ -13,13 +13,24 @@ /* */ /**************************************************************************/ +#define _GNU_SOURCE #include #include "unixsupport.h" +#include -CAMLprim value unix_dup(value fd) +CAMLprim value unix_dup(value cloexec, value fd) { int ret; +#ifdef F_DUPFD_CLOEXEC + ret = fcntl(Int_val(fd), + (unix_cloexec_p(cloexec) ? F_DUPFD_CLOEXEC : F_DUPFD), + 0); +#else ret = dup(Int_val(fd)); +#endif if (ret == -1) uerror("dup", Nothing); +#ifndef F_DUPFD_CLOEXEC + if (unix_cloexec_p(cloexec)) unix_set_cloexec(ret, "dup", Nothing); +#endif return Val_int(ret); } diff --git a/otherlibs/unix/dup2.c b/otherlibs/unix/dup2.c index c824cc58..78539765 100644 --- a/otherlibs/unix/dup2.c +++ b/otherlibs/unix/dup2.c @@ -13,37 +13,32 @@ /* */ /**************************************************************************/ +#define _GNU_SOURCE #include #include "unixsupport.h" +#include -#ifdef HAS_DUP2 - -CAMLprim value unix_dup2(value fd1, value fd2) +CAMLprim value unix_dup2(value cloexec, value fd1, value fd2) { - if (dup2(Int_val(fd1), Int_val(fd2)) == -1) uerror("dup2", Nothing); - return Val_unit; -} - + if (Int_val(fd2) == Int_val(fd1)) { + /* In this case, dup3 fails and dup2 does nothing. */ + /* Just apply the cloexec flag to fd2, if it is given. */ + if (Is_block(cloexec)) { + if (Bool_val(Field(cloexec, 0))) + unix_set_cloexec(Int_val(fd2), "dup2", Nothing); + else + unix_clear_cloexec(Int_val(fd2), "dup2", Nothing); + } + } else { +#ifdef HAS_DUP3 + if (dup3(Int_val(fd1), Int_val(fd2), + unix_cloexec_p(cloexec) ? O_CLOEXEC : 0) == -1) + uerror("dup2", Nothing); #else - -static int do_dup2(int fd1, int fd2) -{ - int fd; - int res; - - fd = dup(fd1); - if (fd == -1) return -1; - if (fd == fd2) return 0; - res = do_dup2(fd1, fd2); - close(fd); - return res; -} - -CAMLprim value unix_dup2(value fd1, value fd2) -{ - close(Int_val(fd2)); - if (do_dup2(Int_val(fd1), Int_val(fd2)) == -1) uerror("dup2", Nothing); + if (dup2(Int_val(fd1), Int_val(fd2)) == -1) uerror("dup2", Nothing); + if (unix_cloexec_p(cloexec)) + unix_set_cloexec(Int_val(fd2), "dup2", Nothing); +#endif + } return Val_unit; } - -#endif diff --git a/otherlibs/unix/envir.c b/otherlibs/unix/envir.c index b9d451ea..3c6b54dc 100644 --- a/otherlibs/unix/envir.c +++ b/otherlibs/unix/envir.c @@ -23,7 +23,7 @@ extern char ** environ; CAMLprim value unix_environment(value unit) { if (environ != NULL) { - return copy_string_array((const char**)environ); + return caml_copy_string_array((const char**)environ); } else { return Atom(0); } diff --git a/otherlibs/unix/errmsg.c b/otherlibs/unix/errmsg.c index 927e2cfa..fef473ea 100644 --- a/otherlibs/unix/errmsg.c +++ b/otherlibs/unix/errmsg.c @@ -24,5 +24,5 @@ CAMLprim value unix_error_message(value err) { int errnum; errnum = Is_block(err) ? Int_val(Field(err, 0)) : error_table[Int_val(err)]; - return copy_string(strerror(errnum)); + return caml_copy_string(strerror(errnum)); } diff --git a/otherlibs/unix/execv.c b/otherlibs/unix/execv.c index 2a77224d..58f2e45e 100644 --- a/otherlibs/unix/execv.c +++ b/otherlibs/unix/execv.c @@ -23,7 +23,7 @@ CAMLprim value unix_execv(value path, value args) caml_unix_check_path(path, "execv"); argv = cstringvect(args, "execv"); (void) execv(String_val(path), argv); - stat_free((char *) argv); + caml_stat_free((char *) argv); uerror("execv", path); return Val_unit; /* never reached, but suppress warnings */ /* from smart compilers */ diff --git a/otherlibs/unix/execve.c b/otherlibs/unix/execve.c index 65f6a349..dfdef299 100644 --- a/otherlibs/unix/execve.c +++ b/otherlibs/unix/execve.c @@ -25,8 +25,8 @@ CAMLprim value unix_execve(value path, value args, value env) argv = cstringvect(args, "execve"); envp = cstringvect(env, "execve"); (void) execve(String_val(path), argv, envp); - stat_free((char *) argv); - stat_free((char *) envp); + caml_stat_free((char *) argv); + caml_stat_free((char *) envp); uerror("execve", path); return Val_unit; /* never reached, but suppress warnings */ /* from smart compilers */ diff --git a/otherlibs/unix/execvp.c b/otherlibs/unix/execvp.c index 72a986e1..d521adcf 100644 --- a/otherlibs/unix/execvp.c +++ b/otherlibs/unix/execvp.c @@ -15,6 +15,8 @@ #include #include +#define CAML_INTERNALS +#include #include "unixsupport.h" #ifndef _WIN32 @@ -27,25 +29,26 @@ CAMLprim value unix_execvp(value path, value args) caml_unix_check_path(path, "execvp"); argv = cstringvect(args, "execvp"); (void) execvp(String_val(path), argv); - stat_free((char *) argv); + caml_stat_free((char *) argv); uerror("execvp", path); return Val_unit; /* never reached, but suppress warnings */ - /* from smart compilers */ + /* from smart compilers */ } CAMLprim value unix_execvpe(value path, value args, value env) { + char * exefile; char ** argv; - char ** saved_environ; + char ** envp; caml_unix_check_path(path, "execvpe"); + exefile = caml_search_exe_in_path(String_val(path)); argv = cstringvect(args, "execvpe"); - saved_environ = environ; - environ = cstringvect(env, "execvpe"); - (void) execvp(String_val(path), argv); - stat_free((char *) argv); - stat_free((char *) environ); - environ = saved_environ; - uerror("execvp", path); + envp = cstringvect(env, "execvpe"); + (void) execve(exefile, argv, envp); + caml_stat_free(exefile); + caml_stat_free((char *) argv); + caml_stat_free((char *) envp); + uerror("execvpe", path); return Val_unit; /* never reached, but suppress warnings */ - /* from smart compilers */ + /* from smart compilers */ } diff --git a/otherlibs/unix/fchmod.c b/otherlibs/unix/fchmod.c index 5fe50c46..49c7e8b0 100644 --- a/otherlibs/unix/fchmod.c +++ b/otherlibs/unix/fchmod.c @@ -35,6 +35,6 @@ CAMLprim value unix_fchmod(value fd, value perm) #else CAMLprim value unix_fchmod(value fd, value perm) -{ invalid_argument("fchmod not implemented"); } +{ caml_invalid_argument("fchmod not implemented"); } #endif diff --git a/otherlibs/unix/fchown.c b/otherlibs/unix/fchown.c index c1d86d62..8e441967 100644 --- a/otherlibs/unix/fchown.c +++ b/otherlibs/unix/fchown.c @@ -33,6 +33,6 @@ CAMLprim value unix_fchown(value fd, value uid, value gid) #else CAMLprim value unix_fchown(value fd, value uid, value gid) -{ invalid_argument("fchown not implemented"); } +{ caml_invalid_argument("fchown not implemented"); } #endif diff --git a/otherlibs/unix/fcntl.c b/otherlibs/unix/fcntl.c index 869534db..e10a98e3 100644 --- a/otherlibs/unix/fcntl.c +++ b/otherlibs/unix/fcntl.c @@ -45,34 +45,14 @@ CAMLprim value unix_clear_nonblock(value fd) return Val_unit; } -#ifdef FD_CLOEXEC - CAMLprim value unix_set_close_on_exec(value fd) { - int retcode; - retcode = fcntl(Int_val(fd), F_GETFD, 0); - if (retcode == -1 || - fcntl(Int_val(fd), F_SETFD, retcode | FD_CLOEXEC) == -1) - uerror("set_close_on_exec", Nothing); + unix_set_cloexec(Int_val(fd), "set_close_on_exec", Nothing); return Val_unit; } CAMLprim value unix_clear_close_on_exec(value fd) { - int retcode; - retcode = fcntl(Int_val(fd), F_GETFD, 0); - if (retcode == -1 || - fcntl(Int_val(fd), F_SETFD, retcode & ~FD_CLOEXEC) == -1) - uerror("clear_close_on_exec", Nothing); + unix_clear_cloexec(Int_val(fd), "set_close_on_exec", Nothing); return Val_unit; } - -#else - -CAMLprim value unix_set_close_on_exec(value fd) -{ invalid_argument("set_close_on_exec not implemented"); } - -CAMLprim value unix_clear_close_on_exec(value fd) -{ invalid_argument("clear_close_on_exec not implemented"); } - -#endif diff --git a/otherlibs/unix/ftruncate.c b/otherlibs/unix/ftruncate.c index 7c49f2d6..335ffe08 100644 --- a/otherlibs/unix/ftruncate.c +++ b/otherlibs/unix/ftruncate.c @@ -51,9 +51,9 @@ CAMLprim value unix_ftruncate_64(value fd, value len) #else CAMLprim value unix_ftruncate(value fd, value len) -{ invalid_argument("ftruncate not implemented"); } +{ caml_invalid_argument("ftruncate not implemented"); } CAMLprim value unix_ftruncate_64(value fd, value len) -{ invalid_argument("ftruncate not implemented"); } +{ caml_invalid_argument("ftruncate not implemented"); } #endif diff --git a/otherlibs/unix/getaddrinfo.c b/otherlibs/unix/getaddrinfo.c index 837794ed..90c27dae 100644 --- a/otherlibs/unix/getaddrinfo.c +++ b/otherlibs/unix/getaddrinfo.c @@ -45,8 +45,8 @@ static value convert_addrinfo(struct addrinfo * a) if (len > sizeof(sa)) len = sizeof(sa); memcpy(&sa.s_gen, a->ai_addr, len); vaddr = alloc_sockaddr(&sa, len, -1); - vcanonname = copy_string(a->ai_canonname == NULL ? "" : a->ai_canonname); - vres = alloc_small(5, 0); + vcanonname = caml_copy_string(a->ai_canonname == NULL ? "" : a->ai_canonname); + vres = caml_alloc_small(5, 0); Field(vres, 0) = cst_to_constr(a->ai_family, socket_domain_table, 3, 0); Field(vres, 1) = cst_to_constr(a->ai_socktype, socket_type_table, 4, 0); Field(vres, 2) = Val_int(a->ai_protocol); @@ -107,17 +107,17 @@ CAMLprim value unix_getaddrinfo(value vnode, value vserv, value vopts) } } /* Do the call */ - enter_blocking_section(); + caml_enter_blocking_section(); retcode = getaddrinfo(node, serv, &hints, &res); - leave_blocking_section(); - if (node != NULL) stat_free(node); - if (serv != NULL) stat_free(serv); + caml_leave_blocking_section(); + if (node != NULL) caml_stat_free(node); + if (serv != NULL) caml_stat_free(serv); /* Convert result */ vres = Val_int(0); if (retcode == 0) { for (r = res; r != NULL; r = r->ai_next) { e = convert_addrinfo(r); - v = alloc_small(2, 0); + v = caml_alloc_small(2, 0); Field(v, 0) = e; Field(v, 1) = vres; vres = v; @@ -130,6 +130,6 @@ CAMLprim value unix_getaddrinfo(value vnode, value vserv, value vopts) #else CAMLprim value unix_getaddrinfo(value vnode, value vserv, value vopts) -{ invalid_argument("getaddrinfo not implemented"); } +{ caml_invalid_argument("getaddrinfo not implemented"); } #endif diff --git a/otherlibs/unix/getcwd.c b/otherlibs/unix/getcwd.c index 9dac1477..74c8a07f 100644 --- a/otherlibs/unix/getcwd.c +++ b/otherlibs/unix/getcwd.c @@ -36,7 +36,7 @@ CAMLprim value unix_getcwd(value unit) { char buff[PATH_MAX]; if (getcwd(buff, sizeof(buff)) == 0) uerror("getcwd", Nothing); - return copy_string(buff); + return caml_copy_string(buff); } #else @@ -52,7 +52,7 @@ CAMLprim value unix_getcwd(value unit) #else CAMLprim value unix_getcwd(value unit) -{ invalid_argument("getcwd not implemented"); } +{ caml_invalid_argument("getcwd not implemented"); } #endif #endif diff --git a/otherlibs/unix/getgr.c b/otherlibs/unix/getgr.c index ee194fa7..5aa8762b 100644 --- a/otherlibs/unix/getgr.c +++ b/otherlibs/unix/getgr.c @@ -27,10 +27,11 @@ static value alloc_group_entry(struct group *entry) value name = Val_unit, pass = Val_unit, mem = Val_unit; Begin_roots3 (name, pass, mem); - name = copy_string(entry->gr_name); - pass = copy_string(entry->gr_passwd); - mem = copy_string_array((const char**)entry->gr_mem); - res = alloc_small(4, 0); + name = caml_copy_string(entry->gr_name); + /* on some platforms, namely Android, gr_passwd can be NULL - hence this workaround */ + pass = caml_copy_string(entry->gr_passwd ? entry->gr_passwd : ""); + mem = caml_copy_string_array((const char**)entry->gr_mem); + res = caml_alloc_small(4, 0); Field(res,0) = name; Field(res,1) = pass; Field(res,2) = Val_int(entry->gr_gid); @@ -42,9 +43,9 @@ static value alloc_group_entry(struct group *entry) CAMLprim value unix_getgrnam(value name) { struct group * entry; - if (! caml_string_is_c_safe(name)) raise_not_found(); + if (! caml_string_is_c_safe(name)) caml_raise_not_found(); entry = getgrnam(String_val(name)); - if (entry == NULL) raise_not_found(); + if (entry == NULL) caml_raise_not_found(); return alloc_group_entry(entry); } @@ -52,6 +53,6 @@ CAMLprim value unix_getgrgid(value gid) { struct group * entry; entry = getgrgid(Int_val(gid)); - if (entry == NULL) raise_not_found(); + if (entry == NULL) caml_raise_not_found(); return alloc_group_entry(entry); } diff --git a/otherlibs/unix/getgroups.c b/otherlibs/unix/getgroups.c index bc65e3a8..4bccd69d 100644 --- a/otherlibs/unix/getgroups.c +++ b/otherlibs/unix/getgroups.c @@ -35,7 +35,7 @@ CAMLprim value unix_getgroups(value unit) n = getgroups(NGROUPS_MAX, gidset); if (n == -1) uerror("getgroups", Nothing); - res = alloc_tuple(n); + res = caml_alloc_tuple(n); for (i = 0; i < n; i++) Field(res, i) = Val_int(gidset[i]); return res; @@ -44,6 +44,6 @@ CAMLprim value unix_getgroups(value unit) #else CAMLprim value unix_getgroups(value unit) -{ invalid_argument("getgroups not implemented"); } +{ caml_invalid_argument("getgroups not implemented"); } #endif diff --git a/otherlibs/unix/gethost.c b/otherlibs/unix/gethost.c index 8d211dd5..1c1f5efa 100644 --- a/otherlibs/unix/gethost.c +++ b/otherlibs/unix/gethost.c @@ -61,22 +61,22 @@ static value alloc_host_entry(struct hostent *entry) value addr_list = Val_unit, adr = Val_unit; Begin_roots4 (name, aliases, addr_list, adr); - name = copy_string((char *)(entry->h_name)); + name = caml_copy_string((char *)(entry->h_name)); /* PR#4043: protect against buggy implementations of gethostbyname() that return a NULL pointer in h_aliases */ if (entry->h_aliases) - aliases = copy_string_array((const char**)entry->h_aliases); + aliases = caml_copy_string_array((const char**)entry->h_aliases); else aliases = Atom(0); entry_h_length = entry->h_length; #ifdef h_addr - addr_list = alloc_array(alloc_one_addr, (const char**)entry->h_addr_list); + addr_list = caml_alloc_array(alloc_one_addr, (const char**)entry->h_addr_list); #else adr = alloc_one_addr(entry->h_addr); - addr_list = alloc_small(1, 0); + addr_list = caml_alloc_small(1, 0); Field(addr_list, 0) = adr; #endif - res = alloc_small(4, 0); + res = caml_alloc_small(4, 0); Field(res, 0) = name; Field(res, 1) = aliases; switch (entry->h_addrtype) { @@ -97,29 +97,29 @@ CAMLprim value unix_gethostbyaddr(value a) struct hostent h; char buffer[NETDB_BUFFER_SIZE]; int h_errnop; - enter_blocking_section(); + caml_enter_blocking_section(); hp = gethostbyaddr_r((char *) &adr, 4, AF_INET, &h, buffer, sizeof(buffer), &h_errnop); - leave_blocking_section(); + caml_leave_blocking_section(); #elif HAS_GETHOSTBYADDR_R == 8 struct hostent h; char buffer[NETDB_BUFFER_SIZE]; int h_errnop, rc; - enter_blocking_section(); + caml_enter_blocking_section(); rc = gethostbyaddr_r((char *) &adr, 4, AF_INET, &h, buffer, sizeof(buffer), &hp, &h_errnop); - leave_blocking_section(); + caml_leave_blocking_section(); if (rc != 0) hp = NULL; #else #ifdef GETHOSTBYADDR_IS_REENTRANT - enter_blocking_section(); + caml_enter_blocking_section(); #endif hp = gethostbyaddr((char *) &adr, 4, AF_INET); #ifdef GETHOSTBYADDR_IS_REENTRANT - leave_blocking_section(); + caml_leave_blocking_section(); #endif #endif - if (hp == (struct hostent *) NULL) raise_not_found(); + if (hp == (struct hostent *) NULL) caml_raise_not_found(); return alloc_host_entry(hp); } @@ -133,7 +133,7 @@ CAMLprim value unix_gethostbyname(value name) int err; #endif - if (! caml_string_is_c_safe(name)) raise_not_found(); + if (! caml_string_is_c_safe(name)) caml_raise_not_found(); #if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT hostname = caml_strdup(String_val(name)); @@ -143,42 +143,42 @@ CAMLprim value unix_gethostbyname(value name) #if HAS_GETHOSTBYNAME_R == 5 { - enter_blocking_section(); + caml_enter_blocking_section(); hp = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &err); - leave_blocking_section(); + caml_leave_blocking_section(); } #elif HAS_GETHOSTBYNAME_R == 6 { int rc; - enter_blocking_section(); + caml_enter_blocking_section(); rc = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &hp, &err); - leave_blocking_section(); + caml_leave_blocking_section(); if (rc != 0) hp = NULL; } #else #ifdef GETHOSTBYNAME_IS_REENTRANT - enter_blocking_section(); + caml_enter_blocking_section(); #endif hp = gethostbyname(hostname); #ifdef GETHOSTBYNAME_IS_REENTRANT - leave_blocking_section(); + caml_leave_blocking_section(); #endif #endif #if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT - stat_free(hostname); + caml_stat_free(hostname); #endif - if (hp == (struct hostent *) NULL) raise_not_found(); + if (hp == (struct hostent *) NULL) caml_raise_not_found(); return alloc_host_entry(hp); } #else CAMLprim value unix_gethostbyaddr(value name) -{ invalid_argument("gethostbyaddr not implemented"); } +{ caml_invalid_argument("gethostbyaddr not implemented"); } CAMLprim value unix_gethostbyname(value name) -{ invalid_argument("gethostbyname not implemented"); } +{ caml_invalid_argument("gethostbyname not implemented"); } #endif diff --git a/otherlibs/unix/gethostname.c b/otherlibs/unix/gethostname.c index b7f88b84..0552a448 100644 --- a/otherlibs/unix/gethostname.c +++ b/otherlibs/unix/gethostname.c @@ -32,7 +32,7 @@ CAMLprim value unix_gethostname(value unit) char name[MAXHOSTNAMELEN]; gethostname(name, MAXHOSTNAMELEN); name[MAXHOSTNAMELEN-1] = 0; - return copy_string(name); + return caml_copy_string(name); } #else @@ -50,7 +50,7 @@ CAMLprim value unix_gethostname(value unit) #else CAMLprim value unix_gethostname(value unit) -{ invalid_argument("gethostname not implemented"); } +{ caml_invalid_argument("gethostname not implemented"); } #endif #endif diff --git a/otherlibs/unix/getlogin.c b/otherlibs/unix/getlogin.c index 9ed4936b..9cbb9518 100644 --- a/otherlibs/unix/getlogin.c +++ b/otherlibs/unix/getlogin.c @@ -25,5 +25,5 @@ CAMLprim value unix_getlogin(value unit) char * name; name = getlogin(); if (name == NULL) unix_error(ENOENT, "getlogin", Nothing); - return copy_string(name); + return caml_copy_string(name); } diff --git a/otherlibs/unix/getnameinfo.c b/otherlibs/unix/getnameinfo.c index 0e6e6c3b..cd2ec336 100644 --- a/otherlibs/unix/getnameinfo.c +++ b/otherlibs/unix/getnameinfo.c @@ -44,16 +44,16 @@ CAMLprim value unix_getnameinfo(value vaddr, value vopts) int opts, retcode; get_sockaddr(vaddr, &addr, &addr_len); - opts = convert_flag_list(vopts, getnameinfo_flag_table); - enter_blocking_section(); + opts = caml_convert_flag_list(vopts, getnameinfo_flag_table); + caml_enter_blocking_section(); retcode = getnameinfo((const struct sockaddr *) &addr.s_gen, addr_len, host, sizeof(host), serv, sizeof(serv), opts); - leave_blocking_section(); - if (retcode != 0) raise_not_found(); /* TODO: detailed error reporting? */ - vhost = copy_string(host); - vserv = copy_string(serv); - vres = alloc_small(2, 0); + caml_leave_blocking_section(); + if (retcode != 0) caml_raise_not_found(); /* TODO: detailed error reporting? */ + vhost = caml_copy_string(host); + vserv = caml_copy_string(serv); + vres = caml_alloc_small(2, 0); Field(vres, 0) = vhost; Field(vres, 1) = vserv; CAMLreturn(vres); @@ -62,6 +62,6 @@ CAMLprim value unix_getnameinfo(value vaddr, value vopts) #else CAMLprim value unix_getnameinfo(value vaddr, value vopts) -{ invalid_argument("getnameinfo not implemented"); } +{ caml_invalid_argument("getnameinfo not implemented"); } #endif diff --git a/otherlibs/unix/getpeername.c b/otherlibs/unix/getpeername.c index 86108c33..9390b55b 100644 --- a/otherlibs/unix/getpeername.c +++ b/otherlibs/unix/getpeername.c @@ -36,6 +36,6 @@ CAMLprim value unix_getpeername(value sock) #else CAMLprim value unix_getpeername(value sock) -{ invalid_argument("getpeername not implemented"); } +{ caml_invalid_argument("getpeername not implemented"); } #endif diff --git a/otherlibs/unix/getproto.c b/otherlibs/unix/getproto.c index c4edcdcc..d50c2d4a 100644 --- a/otherlibs/unix/getproto.c +++ b/otherlibs/unix/getproto.c @@ -31,9 +31,9 @@ static value alloc_proto_entry(struct protoent *entry) value name = Val_unit, aliases = Val_unit; Begin_roots2 (name, aliases); - name = copy_string(entry->p_name); - aliases = copy_string_array((const char**)entry->p_aliases); - res = alloc_small(3, 0); + name = caml_copy_string(entry->p_name); + aliases = caml_copy_string_array((const char**)entry->p_aliases); + res = caml_alloc_small(3, 0); Field(res,0) = name; Field(res,1) = aliases; Field(res,2) = Val_int(entry->p_proto); @@ -44,9 +44,9 @@ static value alloc_proto_entry(struct protoent *entry) CAMLprim value unix_getprotobyname(value name) { struct protoent * entry; - if (! caml_string_is_c_safe(name)) raise_not_found(); + if (! caml_string_is_c_safe(name)) caml_raise_not_found(); entry = getprotobyname(String_val(name)); - if (entry == (struct protoent *) NULL) raise_not_found(); + if (entry == (struct protoent *) NULL) caml_raise_not_found(); return alloc_proto_entry(entry); } @@ -54,16 +54,16 @@ CAMLprim value unix_getprotobynumber(value proto) { struct protoent * entry; entry = getprotobynumber(Int_val(proto)); - if (entry == (struct protoent *) NULL) raise_not_found(); + if (entry == (struct protoent *) NULL) caml_raise_not_found(); return alloc_proto_entry(entry); } #else CAMLprim value unix_getprotobynumber(value proto) -{ invalid_argument("getprotobynumber not implemented"); } +{ caml_invalid_argument("getprotobynumber not implemented"); } CAMLprim value unix_getprotobyname(value name) -{ invalid_argument("getprotobyname not implemented"); } +{ caml_invalid_argument("getprotobyname not implemented"); } #endif diff --git a/otherlibs/unix/getpw.c b/otherlibs/unix/getpw.c index 07dc36b5..b49c23f3 100644 --- a/otherlibs/unix/getpw.c +++ b/otherlibs/unix/getpw.c @@ -27,16 +27,16 @@ static value alloc_passwd_entry(struct passwd *entry) value dir = Val_unit, shell = Val_unit; Begin_roots5 (name, passwd, gecos, dir, shell); - name = copy_string(entry->pw_name); - passwd = copy_string(entry->pw_passwd); + name = caml_copy_string(entry->pw_name); + passwd = caml_copy_string(entry->pw_passwd); #if !defined(__BEOS__) && !defined(__ANDROID__) - gecos = copy_string(entry->pw_gecos); + gecos = caml_copy_string(entry->pw_gecos); #else - gecos = copy_string(""); + gecos = caml_copy_string(""); #endif - dir = copy_string(entry->pw_dir); - shell = copy_string(entry->pw_shell); - res = alloc_small(7, 0); + dir = caml_copy_string(entry->pw_dir); + shell = caml_copy_string(entry->pw_shell); + res = caml_alloc_small(7, 0); Field(res,0) = name; Field(res,1) = passwd; Field(res,2) = Val_int(entry->pw_uid); @@ -51,9 +51,9 @@ static value alloc_passwd_entry(struct passwd *entry) CAMLprim value unix_getpwnam(value name) { struct passwd * entry; - if (! caml_string_is_c_safe(name)) raise_not_found(); + if (! caml_string_is_c_safe(name)) caml_raise_not_found(); entry = getpwnam(String_val(name)); - if (entry == (struct passwd *) NULL) raise_not_found(); + if (entry == (struct passwd *) NULL) caml_raise_not_found(); return alloc_passwd_entry(entry); } @@ -61,6 +61,6 @@ CAMLprim value unix_getpwuid(value uid) { struct passwd * entry; entry = getpwuid(Int_val(uid)); - if (entry == (struct passwd *) NULL) raise_not_found(); + if (entry == (struct passwd *) NULL) caml_raise_not_found(); return alloc_passwd_entry(entry); } diff --git a/otherlibs/unix/getserv.c b/otherlibs/unix/getserv.c index 1ece7900..9edfa879 100644 --- a/otherlibs/unix/getserv.c +++ b/otherlibs/unix/getserv.c @@ -35,10 +35,10 @@ static value alloc_service_entry(struct servent *entry) value name = Val_unit, aliases = Val_unit, proto = Val_unit; Begin_roots3 (name, aliases, proto); - name = copy_string(entry->s_name); - aliases = copy_string_array((const char**)entry->s_aliases); - proto = copy_string(entry->s_proto); - res = alloc_small(4, 0); + name = caml_copy_string(entry->s_name); + aliases = caml_copy_string_array((const char**)entry->s_aliases); + proto = caml_copy_string(entry->s_proto); + res = caml_alloc_small(4, 0); Field(res,0) = name; Field(res,1) = aliases; Field(res,2) = Val_int(ntohs(entry->s_port)); @@ -51,27 +51,27 @@ CAMLprim value unix_getservbyname(value name, value proto) { struct servent * entry; if (! (caml_string_is_c_safe(name) && caml_string_is_c_safe(proto))) - raise_not_found(); + caml_raise_not_found(); entry = getservbyname(String_val(name), String_val(proto)); - if (entry == (struct servent *) NULL) raise_not_found(); + if (entry == (struct servent *) NULL) caml_raise_not_found(); return alloc_service_entry(entry); } CAMLprim value unix_getservbyport(value port, value proto) { struct servent * entry; - if (! caml_string_is_c_safe(proto)) raise_not_found(); + if (! caml_string_is_c_safe(proto)) caml_raise_not_found(); entry = getservbyport(htons(Int_val(port)), String_val(proto)); - if (entry == (struct servent *) NULL) raise_not_found(); + if (entry == (struct servent *) NULL) caml_raise_not_found(); return alloc_service_entry(entry); } #else CAMLprim value unix_getservbyport(value port, value proto) -{ invalid_argument("getservbyport not implemented"); } +{ caml_invalid_argument("getservbyport not implemented"); } CAMLprim value unix_getservbyname(value name, value proto) -{ invalid_argument("getservbyname not implemented"); } +{ caml_invalid_argument("getservbyname not implemented"); } #endif diff --git a/otherlibs/unix/getsockname.c b/otherlibs/unix/getsockname.c index 008da873..3544b25f 100644 --- a/otherlibs/unix/getsockname.c +++ b/otherlibs/unix/getsockname.c @@ -36,6 +36,6 @@ CAMLprim value unix_getsockname(value sock) #else CAMLprim value unix_getsockname(value sock) -{ invalid_argument("getsockname not implemented"); } +{ caml_invalid_argument("getsockname not implemented"); } #endif diff --git a/otherlibs/unix/gettimeofday.c b/otherlibs/unix/gettimeofday.c index 3b8250ad..609a9a82 100644 --- a/otherlibs/unix/gettimeofday.c +++ b/otherlibs/unix/gettimeofday.c @@ -27,12 +27,12 @@ CAMLprim value unix_gettimeofday(value unit) { struct timeval tp; if (gettimeofday(&tp, NULL) == -1) uerror("gettimeofday", Nothing); - return copy_double((double) tp.tv_sec + (double) tp.tv_usec / 1e6); + return caml_copy_double((double) tp.tv_sec + (double) tp.tv_usec / 1e6); } #else CAMLprim value unix_gettimeofday(value unit) -{ invalid_argument("gettimeofday not implemented"); } +{ caml_invalid_argument("gettimeofday not implemented"); } #endif diff --git a/otherlibs/unix/gmtime.c b/otherlibs/unix/gmtime.c index 9ffbbc65..b0c2711a 100644 --- a/otherlibs/unix/gmtime.c +++ b/otherlibs/unix/gmtime.c @@ -24,7 +24,7 @@ static value alloc_tm(struct tm *tm) { value res; - res = alloc_small(9, 0); + res = caml_alloc_small(9, 0); Field(res,0) = Val_int(tm->tm_sec); Field(res,1) = Val_int(tm->tm_min); Field(res,2) = Val_int(tm->tm_hour); @@ -79,8 +79,8 @@ CAMLprim value unix_mktime(value t) clock = mktime(&tm); if (clock == (time_t) -1) unix_error(ERANGE, "mktime", Nothing); tmval = alloc_tm(&tm); - clkval = copy_double((double) clock); - res = alloc_small(2, 0); + clkval = caml_copy_double((double) clock); + res = caml_alloc_small(2, 0); Field(res, 0) = clkval; Field(res, 1) = tmval; End_roots (); @@ -90,6 +90,6 @@ CAMLprim value unix_mktime(value t) #else CAMLprim value unix_mktime(value t) -{ invalid_argument("mktime not implemented"); } +{ caml_invalid_argument("mktime not implemented"); } #endif diff --git a/otherlibs/unix/initgroups.c b/otherlibs/unix/initgroups.c index 48fb532f..77be82f0 100644 --- a/otherlibs/unix/initgroups.c +++ b/otherlibs/unix/initgroups.c @@ -41,6 +41,6 @@ CAMLprim value unix_initgroups(value user, value group) #else CAMLprim value unix_initgroups(value user, value group) -{ invalid_argument("initgroups not implemented"); } +{ caml_invalid_argument("initgroups not implemented"); } #endif diff --git a/otherlibs/unix/itimer.c b/otherlibs/unix/itimer.c index 713a4f34..09993706 100644 --- a/otherlibs/unix/itimer.c +++ b/otherlibs/unix/itimer.c @@ -38,7 +38,7 @@ static void unix_set_timeval(struct timeval * tv, double d) static value unix_convert_itimer(struct itimerval *tp) { #define Get_timeval(tv) (double) tv.tv_sec + (double) tv.tv_usec / 1e6 - value res = alloc_small(Double_wosize * 2, Double_array_tag); + value res = caml_alloc_small(Double_wosize * 2, Double_array_tag); Store_double_field(res, 0, Get_timeval(tp->it_interval)); Store_double_field(res, 1, Get_timeval(tp->it_value)); return res; @@ -68,8 +68,8 @@ CAMLprim value unix_getitimer(value which) #else CAMLprim value unix_setitimer(value which, value newval) -{ invalid_argument("setitimer not implemented"); } +{ caml_invalid_argument("setitimer not implemented"); } CAMLprim value unix_getitimer(value which) -{ invalid_argument("getitimer not implemented"); } +{ caml_invalid_argument("getitimer not implemented"); } #endif diff --git a/otherlibs/unix/kill.c b/otherlibs/unix/kill.c index 7177c18f..d229d3e9 100644 --- a/otherlibs/unix/kill.c +++ b/otherlibs/unix/kill.c @@ -24,7 +24,7 @@ CAMLprim value unix_kill(value pid, value signal) { int sig; - sig = convert_signal_number(Int_val(signal)); + sig = caml_convert_signal_number(Int_val(signal)); if (kill(Int_val(pid), sig) == -1) uerror("kill", Nothing); return Val_unit; diff --git a/otherlibs/unix/listen.c b/otherlibs/unix/listen.c index 40b511b1..f5ac130d 100644 --- a/otherlibs/unix/listen.c +++ b/otherlibs/unix/listen.c @@ -30,6 +30,6 @@ CAMLprim value unix_listen(value sock, value backlog) #else CAMLprim value unix_listen(value sock, value backlog) -{ invalid_argument("listen not implemented"); } +{ caml_invalid_argument("listen not implemented"); } #endif diff --git a/otherlibs/unix/lockf.c b/otherlibs/unix/lockf.c index 130b107a..cdcc4afe 100644 --- a/otherlibs/unix/lockf.c +++ b/otherlibs/unix/lockf.c @@ -46,9 +46,9 @@ CAMLprim value unix_lockf(value fd, value cmd, value span) break; case 1: /* F_LOCK */ l.l_type = F_WRLCK; - enter_blocking_section(); + caml_enter_blocking_section(); ret = fcntl(fildes, F_SETLKW, &l); - leave_blocking_section(); + caml_leave_blocking_section(); break; case 2: /* F_TLOCK */ l.l_type = F_WRLCK; @@ -68,9 +68,9 @@ CAMLprim value unix_lockf(value fd, value cmd, value span) break; case 4: /* F_RLOCK */ l.l_type = F_RDLCK; - enter_blocking_section(); + caml_enter_blocking_section(); ret = fcntl(fildes, F_SETLKW, &l); - leave_blocking_section(); + caml_leave_blocking_section(); break; case 5: /* F_TRLOCK */ l.l_type = F_RDLCK; @@ -110,7 +110,7 @@ CAMLprim value unix_lockf(value fd, value cmd, value span) #else CAMLprim value unix_lockf(value fd, value cmd, value span) -{ invalid_argument("lockf not implemented"); } +{ caml_invalid_argument("lockf not implemented"); } #endif #endif diff --git a/otherlibs/unix/mkfifo.c b/otherlibs/unix/mkfifo.c index eb726ca5..4b97c1c4 100644 --- a/otherlibs/unix/mkfifo.c +++ b/otherlibs/unix/mkfifo.c @@ -66,7 +66,7 @@ CAMLprim value unix_mkfifo(value path, value mode) CAMLprim value unix_mkfifo(value path, value mode) { - invalid_argument("mkfifo not implemented"); + caml_invalid_argument("mkfifo not implemented"); } #endif diff --git a/otherlibs/unix/open.c b/otherlibs/unix/open.c index d1feb6a1..1892d44c 100644 --- a/otherlibs/unix/open.c +++ b/otherlibs/unix/open.c @@ -37,49 +37,51 @@ #ifndef O_RSYNC #define O_RSYNC 0 #endif -#ifndef O_CLOEXEC -#define NEED_CLOEXEC_EMULATION -#define O_CLOEXEC 0 -#endif -static int open_flag_table[14] = { +static int open_flag_table[15] = { O_RDONLY, O_WRONLY, O_RDWR, O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL, O_NOCTTY, O_DSYNC, O_SYNC, O_RSYNC, 0, /* O_SHARE_DELETE, Windows-only */ - O_CLOEXEC + 0, /* O_CLOEXEC, treated specially */ + 0 /* O_KEEPEXEC, treated specially */ }; -#ifdef NEED_CLOEXEC_EMULATION -static int open_cloexec_table[14] = { +enum { CLOEXEC = 1, KEEPEXEC = 2 }; + +static int open_cloexec_table[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1 + CLOEXEC, KEEPEXEC }; -#endif CAMLprim value unix_open(value path, value flags, value perm) { CAMLparam3(path, flags, perm); - int fd, cv_flags; + int fd, cv_flags, clo_flags, cloexec; char * p; caml_unix_check_path(path, "open"); - cv_flags = convert_flag_list(flags, open_flag_table); + cv_flags = caml_convert_flag_list(flags, open_flag_table); + clo_flags = caml_convert_flag_list(flags, open_cloexec_table); + if (clo_flags & CLOEXEC) + cloexec = 1; + else if (clo_flags & KEEPEXEC) + cloexec = 0; + else + cloexec = unix_cloexec_default; +#if defined(O_CLOEXEC) + if (cloexec) cv_flags |= O_CLOEXEC; +#endif p = caml_strdup(String_val(path)); /* open on a named FIFO can block (PR#1533) */ - enter_blocking_section(); + caml_enter_blocking_section(); fd = open(p, cv_flags, Int_val(perm)); - leave_blocking_section(); - stat_free(p); + caml_leave_blocking_section(); + caml_stat_free(p); if (fd == -1) uerror("open", path); -#if defined(NEED_CLOEXEC_EMULATION) && defined(FD_CLOEXEC) - if (convert_flag_list(flags, open_cloexec_table) != 0) { - int flags = fcntl(fd, F_GETFD, 0); - if (flags == -1 || - fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) - uerror("open", path); - } +#if !defined(O_CLOEXEC) + if (cloexec) unix_set_cloexec(fd, "open", path); #endif CAMLreturn (Val_int(fd)); } diff --git a/otherlibs/unix/opendir.c b/otherlibs/unix/opendir.c index 387d108a..067cacc5 100644 --- a/otherlibs/unix/opendir.c +++ b/otherlibs/unix/opendir.c @@ -39,7 +39,7 @@ CAMLprim value unix_opendir(value path) caml_leave_blocking_section(); caml_stat_free(p); if (d == (DIR *) NULL) uerror("opendir", path); - res = alloc_small(1, Abstract_tag); + res = caml_alloc_small(1, Abstract_tag); DIR_Val(res) = d; CAMLreturn(res); } diff --git a/otherlibs/unix/pipe.c b/otherlibs/unix/pipe.c index 315d9042..103f826c 100644 --- a/otherlibs/unix/pipe.c +++ b/otherlibs/unix/pipe.c @@ -13,16 +13,27 @@ /* */ /**************************************************************************/ +#define _GNU_SOURCE #include #include #include "unixsupport.h" +#include -CAMLprim value unix_pipe(value unit) +CAMLprim value unix_pipe(value cloexec, value vunit) { int fd[2]; value res; +#ifdef HAS_PIPE2 + if (pipe2(fd, unix_cloexec_p(cloexec) ? O_CLOEXEC : 0) == -1) + uerror("pipe", Nothing); +#else if (pipe(fd) == -1) uerror("pipe", Nothing); - res = alloc_small(2, 0); + if (unix_cloexec_p(cloexec)) { + unix_set_cloexec(fd[0], "pipe", Nothing); + unix_set_cloexec(fd[1], "pipe", Nothing); + } +#endif + res = caml_alloc_small(2, 0); Field(res, 0) = Val_int(fd[0]); Field(res, 1) = Val_int(fd[1]); return res; diff --git a/otherlibs/unix/putenv.c b/otherlibs/unix/putenv.c index 5e1ff1fe..f5709b69 100644 --- a/otherlibs/unix/putenv.c +++ b/otherlibs/unix/putenv.c @@ -27,8 +27,8 @@ CAMLprim value unix_putenv(value name, value val) { - mlsize_t namelen = string_length(name); - mlsize_t vallen = string_length(val); + mlsize_t namelen = caml_string_length(name); + mlsize_t vallen = caml_string_length(val); char * s; if (! (caml_string_is_c_safe(name) && caml_string_is_c_safe(val))) @@ -48,6 +48,6 @@ CAMLprim value unix_putenv(value name, value val) #else CAMLprim value unix_putenv(value name, value val) -{ invalid_argument("putenv not implemented"); } +{ caml_invalid_argument("putenv not implemented"); } #endif diff --git a/otherlibs/unix/read.c b/otherlibs/unix/read.c index feaa7691..428e49fc 100644 --- a/otherlibs/unix/read.c +++ b/otherlibs/unix/read.c @@ -28,9 +28,9 @@ CAMLprim value unix_read(value fd, value buf, value ofs, value len) Begin_root (buf); numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; - enter_blocking_section(); + caml_enter_blocking_section(); ret = read(Int_val(fd), iobuf, (int) numbytes); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) uerror("read", Nothing); memmove (&Byte(buf, Long_val(ofs)), iobuf, ret); End_roots(); diff --git a/otherlibs/unix/readdir.c b/otherlibs/unix/readdir.c index 6c891de0..d741fc4f 100644 --- a/otherlibs/unix/readdir.c +++ b/otherlibs/unix/readdir.c @@ -37,6 +37,6 @@ CAMLprim value unix_readdir(value vd) caml_enter_blocking_section(); e = readdir((DIR *) d); caml_leave_blocking_section(); - if (e == (directory_entry *) NULL) raise_end_of_file(); - return copy_string(e->d_name); + if (e == (directory_entry *) NULL) caml_raise_end_of_file(); + return caml_copy_string(e->d_name); } diff --git a/otherlibs/unix/readlink.c b/otherlibs/unix/readlink.c index 94a2eb9a..4e9f0453 100644 --- a/otherlibs/unix/readlink.c +++ b/otherlibs/unix/readlink.c @@ -46,12 +46,12 @@ CAMLprim value unix_readlink(value path) caml_stat_free(p); if (len == -1) uerror("readlink", path); buffer[len] = '\0'; - CAMLreturn(copy_string(buffer)); + CAMLreturn(caml_copy_string(buffer)); } #else CAMLprim value unix_readlink(value path) -{ invalid_argument("readlink not implemented"); } +{ caml_invalid_argument("readlink not implemented"); } #endif diff --git a/otherlibs/unix/rewinddir.c b/otherlibs/unix/rewinddir.c index 2ebc1664..e3f889f2 100644 --- a/otherlibs/unix/rewinddir.c +++ b/otherlibs/unix/rewinddir.c @@ -37,6 +37,6 @@ CAMLprim value unix_rewinddir(value vd) #else CAMLprim value unix_rewinddir(value d) -{ invalid_argument("rewinddir not implemented"); } +{ caml_invalid_argument("rewinddir not implemented"); } #endif diff --git a/otherlibs/unix/select.c b/otherlibs/unix/select.c index 1fab0996..aaf3ddc7 100644 --- a/otherlibs/unix/select.c +++ b/otherlibs/unix/select.c @@ -54,7 +54,7 @@ static value fdset_to_fdlist(value fdlist, fd_set *fdset) for (l = fdlist; l != Val_int(0); l = Field(l, 1)) { int fd = Int_val(Field(l, 0)); if (FD_ISSET(fd, fdset)) { - value newres = alloc_small(2, 0); + value newres = caml_alloc_small(2, 0); Field(newres, 0) = Val_int(fd); Field(newres, 1) = res; res = newres; @@ -90,14 +90,14 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, tv.tv_usec = (int) (1e6 * (tm - tv.tv_sec)); tvp = &tv; } - enter_blocking_section(); + caml_enter_blocking_section(); retcode = select(maxfd + 1, &read, &write, &except, tvp); - leave_blocking_section(); + caml_leave_blocking_section(); if (retcode == -1) uerror("select", Nothing); readfds = fdset_to_fdlist(readfds, &read); writefds = fdset_to_fdlist(writefds, &write); exceptfds = fdset_to_fdlist(exceptfds, &except); - res = alloc_small(3, 0); + res = caml_alloc_small(3, 0); Field(res, 0) = readfds; Field(res, 1) = writefds; Field(res, 2) = exceptfds; @@ -109,6 +109,6 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value timeout) -{ invalid_argument("select not implemented"); } +{ caml_invalid_argument("select not implemented"); } #endif diff --git a/otherlibs/unix/sendrecv.c b/otherlibs/unix/sendrecv.c index c4af2b45..4b8e7554 100644 --- a/otherlibs/unix/sendrecv.c +++ b/otherlibs/unix/sendrecv.c @@ -35,13 +35,13 @@ CAMLprim value unix_recv(value sock, value buff, value ofs, value len, long numbytes; char iobuf[UNIX_BUFFER_SIZE]; - cv_flags = convert_flag_list(flags, msg_flag_table); + cv_flags = caml_convert_flag_list(flags, msg_flag_table); Begin_root (buff); numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; - enter_blocking_section(); + caml_enter_blocking_section(); ret = recv(Int_val(sock), iobuf, (int) numbytes, cv_flags); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) uerror("recv", Nothing); memmove (&Byte(buff, Long_val(ofs)), iobuf, ret); End_roots(); @@ -59,19 +59,19 @@ CAMLprim value unix_recvfrom(value sock, value buff, value ofs, value len, union sock_addr_union addr; socklen_param_type addr_len; - cv_flags = convert_flag_list(flags, msg_flag_table); + cv_flags = caml_convert_flag_list(flags, msg_flag_table); Begin_roots2 (buff, adr); numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; addr_len = sizeof(addr); - enter_blocking_section(); + caml_enter_blocking_section(); ret = recvfrom(Int_val(sock), iobuf, (int) numbytes, cv_flags, &addr.s_gen, &addr_len); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) uerror("recvfrom", Nothing); memmove (&Byte(buff, Long_val(ofs)), iobuf, ret); adr = alloc_sockaddr(&addr, addr_len, -1); - res = alloc_small(2, 0); + res = caml_alloc_small(2, 0); Field(res, 0) = Val_int(ret); Field(res, 1) = adr; End_roots(); @@ -85,13 +85,13 @@ CAMLprim value unix_send(value sock, value buff, value ofs, value len, long numbytes; char iobuf[UNIX_BUFFER_SIZE]; - cv_flags = convert_flag_list(flags, msg_flag_table); + cv_flags = caml_convert_flag_list(flags, msg_flag_table); numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; memmove (iobuf, &Byte(buff, Long_val(ofs)), numbytes); - enter_blocking_section(); + caml_enter_blocking_section(); ret = send(Int_val(sock), iobuf, (int) numbytes, cv_flags); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) uerror("send", Nothing); return Val_int(ret); } @@ -105,15 +105,15 @@ CAMLprim value unix_sendto_native(value sock, value buff, value ofs, value len, union sock_addr_union addr; socklen_param_type addr_len; - cv_flags = convert_flag_list(flags, msg_flag_table); + cv_flags = caml_convert_flag_list(flags, msg_flag_table); get_sockaddr(dest, &addr, &addr_len); numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; memmove (iobuf, &Byte(buff, Long_val(ofs)), numbytes); - enter_blocking_section(); + caml_enter_blocking_section(); ret = sendto(Int_val(sock), iobuf, (int) numbytes, cv_flags, &addr.s_gen, addr_len); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) uerror("sendto", Nothing); return Val_int(ret); } @@ -128,21 +128,21 @@ CAMLprim value unix_sendto(value *argv, int argc) CAMLprim value unix_recv(value sock, value buff, value ofs, value len, value flags) -{ invalid_argument("recv not implemented"); } +{ caml_invalid_argument("recv not implemented"); } CAMLprim value unix_recvfrom(value sock, value buff, value ofs, value len, value flags) -{ invalid_argument("recvfrom not implemented"); } +{ caml_invalid_argument("recvfrom not implemented"); } CAMLprim value unix_send(value sock, value buff, value ofs, value len, value flags) -{ invalid_argument("send not implemented"); } +{ caml_invalid_argument("send not implemented"); } CAMLprim value unix_sendto_native(value sock, value buff, value ofs, value len, value flags, value dest) -{ invalid_argument("sendto not implemented"); } +{ caml_invalid_argument("sendto not implemented"); } CAMLprim value unix_sendto(value *argv, int argc) -{ invalid_argument("sendto not implemented"); } +{ caml_invalid_argument("sendto not implemented"); } #endif diff --git a/otherlibs/unix/setgroups.c b/otherlibs/unix/setgroups.c index 91b6bffb..6c63cce0 100644 --- a/otherlibs/unix/setgroups.c +++ b/otherlibs/unix/setgroups.c @@ -40,7 +40,7 @@ CAMLprim value unix_setgroups(value groups) n = setgroups(size, gidset); - stat_free(gidset); + caml_stat_free(gidset); if (n == -1) uerror("setgroups", Nothing); return Val_unit; } @@ -48,6 +48,6 @@ CAMLprim value unix_setgroups(value groups) #else CAMLprim value unix_setgroups(value groups) -{ invalid_argument("setgroups not implemented"); } +{ caml_invalid_argument("setgroups not implemented"); } #endif diff --git a/otherlibs/unix/setsid.c b/otherlibs/unix/setsid.c index 5caa4359..b4449e67 100644 --- a/otherlibs/unix/setsid.c +++ b/otherlibs/unix/setsid.c @@ -25,7 +25,7 @@ CAMLprim value unix_setsid(value unit) #ifdef HAS_SETSID return Val_int(setsid()); #else - invalid_argument("setsid not implemented"); + caml_invalid_argument("setsid not implemented"); return Val_unit; #endif } diff --git a/otherlibs/unix/shutdown.c b/otherlibs/unix/shutdown.c index db7d7ad6..6c0edd37 100644 --- a/otherlibs/unix/shutdown.c +++ b/otherlibs/unix/shutdown.c @@ -35,6 +35,6 @@ CAMLprim value unix_shutdown(value sock, value cmd) #else CAMLprim value unix_shutdown(value sock, value cmd) -{ invalid_argument("shutdown not implemented"); } +{ caml_invalid_argument("shutdown not implemented"); } #endif diff --git a/otherlibs/unix/signals.c b/otherlibs/unix/signals.c index a46e345f..945e7d16 100644 --- a/otherlibs/unix/signals.c +++ b/otherlibs/unix/signals.c @@ -49,7 +49,7 @@ static value encode_sigset(sigset_t * set) Begin_root(res) for (i = 1; i < NSIG; i++) if (sigismember(set, i) > 0) { - value newcons = alloc_small(2, 0); + value newcons = caml_alloc_small(2, 0); Field(newcons, 0) = Val_int(caml_rev_convert_signal_number(i)); Field(newcons, 1) = res; res = newcons; @@ -68,9 +68,9 @@ CAMLprim value unix_sigprocmask(value vaction, value vset) how = sigprocmask_cmd[Int_val(vaction)]; decode_sigset(vset, &set); - enter_blocking_section(); + caml_enter_blocking_section(); retcode = sigprocmask(how, &set, &oldset); - leave_blocking_section(); + caml_leave_blocking_section(); if (retcode == -1) uerror("sigprocmask", Nothing); return encode_sigset(&oldset); } @@ -87,9 +87,9 @@ CAMLprim value unix_sigsuspend(value vset) sigset_t set; int retcode; decode_sigset(vset, &set); - enter_blocking_section(); + caml_enter_blocking_section(); retcode = sigsuspend(&set); - leave_blocking_section(); + caml_leave_blocking_section(); if (retcode == -1 && errno != EINTR) uerror("sigsuspend", Nothing); return Val_unit; } @@ -97,12 +97,12 @@ CAMLprim value unix_sigsuspend(value vset) #else CAMLprim value unix_sigprocmask(value vaction, value vset) -{ invalid_argument("Unix.sigprocmask not available"); } +{ caml_invalid_argument("Unix.sigprocmask not available"); } CAMLprim value unix_sigpending(value unit) -{ invalid_argument("Unix.sigpending not available"); } +{ caml_invalid_argument("Unix.sigpending not available"); } CAMLprim value unix_sigsuspend(value vset) -{ invalid_argument("Unix.sigsuspend not available"); } +{ caml_invalid_argument("Unix.sigsuspend not available"); } #endif diff --git a/otherlibs/unix/sleep.c b/otherlibs/unix/sleep.c index 5f1b6601..54724312 100644 --- a/otherlibs/unix/sleep.c +++ b/otherlibs/unix/sleep.c @@ -35,26 +35,26 @@ CAMLprim value unix_sleep(value duration) { struct timespec t; int ret; - enter_blocking_section(); + caml_enter_blocking_section(); t.tv_sec = (time_t) d; t.tv_nsec = (d - t.tv_sec) * 1e9; do { ret = nanosleep(&t, &t); } while (ret == -1 && errno == EINTR); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) uerror("sleep", Nothing); } #elif defined(HAS_SELECT) { struct timeval t; int ret; - enter_blocking_section(); + caml_enter_blocking_section(); t.tv_sec = (time_t) d; t.tv_usec = (d - t.tv_sec) * 1e6; do { ret = select(0, NULL, NULL, NULL, &t); } while (ret == -1 && errno == EINTR); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) uerror("sleep", Nothing); } #else @@ -62,9 +62,9 @@ CAMLprim value unix_sleep(value duration) We cannot reliably iterate until sleep() returns 0, because the remaining time returned by sleep() is generally rounded up. */ { - enter_blocking_section(); + caml_enter_blocking_section(); sleep ((unsigned int) d); - leave_blocking_section(); + caml_leave_blocking_section(); } #endif return Val_unit; diff --git a/otherlibs/unix/socket.c b/otherlibs/unix/socket.c index 667381ed..5166ed13 100644 --- a/otherlibs/unix/socket.c +++ b/otherlibs/unix/socket.c @@ -13,6 +13,7 @@ /* */ /**************************************************************************/ +#define _GNU_SOURCE #include #include #include "unixsupport.h" @@ -37,20 +38,28 @@ int socket_type_table[] = { SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET }; -CAMLprim value unix_socket(value domain, value type, value proto) +CAMLprim value unix_socket(value cloexec, value domain, + value type, value proto) { int retcode; + int ty = socket_type_table[Int_val(type)]; +#ifdef SOCK_CLOEXEC + if (unix_cloexec_p(cloexec)) ty |= SOCK_CLOEXEC; +#endif retcode = socket(socket_domain_table[Int_val(domain)], - socket_type_table[Int_val(type)], - Int_val(proto)); + ty, Int_val(proto)); if (retcode == -1) uerror("socket", Nothing); +#ifndef SOCK_CLOEXEC + if (unix_cloexec_p(cloexec)) + unix_set_cloexec(retcode, "socket", Nothing); +#endif return Val_int(retcode); - } #else -CAMLprim value unix_socket(value domain, value type, value proto) -{ invalid_argument("socket not implemented"); } +CAMLprim value unix_socket(value cloexec, value domain, + value type,value proto) +{ caml_invalid_argument("socket not implemented"); } #endif diff --git a/otherlibs/unix/socketaddr.c b/otherlibs/unix/socketaddr.c index cbdfa37f..5f64021f 100644 --- a/otherlibs/unix/socketaddr.c +++ b/otherlibs/unix/socketaddr.c @@ -35,7 +35,7 @@ CAMLexport value alloc_inet_addr(struct in_addr * a) /* Use a string rather than an abstract block so that it can be marshaled safely. Remember that a is in network byte order, hence is marshaled in an endian-independent manner. */ - res = alloc_string(4); + res = caml_alloc_string(4); memcpy(String_val(res), a, 4); return res; } @@ -45,7 +45,7 @@ CAMLexport value alloc_inet_addr(struct in_addr * a) CAMLexport value alloc_inet6_addr(struct in6_addr * a) { value res; - res = alloc_string(16); + res = caml_alloc_string(16); memcpy(String_val(res), a, 16); return res; } @@ -62,7 +62,7 @@ void get_sockaddr(value mladr, { value path; mlsize_t len; path = Field(mladr, 0); - len = string_length(path); + len = caml_string_length(path); adr->s_unix.sun_family = AF_UNIX; if (len >= sizeof(adr->s_unix.sun_path)) { unix_error(ENAMETOOLONG, "", path); @@ -80,7 +80,7 @@ void get_sockaddr(value mladr, #endif case 1: /* ADDR_INET */ #ifdef HAS_IPV6 - if (string_length(Field(mladr, 0)) == 16) { + if (caml_string_length(Field(mladr, 0)) == 16) { memset(&adr->s_inet6, 0, sizeof(struct sockaddr_in6)); adr->s_inet6.sin6_family = AF_INET6; adr->s_inet6.sin6_addr = GET_INET6_ADDR(Field(mladr, 0)); @@ -111,16 +111,16 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/, switch(adr->s_gen.sa_family) { #ifndef _WIN32 case AF_UNIX: - { char * path; - value n; - /* PR#7039: harden against unnamed sockets */ - if (adr_len > (char *)&(adr->s_unix.sun_path) - (char *)&(adr->s_unix)) - path = adr->s_unix.sun_path; - else - path = ""; - n = copy_string(path); + { value n; + /* Based on recommendation in section BUGS of Linux unix(7). See + http://man7.org/linux/man-pages/man7/unix.7.html */ + mlsize_t path_length = + strnlen(adr->s_unix.sun_path, + adr_len - offsetof(struct sockaddr_un, sun_path)); + n = caml_alloc_string(path_length); + memmove(String_val(n), adr->s_unix.sun_path, path_length); Begin_root (n); - res = alloc_small(1, 0); + res = caml_alloc_small(1, 0); Field(res,0) = n; End_roots(); break; @@ -129,7 +129,7 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/, case AF_INET: { value a = alloc_inet_addr(&adr->s_inet.sin_addr); Begin_root (a); - res = alloc_small(2, 1); + res = caml_alloc_small(2, 1); Field(res,0) = a; Field(res,1) = Val_int(ntohs(adr->s_inet.sin_port)); End_roots(); @@ -139,7 +139,7 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/, case AF_INET6: { value a = alloc_inet6_addr(&adr->s_inet6.sin6_addr); Begin_root (a); - res = alloc_small(2, 1); + res = caml_alloc_small(2, 1); Field(res,0) = a; Field(res,1) = Val_int(ntohs(adr->s_inet6.sin6_port)); End_roots(); diff --git a/otherlibs/unix/socketpair.c b/otherlibs/unix/socketpair.c index 4c7b0543..15cc82b2 100644 --- a/otherlibs/unix/socketpair.c +++ b/otherlibs/unix/socketpair.c @@ -24,15 +24,25 @@ extern int socket_domain_table[], socket_type_table[]; -CAMLprim value unix_socketpair(value domain, value type, value proto) +CAMLprim value unix_socketpair(value cloexec, value domain, + value type, value proto) { int sv[2]; value res; + int ty = socket_type_table[Int_val(type)]; +#ifdef SOCK_CLOEXEC + if (unix_cloexec_p(cloexec)) ty |= SOCK_CLOEXEC; +#endif if (socketpair(socket_domain_table[Int_val(domain)], - socket_type_table[Int_val(type)], - Int_val(proto), sv) == -1) + ty, Int_val(proto), sv) == -1) uerror("socketpair", Nothing); - res = alloc_small(2, 0); +#ifndef SOCK_CLOEXEC + if (unix_cloexec_p(cloexec)) { + unix_set_cloexec(sv[0], "socketpair", Nothing); + unix_set_cloexec(sv[1], "socketpair", Nothing); + } +#endif + res = caml_alloc_small(2, 0); Field(res,0) = Val_int(sv[0]); Field(res,1) = Val_int(sv[1]); return res; @@ -41,6 +51,6 @@ CAMLprim value unix_socketpair(value domain, value type, value proto) #else CAMLprim value unix_socketpair(value domain, value type, value proto) -{ invalid_argument("socketpair not implemented"); } +{ caml_invalid_argument("socketpair not implemented"); } #endif diff --git a/otherlibs/unix/sockopt.c b/otherlibs/unix/sockopt.c index e254987a..d2961d09 100644 --- a/otherlibs/unix/sockopt.c +++ b/otherlibs/unix/sockopt.c @@ -203,12 +203,12 @@ unix_getsockopt_aux(char * name, if (optval.lg.l_onoff == 0) { return Val_int(0); /* None */ } else { - value res = alloc_small(1, 0); /* Some */ + value res = caml_alloc_small(1, 0); /* Some */ Field(res, 0) = Val_int(optval.lg.l_linger); return res; } case TYPE_TIMEVAL: - return copy_double((double) optval.tv.tv_sec + return caml_copy_double((double) optval.tv.tv_sec + (double) optval.tv.tv_usec / 1e6); case TYPE_UNIX_ERROR: if (optval.i == 0) { @@ -217,7 +217,7 @@ unix_getsockopt_aux(char * name, value err, res; err = unix_error_of_code(optval.i); Begin_root(err); - res = alloc_small(1, 0); /* Some */ + res = caml_alloc_small(1, 0); /* Some */ Field(res, 0) = err; End_roots(); return res; @@ -293,9 +293,9 @@ CAMLprim value unix_setsockopt(value vty, value vsocket, value voption, #else CAMLprim value unix_getsockopt(value vty, value socket, value option) -{ invalid_argument("getsockopt not implemented"); } +{ caml_invalid_argument("getsockopt not implemented"); } CAMLprim value unix_setsockopt(value vty, value socket, value option, value val) -{ invalid_argument("setsockopt not implemented"); } +{ caml_invalid_argument("setsockopt not implemented"); } #endif diff --git a/otherlibs/unix/stat.c b/otherlibs/unix/stat.c index 6cde064e..cd62dd0b 100644 --- a/otherlibs/unix/stat.c +++ b/otherlibs/unix/stat.c @@ -61,7 +61,7 @@ static value stat_aux(int use_64, struct stat *buf) + (NSEC(buf, c) / 1000000000.0)); #undef NSEC offset = use_64 ? Val_file_offset(buf->st_size) : Val_int (buf->st_size); - v = alloc_small(12, 0); + v = caml_alloc_small(12, 0); Field (v, 0) = Val_int (buf->st_dev); Field (v, 1) = Val_int (buf->st_ino); Field (v, 2) = cst_to_constr(buf->st_mode & S_IFMT, file_kind_table, diff --git a/otherlibs/unix/strofaddr.c b/otherlibs/unix/strofaddr.c index 7e2b2309..45675ad0 100644 --- a/otherlibs/unix/strofaddr.c +++ b/otherlibs/unix/strofaddr.c @@ -31,7 +31,7 @@ CAMLprim value unix_string_of_inet_addr(value a) union sock_addr_union sa; int len; int retcode; - if (string_length(a) == 16) { + if (caml_string_length(a) == 16) { memset(&sa.s_inet6, 0, sizeof(struct sockaddr_in6)); sa.s_inet6.sin6_family = AF_INET6; sa.s_inet6.sin6_addr = GET_INET6_ADDR(a); @@ -50,7 +50,7 @@ CAMLprim value unix_string_of_inet_addr(value a) res = buffer; #else char buffer[64]; - if (string_length(a) == 16) + if (caml_string_length(a) == 16) res = (char *) inet_ntop(AF_INET6, (const void *) &GET_INET6_ADDR(a), buffer, sizeof(buffer)); @@ -63,12 +63,12 @@ CAMLprim value unix_string_of_inet_addr(value a) res = inet_ntoa(GET_INET_ADDR(a)); #endif if (res == NULL) uerror("string_of_inet_addr", Nothing); - return copy_string(res); + return caml_copy_string(res); } #else CAMLprim value unix_string_of_inet_addr(value a) -{ invalid_argument("string_of_inet_addr not implemented"); } +{ caml_invalid_argument("string_of_inet_addr not implemented"); } #endif diff --git a/otherlibs/unix/symlink.c b/otherlibs/unix/symlink.c index 72f9c21c..0bff3f6d 100644 --- a/otherlibs/unix/symlink.c +++ b/otherlibs/unix/symlink.c @@ -50,7 +50,7 @@ CAMLprim value unix_has_symlink(value unit) #else CAMLprim value unix_symlink(value to_dir, value path1, value path2) -{ invalid_argument("symlink not implemented"); } +{ caml_invalid_argument("symlink not implemented"); } CAMLprim value unix_has_symlink(value unit) { diff --git a/otherlibs/unix/termios.c b/otherlibs/unix/termios.c index ff3592af..b6a221ff 100644 --- a/otherlibs/unix/termios.c +++ b/otherlibs/unix/termios.c @@ -303,7 +303,7 @@ CAMLprim value unix_tcgetattr(value fd) if (tcgetattr(Int_val(fd), &terminal_status) == -1) uerror("tcgetattr", Nothing); - res = alloc_tuple(NFIELDS); + res = caml_alloc_tuple(NFIELDS); encode_terminal_status(&Field(res, 0)); return res; } @@ -333,7 +333,7 @@ CAMLprim value unix_tcsendbreak(value fd, value delay) #if defined(__ANDROID__) CAMLprim value unix_tcdrain(value fd) -{ invalid_argument("tcdrain not implemented"); } +{ caml_invalid_argument("tcdrain not implemented"); } #else CAMLprim value unix_tcdrain(value fd) { @@ -367,21 +367,21 @@ CAMLprim value unix_tcflow(value fd, value action) #else CAMLprim value unix_tcgetattr(value fd) -{ invalid_argument("tcgetattr not implemented"); } +{ caml_invalid_argument("tcgetattr not implemented"); } CAMLprim value unix_tcsetattr(value fd, value when, value arg) -{ invalid_argument("tcsetattr not implemented"); } +{ caml_invalid_argument("tcsetattr not implemented"); } CAMLprim value unix_tcsendbreak(value fd, value delay) -{ invalid_argument("tcsendbreak not implemented"); } +{ caml_invalid_argument("tcsendbreak not implemented"); } CAMLprim value unix_tcdrain(value fd) -{ invalid_argument("tcdrain not implemented"); } +{ caml_invalid_argument("tcdrain not implemented"); } CAMLprim value unix_tcflush(value fd, value queue) -{ invalid_argument("tcflush not implemented"); } +{ caml_invalid_argument("tcflush not implemented"); } CAMLprim value unix_tcflow(value fd, value action) -{ invalid_argument("tcflow not implemented"); } +{ caml_invalid_argument("tcflow not implemented"); } #endif diff --git a/otherlibs/unix/time.c b/otherlibs/unix/time.c index f14fc86a..f7916c99 100644 --- a/otherlibs/unix/time.c +++ b/otherlibs/unix/time.c @@ -20,5 +20,5 @@ CAMLprim value unix_time(value unit) { - return copy_double((double) time((time_t *) NULL)); + return caml_copy_double((double) time((time_t *) NULL)); } diff --git a/otherlibs/unix/times.c b/otherlibs/unix/times.c index 91ce67d7..7ad3f59a 100644 --- a/otherlibs/unix/times.c +++ b/otherlibs/unix/times.c @@ -40,7 +40,7 @@ CAMLprim value unix_times(value unit) value res; struct rusage ru; - res = alloc_small(4 * Double_wosize, Double_array_tag); + res = caml_alloc_small(4 * Double_wosize, Double_array_tag); getrusage (RUSAGE_SELF, &ru); Store_double_field (res, 0, ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6); @@ -56,7 +56,7 @@ CAMLprim value unix_times(value unit) struct tms buffer; times(&buffer); - res = alloc_small(4 * Double_wosize, Double_array_tag); + res = caml_alloc_small(4 * Double_wosize, Double_array_tag); Store_double_field(res, 0, (double) buffer.tms_utime / CLK_TCK); Store_double_field(res, 1, (double) buffer.tms_stime / CLK_TCK); Store_double_field(res, 2, (double) buffer.tms_cutime / CLK_TCK); diff --git a/otherlibs/unix/truncate.c b/otherlibs/unix/truncate.c index d2c6f125..4f333cbd 100644 --- a/otherlibs/unix/truncate.c +++ b/otherlibs/unix/truncate.c @@ -64,9 +64,9 @@ CAMLprim value unix_truncate_64(value path, value vlen) #else CAMLprim value unix_truncate(value path, value len) -{ invalid_argument("truncate not implemented"); } +{ caml_invalid_argument("truncate not implemented"); } CAMLprim value unix_truncate_64(value path, value len) -{ invalid_argument("truncate not implemented"); } +{ caml_invalid_argument("truncate not implemented"); } #endif diff --git a/otherlibs/unix/unix.ml b/otherlibs/unix/unix.ml index 420ee027..fa7f90d1 100644 --- a/otherlibs/unix/unix.ml +++ b/otherlibs/unix/unix.ml @@ -187,6 +187,7 @@ let handle_unix_error f arg = external environment : unit -> string array = "unix_environment" external getenv: string -> string = "caml_sys_getenv" +(* external unsafe_getenv: string -> string = "caml_sys_unsafe_getenv" *) external putenv: string -> string -> unit = "unix_putenv" type process_status = @@ -231,6 +232,7 @@ type open_flag = | O_RSYNC | O_SHARE_DELETE | O_CLOEXEC + | O_KEEPEXEC type file_perm = int @@ -354,18 +356,14 @@ external fchown : file_descr -> int -> int -> unit = "unix_fchown" external umask : int -> int = "unix_umask" external access : string -> access_permission list -> unit = "unix_access" -external dup : file_descr -> file_descr = "unix_dup" -external dup2 : file_descr -> file_descr -> unit = "unix_dup2" +external dup : ?cloexec: bool -> file_descr -> file_descr = "unix_dup" +external dup2 : + ?cloexec: bool -> file_descr -> file_descr -> unit = "unix_dup2" external set_nonblock : file_descr -> unit = "unix_set_nonblock" external clear_nonblock : file_descr -> unit = "unix_clear_nonblock" external set_close_on_exec : file_descr -> unit = "unix_set_close_on_exec" external clear_close_on_exec : file_descr -> unit = "unix_clear_close_on_exec" -(* FD_CLOEXEC should be supported on all Unix systems these days, - but just in case... *) -let try_set_close_on_exec fd = - try set_close_on_exec fd; true with Invalid_argument _ -> false - external mkdir : string -> file_perm -> unit = "unix_mkdir" external rmdir : string -> unit = "unix_rmdir" external chdir : string -> unit = "unix_chdir" @@ -379,7 +377,8 @@ external readdir : dir_handle -> string = "unix_readdir" external rewinddir : dir_handle -> unit = "unix_rewinddir" external closedir : dir_handle -> unit = "unix_closedir" -external pipe : unit -> file_descr * file_descr = "unix_pipe" +external pipe : + ?cloexec: bool -> unit -> file_descr * file_descr = "unix_pipe" external symlink : ?to_dir:bool -> string -> string -> unit = "unix_symlink" external has_symlink : unit -> bool = "unix_has_symlink" external readlink : string -> string = "unix_readlink" @@ -526,12 +525,15 @@ type msg_flag = | MSG_DONTROUTE | MSG_PEEK -external socket : socket_domain -> socket_type -> int -> file_descr - = "unix_socket" +external socket : + ?cloexec: bool -> socket_domain -> socket_type -> int -> file_descr + = "unix_socket" external socketpair : - socket_domain -> socket_type -> int -> file_descr * file_descr - = "unix_socketpair" -external accept : file_descr -> file_descr * sockaddr = "unix_accept" + ?cloexec: bool -> socket_domain -> socket_type -> int -> + file_descr * file_descr + = "unix_socketpair" +external accept : + ?cloexec: bool -> file_descr -> file_descr * sockaddr = "unix_accept" external bind : file_descr -> sockaddr -> unit = "unix_bind" external connect : file_descr -> sockaddr -> unit = "unix_connect" external listen : file_descr -> int -> unit = "unix_listen" @@ -873,29 +875,34 @@ let system cmd = end | id -> snd(waitpid_non_intr id) -let rec safe_dup fd = - let new_fd = dup fd in - if new_fd >= 3 then - new_fd - else begin - let res = safe_dup fd in - close new_fd; - res - end +(* Duplicate [fd] if needed to make sure it isn't one of the + standard descriptors (stdin, stdout, stderr). + Note that this function always leaves the standard descriptors open, + the caller must take care of closing them if needed. + The "cloexec" mode doesn't matter, because + the descriptor returned by [dup] will be closed before the [exec], + and because no other thread is running concurrently + (we are in the child process of a fork). + *) +let rec file_descr_not_standard fd = + if fd >= 3 then fd else file_descr_not_standard (dup fd) let safe_close fd = try close fd with Unix_error(_,_,_) -> () let perform_redirections new_stdin new_stdout new_stderr = - let newnewstdin = safe_dup new_stdin in - let newnewstdout = safe_dup new_stdout in - let newnewstderr = safe_dup new_stderr in + let new_stdin = file_descr_not_standard new_stdin in + let new_stdout = file_descr_not_standard new_stdout in + let new_stderr = file_descr_not_standard new_stderr in + (* The three dup2 close the original stdin, stdout, stderr, + which are the descriptors possibly left open + by file_descr_not_standard *) + dup2 ~cloexec:false new_stdin stdin; + dup2 ~cloexec:false new_stdout stdout; + dup2 ~cloexec:false new_stderr stderr; safe_close new_stdin; safe_close new_stdout; - safe_close new_stderr; - dup2 newnewstdin stdin; close newnewstdin; - dup2 newnewstdout stdout; close newnewstdout; - dup2 newnewstderr stderr; close newnewstderr + safe_close new_stderr let create_process cmd args new_stdin new_stdout new_stderr = match fork() with @@ -927,24 +934,26 @@ type popen_process = let popen_processes = (Hashtbl.create 7 : (popen_process, int) Hashtbl.t) -let open_proc cmd proc input output toclose = - let cloexec = List.for_all try_set_close_on_exec toclose in - match fork() with - 0 -> begin try - if input <> stdin then begin dup2 input stdin; close input end; - if output <> stdout then begin dup2 output stdout; close output end; - if not cloexec then List.iter close toclose; - execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |] - with _ -> sys_exit 127 +let open_proc cmd envopt proc input output error = + match fork() with + 0 -> perform_redirections input output error; + let shell = "/bin/sh" in + let argv = [| shell; "-c"; cmd |] in + begin try + match envopt with + | Some env -> execve shell argv env + | None -> execv shell argv + with _ -> + sys_exit 127 end - | id -> Hashtbl.add popen_processes proc id + | id -> Hashtbl.add popen_processes proc id let open_process_in cmd = - let (in_read, in_write) = pipe() in + let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in begin try - open_proc cmd (Process_in inchan) stdin in_write [in_read]; + open_proc cmd None (Process_in inchan) stdin in_write stderr with e -> close_in inchan; close in_write; @@ -954,69 +963,64 @@ let open_process_in cmd = inchan let open_process_out cmd = - let (out_read, out_write) = pipe() in + let (out_read, out_write) = pipe ~cloexec:true () in let outchan = out_channel_of_descr out_write in begin try - open_proc cmd (Process_out outchan) out_read stdout [out_write]; + open_proc cmd None (Process_out outchan) out_read stdout stderr with e -> - close_out outchan; - close out_read; - raise e + close_out outchan; + close out_read; + raise e end; close out_read; outchan let open_process cmd = - let (in_read, in_write) = pipe() in - let fds_to_close = ref [in_read;in_write] in - try - let (out_read, out_write) = pipe() in - fds_to_close := [in_read;in_write;out_read;out_write]; - let inchan = in_channel_of_descr in_read in - let outchan = out_channel_of_descr out_write in - open_proc cmd (Process(inchan, outchan)) out_read in_write - [in_read; out_write]; - close out_read; - close in_write; - (inchan, outchan) - with e -> - List.iter close !fds_to_close; - raise e - -let open_proc_full cmd env proc input output error toclose = - let cloexec = List.for_all try_set_close_on_exec toclose in - match fork() with - 0 -> begin try - dup2 input stdin; close input; - dup2 output stdout; close output; - dup2 error stderr; close error; - if not cloexec then List.iter close toclose; - execve "/bin/sh" [| "/bin/sh"; "-c"; cmd |] env - with _ -> sys_exit 127 - end - | id -> Hashtbl.add popen_processes proc id + let (in_read, in_write) = pipe ~cloexec:true () in + let (out_read, out_write) = + try pipe ~cloexec:true () + with e -> close in_read; close in_write; raise e in + let inchan = in_channel_of_descr in_read in + let outchan = out_channel_of_descr out_write in + begin + try + open_proc cmd None (Process(inchan, outchan)) out_read in_write stderr + with e -> + close out_read; close out_write; + close in_read; close in_write; + raise e + end; + close out_read; + close in_write; + (inchan, outchan) let open_process_full cmd env = - let (in_read, in_write) = pipe() in - let fds_to_close = ref [in_read;in_write] in - try - let (out_read, out_write) = pipe() in - fds_to_close := out_read::out_write:: !fds_to_close; - let (err_read, err_write) = pipe() in - fds_to_close := err_read::err_write:: !fds_to_close; - let inchan = in_channel_of_descr in_read in - let outchan = out_channel_of_descr out_write in - let errchan = in_channel_of_descr err_read in - open_proc_full cmd env (Process_full(inchan, outchan, errchan)) - out_read in_write err_write [in_read; out_write; err_read]; - close out_read; - close in_write; - close err_write; - (inchan, outchan, errchan) - with e -> - List.iter close !fds_to_close; - raise e + let (in_read, in_write) = pipe ~cloexec:true () in + let (out_read, out_write) = + try pipe ~cloexec:true () + with e -> close in_read; close in_write; raise e in + let (err_read, err_write) = + try pipe ~cloexec:true () + with e -> close in_read; close in_write; + close out_read; close out_write; raise e in + let inchan = in_channel_of_descr in_read in + let outchan = out_channel_of_descr out_write in + let errchan = in_channel_of_descr err_read in + begin + try + open_proc cmd (Some env) (Process_full(inchan, outchan, errchan)) + out_read in_write err_write + with e -> + close out_read; close out_write; + close in_read; close in_write; + close err_read; close err_write; + raise e + end; + close out_read; + close in_write; + close err_write; + (inchan, outchan, errchan) let find_proc_id fun_name proc = try @@ -1033,7 +1037,9 @@ let close_process_in inchan = let close_process_out outchan = let pid = find_proc_id "close_process_out" (Process_out outchan) in - close_out outchan; + (* The application may have closed [outchan] already to signal + end-of-input to the process. *) + begin try close_out outchan with Sys_error _ -> () end; snd(waitpid_non_intr pid) let close_process (inchan, outchan) = @@ -1055,10 +1061,9 @@ let close_process_full (inchan, outchan, errchan) = let open_connection sockaddr = let sock = - socket (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in + socket ~cloexec:true (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in try connect sock sockaddr; - ignore(try_set_close_on_exec sock); (in_channel_of_descr sock, out_channel_of_descr sock) with exn -> close sock; raise exn @@ -1067,12 +1072,12 @@ let shutdown_connection inchan = shutdown (descr_of_in_channel inchan) SHUTDOWN_SEND let rec accept_non_intr s = - try accept s + try accept ~cloexec:true s with Unix_error (EINTR, _, _) -> accept_non_intr s let establish_server server_fun sockaddr = let sock = - socket (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in + socket ~cloexec:true (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in setsockopt sock SO_REUSEADDR true; bind sock sockaddr; listen sock 5; @@ -1084,7 +1089,6 @@ let establish_server server_fun sockaddr = 0 -> if fork() <> 0 then sys_exit 0; (* The son exits, the grandson works *) close sock; - ignore(try_set_close_on_exec s); let inchan = in_channel_of_descr s in let outchan = out_channel_of_descr s in server_fun inchan outchan; diff --git a/otherlibs/unix/unix.mli b/otherlibs/unix/unix.mli index abb570e6..e414be00 100644 --- a/otherlibs/unix/unix.mli +++ b/otherlibs/unix/unix.mli @@ -15,8 +15,8 @@ (** Interface to the Unix system. - Note: all the functions of this module (except [error_message] and - [handle_unix_error]) are liable to raise the [Unix_error] + Note: all the functions of this module (except {!error_message} and + {!handle_unix_error}) are liable to raise the {!Unix_error} exception whenever the underlying system call signals an error. *) @@ -112,7 +112,7 @@ val error_message : error -> string val handle_unix_error : ('a -> 'b) -> 'a -> 'b (** [handle_unix_error f x] applies [f] to [x] and returns the result. - If the exception [Unix_error] is raised, it prints a message + If the exception {!Unix_error} is raised, it prints a message describing the error and exits with code 2. *) @@ -124,11 +124,27 @@ val environment : unit -> string array with the format ``variable=value''. *) val getenv : string -> string +(** Return the value associated to a variable in the process + environment, unless the process has special privileges. + @raise Not_found if the variable is unbound or the process has + special privileges. + + (This function is identical to {!Sys.getenv}. *) + +(* +val unsafe_getenv : string -> string (** Return the value associated to a variable in the process environment. - @raise Not_found if the variable is unbound. - (This function is identical to {!Sys.getenv}.) *) + Unlike {!getenv}, this function returns the value even if the + process has special privileges. It is considered unsafe because the + programmer of a setuid or setgid program must be careful to avoid + using maliciously crafted environment variables in the search path + for executables, the locations for temporary files or logs, and the + like. + + @raise Not_found if the variable is unbound. *) +*) val putenv : string -> string -> unit (** [Unix.putenv name value] sets the value associated to a @@ -262,7 +278,11 @@ type open_flag = | O_SHARE_DELETE (** Windows only: allow the file to be deleted while still open *) | O_CLOEXEC (** Set the close-on-exec flag on the - descriptor returned by {!openfile} *) + descriptor returned by {!openfile}. + See {!set_close_on_exec} for more + information. *) + | O_KEEPEXEC (** Clear the close-on-exec flag. + This is currently the default. *) (** The flags to {!Unix.openfile}. *) @@ -297,11 +317,13 @@ val single_write : file_descr -> bytes -> int -> int -> int val write_substring : file_descr -> string -> int -> int -> int (** Same as [write], but take the data from a string instead of a byte - sequence. *) + sequence. + @since 4.02.0 *) val single_write_substring : file_descr -> string -> int -> int -> int (** Same as [single_write], but take the data from a string instead of - a byte sequence. *) + a byte sequence. + @since 4.02.0 *) (** {6 Interfacing with the standard input/output library} *) @@ -459,12 +481,18 @@ module LargeFile : regular integers (type [int]), thus allowing operating on files whose sizes are greater than [max_int]. *) - (** {6 Operations on file names} *) val unlink : string -> unit -(** Removes the named file. *) +(** Removes the named file. + + If the named file is a directory, raises: + {ul + {- [EPERM] on POSIX compliant system} + {- [EISDIR] on Linux >= 2.1.132} + {- [EACCESS] on Windows}} +*) val rename : string -> string -> unit (** [rename old new] changes the name of a file from [old] to [new]. *) @@ -516,13 +544,17 @@ val access : string -> access_permission list -> unit (** {6 Operations on file descriptors} *) -val dup : file_descr -> file_descr +val dup : ?cloexec:bool -> file_descr -> file_descr (** Return a new file descriptor referencing the same file as - the given descriptor. *) + the given descriptor. + See {!set_close_on_exec} for documentation on the [cloexec] + optional argument. *) -val dup2 : file_descr -> file_descr -> unit +val dup2 : ?cloexec:bool -> file_descr -> file_descr -> unit (** [dup2 fd1 fd2] duplicates [fd1] to [fd2], closing [fd2] if already - opened. *) + opened. + See {!set_close_on_exec} for documentation on the [cloexec] + optional argument. *) val set_nonblock : file_descr -> unit (** Set the ``non-blocking'' flag on the given descriptor. @@ -540,7 +572,48 @@ val set_close_on_exec : file_descr -> unit (** Set the ``close-on-exec'' flag on the given descriptor. A descriptor with the close-on-exec flag is automatically closed when the current process starts another program with - one of the [exec] functions. *) + one of the [exec], [create_process] and [open_process] functions. + + It is often a security hole to leak file descriptors opened on, say, + a private file to an external program: the program, then, gets access + to the private file and can do bad things with it. Hence, it is + highly recommended to set all file descriptors ``close-on-exec'', + except in the very few cases where a file descriptor actually needs + to be transmitted to another program. + + The best way to set a file descriptor ``close-on-exec'' is to create + it in this state. To this end, the [openfile] function has + [O_CLOEXEC] and [O_KEEPEXEC] flags to enforce ``close-on-exec'' mode + or ``keep-on-exec'' mode, respectively. All other operations in + the Unix module that create file descriptors have an optional + argument [?cloexec:bool] to indicate whether the file descriptor + should be created in ``close-on-exec'' mode (by writing + [~cloexec:true]) or in ``keep-on-exec'' mode (by writing + [~cloexec:false]). For historical reasons, the default file + descriptor creation mode is ``keep-on-exec'', if no [cloexec] optional + argument is given. This is not a safe default, hence it is highly + recommended to pass explicit [cloexec] arguments to operations that + create file descriptors. + + The [cloexec] optional arguments and the [O_KEEPEXEC] flag were introduced + in OCaml 4.05. Earlier, the common practice was to create file descriptors + in the default, ``keep-on-exec'' mode, then call [set_close_on_exec] + on those freshly-created file descriptors. This is not as safe as + creating the file descriptor in ``close-on-exec'' mode because, in + multithreaded programs, a window of vulnerability exists between the time + when the file descriptor is created and the time [set_close_on_exec] + completes. If another thread spawns another program during this window, + the descriptor will leak, as it is still in the ``keep-on-exec'' mode. + + Regarding the atomicity guarantees given by [~cloexec:true] or by + the use of the [O_CLOEXEC] flag: on all platforms it is guaranteed + that a concurrently-executing Caml thread cannot leak the descriptor + by starting a new process. On Linux, this guarantee extends to + concurrently-executing C threads. As of Feb 2017, other operating + systems lack the necessary system calls and still expose a window + of vulnerability during which a C thread can see the newly-created + file descriptor in ``keep-on-exec'' mode. + *) val clear_close_on_exec : file_descr -> unit (** Clear the ``close-on-exec'' flag on the given descriptor. @@ -587,10 +660,12 @@ val closedir : dir_handle -> unit (** {6 Pipes and redirections} *) -val pipe : unit -> file_descr * file_descr +val pipe : ?cloexec:bool -> unit -> file_descr * file_descr (** Create a pipe. The first component of the result is opened for reading, that's the exit to the pipe. The second component is - opened for writing, that's the entrance to the pipe. *) + opened for writing, that's the entrance to the pipe. + See {!set_close_on_exec} for documentation on the [cloexec] + optional argument. *) val mkfifo : string -> file_perm -> unit (** Create a named pipe with the given permissions (see {!umask}). @@ -683,7 +758,7 @@ val symlink : ?to_dir:bool -> string -> string -> unit points to a directory or a file; if omitted, [symlink] examines [source] using [stat] and picks appropriately, if [source] does not exist then [false] is assumed (for this reason, it is recommended that the [~to_dir] parameter - be specified in new code). On Unix, [~to_dir] ignored. + be specified in new code). On Unix, [~to_dir] is ignored. Windows symbolic links are available in Windows Vista onwards. There are some important differences between Windows symlinks and their POSIX counterparts. @@ -713,7 +788,8 @@ val has_symlink : unit -> bool (** Returns [true] if the user is able to create symbolic links. On Windows, this indicates that the user not only has the SeCreateSymbolicLinkPrivilege but is also running elevated, if necessary. On other platforms, this is - simply indicates that the symlink system call is available. *) + simply indicates that the symlink system call is available. + @since 4.03.0 *) val readlink : string -> string (** Read the contents of a symbolic link. *) @@ -772,7 +848,14 @@ val lockf : file_descr -> lock_command -> int -> unit the specified region. Finally, the [F_TEST] command tests whether a write lock can be acquired on the specified region, without actually putting a lock. - It returns immediately if successful, or fails otherwise. *) + It returns immediately if successful, or fails otherwise. + + What happens when a process tries to lock a region of a file that is + already locked by the same process depends on the OS. On POSIX-compliant + systems, the second lock operation succeeds and may "promote" the older + lock from read lock to write lock. On Windows, the second lock + operation will block or fail. +*) (** {6 Signals} @@ -782,7 +865,7 @@ val lockf : file_descr -> lock_command -> int -> unit val kill : int -> int -> unit (** [kill pid sig] sends signal number [sig] to the process - with id [pid]. On Windows, only the [Sys.sigkill] signal + with id [pid]. On Windows, only the {!Sys.sigkill} signal is emulated. *) type sigprocmask_command = @@ -854,11 +937,14 @@ val gettimeofday : unit -> float val gmtime : float -> tm (** Convert a time in seconds, as returned by {!Unix.time}, into a date and - a time. Assumes UTC (Coordinated Universal Time), also known as GMT. *) + a time. Assumes UTC (Coordinated Universal Time), also known as GMT. + To perform the inverse conversion, set the TZ environment variable + to "UTC", use {!mktime}, and then restore the original value of TZ. *) val localtime : float -> tm (** Convert a time in seconds, as returned by {!Unix.time}, into a date and - a time. Assumes the local time zone. *) + a time. Assumes the local time zone. + The function performing the inverse conversion is {!mktime}. *) val mktime : tm -> float * tm (** Convert a date and time, specified by the [tm] argument, into @@ -1088,22 +1174,30 @@ type sockaddr = domain; [addr] is the Internet address of the machine, and [port] is the port number. *) -val socket : socket_domain -> socket_type -> int -> file_descr +val socket : + ?cloexec:bool -> socket_domain -> socket_type -> int -> file_descr (** Create a new socket in the given domain, and with the given kind. The third argument is the protocol type; 0 selects - the default protocol for that kind of sockets. *) + the default protocol for that kind of sockets. + See {!set_close_on_exec} for documentation on the [cloexec] + optional argument. *) val domain_of_sockaddr: sockaddr -> socket_domain (** Return the socket domain adequate for the given socket address. *) val socketpair : - socket_domain -> socket_type -> int -> file_descr * file_descr -(** Create a pair of unnamed sockets, connected together. *) + ?cloexec:bool -> socket_domain -> socket_type -> int -> + file_descr * file_descr +(** Create a pair of unnamed sockets, connected together. + See {!set_close_on_exec} for documentation on the [cloexec] + optional argument. *) -val accept : file_descr -> file_descr * sockaddr +val accept : ?cloexec:bool -> file_descr -> file_descr * sockaddr (** Accept connections on the given socket. The returned descriptor is a socket connected to the client; the returned address is - the address of the connecting client. *) + the address of the connecting client. + See {!set_close_on_exec} for documentation on the [cloexec] + optional argument. *) val bind : file_descr -> sockaddr -> unit (** Bind a socket to an address. *) @@ -1154,7 +1248,8 @@ val send : file_descr -> bytes -> int -> int -> msg_flag list -> int val send_substring : file_descr -> string -> int -> int -> msg_flag list -> int (** Same as [send], but take the data from a string instead of a byte - sequence. *) + sequence. + @since 4.02.0 *) val sendto : file_descr -> bytes -> int -> int -> msg_flag list -> sockaddr -> int @@ -1163,7 +1258,8 @@ val sendto : val sendto_substring : file_descr -> string -> int -> int -> msg_flag list -> sockaddr -> int (** Same as [sendto], but take the data from a string instead of a - byte sequence. *) + byte sequence. + @since 4.02.0 *) (** {6 Socket options} *) diff --git a/otherlibs/unix/unixLabels.mli b/otherlibs/unix/unixLabels.mli index b3f67164..f1e68061 100644 --- a/otherlibs/unix/unixLabels.mli +++ b/otherlibs/unix/unixLabels.mli @@ -126,6 +126,21 @@ val getenv : string -> string environment. Raise [Not_found] if the variable is unbound. (This function is identical to [Sys.getenv].) *) +(* +val unsafe_getenv : string -> string +(** Return the value associated to a variable in the process + environment. + + Unlike {!getenv}, this function returns the value even if the + process has special privileges. It is considered unsafe because the + programmer of a setuid or setgid program must be careful to avoid + using maliciously crafted environment variables in the search path + for executables, the locations for temporary files or logs, and the + like. + + @raise Not_found if the variable is unbound. *) +*) + val putenv : string -> string -> unit (** [Unix.putenv name value] sets the value associated to a variable in the process environment. @@ -248,6 +263,8 @@ type open_flag = Unix.open_flag = while still open *) | O_CLOEXEC (** Set the close-on-exec flag on the descriptor returned by {!openfile} *) + | O_KEEPEXEC (** Clear the close-on-exec flag. + This is currently the default. *) (** The flags to {!UnixLabels.openfile}. *) @@ -282,12 +299,14 @@ val single_write : file_descr -> buf:bytes -> pos:int -> len:int -> int val write_substring : file_descr -> buf:string -> pos:int -> len:int -> int (** Same as [write], but take the data from a string instead of a byte - sequence. *) + sequence. + @since 4.02.0 *) val single_write_substring : file_descr -> buf:string -> pos:int -> len:int -> int (** Same as [single_write], but take the data from a string instead of - a byte sequence. *) + a byte sequence. + @since 4.02.0 *) (** {6 Interfacing with the standard input/output library} *) @@ -461,11 +480,11 @@ val access : string -> perm:access_permission list -> unit (** {6 Operations on file descriptors} *) -val dup : file_descr -> file_descr +val dup : ?cloexec:bool -> file_descr -> file_descr (** Return a new file descriptor referencing the same file as the given descriptor. *) -val dup2 : src:file_descr -> dst:file_descr -> unit +val dup2 : ?cloexec:bool -> src:file_descr -> dst:file_descr -> unit (** [dup2 fd1 fd2] duplicates [fd1] to [fd2], closing [fd2] if already opened. *) @@ -531,7 +550,7 @@ val closedir : dir_handle -> unit (** {6 Pipes and redirections} *) -val pipe : unit -> file_descr * file_descr +val pipe : ?cloexec:bool -> unit -> file_descr * file_descr (** Create a pipe. The first component of the result is opened for reading, that's the exit to the pipe. The second component is opened for writing, that's the entrance to the pipe. *) @@ -628,7 +647,8 @@ val has_symlink : unit -> bool (** Returns [true] if the user is able to create symbolic links. On Windows, this indicates that the user not only has the SeCreateSymbolicLinkPrivilege but is also running elevated, if necessary. On other platforms, this is - simply indicates that the symlink system call is available. *) + simply indicates that the symlink system call is available. + @since 4.03.0 *) val readlink : string -> string (** Read the contents of a link. *) @@ -961,7 +981,8 @@ type sockaddr = Unix.sockaddr = [port] is the port number. *) val socket : - domain:socket_domain -> kind:socket_type -> protocol:int -> file_descr + ?cloexec:bool -> domain:socket_domain -> kind:socket_type -> protocol:int -> + file_descr (** Create a new socket in the given domain, and with the given kind. The third argument is the protocol type; 0 selects the default protocol for that kind of sockets. *) @@ -970,11 +991,11 @@ val domain_of_sockaddr: sockaddr -> socket_domain (** Return the socket domain adequate for the given socket address. *) val socketpair : - domain:socket_domain -> kind:socket_type -> protocol:int -> + ?cloexec:bool -> domain:socket_domain -> kind:socket_type -> protocol:int -> file_descr * file_descr (** Create a pair of unnamed sockets, connected together. *) -val accept : file_descr -> file_descr * sockaddr +val accept : ?cloexec:bool -> file_descr -> file_descr * sockaddr (** Accept connections on the given socket. The returned descriptor is a socket connected to the client; the returned address is the address of the connecting client. *) @@ -1032,7 +1053,8 @@ val send : val send_substring : file_descr -> buf:string -> pos:int -> len:int -> mode:msg_flag list -> int (** Same as [send], but take the data from a string instead of a byte - sequence. *) + sequence. + @since 4.02.0 *) val sendto : file_descr -> buf:bytes -> pos:int -> len:int -> mode:msg_flag list -> @@ -1040,10 +1062,11 @@ val sendto : (** Send data over an unconnected socket. *) val sendto_substring : - file_descr -> bug:string -> pos:int -> len:int -> mode:msg_flag list + file_descr -> buf:string -> pos:int -> len:int -> mode:msg_flag list -> sockaddr -> int (** Same as [sendto], but take the data from a string instead of a - byte sequence. *) + byte sequence. + @since 4.02.0 *) diff --git a/otherlibs/unix/unixsupport.c b/otherlibs/unix/unixsupport.c index 6280c100..b3ff8a4b 100644 --- a/otherlibs/unix/unixsupport.c +++ b/otherlibs/unix/unixsupport.c @@ -21,6 +21,10 @@ #include "unixsupport.h" #include "cst2constr.h" #include +#ifdef HAS_UNISTD +#include +#endif +#include #ifndef E2BIG #define E2BIG (-1) @@ -264,7 +268,7 @@ value unix_error_of_code (int errcode) errconstr = cst_to_constr(errcode, error_table, sizeof(error_table)/sizeof(int), -1); if (errconstr == Val_int(-1)) { - err = alloc_small(1, 0); + err = caml_alloc_small(1, 0); Field(err, 0) = Val_int(errcode); } else { err = errconstr; @@ -287,22 +291,22 @@ void unix_error(int errcode, char *cmdname, value cmdarg) value name = Val_unit, err = Val_unit, arg = Val_unit; Begin_roots3 (name, err, arg); - arg = cmdarg == Nothing ? copy_string("") : cmdarg; - name = copy_string(cmdname); + arg = cmdarg == Nothing ? caml_copy_string("") : cmdarg; + name = caml_copy_string(cmdname); err = unix_error_of_code (errcode); if (unix_error_exn == NULL) { unix_error_exn = caml_named_value("Unix.Unix_error"); if (unix_error_exn == NULL) - invalid_argument("Exception Unix.Unix_error not initialized," + caml_invalid_argument("Exception Unix.Unix_error not initialized," " please link unix.cma"); } - res = alloc_small(4, 0); + res = caml_alloc_small(4, 0); Field(res, 0) = *unix_error_exn; Field(res, 1) = err; Field(res, 2) = name; Field(res, 3) = arg; End_roots(); - mlraise(res); + caml_raise(res); } void uerror(char *cmdname, value cmdarg) @@ -314,3 +318,30 @@ void caml_unix_check_path(value path, char * cmdname) { if (! caml_string_is_c_safe(path)) unix_error(ENOENT, cmdname, path); } + +int unix_cloexec_default = 0; + +int unix_cloexec_p(value cloexec) +{ + /* [cloexec] is a [bool option]. */ + if (Is_block(cloexec)) + return Bool_val(Field(cloexec, 0)); + else + return unix_cloexec_default; +} + +void unix_set_cloexec(int fd, char *cmdname, value cmdarg) +{ + int flags = fcntl(fd, F_GETFD, 0); + if (flags == -1 || + fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + uerror(cmdname, cmdarg); +} + +void unix_clear_cloexec(int fd, char *cmdname, value cmdarg) +{ + int flags = fcntl(fd, F_GETFD, 0); + if (flags == -1 || + fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) == -1) + uerror(cmdname, cmdarg); +} diff --git a/otherlibs/unix/unixsupport.h b/otherlibs/unix/unixsupport.h index a615f7ae..41698e64 100644 --- a/otherlibs/unix/unixsupport.h +++ b/otherlibs/unix/unixsupport.h @@ -45,6 +45,11 @@ extern void caml_unix_check_path(value path, char * cmdname); extern char ** cstringvect(value arg, char * cmdname); +extern int unix_cloexec_default; +extern int unix_cloexec_p(value cloexec); +extern void unix_set_cloexec(int fd, char * cmdname, value arg); +extern void unix_clear_cloexec(int fd, char * cmdname, value arg); + #ifdef __cplusplus } #endif diff --git a/otherlibs/unix/utimes.c b/otherlibs/unix/utimes.c index f5efd7d1..f60fbbce 100644 --- a/otherlibs/unix/utimes.c +++ b/otherlibs/unix/utimes.c @@ -90,6 +90,6 @@ CAMLprim value unix_utimes(value path, value atime, value mtime) #else CAMLprim value unix_utimes(value path, value atime, value mtime) -{ invalid_argument("utimes not implemented"); } +{ caml_invalid_argument("utimes not implemented"); } #endif diff --git a/otherlibs/unix/wait.c b/otherlibs/unix/wait.c index fee298f2..448b3f31 100644 --- a/otherlibs/unix/wait.c +++ b/otherlibs/unix/wait.c @@ -44,19 +44,19 @@ static value alloc_process_status(int pid, int status) value st, res; if (WIFEXITED(status)) { - st = alloc_small(1, TAG_WEXITED); + st = caml_alloc_small(1, TAG_WEXITED); Field(st, 0) = Val_int(WEXITSTATUS(status)); } else if (WIFSTOPPED(status)) { - st = alloc_small(1, TAG_WSTOPPED); + st = caml_alloc_small(1, TAG_WSTOPPED); Field(st, 0) = Val_int(caml_rev_convert_signal_number(WSTOPSIG(status))); } else { - st = alloc_small(1, TAG_WSIGNALED); + st = caml_alloc_small(1, TAG_WSIGNALED); Field(st, 0) = Val_int(caml_rev_convert_signal_number(WTERMSIG(status))); } Begin_root (st); - res = alloc_small(2, 0); + res = caml_alloc_small(2, 0); Field(res, 0) = Val_int(pid); Field(res, 1) = st; End_roots(); @@ -67,9 +67,9 @@ CAMLprim value unix_wait(value unit) { int pid, status; - enter_blocking_section(); + caml_enter_blocking_section(); pid = wait(&status); - leave_blocking_section(); + caml_leave_blocking_section(); if (pid == -1) uerror("wait", Nothing); return alloc_process_status(pid, status); } @@ -88,10 +88,10 @@ CAMLprim value unix_waitpid(value flags, value pid_req) { int pid, status, cv_flags; - cv_flags = convert_flag_list(flags, wait_flag_table); - enter_blocking_section(); + cv_flags = caml_convert_flag_list(flags, wait_flag_table); + caml_enter_blocking_section(); pid = waitpid(Int_val(pid_req), &status, cv_flags); - leave_blocking_section(); + caml_leave_blocking_section(); if (pid == -1) uerror("waitpid", Nothing); return alloc_process_status(pid, status); } @@ -99,6 +99,6 @@ CAMLprim value unix_waitpid(value flags, value pid_req) #else CAMLprim value unix_waitpid(value flags, value pid_req) -{ invalid_argument("waitpid not implemented"); } +{ caml_invalid_argument("waitpid not implemented"); } #endif diff --git a/otherlibs/unix/write.c b/otherlibs/unix/write.c index 0d12d48a..8d5b6a87 100644 --- a/otherlibs/unix/write.c +++ b/otherlibs/unix/write.c @@ -40,9 +40,9 @@ CAMLprim value unix_write(value fd, value buf, value vofs, value vlen) while (len > 0) { numbytes = len > UNIX_BUFFER_SIZE ? UNIX_BUFFER_SIZE : len; memmove (iobuf, &Byte(buf, ofs), numbytes); - enter_blocking_section(); + caml_enter_blocking_section(); ret = write(Int_val(fd), iobuf, numbytes); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) { if ((errno == EAGAIN || errno == EWOULDBLOCK) && written > 0) break; uerror("write", Nothing); @@ -76,9 +76,9 @@ CAMLprim value unix_single_write(value fd, value buf, value vofs, value vlen) if (len > 0) { numbytes = len > UNIX_BUFFER_SIZE ? UNIX_BUFFER_SIZE : len; memmove (iobuf, &Byte(buf, ofs), numbytes); - enter_blocking_section(); + caml_enter_blocking_section(); ret = write(Int_val(fd), iobuf, numbytes); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) uerror("single_write", Nothing); } End_roots(); diff --git a/otherlibs/num/Makefile.shared b/otherlibs/win32graph/Makefile similarity index 62% rename from otherlibs/num/Makefile.shared rename to otherlibs/win32graph/Makefile index 1487786e..244820ba 100644 --- a/otherlibs/num/Makefile.shared +++ b/otherlibs/win32graph/Makefile @@ -4,7 +4,7 @@ #* * #* Xavier Leroy, projet Cristal, INRIA Rocquencourt * #* * -#* Copyright 1999 Institut National de Recherche en Informatique et * +#* Copyright 2001 Institut National de Recherche en Informatique et * #* en Automatique. * #* * #* All rights reserved. This file is distributed under the terms of * @@ -13,25 +13,26 @@ #* * #************************************************************************** -# Makefile for the "num" (exact rational arithmetic) library - -LIBNAME=nums -EXTRACFLAGS=-DBNG_ARCH_$(BNG_ARCH) -DBNG_ASM_LEVEL=$(BNG_ASM_LEVEL) -CAMLOBJS=int_misc.cmo nat.cmo big_int.cmo arith_flags.cmo \ - ratio.cmo num.cmo arith_status.cmo -CMIFILES=big_int.cmi nat.cmi num.cmi ratio.cmi arith_status.cmi -COBJS=bng.$(O) nat_stubs.$(O) +LIBNAME=graphics +COBJS=open.$(O) draw.$(O) events.$(O) +CAMLOBJS=graphics.cmo +WIN32LIBS=$(call SYSLIB,kernel32) $(call SYSLIB,gdi32) $(call SYSLIB,user32) +LINKOPTS=-cclib "\"$(WIN32LIBS)\"" +LDOPTS=-ldopt "$(WIN32LIBS)" include ../Makefile -clean:: - rm -f *~ - -bng.$(O): bng.h bng_digit.c \ - bng_amd64.c bng_ia32.c bng_ppc.c bng_sparc.c +graphics.ml: ../graph/graphics.ml + cp ../graph/graphics.ml graphics.ml +graphics.mli: ../graph/graphics.mli + cp ../graph/graphics.mli graphics.mli depend: - $(CC) -MM $(CFLAGS) *.c > .depend - $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend -include .depend +graphics.cmo: graphics.cmi +graphics.cmx: graphics.cmi +draw.$(O): libgraph.h +open.$(O): libgraph.h + +clean:: partialclean + rm -f graphics.ml graphics.mli diff --git a/otherlibs/win32graph/Makefile.nt b/otherlibs/win32graph/Makefile.nt index e9917ae9..39ad54ae 100644 --- a/otherlibs/win32graph/Makefile.nt +++ b/otherlibs/win32graph/Makefile.nt @@ -13,26 +13,4 @@ #* * #************************************************************************** -LIBNAME=graphics -COBJS=open.$(O) draw.$(O) events.$(O) dib.$(O) -CAMLOBJS=graphics.cmo -WIN32LIBS=$(call SYSLIB,kernel32) $(call SYSLIB,gdi32) $(call SYSLIB,user32) -LINKOPTS=-cclib "\"$(WIN32LIBS)\"" -LDOPTS=-ldopt "$(WIN32LIBS)" - -include ../Makefile - -graphics.ml: ../graph/graphics.ml - cp ../graph/graphics.ml graphics.ml -graphics.mli: ../graph/graphics.mli - cp ../graph/graphics.mli graphics.mli - -depend: - -graphics.cmo: graphics.cmi -graphics.cmx: graphics.cmi -draw.$(O): libgraph.h -open.$(O): libgraph.h - -clean:: partialclean - rm -f graphics.ml graphics.mli +include Makefile diff --git a/otherlibs/win32graph/dib.c b/otherlibs/win32graph/dib.c deleted file mode 100644 index f980869f..00000000 --- a/otherlibs/win32graph/dib.c +++ /dev/null @@ -1,499 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Developed by Jacob Navia */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -//----------------------------------------------------------------------------- -// DIB.C -// -// This is a collection of useful DIB manipulation/information gathering -// functions. Many functions are supplied simply to take the burden -// of taking into account whether a DIB is a Win30 style or OS/2 style -// DIB away from the application. -// -// The functions in this module assume that the DIB pointers or handles -// passed to them point to a block of memory in one of two formats: -// -// a) BITMAPINFOHEADER + color table + DIB bits (3.0 style DIB) -// b) BITMAPCOREHEADER + color table + DIB bits (OS/2 PM style) -// -// The SDK Reference, Volume 2 describes these data structures. -// -// A number of functions in this module were lifted from SHOWDIB, -// and modified to handle OS/2 DIBs. -// -// The functions in this module could be streamlined (made faster and -// smaller) by removing the OS/2 DIB specific code, and assuming all -// DIBs passed to it are Win30 style DIBs. The DIB file reading code -// would need to be modified to always convert DIBs to Win30 style -// DIBs. The only reason this isn't done in DIBView is because DIBView -// was written to test display and printer drivers (which are supposed -// to support OS/2 DIBs wherever they support Win30 style DIBs). SHOWDIB -// is a great example of how to go about doing this. -//----------------------------------------------------------------------------- - - -#include -#include -#include -#include -#include - // Size of window extra bytes (we store a handle to a PALINFO structure). - -#define PAL_CBWNDEXTRA (1 * sizeof (WORD)) - - -typedef struct - { - HPALETTE hPal; // Handle to palette being displayed. - WORD wEntries; // # of entries in the palette. - int nSquareSize; // Size of palette square (see PAL_SIZE) - HWND hInfoWnd; // Handle to the info bar window. - int nRows, nCols; // # of Rows/Columns in window. - int cxSquare, cySquare; // Pixel width/height of palette square. - WORD wEntry; // Currently selected palette square. - } PALINFO, FAR *LPPALINFO; - // Window Words. -#define WW_PAL_HPALINFO 0 // Handle to PALINFO structure. - // The following define is for CopyPaletteChangingFlags(). -#define DONT_CHANGE_FLAGS -1 - // The following is the palette version that goes in a - // LOGPALETTE's palVersion field. -#define PALVERSION 0x300 -// This is an enumeration for the various ways we can display -// a palette in PaletteWndProc(). -enum PAL_SIZE - { - PALSIZE_TINY = 0, - PALSIZE_SMALL, - PALSIZE_MEDIUM, - PALSIZE_LARGE - }; -#define CopyPalette(hPal) CopyPaletteChangingFlags (hPal, DONT_CHANGE_FLAGS) -#define CopyPalForAnimation(hPal) CopyPaletteChangingFlags (hPal, PC_RESERVED) -// WIDTHBYTES takes # of bits in a scan line and rounds up to nearest -// word. -#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) - - // Given a pointer to a DIB header, return TRUE if is a Windows 3.0 style - // DIB, false if otherwise (PM style DIB). -#define IS_WIN30_DIB(lpbi) ((*(LPDWORD) (lpbi)) == sizeof (BITMAPINFOHEADER)) - -static WORD PaletteSize (LPSTR lpbi); - -extern void ShowDbgMsg(char *); -static BOOL MyRead (int, LPSTR, DWORD); -/*-------------- DIB header Marker Define -------------------------*/ -#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B') -/*-------------- MyRead Function Define ---------------------------*/ - -// When we read in a DIB, we read it in in chunks. We read half a segment -// at a time. This way we insure that we don't cross any segment -// boundries in _lread() during a read. We don't read in a full segment -// at a time, since _lread takes some "int" type parms instead of -// WORD type params (it'd work, but the compiler would give you warnings)... - -#define BYTES_PER_READ 32767 - -/*-------------- Define for PM DIB -------------------------------*/ -// The constants for RGB, RLE4, RLE8 are already defined inside -// of Windows.h - -#define BI_PM 3L - - -/*-------------- Magic numbers -------------------------------------*/ -// Maximum length of a filename for DOS is 128 characters. - -#define MAX_FILENAME 129 - - -/*-------------- TypeDef Structures -------------------------------*/ - -typedef struct InfoStruct - { - char szName[13]; - char szType[15]; - DWORD cbWidth; - DWORD cbHeight; - DWORD cbColors; - char szCompress[5]; - } INFOSTRUCT; - -// Some macros. -#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left) -#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top) -//--------------------------------------------------------------------- -// -// Function: FindDIBBits -// -// Purpose: Given a pointer to a DIB, returns a pointer to the -// DIB's bitmap bits. -// -// Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER -// or BITMAPCOREHEADER) -// -// History: Date Reason -// 6/01/91 Created -// -//--------------------------------------------------------------------- -static LPSTR FindDIBBits (LPSTR lpbi) -{ - return (lpbi + *(LPDWORD)lpbi + PaletteSize (lpbi)); -} - - -//--------------------------------------------------------------------- -// -// Function: DIBNumColors -// -// Purpose: Given a pointer to a DIB, returns a number of colors in -// the DIB's color table. -// -// Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER -// or BITMAPCOREHEADER) -// -// History: Date Reason -// 6/01/91 Created -// -//--------------------------------------------------------------------- -static WORD DIBNumColors (LPSTR lpbi) -{ - WORD wBitCount; - - - // If this is a Windows style DIB, the number of colors in the - // color table can be less than the number of bits per pixel - // allows for (i.e. lpbi->biClrUsed can be set to some value). - // If this is the case, return the appropriate value. - - if (IS_WIN30_DIB (lpbi)) - { - DWORD dwClrUsed; - - dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed; - - if (dwClrUsed) - return (WORD) dwClrUsed; - } - - - // Calculate the number of colors in the color table based on - // the number of bits per pixel for the DIB. - - if (IS_WIN30_DIB (lpbi)) - wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount; - else - wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount; - - switch (wBitCount) - { - case 1: - return 2; - - case 4: - return 16; - - case 8: - return 256; - - default: - return 0; - } -} - -//--------------------------------------------------------------------- -// -// Function: PaletteSize -// -// Purpose: Given a pointer to a DIB, returns number of bytes -// in the DIB's color table. -// -// Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER -// or BITMAPCOREHEADER) -// -// History: Date Reason -// 6/01/91 Created -// -//--------------------------------------------------------------------- -static WORD PaletteSize (LPSTR lpbi) -{ - if (IS_WIN30_DIB (lpbi)) - return (DIBNumColors (lpbi) * sizeof (RGBQUAD)); - else - return (DIBNumColors (lpbi) * sizeof (RGBTRIPLE)); -} - -//--------------------------------------------------------------------- -// -// Function: DIBHeight -// -// Purpose: Given a pointer to a DIB, returns its height. Note -// that it returns a DWORD (since a Win30 DIB can have -// a DWORD in its height field), but under Win30, the -// high order word isn't used! -// -// Parms: lpDIB == pointer to DIB header (either BITMAPINFOHEADER -// or BITMAPCOREHEADER) -// -// History: Date Reason -// 6/01/91 Created -// -//--------------------------------------------------------------------- -static DWORD DIBHeight (LPSTR lpDIB) -{ - LPBITMAPINFOHEADER lpbmi; - LPBITMAPCOREHEADER lpbmc; - - lpbmi = (LPBITMAPINFOHEADER) lpDIB; - lpbmc = (LPBITMAPCOREHEADER) lpDIB; - - if (lpbmi->biSize == sizeof (BITMAPINFOHEADER)) - return lpbmi->biHeight; - else - return (DWORD) lpbmc->bcHeight; -} - -/************************************************************************* - - Function: ReadDIBFile (int) - - Purpose: Reads in the specified DIB file into a global chunk of - memory. - - Returns: A handle to a dib (hDIB) if successful. - NULL if an error occurs. - - Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything - from the end of the BITMAPFILEHEADER structure on is - returned in the global memory handle. - - History: Date Author Reason - - 6/1/91 Created - 6/27/91 Removed PM bitmap conversion routines. - 6/31/91 Removed logic which overallocated memory - (to account for bad display drivers). - 11/08/91 Again removed logic which overallocated - memory (it had creeped back in!) - -*************************************************************************/ -static HANDLE ReadDIBFile (int hFile,int dwBitsSize) -{ - BITMAPFILEHEADER bmfHeader; - HANDLE hDIB; - LPSTR pDIB; - - - - // Go read the DIB file header and check if it's valid. - - if ((_lread (hFile, (LPSTR) &bmfHeader, sizeof (bmfHeader)) - != sizeof (bmfHeader)) - || (bmfHeader.bfType != DIB_HEADER_MARKER)) - { - // ShowDbgMsg("Not a DIB file!"); - return NULL; - } - - // Allocate memory for DIB - - hDIB = GlobalAlloc (GMEM_SHARE|GMEM_MOVEABLE | GMEM_ZEROINIT, - dwBitsSize - sizeof(BITMAPFILEHEADER)); - - if (hDIB == 0) - { - // ShowDbgMsg("Couldn't allocate memory!"); - return NULL; - } - - pDIB = GlobalLock (hDIB); - - // Go read the bits. - - if (!MyRead (hFile, pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER))) - { - GlobalUnlock (hDIB); - GlobalFree (hDIB); - // ShowDbgMsg("Error reading file!"); - return NULL; - } - - - GlobalUnlock (hDIB); - return hDIB; -} - -/************************************************************************* - - Function: MyRead (int, LPSTR, DWORD) - - Purpose: Routine to read files greater than 64K in size. - - Returns: TRUE if successful. - FALSE if an error occurs. - - Comments: - - History: Date Reason - - 6/1/91 Created - -*************************************************************************/ -static BOOL MyRead (int hFile, LPSTR lpBuffer, DWORD dwSize) -{ - char *lpInBuf = (char *) lpBuffer; - int nBytes; - - - while (dwSize) - { - nBytes = (int) (dwSize > (DWORD) BYTES_PER_READ ? BYTES_PER_READ : - LOWORD (dwSize)); - - if (_lread (hFile, (LPSTR) lpInBuf, nBytes) != (WORD) nBytes) - return FALSE; - - dwSize -= nBytes; - lpInBuf += nBytes; - } - - return TRUE; -} - -//--------------------------------------------------------------------- -// -// Function: DIBPaint -// -// Purpose: Painting routine for a DIB. Calls StretchDIBits() or -// SetDIBitsToDevice() to paint the DIB. The DIB is -// output to the specified DC, at the coordinates given -// in lpDCRect. The area of the DIB to be output is -// given by lpDIBRect. The specified palette is used. -// -// Parms: hDC == DC to do output to. -// lpDCRect == Rectangle on DC to do output to. -// hDIB == Handle to global memory with a DIB spec -// in it (either a BITMAPINFO or BITMAPCOREINFO -// followed by the DIB bits). -// lpDIBRect == Rect of DIB to output into lpDCRect. -// hPal == Palette to be used. -// -// History: Date Reason -// 6/01/91 Created -// -//--------------------------------------------------------------------- -static void DIBPaint (HDC hDC,LPRECT lpDCRect,HANDLE hDIB) -{ - LPSTR lpDIBHdr, lpDIBBits; - - if (!hDIB) - return; - // Lock down the DIB, and get a pointer to the beginning of the bit - // buffer. - lpDIBHdr = GlobalLock (hDIB); - lpDIBBits = FindDIBBits (lpDIBHdr); - // Make sure to use the stretching mode best for color pictures. - SetStretchBltMode (hDC, COLORONCOLOR); - SetDIBitsToDevice (hDC, // hDC - lpDCRect->left, // DestX - lpDCRect->top, // DestY - RECTWIDTH (lpDCRect), // nDestWidth - RECTHEIGHT (lpDCRect), // nDestHeight - 0, // SrcX - 0, - // (int) DIBHeight (lpDIBHdr), // SrcY - 0, // nStartScan - (WORD) DIBHeight (lpDIBHdr), // nNumScans - lpDIBBits, // lpBits - (LPBITMAPINFO) lpDIBHdr, // lpBitsInfo - DIB_RGB_COLORS); // wUsage - - GlobalUnlock (hDIB); -} - -static unsigned int Getfilesize(char *name) -{ - FILE *f; - unsigned int size; - - f = fopen(name,"rb"); - if (f == NULL) - return 0; - fseek(f,0,SEEK_END); - size = ftell(f); - fclose(f); - return size; -} - - -HANDLE ChargerBitmap(char *FileName,POINT *lppt) -{ - HFILE hFile; - OFSTRUCT ofstruct; - HANDLE result; - LPSTR lpDIBHdr; - unsigned int size; - - size = Getfilesize(FileName); - hFile=OpenFile((LPSTR) FileName, &ofstruct, - OF_READ | OF_SHARE_DENY_WRITE); - result = ReadDIBFile(hFile,size); - if (hFile) _lclose(hFile); - if (result) { - LPBITMAPINFOHEADER lpbmi; - LPBITMAPCOREHEADER lpbmc; - - lpDIBHdr = GlobalLock (result); - lpbmi = (LPBITMAPINFOHEADER) lpDIBHdr; - lpbmc = (LPBITMAPCOREHEADER) lpDIBHdr; - - if (lpbmi->biSize == sizeof (BITMAPINFOHEADER)) { - lppt->y = lpbmi->biHeight; - lppt->x = lpbmi->biWidth; - } - else { - lppt->y = lpbmc->bcHeight; - lppt->x = lpbmc->bcWidth; - } - GlobalUnlock(result); - } - return(result); -} - -void DessinerBitmap(HANDLE hDIB,HDC hDC,LPRECT lpDCRect) -{ - DIBPaint (hDC, - lpDCRect, - hDIB); -} - -void AfficheBitmap(char *filename,HDC hDC,int x,int y) -{ - RECT rc; - HANDLE hdib; - POINT pt; - char titi[60]; - - hdib = ChargerBitmap(filename,&pt); - if (hdib == NULL) { - return; - } - rc.top = y; - rc.left = x; - rc.right = pt.x+x; - rc.bottom = pt.y+y; - pt.y += GetSystemMetrics(SM_CYCAPTION); - DessinerBitmap(hdib,hDC,&rc); - GlobalFree(hdib); -} diff --git a/otherlibs/win32graph/draw.c b/otherlibs/win32graph/draw.c index 482299b3..209b76a6 100644 --- a/otherlibs/win32graph/draw.c +++ b/otherlibs/win32graph/draw.c @@ -195,7 +195,8 @@ CAMLprim value caml_gr_draw_arc(value *argv, int argc) argv[4], argv[5], FALSE); } -CAMLprim value caml_gr_draw_arc_nat(vx, vy, vrx, vry, vstart, vend) +CAMLprim value caml_gr_draw_arc_nat(value vx, value vy, value vrx, value vry, + value vstart, value vend) { return gr_draw_or_fill_arc(vx, vy, vrx, vry, vstart, vend, FALSE); } @@ -262,7 +263,7 @@ static value gr_draw_or_fill_arc(value vx, value vy, value vrx, value vry, r_x = Int_val(vrx); r_y = Int_val(vry); if ((r_x < 0) || (r_y < 0)) - invalid_argument("draw_arc: radius must be positive"); + caml_invalid_argument("draw_arc: radius must be positive"); x = Int_val(vx); y = Int_val(vy); start = Int_val(vstart); @@ -304,15 +305,6 @@ static value gr_draw_or_fill_arc(value vx, value vy, value vrx, value vry, return Val_unit; } -CAMLprim value caml_gr_show_bitmap(value filename,int x,int y) -{ - AfficheBitmap(filename,grwindow.gcBitmap,x,Wcvt(y)); - AfficheBitmap(filename,grwindow.gc,x,Wcvt(y)); - return Val_unit; -} - - - CAMLprim value caml_gr_get_mousex(value unit) { POINT pt; @@ -366,7 +358,7 @@ CAMLprim value caml_gr_draw_char(value chr) CAMLprim value caml_gr_draw_string(value str) { gr_check_open(); - caml_gr_draw_text(str, string_length(str)); + caml_gr_draw_text(str, caml_string_length(str)); return Val_unit; } @@ -375,12 +367,12 @@ CAMLprim value caml_gr_text_size(value str) SIZE extent; value res; - mlsize_t len = string_length(str); + mlsize_t len = caml_string_length(str); if (len > 32767) len = 32767; GetTextExtentPoint(grwindow.gc,String_val(str), len,&extent); - res = alloc_tuple(2); + res = caml_alloc_tuple(2); Field(res, 0) = Val_long(extent.cx); Field(res, 1) = Val_long(extent.cy); @@ -422,7 +414,8 @@ CAMLprim value caml_gr_fill_arc(value *argv, int argc) argv[4], argv[5], TRUE); } -CAMLprim value caml_gr_fill_arc_nat(vx, vy, vrx, vry, vstart, vend) +CAMLprim value caml_gr_fill_arc_nat(value vx, value vy, value vrx, value vry, + value vstart, value vend) { return gr_draw_or_fill_arc(vx, vy, vrx, vry, vstart, vend, TRUE); } @@ -470,7 +463,7 @@ CAMLprim value caml_gr_create_image(value vw, value vh) cbm = CreateCompatibleBitmap(grwindow.gc, w, h); if (cbm == NULL) gr_fail("create_image: cannot create bitmap", 0); - res = alloc_custom(&image_ops, sizeof(struct image), + res = caml_alloc_custom(&image_ops, sizeof(struct image), w * h, Max_image_mem); if (res) { Width (res) = w; @@ -602,10 +595,10 @@ static value alloc_int_vect(mlsize_t size) if (size == 0) return Atom(0); if (size <= Max_young_wosize) { - res = alloc(size, 0); + res = caml_alloc(size, 0); } else { - res = alloc_shr(size, 0); + res = caml_alloc_shr(size, 0); } for (i = 0; i < size; i++) { Field(res, i) = Val_long(0); @@ -624,7 +617,7 @@ CAMLprim value caml_gr_dump_image (value img) Begin_roots2(img, matrix) matrix = alloc_int_vect (height); for (i = 0; i < height; i++) { - modify (&Field (matrix, i), alloc_int_vect (width)); + caml_modify (&Field (matrix, i), alloc_int_vect (width)); } End_roots(); diff --git a/otherlibs/win32graph/events.c b/otherlibs/win32graph/events.c index aaedcfa7..810d8632 100755 --- a/otherlibs/win32graph/events.c +++ b/otherlibs/win32graph/events.c @@ -117,7 +117,7 @@ static value caml_gr_wait_allocate_result(int mouse_x, int mouse_y, int button, int keypressed, int key) { - value res = alloc_small(5, 0); + value res = caml_alloc_small(5, 0); Field(res, 0) = Val_int(mouse_x); Field(res, 1) = Val_int(grwindow.height - 1 - mouse_y); Field(res, 2) = Val_bool(button); diff --git a/otherlibs/win32graph/open.c b/otherlibs/win32graph/open.c index 15c029a8..7e3b77de 100644 --- a/otherlibs/win32graph/open.c +++ b/otherlibs/win32graph/open.c @@ -260,7 +260,7 @@ static DWORD WINAPI gr_open_graph_internal(value arg) CAMLprim value caml_gr_open_graph(value arg) { - long tid; + DWORD tid; if (gr_initialized) return Val_unit; open_graph_event = CreateEvent(NULL, FALSE, FALSE, NULL); threadHandle = @@ -359,11 +359,11 @@ void gr_fail(char *fmt, char *arg) if (graphic_failure_exn == NULL) { graphic_failure_exn = caml_named_value("Graphics.Graphic_failure"); if (graphic_failure_exn == NULL) - invalid_argument("Exception Graphics.Graphic_failure not initialized, " + caml_invalid_argument("Exception Graphics.Graphic_failure not initialized, " "must link graphics.cma"); } sprintf(buffer, fmt, arg); - raise_with_string(*graphic_failure_exn, buffer); + caml_raise_with_string(*graphic_failure_exn, buffer); } void gr_check_open(void) diff --git a/otherlibs/win32unix/Makefile b/otherlibs/win32unix/Makefile new file mode 100644 index 00000000..3824905b --- /dev/null +++ b/otherlibs/win32unix/Makefile @@ -0,0 +1,67 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1999 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# Note: since this directory is Windows-specific, it may be good to make sure +# its content can not be compiled under Unix. +# This directory could even become a subdirectory of the unix directory. + +# Files in this directory +WIN_FILES = accept.c bind.c channels.c close.c \ + close_on.c connect.c createprocess.c dup.c dup2.c errmsg.c \ + getpeername.c getpid.c getsockname.c gettimeofday.c \ + link.c listen.c lockf.c lseek.c nonblock.c \ + mkdir.c open.c pipe.c read.c readlink.c rename.c \ + select.c sendrecv.c \ + shutdown.c sleep.c socket.c sockopt.c startup.c stat.c \ + symlink.c system.c times.c unixsupport.c windir.c winwait.c write.c \ + winlist.c winworker.c windbug.c + +# Files from the ../unix directory +UNIX_FILES = access.c addrofstr.c chdir.c chmod.c cst2constr.c \ + cstringv.c envir.c execv.c execve.c execvp.c \ + exit.c getaddrinfo.c getcwd.c gethost.c gethostname.c \ + getnameinfo.c getproto.c \ + getserv.c gmtime.c putenv.c rmdir.c \ + socketaddr.c strofaddr.c time.c unlink.c utimes.c + +UNIX_CAML_FILES = unix.mli unixLabels.mli unixLabels.ml + +ALL_FILES=$(WIN_FILES) $(UNIX_FILES) +WSOCKLIB=$(call SYSLIB,ws2_32) +ADVAPI32LIB=$(call SYSLIB,advapi32) + +LIBNAME=unix +COBJS=$(ALL_FILES:.c=.$(O)) +CAMLOBJS=unix.cmo unixLabels.cmo +LINKOPTS=-cclib $(WSOCKLIB) -cclib $(ADVAPI32LIB) +LDOPTS=-ldopt $(WSOCKLIB) -ldopt $(ADVAPI32LIB) +EXTRACAMLFLAGS=-nolabels +EXTRACFLAGS=-I../unix +HEADERS=unixsupport.h socketaddr.h + + +include ../Makefile + +clean:: + rm -f $(UNIX_FILES) $(UNIX_CAML_FILES) + +$(UNIX_FILES) $(UNIX_CAML_FILES): %: ../unix/% + cp ../unix/$* $* + +depend: + +$(COBJS): unixsupport.h + +include .depend diff --git a/otherlibs/win32unix/Makefile.nt b/otherlibs/win32unix/Makefile.nt index ddedd03e..ed9900bb 100644 --- a/otherlibs/win32unix/Makefile.nt +++ b/otherlibs/win32unix/Makefile.nt @@ -13,51 +13,4 @@ #* * #************************************************************************** -# Files in this directory -WIN_FILES = accept.c bind.c channels.c close.c \ - close_on.c connect.c createprocess.c dup.c dup2.c errmsg.c \ - getpeername.c getpid.c getsockname.c gettimeofday.c \ - link.c listen.c lockf.c lseek.c nonblock.c \ - mkdir.c open.c pipe.c read.c readlink.c rename.c \ - select.c sendrecv.c \ - shutdown.c sleep.c socket.c sockopt.c startup.c stat.c \ - symlink.c system.c times.c unixsupport.c windir.c winwait.c write.c \ - winlist.c winworker.c windbug.c - -# Files from the ../unix directory -UNIX_FILES = access.c addrofstr.c chdir.c chmod.c cst2constr.c \ - cstringv.c envir.c execv.c execve.c execvp.c \ - exit.c getaddrinfo.c getcwd.c gethost.c gethostname.c \ - getnameinfo.c getproto.c \ - getserv.c gmtime.c putenv.c rmdir.c \ - socketaddr.c strofaddr.c time.c unlink.c utimes.c - -UNIX_CAML_FILES = unix.mli unixLabels.mli unixLabels.ml - -ALL_FILES=$(WIN_FILES) $(UNIX_FILES) -WSOCKLIB=$(call SYSLIB,ws2_32) -ADVAPI32LIB=$(call SYSLIB,advapi32) - -LIBNAME=unix -COBJS=$(ALL_FILES:.c=.$(O)) -CAMLOBJS=unix.cmo unixLabels.cmo -LINKOPTS=-cclib $(WSOCKLIB) -cclib $(ADVAPI32LIB) -LDOPTS=-ldopt $(WSOCKLIB) -ldopt $(ADVAPI32LIB) -EXTRACAMLFLAGS=-nolabels -EXTRACFLAGS=-I../unix -HEADERS=unixsupport.h socketaddr.h - - -include ../Makefile - -clean:: - rm -f $(UNIX_FILES) $(UNIX_CAML_FILES) - -$(UNIX_FILES) $(UNIX_CAML_FILES): %: ../unix/% - cp ../unix/$* $* - -depend: - -$(COBJS): unixsupport.h - -include .depend +include Makefile diff --git a/otherlibs/win32unix/accept.c b/otherlibs/win32unix/accept.c index ec7053c7..0a15673e 100644 --- a/otherlibs/win32unix/accept.c +++ b/otherlibs/win32unix/accept.c @@ -20,8 +20,7 @@ #include "unixsupport.h" #include "socketaddr.h" -CAMLprim value unix_accept(sock) - value sock; +CAMLprim value unix_accept(value cloexec, value sock) { SOCKET sconn = Socket_val(sock); SOCKET snew; @@ -31,18 +30,22 @@ CAMLprim value unix_accept(sock) DWORD err = 0; addr_len = sizeof(sock_addr); - enter_blocking_section(); + caml_enter_blocking_section(); snew = accept(sconn, &addr.s_gen, &addr_len); if (snew == INVALID_SOCKET) err = WSAGetLastError (); - leave_blocking_section(); + caml_leave_blocking_section(); if (snew == INVALID_SOCKET) { win32_maperr(err); uerror("accept", Nothing); } + /* This is a best effort, not guaranteed to work, so don't fail on error */ + SetHandleInformation((HANDLE) snew, + HANDLE_FLAG_INHERIT, + unix_cloexec_p(cloexec) ? 0 : HANDLE_FLAG_INHERIT); Begin_roots2 (fd, adr) fd = win_alloc_socket(snew); adr = alloc_sockaddr(&addr, addr_len, snew); - res = alloc_small(2, 0); + res = caml_alloc_small(2, 0); Field(res, 0) = fd; Field(res, 1) = adr; End_roots(); diff --git a/otherlibs/win32unix/channels.c b/otherlibs/win32unix/channels.c index 1210e6e5..0347bd38 100644 --- a/otherlibs/win32unix/channels.c +++ b/otherlibs/win32unix/channels.c @@ -21,15 +21,13 @@ #include #include "unixsupport.h" #include +#include #if defined(_MSC_VER) && !defined(_INTPTR_T_DEFINED) typedef int intptr_t; #define _INTPTR_T_DEFINED #endif -extern intptr_t _get_osfhandle(int); -extern int _open_osfhandle(intptr_t, int); - int win_CRT_fd_of_filedescr(value handle) { if (CRT_fd_val(handle) != NO_CRT_FD) { diff --git a/otherlibs/win32unix/close.c b/otherlibs/win32unix/close.c index a4adee3f..289e3b11 100644 --- a/otherlibs/win32unix/close.c +++ b/otherlibs/win32unix/close.c @@ -17,8 +17,6 @@ #include "unixsupport.h" #include -extern int _close(int); - CAMLprim value unix_close(value fd) { if (Descr_kind_val(fd) == KIND_SOCKET) { diff --git a/otherlibs/win32unix/connect.c b/otherlibs/win32unix/connect.c index e30243c1..9ce86c03 100644 --- a/otherlibs/win32unix/connect.c +++ b/otherlibs/win32unix/connect.c @@ -27,10 +27,10 @@ CAMLprim value unix_connect(socket, address) DWORD err = 0; get_sockaddr(address, &addr, &addr_len); - enter_blocking_section(); + caml_enter_blocking_section(); if (connect(s, &addr.s_gen, addr_len) == -1) err = WSAGetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); if (err) { win32_maperr(err); uerror("connect", Nothing); diff --git a/otherlibs/win32unix/createprocess.c b/otherlibs/win32unix/createprocess.c index 96dbfe4a..8c855aa1 100644 --- a/otherlibs/win32unix/createprocess.c +++ b/otherlibs/win32unix/createprocess.c @@ -13,7 +13,10 @@ /* */ /**************************************************************************/ +#define CAML_INTERNALS + #include +#include #include "unixsupport.h" #include #include @@ -27,14 +30,16 @@ value win_create_process_native(value cmd, value cmdline, value env, PROCESS_INFORMATION pi; STARTUPINFO si; char * exefile, * envp; - int flags; + DWORD flags, err; + HANDLE hp; caml_unix_check_path(cmd, "create_process"); if (! caml_string_is_c_safe(cmdline)) unix_error(EINVAL, "create_process", cmdline); /* [env] is checked for null bytes at construction time, see unix.ml */ - exefile = search_exe_in_path(String_val(cmd)); + err = ERROR_SUCCESS; + exefile = caml_search_exe_in_path(String_val(cmd)); if (env != Val_int(0)) { envp = String_val(Field(env, 0)); } else { @@ -44,9 +49,20 @@ value win_create_process_native(value cmd, value cmdline, value env, ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = Handle_val(fd1); - si.hStdOutput = Handle_val(fd2); - si.hStdError = Handle_val(fd3); + /* Duplicate the handles fd1, fd2, fd3 to make sure they are inheritable */ + hp = GetCurrentProcess(); + if (! DuplicateHandle(hp, Handle_val(fd1), hp, &(si.hStdInput), + 0, TRUE, DUPLICATE_SAME_ACCESS)) { + err = GetLastError(); goto ret1; + } + if (! DuplicateHandle(hp, Handle_val(fd2), hp, &(si.hStdOutput), + 0, TRUE, DUPLICATE_SAME_ACCESS)) { + err = GetLastError(); goto ret2; + } + if (! DuplicateHandle(hp, Handle_val(fd3), hp, &(si.hStdError), + 0, TRUE, DUPLICATE_SAME_ACCESS)) { + err = GetLastError(); goto ret3; + } /* If we do not have a console window, then we must create one before running the process (keep it hidden for apparence). If we are starting a GUI application, the newly created @@ -61,12 +77,21 @@ value win_create_process_native(value cmd, value cmdline, value env, /* Create the process */ if (! CreateProcess(exefile, String_val(cmdline), NULL, NULL, TRUE, flags, envp, NULL, &si, &pi)) { - caml_stat_free(exefile); - win32_maperr(GetLastError()); - uerror("create_process", cmd); + err = GetLastError(); goto ret4; } - caml_stat_free(exefile); CloseHandle(pi.hThread); + ret4: + CloseHandle(si.hStdError); + ret3: + CloseHandle(si.hStdOutput); + ret2: + CloseHandle(si.hStdInput); + ret1: + caml_stat_free(exefile); + if (err != ERROR_SUCCESS) { + win32_maperr(err); + uerror("create_process", cmd); + } /* Return the process handle as pseudo-PID (this is consistent with the wait() emulation in the MSVC C library */ return Val_long(pi.hProcess); diff --git a/otherlibs/win32unix/dup.c b/otherlibs/win32unix/dup.c index d43f66d3..c02153b5 100644 --- a/otherlibs/win32unix/dup.c +++ b/otherlibs/win32unix/dup.c @@ -16,14 +16,16 @@ #include #include "unixsupport.h" -CAMLprim value unix_dup(value fd) +CAMLprim value unix_dup(value cloexec, value fd) { HANDLE newh; value newfd; int kind = Descr_kind_val(fd); if (! DuplicateHandle(GetCurrentProcess(), Handle_val(fd), GetCurrentProcess(), &newh, - 0L, TRUE, DUPLICATE_SAME_ACCESS)) { + 0L, + unix_cloexec_p(cloexec) ? FALSE : TRUE, + DUPLICATE_SAME_ACCESS)) { win32_maperr(GetLastError()); return -1; } diff --git a/otherlibs/win32unix/dup2.c b/otherlibs/win32unix/dup2.c index c6c258f9..44ff41d6 100644 --- a/otherlibs/win32unix/dup2.c +++ b/otherlibs/win32unix/dup2.c @@ -16,16 +16,16 @@ #include #include "unixsupport.h" -extern int _dup2(int, int); - -CAMLprim value unix_dup2(value fd1, value fd2) +CAMLprim value unix_dup2(value cloexec, value fd1, value fd2) { HANDLE oldh, newh; oldh = Handle_val(fd2); if (! DuplicateHandle(GetCurrentProcess(), Handle_val(fd1), GetCurrentProcess(), &newh, - 0L, TRUE, DUPLICATE_SAME_ACCESS)) { + 0L, + unix_cloexec_p(cloexec) ? FALSE : TRUE, + DUPLICATE_SAME_ACCESS)) { win32_maperr(GetLastError()); return -1; } diff --git a/otherlibs/win32unix/errmsg.c b/otherlibs/win32unix/errmsg.c index cdefa601..16a93ed4 100644 --- a/otherlibs/win32unix/errmsg.c +++ b/otherlibs/win32unix/errmsg.c @@ -29,7 +29,7 @@ CAMLprim value unix_error_message(value err) errnum = Is_block(err) ? Int_val(Field(err, 0)) : error_table[Int_val(err)]; if (errnum > 0) - return copy_string(strerror(errnum)); + return caml_copy_string(strerror(errnum)); if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, -errnum, @@ -37,7 +37,7 @@ CAMLprim value unix_error_message(value err) buffer, sizeof(buffer), NULL)) - return copy_string(buffer); + return caml_copy_string(buffer); sprintf(buffer, "unknown error #%d", errnum); - return copy_string(buffer); + return caml_copy_string(buffer); } diff --git a/otherlibs/win32unix/gettimeofday.c b/otherlibs/win32unix/gettimeofday.c index 0afd29b6..20f62a1f 100644 --- a/otherlibs/win32unix/gettimeofday.c +++ b/otherlibs/win32unix/gettimeofday.c @@ -36,5 +36,5 @@ CAMLprim value unix_gettimeofday(value unit) #else tm = *(uint64_t *)&ft - epoch_ft; /* shift to Epoch-relative time */ #endif - return copy_double(tm * 1e-7); /* tm is in 100ns */ + return caml_copy_double(tm * 1e-7); /* tm is in 100ns */ } diff --git a/otherlibs/win32unix/link.c b/otherlibs/win32unix/link.c index 5116fe02..54897de1 100644 --- a/otherlibs/win32unix/link.c +++ b/otherlibs/win32unix/link.c @@ -33,7 +33,7 @@ CAMLprim value unix_link(value path1, value path2) pCreateHardLink = (tCreateHardLink) GetProcAddress(hModKernel32, "CreateHardLinkA"); if (pCreateHardLink == NULL) - invalid_argument("Unix.link not implemented"); + caml_invalid_argument("Unix.link not implemented"); caml_unix_check_path(path1, "link"); caml_unix_check_path(path2, "link"); if (! pCreateHardLink(String_val(path2), String_val(path1), NULL)) { diff --git a/otherlibs/win32unix/lockf.c b/otherlibs/win32unix/lockf.c index bd732076..83bf4a96 100644 --- a/otherlibs/win32unix/lockf.c +++ b/otherlibs/win32unix/lockf.c @@ -63,11 +63,11 @@ CAMLprim value unix_lockf(value fd, value cmd, value span) version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(GetVersionEx(&version) == 0) { - invalid_argument("lockf only supported on WIN32_NT platforms:" + caml_invalid_argument("lockf only supported on WIN32_NT platforms:" " could not determine current platform."); } if(version.dwPlatformId != VER_PLATFORM_WIN32_NT) { - invalid_argument("lockf only supported on WIN32_NT platforms"); + caml_invalid_argument("lockf only supported on WIN32_NT platforms"); } h = Handle_val(fd); @@ -112,11 +112,11 @@ CAMLprim value unix_lockf(value fd, value cmd, value span) err = GetLastError(); break; case 1: /* F_LOCK - blocking write lock */ - enter_blocking_section(); + caml_enter_blocking_section(); if (! LockFileEx(h, LOCKFILE_EXCLUSIVE_LOCK, 0, lock_len.LowPart, lock_len.HighPart, &overlap)) err = GetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); break; case 2: /* F_TLOCK - non-blocking write lock */ if (! LockFileEx(h, LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK, 0, @@ -137,11 +137,11 @@ CAMLprim value unix_lockf(value fd, value cmd, value span) } break; case 4: /* F_RLOCK - blocking read lock */ - enter_blocking_section(); + caml_enter_blocking_section(); if (! LockFileEx(h, 0, 0, lock_len.LowPart, lock_len.HighPart, &overlap)) err = GetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); break; case 5: /* F_TRLOCK - non-blocking read lock */ if (! LockFileEx(h, LOCKFILE_FAIL_IMMEDIATELY, 0, diff --git a/otherlibs/win32unix/lseek.c b/otherlibs/win32unix/lseek.c index bf5b80f8..79639870 100644 --- a/otherlibs/win32unix/lseek.c +++ b/otherlibs/win32unix/lseek.c @@ -66,5 +66,5 @@ CAMLprim value unix_lseek_64(value fd, value ofs, value cmd) ret = caml_set_file_pointer(Handle_val(fd), Int64_val(ofs), seek_command_table[Int_val(cmd)]); - return copy_int64(ret); + return caml_copy_int64(ret); } diff --git a/otherlibs/win32unix/open.c b/otherlibs/win32unix/open.c index 65568b64..cff95259 100644 --- a/otherlibs/win32unix/open.c +++ b/otherlibs/win32unix/open.c @@ -18,21 +18,23 @@ #include "unixsupport.h" #include -static int open_access_flags[14] = { +static int open_access_flags[15] = { GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static int open_create_flags[14] = { - 0, 0, 0, 0, 0, O_CREAT, O_TRUNC, O_EXCL, 0, 0, 0, 0, 0, 0 +static int open_create_flags[15] = { + 0, 0, 0, 0, 0, O_CREAT, O_TRUNC, O_EXCL, 0, 0, 0, 0, 0, 0, 0 }; -static int open_share_flags[14] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FILE_SHARE_DELETE, 0 +static int open_share_flags[15] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FILE_SHARE_DELETE, 0, 0 }; -static int open_cloexec_flags[14] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +enum { CLOEXEC = 1, KEEPEXEC = 2 }; + +static int open_cloexec_flags[15] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CLOEXEC, KEEPEXEC }; CAMLprim value unix_open(value path, value flags, value perm) @@ -42,11 +44,11 @@ CAMLprim value unix_open(value path, value flags, value perm) HANDLE h; caml_unix_check_path(path, "open"); - fileaccess = convert_flag_list(flags, open_access_flags); + fileaccess = caml_convert_flag_list(flags, open_access_flags); sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE - | convert_flag_list(flags, open_share_flags); + | caml_convert_flag_list(flags, open_share_flags); - createflags = convert_flag_list(flags, open_create_flags); + createflags = caml_convert_flag_list(flags, open_create_flags); if ((createflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) filecreate = CREATE_NEW; else if ((createflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) @@ -63,10 +65,13 @@ CAMLprim value unix_open(value path, value flags, value perm) else fileattrib = FILE_ATTRIBUTE_NORMAL; - cloexec = convert_flag_list(flags, open_cloexec_flags); + cloexec = caml_convert_flag_list(flags, open_cloexec_flags); attr.nLength = sizeof(attr); attr.lpSecurityDescriptor = NULL; - attr.bInheritHandle = cloexec ? FALSE : TRUE; + attr.bInheritHandle = + cloexec & CLOEXEC ? FALSE + : cloexec & KEEPEXEC ? TRUE + : !unix_cloexec_default; h = CreateFile(String_val(path), fileaccess, sharemode, &attr, diff --git a/otherlibs/win32unix/pipe.c b/otherlibs/win32unix/pipe.c index 64a63c60..a48c686a 100644 --- a/otherlibs/win32unix/pipe.c +++ b/otherlibs/win32unix/pipe.c @@ -22,7 +22,7 @@ /* PR#4749: pick a size that matches that of I/O buffers */ #define SIZEBUF 4096 -CAMLprim value unix_pipe(value unit) +CAMLprim value unix_pipe(value cloexec, value unit) { SECURITY_ATTRIBUTES attr; HANDLE readh, writeh; @@ -30,7 +30,7 @@ CAMLprim value unix_pipe(value unit) attr.nLength = sizeof(attr); attr.lpSecurityDescriptor = NULL; - attr.bInheritHandle = TRUE; + attr.bInheritHandle = unix_cloexec_p(cloexec) ? FALSE : TRUE; if (! CreatePipe(&readh, &writeh, &attr, SIZEBUF)) { win32_maperr(GetLastError()); uerror("pipe", Nothing); @@ -38,7 +38,7 @@ CAMLprim value unix_pipe(value unit) Begin_roots2(readfd, writefd) readfd = win_alloc_handle(readh); writefd = win_alloc_handle(writeh); - res = alloc_small(2, 0); + res = caml_alloc_small(2, 0); Field(res, 0) = readfd; Field(res, 1) = writefd; End_roots(); diff --git a/otherlibs/win32unix/read.c b/otherlibs/win32unix/read.c index 532a0bfb..a96951e4 100644 --- a/otherlibs/win32unix/read.c +++ b/otherlibs/win32unix/read.c @@ -32,21 +32,28 @@ CAMLprim value unix_read(value fd, value buf, value ofs, value vlen) if (Descr_kind_val(fd) == KIND_SOCKET) { int ret; SOCKET s = Socket_val(fd); - enter_blocking_section(); + caml_enter_blocking_section(); ret = recv(s, iobuf, numbytes, 0); if (ret == SOCKET_ERROR) err = WSAGetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); numread = ret; } else { HANDLE h = Handle_val(fd); - enter_blocking_section(); + caml_enter_blocking_section(); if (! ReadFile(h, iobuf, numbytes, &numread, NULL)) err = GetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); } if (err) { - win32_maperr(err); - uerror("read", Nothing); + if (err == ERROR_BROKEN_PIPE) { + // The write handle for an anonymous pipe has been closed. We match the + // Unix behavior, and treat this as a zero-read instead of a Unix_error. + err = 0; + numread = 0; + } else { + win32_maperr(err); + uerror("read", Nothing); + } } memmove (&Byte(buf, Long_val(ofs)), iobuf, numread); End_roots(); diff --git a/otherlibs/win32unix/select.c b/otherlibs/win32unix/select.c index f693941d..dd263869 100644 --- a/otherlibs/win32unix/select.c +++ b/otherlibs/win32unix/select.c @@ -914,6 +914,8 @@ static value find_handle(LPSELECTRESULT iterResult, value readfds, case SELECT_MODE_EXCEPT: list = exceptfds; break; + case SELECT_MODE_NONE: + CAMLassert(0); }; for(i=0; list != Val_unit && i < iterResult->lpOrigIdx; ++i ) @@ -922,7 +924,7 @@ static value find_handle(LPSELECTRESULT iterResult, value readfds, } if (list == Val_unit) - failwith ("select.c: original file handle not found"); + caml_failwith ("select.c: original file handle not found"); result = Field(list, 0); @@ -963,7 +965,7 @@ static value fdset_to_fdlist(value fdlist, fd_set *fdset) for (/*nothing*/; fdlist != Val_int(0); fdlist = Field(fdlist, 1)) { value s = Field(fdlist, 0); if (FD_ISSET(Socket_val(s), fdset)) { - value newres = alloc_small(2, 0); + value newres = caml_alloc_small(2, 0); Field(newres, 0) = s; Field(newres, 1) = res; res = newres; @@ -1031,9 +1033,9 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, && exceptfds == Val_int(0)) { DEBUG_PRINT("nothing to do"); if ( tm > 0.0 ) { - enter_blocking_section(); + caml_enter_blocking_section(); Sleep( (int)(tm * 1000)); - leave_blocking_section(); + caml_leave_blocking_section(); } read_list = write_list = except_list = Val_int(0); } else { @@ -1048,12 +1050,12 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, tv.tv_usec = (int) (1e6 * (tm - (int) tm)); tvp = &tv; } - enter_blocking_section(); + caml_enter_blocking_section(); if (select(FD_SETSIZE, &read, &write, &except, tvp) == -1) { err = WSAGetLastError(); DEBUG_PRINT("Error %ld occurred", err); } - leave_blocking_section(); + caml_leave_blocking_section(); if (err) { DEBUG_PRINT("Error %ld occurred", err); win32_maperr(err); @@ -1189,7 +1191,7 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, DEBUG_PRINT("Need to watch %d workers", nEventsCount); /* Processing select itself */ - enter_blocking_section(); + caml_enter_blocking_section(); /* There are worker started, waiting to be monitored */ if (nEventsCount > 0) { @@ -1244,7 +1246,7 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, { Sleep(milliseconds); } - leave_blocking_section(); + caml_leave_blocking_section(); DEBUG_PRINT("Error status: %d (0 is ok)", err); /* Build results */ @@ -1261,7 +1263,7 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, for (i = 0; i < iterSelectData->nResultsCount; i++) { iterResult = &(iterSelectData->aResults[i]); - l = alloc_small(2, 0); + l = caml_alloc_small(2, 0); Store_field(l, 0, find_handle(iterResult, readfds, writefds, exceptfds)); switch (iterResult->EMode) @@ -1278,6 +1280,8 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, Store_field(l, 1, except_list); except_list = l; break; + case SELECT_MODE_NONE: + CAMLassert(0); } } /* We try to only process the first error, bypass other errors */ @@ -1315,7 +1319,7 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, } DEBUG_PRINT("Build final result"); - res = alloc_small(3, 0); + res = caml_alloc_small(3, 0); Store_field(res, 0, read_list); Store_field(res, 1, write_list); Store_field(res, 2, except_list); diff --git a/otherlibs/win32unix/sendrecv.c b/otherlibs/win32unix/sendrecv.c index 1c9ed08a..1daa8e99 100644 --- a/otherlibs/win32unix/sendrecv.c +++ b/otherlibs/win32unix/sendrecv.c @@ -28,7 +28,7 @@ CAMLprim value unix_recv(value sock, value buff, value ofs, value len, value flags) { SOCKET s = Socket_val(sock); - int flg = convert_flag_list(flags, msg_flag_table); + int flg = caml_convert_flag_list(flags, msg_flag_table); int ret; intnat numbytes; char iobuf[UNIX_BUFFER_SIZE]; @@ -37,10 +37,10 @@ CAMLprim value unix_recv(value sock, value buff, value ofs, value len, Begin_root (buff); numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; - enter_blocking_section(); + caml_enter_blocking_section(); ret = recv(s, iobuf, (int) numbytes, flg); if (ret == -1) err = WSAGetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) { win32_maperr(err); uerror("recv", Nothing); @@ -54,7 +54,7 @@ CAMLprim value unix_recvfrom(value sock, value buff, value ofs, value len, value flags) { SOCKET s = Socket_val(sock); - int flg = convert_flag_list(flags, msg_flag_table); + int flg = caml_convert_flag_list(flags, msg_flag_table); int ret; intnat numbytes; char iobuf[UNIX_BUFFER_SIZE]; @@ -68,17 +68,17 @@ CAMLprim value unix_recvfrom(value sock, value buff, value ofs, value len, numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; addr_len = sizeof(sock_addr); - enter_blocking_section(); + caml_enter_blocking_section(); ret = recvfrom(s, iobuf, (int) numbytes, flg, &addr.s_gen, &addr_len); if (ret == -1) err = WSAGetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) { win32_maperr(err); uerror("recvfrom", Nothing); } memmove (&Byte(buff, Long_val(ofs)), iobuf, ret); adr = alloc_sockaddr(&addr, addr_len, -1); - res = alloc_small(2, 0); + res = caml_alloc_small(2, 0); Field(res, 0) = Val_int(ret); Field(res, 1) = adr; End_roots(); @@ -89,7 +89,7 @@ CAMLprim value unix_send(value sock, value buff, value ofs, value len, value flags) { SOCKET s = Socket_val(sock); - int flg = convert_flag_list(flags, msg_flag_table); + int flg = caml_convert_flag_list(flags, msg_flag_table); int ret; intnat numbytes; char iobuf[UNIX_BUFFER_SIZE]; @@ -98,10 +98,10 @@ CAMLprim value unix_send(value sock, value buff, value ofs, value len, numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; memmove (iobuf, &Byte(buff, Long_val(ofs)), numbytes); - enter_blocking_section(); + caml_enter_blocking_section(); ret = send(s, iobuf, (int) numbytes, flg); if (ret == -1) err = WSAGetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) { win32_maperr(err); uerror("send", Nothing); @@ -113,7 +113,7 @@ value unix_sendto_native(value sock, value buff, value ofs, value len, value flags, value dest) { SOCKET s = Socket_val(sock); - int flg = convert_flag_list(flags, msg_flag_table); + int flg = caml_convert_flag_list(flags, msg_flag_table); int ret; intnat numbytes; char iobuf[UNIX_BUFFER_SIZE]; @@ -125,10 +125,10 @@ value unix_sendto_native(value sock, value buff, value ofs, value len, numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; memmove (iobuf, &Byte(buff, Long_val(ofs)), numbytes); - enter_blocking_section(); + caml_enter_blocking_section(); ret = sendto(s, iobuf, (int) numbytes, flg, &addr.s_gen, addr_len); if (ret == -1) err = WSAGetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); if (ret == -1) { win32_maperr(err); uerror("sendto", Nothing); diff --git a/otherlibs/win32unix/sleep.c b/otherlibs/win32unix/sleep.c index 6389adea..40127376 100644 --- a/otherlibs/win32unix/sleep.c +++ b/otherlibs/win32unix/sleep.c @@ -21,8 +21,8 @@ CAMLprim value unix_sleep(t) value t; { double d = Double_val(t); - enter_blocking_section(); + caml_enter_blocking_section(); Sleep(d * 1e3); - leave_blocking_section(); + caml_leave_blocking_section(); return Val_unit; } diff --git a/otherlibs/win32unix/socket.c b/otherlibs/win32unix/socket.c index d684034f..dc88fcbb 100644 --- a/otherlibs/win32unix/socket.c +++ b/otherlibs/win32unix/socket.c @@ -29,8 +29,7 @@ int socket_type_table[] = { SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET }; -CAMLprim value unix_socket(domain, type, proto) - value domain, type, proto; +CAMLprim value unix_socket(value cloexec, value domain, value type, value proto) { SOCKET s; @@ -49,5 +48,9 @@ CAMLprim value unix_socket(domain, type, proto) win32_maperr(WSAGetLastError()); uerror("socket", Nothing); } + /* This is a best effort, not guaranteed to work, so don't fail on error */ + SetHandleInformation((HANDLE) s, + HANDLE_FLAG_INHERIT, + unix_cloexec_p(cloexec) ? 0 : HANDLE_FLAG_INHERIT); return win_alloc_socket(s); } diff --git a/otherlibs/win32unix/sockopt.c b/otherlibs/win32unix/sockopt.c index 53219fe9..6035556f 100644 --- a/otherlibs/win32unix/sockopt.c +++ b/otherlibs/win32unix/sockopt.c @@ -140,12 +140,12 @@ unix_getsockopt_aux(char * name, if (optval.lg.l_onoff == 0) { return Val_int(0); /* None */ } else { - value res = alloc_small(1, 0); /* Some */ + value res = caml_alloc_small(1, 0); /* Some */ Field(res, 0) = Val_int(optval.lg.l_linger); return res; } case TYPE_TIMEVAL: - return copy_double((double) optval.tv.tv_sec + return caml_copy_double((double) optval.tv.tv_sec + (double) optval.tv.tv_usec / 1e6); case TYPE_UNIX_ERROR: if (optval.i == 0) { @@ -154,7 +154,7 @@ unix_getsockopt_aux(char * name, value err, res; err = unix_error_of_code(optval.i); Begin_root(err); - res = alloc_small(1, 0); /* Some */ + res = caml_alloc_small(1, 0); /* Some */ Field(res, 0) = err; End_roots(); return res; diff --git a/otherlibs/win32unix/stat.c b/otherlibs/win32unix/stat.c index dd5fae22..45360a06 100644 --- a/otherlibs/win32unix/stat.c +++ b/otherlibs/win32unix/stat.c @@ -68,10 +68,10 @@ static value stat_aux(int use_64, __int64 st_ino, struct _stat64 *buf) Store_field (v, 6, Val_int (buf->st_gid)); Store_field (v, 7, Val_int (buf->st_rdev)); Store_field (v, 8, - use_64 ? copy_int64(buf->st_size) : Val_int (buf->st_size)); - Store_field (v, 9, copy_double((double) buf->st_atime)); - Store_field (v, 10, copy_double((double) buf->st_mtime)); - Store_field (v, 11, copy_double((double) buf->st_ctime)); + use_64 ? caml_copy_int64(buf->st_size) : Val_int (buf->st_size)); + Store_field (v, 9, caml_copy_double((double) buf->st_atime / 10000000.0)); + Store_field (v, 10, caml_copy_double((double) buf->st_mtime / 10000000.0)); + Store_field (v, 11, caml_copy_double((double) buf->st_ctime / 10000000.0)); CAMLreturn (v); } @@ -117,23 +117,17 @@ static value stat_aux(int use_64, __int64 st_ino, struct _stat64 *buf) static int convert_time(FILETIME* time, __time64_t* result, __time64_t def) { - SYSTEMTIME sys; - FILETIME local; + /* Tempting though it may be, MSDN prohibits casting FILETIME directly + * to __int64 for alignment concerns. While this doesn't affect our supported + * platforms, it's easier to go with the flow... + */ + ULARGE_INTEGER utime = {{time->dwLowDateTime, time->dwHighDateTime}}; - if (time->dwLowDateTime || time->dwHighDateTime) { - if (!FileTimeToLocalFileTime(time, &local) || - !FileTimeToSystemTime(&local, &sys)) - { - win32_maperr(GetLastError()); - return 0; - } - else - { - struct tm stamp = {sys.wSecond, sys.wMinute, sys.wHour, - sys.wDay, sys.wMonth - 1, sys.wYear - 1900, - 0, 0, 0}; - *result = _mktime64(&stamp); - } + if (utime.QuadPart) { + /* There are 11644473600000 seconds between 1 January 1601 (the NT Epoch) + * and 1 January 1970 (the Unix Epoch). FILETIME is measured in 100ns ticks. + */ + *result = (utime.QuadPart - INT64_LITERAL(116444736000000000U)); } else { *result = def; diff --git a/otherlibs/win32unix/symlink.c b/otherlibs/win32unix/symlink.c index 36597ab0..326cefcb 100644 --- a/otherlibs/win32unix/symlink.c +++ b/otherlibs/win32unix/symlink.c @@ -15,6 +15,7 @@ /* * Windows Vista functions enabled */ +#undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include @@ -41,7 +42,7 @@ CAMLprim value unix_symlink(value to_dir, value osource, value odest) again: if (no_symlink) { - invalid_argument("symlink not available"); + caml_invalid_argument("symlink not available"); } if (!pCreateSymbolicLink) { diff --git a/otherlibs/win32unix/system.c b/otherlibs/win32unix/system.c index aff4033f..a7946b6e 100644 --- a/otherlibs/win32unix/system.c +++ b/otherlibs/win32unix/system.c @@ -33,13 +33,13 @@ CAMLprim value win_system(cmd) len = caml_string_length (cmd); buf = caml_stat_alloc (len + 1); memmove (buf, String_val (cmd), len + 1); - enter_blocking_section(); + caml_enter_blocking_section(); _flushall(); ret = system(buf); - leave_blocking_section(); + caml_leave_blocking_section(); caml_stat_free(buf); if (ret == -1) uerror("system", Nothing); - st = alloc_small(1, 0); /* Tag 0: Exited */ + st = caml_alloc_small(1, 0); /* Tag 0: Exited */ Field(st, 0) = Val_int(ret); return st; } diff --git a/otherlibs/win32unix/times.c b/otherlibs/win32unix/times.c index dc0519dc..18cd9aa9 100644 --- a/otherlibs/win32unix/times.c +++ b/otherlibs/win32unix/times.c @@ -49,7 +49,7 @@ value unix_times(value unit) { uerror("times", Nothing); } - res = alloc_small(4 * Double_wosize, Double_array_tag); + res = caml_alloc_small(4 * Double_wosize, Double_array_tag); Store_double_field(res, 0, to_sec(utime)); Store_double_field(res, 1, to_sec(stime)); Store_double_field(res, 2, 0); diff --git a/otherlibs/win32unix/unix.ml b/otherlibs/win32unix/unix.ml index eea61ebb..7fa865aa 100644 --- a/otherlibs/win32unix/unix.ml +++ b/otherlibs/win32unix/unix.ml @@ -122,6 +122,7 @@ let handle_unix_error f arg = external environment : unit -> string array = "unix_environment" external getenv: string -> string = "caml_sys_getenv" +(* external unsafe_getenv: string -> string = "caml_sys_unsafe_getenv" *) external putenv: string -> string -> unit = "unix_putenv" type process_status = @@ -172,6 +173,7 @@ type open_flag = | O_RSYNC | O_SHARE_DELETE | O_CLOEXEC + | O_KEEPEXEC type file_perm = int @@ -311,8 +313,9 @@ external access : string -> access_permission list -> unit = "unix_access" (* Operations on file descriptors *) -external dup : file_descr -> file_descr = "unix_dup" -external dup2 : file_descr -> file_descr -> unit = "unix_dup2" +external dup : ?cloexec: bool -> file_descr -> file_descr = "unix_dup" +external dup2 : + ?cloexec: bool -> file_descr -> file_descr -> unit = "unix_dup2" external set_nonblock : file_descr -> unit = "unix_set_nonblock" external clear_nonblock : file_descr -> unit = "unix_clear_nonblock" @@ -369,7 +372,8 @@ let rewinddir d = (* Pipes *) -external pipe : unit -> file_descr * file_descr = "unix_pipe" +external pipe : + ?cloexec: bool -> unit -> file_descr * file_descr = "unix_pipe" let mkfifo _name _perm = invalid_arg "Unix.mkfifo not implemented" @@ -547,10 +551,12 @@ type msg_flag = | MSG_DONTROUTE | MSG_PEEK -external socket : socket_domain -> socket_type -> int -> file_descr - = "unix_socket" -let socketpair _dom _ty _proto = invalid_arg "Unix.socketpair not implemented" -external accept : file_descr -> file_descr * sockaddr = "unix_accept" +external socket : + ?cloexec: bool -> socket_domain -> socket_type -> int -> file_descr + = "unix_socket" +let socketpair ?cloexec:_ _dom _ty _proto = invalid_arg "Unix.socketpair not implemented" +external accept : + ?cloexec: bool -> file_descr -> file_descr * sockaddr = "unix_accept" external bind : file_descr -> sockaddr -> unit = "unix_bind" external connect : file_descr -> sockaddr -> unit = "unix_connect" external listen : file_descr -> int -> unit = "unix_listen" @@ -826,7 +832,10 @@ external win_create_process : string -> string -> string option -> let make_cmdline args = let maybe_quote f = - if String.contains f ' ' || String.contains f '\"' || f = "" + if String.contains f ' ' || + String.contains f '\"' || + String.contains f '\t' || + f = "" then Filename.quote f else f in String.concat " " (List.map maybe_quote (Array.to_list args)) @@ -865,46 +874,78 @@ let open_proc cmd optenv proc input output error = Hashtbl.add popen_processes proc pid let open_process_in cmd = - let (in_read, in_write) = pipe() in - set_close_on_exec in_read; + let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in - open_proc cmd None (Process_in inchan) stdin in_write stderr; + begin + try + open_proc cmd None (Process_in inchan) stdin in_write stderr + with e -> + close_in inchan; + close in_write; + raise e + end; close in_write; inchan let open_process_out cmd = - let (out_read, out_write) = pipe() in - set_close_on_exec out_write; + let (out_read, out_write) = pipe ~cloexec:true () in let outchan = out_channel_of_descr out_write in - open_proc cmd None (Process_out outchan) out_read stdout stderr; + begin + try + open_proc cmd None (Process_out outchan) out_read stdout stderr + with e -> + close_out outchan; + close out_read; + raise e + end; close out_read; outchan let open_process cmd = - let (in_read, in_write) = pipe() in - let (out_read, out_write) = pipe() in - set_close_on_exec in_read; - set_close_on_exec out_write; + let (in_read, in_write) = pipe ~cloexec:true () in + let (out_read, out_write) = + try pipe ~cloexec:true () + with e -> close in_read; close in_write; raise e in let inchan = in_channel_of_descr in_read in let outchan = out_channel_of_descr out_write in - open_proc cmd None (Process(inchan, outchan)) out_read in_write stderr; - close out_read; close in_write; + begin + try + open_proc cmd None (Process(inchan, outchan)) out_read in_write stderr + with e -> + close out_read; close out_write; + close in_read; close in_write; + raise e + end; + close out_read; + close in_write; (inchan, outchan) let open_process_full cmd env = - let (in_read, in_write) = pipe() in - let (out_read, out_write) = pipe() in - let (err_read, err_write) = pipe() in - set_close_on_exec in_read; - set_close_on_exec out_write; - set_close_on_exec err_read; + let (in_read, in_write) = pipe ~cloexec:true () in + let (out_read, out_write) = + try pipe ~cloexec:true () + with e -> close in_read; close in_write; raise e in + let (err_read, err_write) = + try pipe ~cloexec:true () + with e -> close in_read; close in_write; + close out_read; close out_write; raise e in let inchan = in_channel_of_descr in_read in let outchan = out_channel_of_descr out_write in let errchan = in_channel_of_descr err_read in - open_proc cmd (Some(make_process_env env)) - (Process_full(inchan, outchan, errchan)) - out_read in_write err_write; - close out_read; close in_write; close err_write; + begin + try + open_proc cmd (Some (make_process_env env)) + (Process_full(inchan, outchan, errchan)) + out_read in_write err_write + with e -> + close out_read; close out_write; + close in_read; close in_write; + close err_read; close err_write; + raise e + end; + close out_read; + close in_write; + close err_write; (inchan, outchan, errchan) let find_proc_id fun_name proc = @@ -947,10 +988,9 @@ external select : let open_connection sockaddr = let sock = - socket (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in + socket ~cloexec:true (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in try connect sock sockaddr; - set_close_on_exec sock; (in_channel_of_descr sock, out_channel_of_descr sock) with exn -> close sock; raise exn diff --git a/otherlibs/win32unix/unixsupport.c b/otherlibs/win32unix/unixsupport.c index 9fddba6c..ced62fd8 100644 --- a/otherlibs/win32unix/unixsupport.c +++ b/otherlibs/win32unix/unixsupport.c @@ -50,7 +50,7 @@ static struct custom_operations win_handle_ops = { value win_alloc_handle(HANDLE h) { - value res = alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1); + value res = caml_alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1); Handle_val(res) = h; Descr_kind_val(res) = KIND_HANDLE; CRT_fd_val(res) = NO_CRT_FD; @@ -60,7 +60,7 @@ value win_alloc_handle(HANDLE h) value win_alloc_socket(SOCKET s) { - value res = alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1); + value res = caml_alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1); Socket_val(res) = s; Descr_kind_val(res) = KIND_SOCKET; CRT_fd_val(res) = NO_CRT_FD; @@ -272,7 +272,7 @@ value unix_error_of_code (int errcode) errconstr = cst_to_constr(errcode, error_table, sizeof(error_table)/sizeof(int), -1); if (errconstr == Val_int(-1)) { - err = alloc_small(1, 0); + err = caml_alloc_small(1, 0); Field(err, 0) = Val_int(errcode); } else { err = errconstr; @@ -287,22 +287,22 @@ void unix_error(int errcode, char *cmdname, value cmdarg) int errconstr; Begin_roots3 (name, err, arg); - arg = cmdarg == Nothing ? copy_string("") : cmdarg; - name = copy_string(cmdname); + arg = cmdarg == Nothing ? caml_copy_string("") : cmdarg; + name = caml_copy_string(cmdname); err = unix_error_of_code (errcode); if (unix_error_exn == NULL) { unix_error_exn = caml_named_value("Unix.Unix_error"); if (unix_error_exn == NULL) - invalid_argument("Exception Unix.Unix_error not initialized," + caml_invalid_argument("Exception Unix.Unix_error not initialized," " please link unix.cma"); } - res = alloc_small(4, 0); + res = caml_alloc_small(4, 0); Field(res, 0) = *unix_error_exn; Field(res, 1) = err; Field(res, 2) = name; Field(res, 3) = arg; End_roots(); - mlraise(res); + caml_raise(res); } void uerror(char * cmdname, value cmdarg) @@ -314,3 +314,14 @@ void caml_unix_check_path(value path, char * cmdname) { if (! caml_string_is_c_safe(path)) unix_error(ENOENT, cmdname, path); } + +int unix_cloexec_default = 0; + +int unix_cloexec_p(value cloexec) +{ + /* [cloexec] is a [bool option]. */ + if (Is_block(cloexec)) + return Bool_val(Field(cloexec, 0)); + else + return unix_cloexec_default; +} diff --git a/otherlibs/win32unix/unixsupport.h b/otherlibs/win32unix/unixsupport.h index 3bfeb0c6..139e179c 100644 --- a/otherlibs/win32unix/unixsupport.h +++ b/otherlibs/win32unix/unixsupport.h @@ -59,12 +59,22 @@ extern int win_CRT_fd_of_filedescr(value handle); extern void win32_maperr(DWORD errcode); extern value unix_error_of_code (int errcode); -extern void unix_error (int errcode, char * cmdname, value arg); -extern void uerror (char * cmdname, value arg); + +CAMLnoreturn_start +extern void unix_error (int errcode, char * cmdname, value arg) +CAMLnoreturn_end; + +CAMLnoreturn_start +extern void uerror (char * cmdname, value arg) +CAMLnoreturn_end; + extern void caml_unix_check_path(value path, char * cmdname); extern value unix_freeze_buffer (value); extern char ** cstringvect(value arg, char * cmdname); +extern int unix_cloexec_default; +extern int unix_cloexec_p(value cloexec); + /* Information stored in flags_fd, describing more precisely the socket * and its status. The whole flags_fd is initialized to 0. */ diff --git a/otherlibs/win32unix/windir.c b/otherlibs/win32unix/windir.c index fcf68c1d..b0746d51 100644 --- a/otherlibs/win32unix/windir.c +++ b/otherlibs/win32unix/windir.c @@ -34,15 +34,15 @@ CAMLprim value win_findfirst(value name) if (h == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); if (err == ERROR_NO_MORE_FILES) - raise_end_of_file(); + caml_raise_end_of_file(); else { win32_maperr(err); uerror("opendir", Nothing); } } - valname = copy_string(fileinfo.cFileName); + valname = caml_copy_string(fileinfo.cFileName); valh = win_alloc_handle(h); - v = alloc_small(2, 0); + v = caml_alloc_small(2, 0); Field(v,0) = valname; Field(v,1) = valh; End_roots(); @@ -58,13 +58,13 @@ CAMLprim value win_findnext(value valh) if (!retcode) { DWORD err = GetLastError(); if (err == ERROR_NO_MORE_FILES) - raise_end_of_file(); + caml_raise_end_of_file(); else { win32_maperr(err); uerror("readdir", Nothing); } } - return copy_string(fileinfo.cFileName); + return caml_copy_string(fileinfo.cFileName); } CAMLprim value win_findclose(value valh) diff --git a/otherlibs/win32unix/winwait.c b/otherlibs/win32unix/winwait.c index 2be7a564..2bf539f2 100644 --- a/otherlibs/win32unix/winwait.c +++ b/otherlibs/win32unix/winwait.c @@ -25,10 +25,10 @@ static value alloc_process_status(HANDLE pid, int status) { value res, st; - st = alloc(1, 0); + st = caml_alloc(1, 0); Field(st, 0) = Val_int(status); Begin_root (st); - res = alloc_small(2, 0); + res = caml_alloc_small(2, 0); Field(res, 0) = Val_long((intnat) pid); Field(res, 1) = st; End_roots(); @@ -46,12 +46,12 @@ CAMLprim value win_waitpid(value vflags, value vpid_req) HANDLE pid_req = (HANDLE) Long_val(vpid_req); DWORD err = 0; - flags = convert_flag_list(vflags, wait_flag_table); + flags = caml_convert_flag_list(vflags, wait_flag_table); if ((flags & CAML_WNOHANG) == 0) { - enter_blocking_section(); + caml_enter_blocking_section(); retcode = WaitForSingleObject(pid_req, INFINITE); if (retcode == WAIT_FAILED) err = GetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); if (err) { win32_maperr(err); uerror("waitpid", Nothing); diff --git a/otherlibs/win32unix/winworker.c b/otherlibs/win32unix/winworker.c index dff729d6..8007bc2d 100644 --- a/otherlibs/win32unix/winworker.c +++ b/otherlibs/win32unix/winworker.c @@ -283,10 +283,10 @@ LPWORKER worker_job_submit (WORKERFUNC f, void *user_data) LPWORKER lpWorker = worker_pop(); DEBUG_PRINT("Waiting for worker to be ready"); - enter_blocking_section(); + caml_enter_blocking_section(); WaitForSingleObject(lpWorker->hWorkerReady, INFINITE); ResetEvent(lpWorker->hWorkerReady); - leave_blocking_section(); + caml_leave_blocking_section(); DEBUG_PRINT("Worker is ready"); lpWorker->hJobFunc = f; @@ -314,9 +314,9 @@ void worker_job_stop (LPWORKER lpWorker) void worker_job_finish (LPWORKER lpWorker) { DEBUG_PRINT("Finishing call of worker %x", lpWorker); - enter_blocking_section(); + caml_enter_blocking_section(); WaitForSingleObject(lpWorker->hJobDone, INFINITE); - leave_blocking_section(); + caml_leave_blocking_section(); worker_push(lpWorker); } diff --git a/otherlibs/win32unix/winworker.h b/otherlibs/win32unix/winworker.h index fbe4af26..c3a5dd0e 100644 --- a/otherlibs/win32unix/winworker.h +++ b/otherlibs/win32unix/winworker.h @@ -16,6 +16,7 @@ #ifndef _WINWORKER_H #define _WINWORKER_H +#undef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #include "unixsupport.h" #include diff --git a/otherlibs/win32unix/write.c b/otherlibs/win32unix/write.c index 866eb06a..3114763a 100644 --- a/otherlibs/win32unix/write.c +++ b/otherlibs/win32unix/write.c @@ -37,17 +37,17 @@ CAMLprim value unix_write(value fd, value buf, value vofs, value vlen) if (Descr_kind_val(fd) == KIND_SOCKET) { int ret; SOCKET s = Socket_val(fd); - enter_blocking_section(); + caml_enter_blocking_section(); ret = send(s, iobuf, numbytes, 0); if (ret == SOCKET_ERROR) err = WSAGetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); numwritten = ret; } else { HANDLE h = Handle_val(fd); - enter_blocking_section(); + caml_enter_blocking_section(); if (! WriteFile(h, iobuf, numbytes, &numwritten, NULL)) err = GetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); } if (err) { win32_maperr(err); @@ -78,17 +78,17 @@ CAMLprim value unix_single_write(value fd, value buf, value vofs, value vlen) if (Descr_kind_val(fd) == KIND_SOCKET) { int ret; SOCKET s = Socket_val(fd); - enter_blocking_section(); + caml_enter_blocking_section(); ret = send(s, iobuf, numbytes, 0); if (ret == SOCKET_ERROR) err = WSAGetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); numwritten = ret; } else { HANDLE h = Handle_val(fd); - enter_blocking_section(); + caml_enter_blocking_section(); if (! WriteFile(h, iobuf, numbytes, &numwritten, NULL)) err = GetLastError(); - leave_blocking_section(); + caml_leave_blocking_section(); } if (err) { win32_maperr(err); diff --git a/parsing/HACKING.adoc b/parsing/HACKING.adoc new file mode 100644 index 00000000..7da8b22f --- /dev/null +++ b/parsing/HACKING.adoc @@ -0,0 +1,9 @@ +link:parsetree.mli[Parsetree] and link:asttypes.mli[Asttypes]:: +Parsetree is an Abstract Syntax Tree (AST) representation of OCaml +source code. It is well annotated with examples and is a recommended +read before any further exploration of the compiler. + +link:location.mli[Location]:: This module contains utilities +related to locations and error handling. In particular, it contains +handlers that are used for all the error reporting in the compiler. + diff --git a/parsing/ast_helper.ml b/parsing/ast_helper.ml index 82db57bd..ac1fc40d 100644 --- a/parsing/ast_helper.ml +++ b/parsing/ast_helper.ml @@ -65,6 +65,57 @@ module Typ = struct match t.ptyp_desc with | Ptyp_poly _ -> t | _ -> poly ~loc:t.ptyp_loc [] t (* -> ghost? *) + + let varify_constructors var_names t = + let check_variable vl loc v = + if List.mem v vl then + raise Syntaxerr.(Error(Variable_in_scope(loc,v))) in + let var_names = List.map (fun v -> v.txt) var_names in + let rec loop t = + let desc = + match t.ptyp_desc with + | Ptyp_any -> Ptyp_any + | Ptyp_var x -> + check_variable var_names t.ptyp_loc x; + Ptyp_var x + | Ptyp_arrow (label,core_type,core_type') -> + Ptyp_arrow(label, loop core_type, loop core_type') + | Ptyp_tuple lst -> Ptyp_tuple (List.map loop lst) + | Ptyp_constr( { txt = Longident.Lident s }, []) + when List.mem s var_names -> + Ptyp_var s + | Ptyp_constr(longident, lst) -> + Ptyp_constr(longident, List.map loop lst) + | Ptyp_object (lst, o) -> + Ptyp_object + (List.map (fun (s, attrs, t) -> (s, attrs, loop t)) lst, o) + | Ptyp_class (longident, lst) -> + Ptyp_class (longident, List.map loop lst) + | Ptyp_alias(core_type, string) -> + check_variable var_names t.ptyp_loc string; + Ptyp_alias(loop core_type, string) + | Ptyp_variant(row_field_list, flag, lbl_lst_option) -> + Ptyp_variant(List.map loop_row_field row_field_list, + flag, lbl_lst_option) + | Ptyp_poly(string_lst, core_type) -> + List.iter (fun v -> + check_variable var_names t.ptyp_loc v.txt) string_lst; + Ptyp_poly(string_lst, loop core_type) + | Ptyp_package(longident,lst) -> + Ptyp_package(longident,List.map (fun (n,typ) -> (n,loop typ) ) lst) + | Ptyp_extension (s, arg) -> + Ptyp_extension (s, arg) + in + {t with ptyp_desc = desc} + and loop_row_field = + function + | Rtag(label,attrs,flag,lst) -> + Rtag(label,attrs,flag,List.map loop lst) + | Rinherit t -> + Rinherit (loop t) + in + loop t + end module Pat = struct diff --git a/parsing/ast_helper.mli b/parsing/ast_helper.mli index dc5d0dcc..0a216bdb 100644 --- a/parsing/ast_helper.mli +++ b/parsing/ast_helper.mli @@ -61,18 +61,27 @@ module Typ : val tuple: ?loc:loc -> ?attrs:attrs -> core_type list -> core_type val constr: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> core_type val object_: ?loc:loc -> ?attrs:attrs -> - (string * attributes * core_type) list -> closed_flag -> + (str * attributes * core_type) list -> closed_flag -> core_type val class_: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> core_type val alias: ?loc:loc -> ?attrs:attrs -> core_type -> string -> core_type val variant: ?loc:loc -> ?attrs:attrs -> row_field list -> closed_flag -> label list option -> core_type - val poly: ?loc:loc -> ?attrs:attrs -> string list -> core_type -> core_type + val poly: ?loc:loc -> ?attrs:attrs -> str list -> core_type -> core_type val package: ?loc:loc -> ?attrs:attrs -> lid -> (lid * core_type) list -> core_type val extension: ?loc:loc -> ?attrs:attrs -> extension -> core_type val force_poly: core_type -> core_type + + val varify_constructors: str list -> core_type -> core_type + (** [varify_constructors newtypes te] is type expression [te], of which + any of nullary type constructor [tc] is replaced by type variable of + the same name, if [tc]'s name appears in [newtypes]. + Raise [Syntaxerr.Variable_in_scope] if any type variable inside [te] + appears in [newtypes]. + @since 4.05 + *) end (** Patterns *) @@ -143,7 +152,7 @@ module Exp: -> core_type -> expression val constraint_: ?loc:loc -> ?attrs:attrs -> expression -> core_type -> expression - val send: ?loc:loc -> ?attrs:attrs -> expression -> string -> expression + val send: ?loc:loc -> ?attrs:attrs -> expression -> str -> expression val new_: ?loc:loc -> ?attrs:attrs -> lid -> expression val setinstvar: ?loc:loc -> ?attrs:attrs -> str -> expression -> expression val override: ?loc:loc -> ?attrs:attrs -> (str * expression) list @@ -158,7 +167,7 @@ module Exp: val poly: ?loc:loc -> ?attrs:attrs -> expression -> core_type option -> expression val object_: ?loc:loc -> ?attrs:attrs -> class_structure -> expression - val newtype: ?loc:loc -> ?attrs:attrs -> string -> expression -> expression + val newtype: ?loc:loc -> ?attrs:attrs -> str -> expression -> expression val pack: ?loc:loc -> ?attrs:attrs -> module_expr -> expression val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> expression -> expression @@ -354,9 +363,9 @@ module Ctf: val attr: class_type_field -> attribute -> class_type_field val inherit_: ?loc:loc -> ?attrs:attrs -> class_type -> class_type_field - val val_: ?loc:loc -> ?attrs:attrs -> string -> mutable_flag -> + val val_: ?loc:loc -> ?attrs:attrs -> str -> mutable_flag -> virtual_flag -> core_type -> class_type_field - val method_: ?loc:loc -> ?attrs:attrs -> string -> private_flag -> + val method_: ?loc:loc -> ?attrs:attrs -> str -> private_flag -> virtual_flag -> core_type -> class_type_field val constraint_: ?loc:loc -> ?attrs:attrs -> core_type -> core_type -> class_type_field @@ -392,7 +401,7 @@ module Cf: val attr: class_field -> attribute -> class_field val inherit_: ?loc:loc -> ?attrs:attrs -> override_flag -> class_expr -> - string option -> class_field + str option -> class_field val val_: ?loc:loc -> ?attrs:attrs -> str -> mutable_flag -> class_field_kind -> class_field val method_: ?loc:loc -> ?attrs:attrs -> str -> private_flag -> diff --git a/parsing/ast_mapper.ml b/parsing/ast_mapper.ml index ec409be9..d58663ec 100644 --- a/parsing/ast_mapper.ml +++ b/parsing/ast_mapper.ml @@ -101,14 +101,16 @@ module T = struct | Ptyp_constr (lid, tl) -> constr ~loc ~attrs (map_loc sub lid) (List.map (sub.typ sub) tl) | Ptyp_object (l, o) -> - let f (s, a, t) = (s, sub.attributes sub a, sub.typ sub t) in + let f (s, a, t) = + (map_loc sub s, sub.attributes sub a, sub.typ sub t) in object_ ~loc ~attrs (List.map f l) o | Ptyp_class (lid, tl) -> class_ ~loc ~attrs (map_loc sub lid) (List.map (sub.typ sub) tl) | Ptyp_alias (t, s) -> alias ~loc ~attrs (sub.typ sub t) s | Ptyp_variant (rl, b, ll) -> variant ~loc ~attrs (List.map (row_field sub) rl) b ll - | Ptyp_poly (sl, t) -> poly ~loc ~attrs sl (sub.typ sub t) + | Ptyp_poly (sl, t) -> poly ~loc ~attrs + (List.map (map_loc sub) sl) (sub.typ sub t) | Ptyp_package (lid, l) -> package ~loc ~attrs (map_loc sub lid) (List.map (map_tuple (map_loc sub) (sub.typ sub)) l) @@ -197,8 +199,10 @@ module CT = struct let attrs = sub.attributes sub attrs in match desc with | Pctf_inherit ct -> inherit_ ~loc ~attrs (sub.class_type sub ct) - | Pctf_val (s, m, v, t) -> val_ ~loc ~attrs s m v (sub.typ sub t) - | Pctf_method (s, p, v, t) -> method_ ~loc ~attrs s p v (sub.typ sub t) + | Pctf_val (s, m, v, t) -> + val_ ~loc ~attrs (map_loc sub s) m v (sub.typ sub t) + | Pctf_method (s, p, v, t) -> + method_ ~loc ~attrs (map_loc sub s) p v (sub.typ sub t) | Pctf_constraint (t1, t2) -> constraint_ ~loc ~attrs (sub.typ sub t1) (sub.typ sub t2) | Pctf_attribute x -> attribute ~loc (sub.attribute sub x) @@ -360,7 +364,8 @@ module E = struct (sub.typ sub t2) | Pexp_constraint (e, t) -> constraint_ ~loc ~attrs (sub.expr sub e) (sub.typ sub t) - | Pexp_send (e, s) -> send ~loc ~attrs (sub.expr sub e) s + | Pexp_send (e, s) -> + send ~loc ~attrs (sub.expr sub e) (map_loc sub s) | Pexp_new lid -> new_ ~loc ~attrs (map_loc sub lid) | Pexp_setinstvar (s, e) -> setinstvar ~loc ~attrs (map_loc sub s) (sub.expr sub e) @@ -379,7 +384,8 @@ module E = struct | Pexp_poly (e, t) -> poly ~loc ~attrs (sub.expr sub e) (map_opt (sub.typ sub) t) | Pexp_object cls -> object_ ~loc ~attrs (sub.class_structure sub cls) - | Pexp_newtype (s, e) -> newtype ~loc ~attrs s (sub.expr sub e) + | Pexp_newtype (s, e) -> + newtype ~loc ~attrs (map_loc sub s) (sub.expr sub e) | Pexp_pack me -> pack ~loc ~attrs (sub.module_expr sub me) | Pexp_open (ovf, lid, e) -> open_ ~loc ~attrs ovf (map_loc sub lid) (sub.expr sub e) @@ -455,7 +461,9 @@ module CE = struct let loc = sub.location sub loc in let attrs = sub.attributes sub attrs in match desc with - | Pcf_inherit (o, ce, s) -> inherit_ ~loc ~attrs o (sub.class_expr sub ce) s + | Pcf_inherit (o, ce, s) -> + inherit_ ~loc ~attrs o (sub.class_expr sub ce) + (map_opt (map_loc sub) s) | Pcf_val (s, m, k) -> val_ ~loc ~attrs (map_loc sub s) m (map_kind sub k) | Pcf_method (s, p, k) -> method_ ~loc ~attrs (map_loc sub s) p (map_kind sub k) diff --git a/parsing/ast_mapper.mli b/parsing/ast_mapper.mli index 95c365f7..8889d2f3 100644 --- a/parsing/ast_mapper.mli +++ b/parsing/ast_mapper.mli @@ -113,9 +113,9 @@ val tool_name: unit -> string calling it ["ocamlc"], ["ocamlopt"], ["ocamldoc"], ["ocamldep"], ["ocaml"], ... Some global variables that reflect command-line options are automatically synchronized between the calling tool - and the ppx preprocessor: [Clflags.include_dirs], - [Config.load_path], [Clflags.open_modules], [Clflags.for_package], - [Clflags.debug]. *) + and the ppx preprocessor: {!Clflags.include_dirs}, + {!Config.load_path}, {!Clflags.open_modules}, {!Clflags.for_package}, + {!Clflags.debug}. *) val apply: source:string -> target:string -> mapper -> unit @@ -127,7 +127,7 @@ val apply: source:string -> target:string -> mapper -> unit val run_main: (string list -> mapper) -> unit (** Entry point to call to implement a standalone -ppx rewriter from a mapper, parametrized by the command line arguments. The current - unit name can be obtained from [Location.input_name]. This + unit name can be obtained from {!Location.input_name}. This function implements proper error reporting for uncaught exceptions. *) diff --git a/parsing/parser.mly b/parsing/parser.mly index 1b642b2a..f444810e 100644 --- a/parsing/parser.mly +++ b/parsing/parser.mly @@ -219,54 +219,6 @@ let exp_of_label lbl pos = let pat_of_label lbl pos = mkpat (Ppat_var (mkrhs (Longident.last lbl) pos)) -let check_variable vl loc v = - if List.mem v vl then - raise Syntaxerr.(Error(Variable_in_scope(loc,v))) - -let varify_constructors var_names t = - let rec loop t = - let desc = - match t.ptyp_desc with - | Ptyp_any -> Ptyp_any - | Ptyp_var x -> - check_variable var_names t.ptyp_loc x; - Ptyp_var x - | Ptyp_arrow (label,core_type,core_type') -> - Ptyp_arrow(label, loop core_type, loop core_type') - | Ptyp_tuple lst -> Ptyp_tuple (List.map loop lst) - | Ptyp_constr( { txt = Lident s }, []) when List.mem s var_names -> - Ptyp_var s - | Ptyp_constr(longident, lst) -> - Ptyp_constr(longident, List.map loop lst) - | Ptyp_object (lst, o) -> - Ptyp_object - (List.map (fun (s, attrs, t) -> (s, attrs, loop t)) lst, o) - | Ptyp_class (longident, lst) -> - Ptyp_class (longident, List.map loop lst) - | Ptyp_alias(core_type, string) -> - check_variable var_names t.ptyp_loc string; - Ptyp_alias(loop core_type, string) - | Ptyp_variant(row_field_list, flag, lbl_lst_option) -> - Ptyp_variant(List.map loop_row_field row_field_list, - flag, lbl_lst_option) - | Ptyp_poly(string_lst, core_type) -> - List.iter (check_variable var_names t.ptyp_loc) string_lst; - Ptyp_poly(string_lst, loop core_type) - | Ptyp_package(longident,lst) -> - Ptyp_package(longident,List.map (fun (n,typ) -> (n,loop typ) ) lst) - | Ptyp_extension (s, arg) -> - Ptyp_extension (s, arg) - in - {t with ptyp_desc = desc} - and loop_row_field = - function - | Rtag(label,attrs,flag,lst) -> - Rtag(label,attrs,flag,List.map loop lst) - | Rinherit t -> - Rinherit (loop t) - in - loop t - let mk_newtypes newtypes exp = List.fold_right (fun newtype exp -> mkexp (Pexp_newtype (newtype, exp))) newtypes exp @@ -274,7 +226,7 @@ let mk_newtypes newtypes exp = let wrap_type_annotation newtypes core_type body = let exp = mkexp(Pexp_constraint(body,core_type)) in let exp = mk_newtypes newtypes exp in - (exp, ghtyp(Ptyp_poly(newtypes,varify_constructors newtypes core_type))) + (exp, ghtyp(Ptyp_poly(newtypes, Typ.varify_constructors newtypes core_type))) let wrap_exp_attrs body (ext, attrs) = (* todo: keep exact location for the entire attribute *) @@ -763,13 +715,20 @@ module_expr: (fun acc (n, t) -> mkmod(Pmod_functor(n, t, acc))) $5 $3 in wrap_mod_attrs modexp $2 } - | module_expr LPAREN module_expr RPAREN - { mkmod(Pmod_apply($1, $3)) } + | module_expr paren_module_expr + { mkmod(Pmod_apply($1, $2)) } | module_expr LPAREN RPAREN { mkmod(Pmod_apply($1, mkmod (Pmod_structure []))) } - | module_expr LPAREN module_expr error - { unclosed "(" 2 ")" 4 } - | LPAREN module_expr COLON module_type RPAREN + | paren_module_expr + { $1 } + | module_expr attribute + { Mod.attr $1 $2 } + | extension + { mkmod(Pmod_extension $1) } +; + +paren_module_expr: + LPAREN module_expr COLON module_type RPAREN { mkmod(Pmod_constraint($2, $4)) } | LPAREN module_expr COLON module_type error { unclosed "(" 1 ")" 5 } @@ -799,10 +758,6 @@ module_expr: { unclosed "(" 1 ")" 6 } | LPAREN VAL attributes expr error { unclosed "(" 1 ")" 5 } - | module_expr attribute - { Mod.attr $1 $2 } - | extension - { mkmod(Pmod_extension $1) } ; structure: @@ -1141,7 +1096,7 @@ class_field: ; parent_binder: AS LIDENT - { Some $2 } + { Some (mkrhs $2 2) } | /* empty */ { None } ; @@ -1234,7 +1189,7 @@ class_sig_field: post_item_attributes { let (p, v) = $3 in - mkctf (Pctf_method ($4, p, v, $6)) ~attrs:($2@$7) ~docs:(symbol_docs ()) + mkctf (Pctf_method (mkrhs $4 4, p, v, $6)) ~attrs:($2@$7) ~docs:(symbol_docs ()) } | CONSTRAINT attributes constrain_field post_item_attributes { mkctf (Pctf_constraint $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } @@ -1246,11 +1201,11 @@ class_sig_field: ; value_type: VIRTUAL mutable_flag label COLON core_type - { $3, $2, Virtual, $5 } + { mkrhs $3 3, $2, Virtual, $5 } | MUTABLE virtual_flag label COLON core_type - { $3, Mutable, $2, $5 } + { mkrhs $3 3, Mutable, $2, $5 } | label COLON core_type - { $1, Immutable, Concrete, $3 } + { mkrhs $1 1, Immutable, Concrete, $3 } ; constrain: core_type EQUAL core_type { $1, $3, symbol_rloc() } @@ -1565,7 +1520,7 @@ simple_expr: | mod_longident DOT LBRACELESS field_expr_list error { unclosed "{<" 3 ">}" 5 } | simple_expr HASH label - { mkexp(Pexp_send($1, $3)) } + { mkexp(Pexp_send($1, mkrhs $3 3)) } | simple_expr HASHOP simple_expr { mkinfix $1 $2 $3 } | LPAREN MODULE ext_attributes module_expr RPAREN @@ -1613,8 +1568,8 @@ label_ident: LIDENT { ($1, mkexp(Pexp_ident(mkrhs (Lident $1) 1))) } ; lident_list: - LIDENT { [$1] } - | LIDENT lident_list { $1 :: $2 } + LIDENT { [mkrhs $1 1] } + | LIDENT lident_list { mkrhs $1 1 :: $2 } ; let_binding_body: val_ident fun_binding @@ -2187,8 +2142,8 @@ with_type_binder: /* Polymorphic types */ typevar_list: - QUOTE ident { [$2] } - | typevar_list QUOTE ident { $3 :: $1 } + QUOTE ident { [mkrhs $2 2] } + | typevar_list QUOTE ident { mkrhs $3 3 :: $1 } ; poly_type: core_type @@ -2336,7 +2291,7 @@ meth_list: ; field: label COLON poly_type_no_attr attributes - { ($1, add_info_attrs (symbol_info ()) $4, $3) } + { (mkrhs $1 1, add_info_attrs (symbol_info ()) $4, $3) } ; field_semi: @@ -2346,7 +2301,7 @@ field_semi: | Some _ as info_before_semi -> info_before_semi | None -> symbol_info () in - ($1, add_info_attrs info ($4 @ $6), $3) } + (mkrhs $1 1, add_info_attrs info ($4 @ $6), $3) } ; label: diff --git a/parsing/parsetree.mli b/parsing/parsetree.mli index d61b3392..1155ddc9 100644 --- a/parsing/parsetree.mli +++ b/parsing/parsetree.mli @@ -93,7 +93,7 @@ and core_type_desc = T tconstr (T1, ..., Tn) tconstr *) - | Ptyp_object of (string * attributes * core_type) list * closed_flag + | Ptyp_object of (string loc * attributes * core_type) list * closed_flag (* < l1:T1; ...; ln:Tn > (flag = Closed) < l1:T1; ...; ln:Tn; .. > (flag = Open) *) @@ -110,7 +110,7 @@ and core_type_desc = [< `A|`B ] (flag = Closed; labels = Some []) [< `A|`B > `X `Y ](flag = Closed; labels = Some ["X";"Y"]) *) - | Ptyp_poly of string list * core_type + | Ptyp_poly of string loc list * core_type (* 'a1 ... 'an. T Can only appear in the following context: @@ -221,6 +221,7 @@ and pattern_desc = | Ppat_extension of extension (* [%id] *) | Ppat_open of Longident.t loc * pattern + (* M.(P) *) (* Value expressions *) @@ -309,7 +310,7 @@ and expression_desc = (* (E :> T) (None, T) (E : T0 :> T) (Some T0, T) *) - | Pexp_send of expression * string + | Pexp_send of expression * string loc (* E # m *) | Pexp_new of Longident.t loc (* new M.c *) @@ -334,7 +335,7 @@ and expression_desc = for methods (not values). *) | Pexp_object of class_structure (* object ... end *) - | Pexp_newtype of string * expression + | Pexp_newtype of string loc * expression (* fun (type t) -> E *) | Pexp_pack of module_expr (* (module ME) @@ -342,9 +343,9 @@ and expression_desc = (module ME : S) is represented as Pexp_constraint(Pexp_pack, Ptyp_package S) *) | Pexp_open of override_flag * Longident.t loc * expression - (* let open M in E - let! open M in E - *) + (* M.(E) + let open M in E + let! open M in E *) | Pexp_extension of extension (* [%id] *) | Pexp_unreachable @@ -520,9 +521,9 @@ and class_type_field = and class_type_field_desc = | Pctf_inherit of class_type (* inherit CT *) - | Pctf_val of (string * mutable_flag * virtual_flag * core_type) + | Pctf_val of (string loc * mutable_flag * virtual_flag * core_type) (* val x: T *) - | Pctf_method of (string * private_flag * virtual_flag * core_type) + | Pctf_method of (string loc * private_flag * virtual_flag * core_type) (* method x: T Note: T can be a Ptyp_poly. @@ -608,7 +609,7 @@ and class_field = } and class_field_desc = - | Pcf_inherit of override_flag * class_expr * string option + | Pcf_inherit of override_flag * class_expr * string loc option (* inherit CE inherit CE as x inherit! CE diff --git a/parsing/pprintast.ml b/parsing/pprintast.ml index f9e51522..c6f48d16 100644 --- a/parsing/pprintast.ml +++ b/parsing/pprintast.ml @@ -26,6 +26,7 @@ open Format open Location open Longident open Parsetree +open Ast_helper let prefix_symbols = [ '!'; '?'; '~' ] ;; let infix_symbols = [ '='; '<'; '>'; '@'; '^'; '|'; '&'; '+'; '-'; '*'; '/'; @@ -47,7 +48,7 @@ let fixity_of_string = function let view_fixity_of_exp = function | {pexp_desc = Pexp_ident {txt=Lident l;_};_} -> fixity_of_string l - | _ -> `Normal ;; + | _ -> `Normal let is_infix = function | `Infix _ -> true | _ -> false @@ -217,6 +218,7 @@ let private_flag f = function let constant_string f s = pp f "%S" s let tyvar f str = pp f "'%s" str +let tyvar_loc f str = pp f "'%s" str.txt let string_quot f x = pp f "`%s" x (* c ['a,'b] *) @@ -251,7 +253,7 @@ and core_type ctxt f x = | [] -> () | _ -> pp f "%a@;.@;" - (list tyvar ~sep:"@;") l) + (list tyvar_loc ~sep:"@;") l) l) sl (core_type ctxt) ct | _ -> pp f "@[<2>%a@]" (core_type1 ctxt) x @@ -299,7 +301,7 @@ and core_type1 ctxt f x = (list string_quot) xs) low | Ptyp_object (l, o) -> let core_field_type f (s, attrs, ct) = - pp f "@[%s: %a@ %a@ @]" s + pp f "@[%s: %a@ %a@ @]" s.txt (core_type ctxt) ct (attributes ctxt) attrs (* Cf #7200 *) in let field_var f = function @@ -545,8 +547,8 @@ and expression ctxt f x = then String.sub s 1 (String.length s -1) else s in begin match l with - | [(Nolabel, _) as v] -> - pp f "@[<2>%s@;%a@]" s (label_x_expression_param ctxt) v + | [(Nolabel, x)] -> + pp f "@[<2>%s@;%a@]" s (simple_expr ctxt) x | _ -> pp f "@[<2>%a %a@]" (simple_expr ctxt) e (list (label_x_expression_param ctxt)) l @@ -570,7 +572,7 @@ and expression ctxt f x = | _ -> assert false) | Pexp_setfield (e1, li, e2) -> pp f "@[<2>%a.%a@ <-@ %a@]" - (simple_expr ctxt) e1 longident_loc li (expression ctxt) e2 + (simple_expr ctxt) e1 longident_loc li (simple_expr ctxt) e2 | Pexp_ifthenelse (e1, e2, eo) -> (* @;@[<2>else@ %a@]@] *) let fmt:(_,_,_)format ="@[@[<2>if@ %a@]@;@[<2>then@ %a@]%a@]" in @@ -636,7 +638,7 @@ and expression2 ctxt f x = else match x.pexp_desc with | Pexp_field (e, li) -> pp f "@[%a.%a@]" (simple_expr ctxt) e longident_loc li - | Pexp_send (e, s) -> pp f "@[%a#%s@]" (simple_expr ctxt) e s + | Pexp_send (e, s) -> pp f "@[%a#%s@]" (simple_expr ctxt) e s.txt | _ -> simple_expr ctxt f x @@ -661,7 +663,7 @@ and simple_expr ctxt f x = | Pexp_pack me -> pp f "(module@;%a)" (module_expr ctxt) me | Pexp_newtype (lid, e) -> - pp f "fun@;(type@;%s)@;->@;%a" lid (expression ctxt) e + pp f "fun@;(type@;%s)@;->@;%a" lid.txt (expression ctxt) e | Pexp_tuple l -> pp f "@[(%a)@]" (list (simple_expr ctxt) ~sep:",@;") l | Pexp_constraint (e, ct) -> @@ -737,11 +739,11 @@ and class_signature ctxt f { pcsig_self = ct; pcsig_fields = l ;_} = (item_attributes ctxt) x.pctf_attributes | Pctf_val (s, mf, vf, ct) -> pp f "@[<2>val @ %a%a%s@ :@ %a@]%a" - mutable_flag mf virtual_flag vf s (core_type ctxt) ct + mutable_flag mf virtual_flag vf s.txt (core_type ctxt) ct (item_attributes ctxt) x.pctf_attributes | Pctf_method (s, pf, vf, ct) -> pp f "@[<2>method %a %a%s :@;%a@]%a" - private_flag pf virtual_flag vf s (core_type ctxt) ct + private_flag pf virtual_flag vf s.txt (core_type ctxt) ct (item_attributes ctxt) x.pctf_attributes | Pctf_constraint (ct1, ct2) -> pp f "@[<2>constraint@ %a@ =@ %a@]%a" @@ -804,7 +806,7 @@ and class_field ctxt f x = (class_expr ctxt) ce (fun f so -> match so with | None -> (); - | Some (s) -> pp f "@ as %s" s ) so + | Some (s) -> pp f "@ as %s" s.txt ) so (item_attributes ctxt) x.pcf_attributes | Pcf_val (s, mf, Cfk_concrete (ovf, e)) -> pp f "@[<2>val%s %a%s =@;%a@]%a" (override ovf) @@ -1077,28 +1079,54 @@ and binding ctxt f {pvb_pat=p; pvb_expr=x; _} = pp f "%a@ %a" (label_exp ctxt) (label,eo,p) pp_print_pexp_function e | Pexp_newtype (str,e) -> - pp f "(type@ %s)@ %a" str pp_print_pexp_function e + pp f "(type@ %s)@ %a" str.txt pp_print_pexp_function e | _ -> pp f "=@;%a" (expression ctxt) x in + let tyvars_str tyvars = List.map (fun v -> v.txt) tyvars in + let is_desugared_gadt p e = + let gadt_pattern = + match p.ppat_desc with + | Ppat_constraint({ppat_desc=Ppat_var _} as pat, + {ptyp_desc=Ptyp_poly (args_tyvars, rt)}) -> + Some (pat, args_tyvars, rt) + | _ -> None in + let rec gadt_exp tyvars e = + match e.pexp_desc with + | Pexp_newtype (tyvar, e) -> gadt_exp (tyvar :: tyvars) e + | Pexp_constraint (e, ct) -> Some (List.rev tyvars, e, ct) + | _ -> None in + let gadt_exp = gadt_exp [] e in + match gadt_pattern, gadt_exp with + | Some (p, pt_tyvars, pt_ct), Some (e_tyvars, e, e_ct) + when tyvars_str pt_tyvars = tyvars_str e_tyvars -> + let ety = Typ.varify_constructors e_tyvars e_ct in + if ety = pt_ct then + Some (p, pt_tyvars, e_ct, e) else None + | _ -> None in if x.pexp_attributes <> [] - then pp f "%a@;=@;%a" (pattern ctxt) p (expression ctxt) x - else match (x.pexp_desc,p.ppat_desc) with - | ( _ , Ppat_constraint( p ,ty)) -> (* special case for the first*) - begin match ty.ptyp_desc with - | Ptyp_poly _ -> - pp f "%a@;:@;%a@;=@;%a" (simple_pattern ctxt) p - (core_type ctxt) ty (expression ctxt) x - | _ -> - pp f "(%a@;:@;%a)@;=@;%a" (simple_pattern ctxt) p - (core_type ctxt) ty (expression ctxt) x - end - | Pexp_constraint (e,t1),Ppat_var {txt;_} -> - pp f "%a@;:@ %a@;=@;%a" protect_ident txt - (core_type ctxt) t1 (expression ctxt) e - | (_, Ppat_var _) -> - pp f "%a@ %a" (simple_pattern ctxt) p pp_print_pexp_function x - | _ -> - pp f "%a@;=@;%a" (pattern ctxt) p (expression ctxt) x + then pp f "%a@;=@;%a" (pattern ctxt) p (expression ctxt) x else + match is_desugared_gadt p x with + | Some (p, tyvars, ct, e) -> begin + pp f "%a@;: type@;%a.%a@;=@;%a" + (simple_pattern ctxt) p (list pp_print_string ~sep:"@;") + (tyvars_str tyvars) (core_type ctxt) ct (expression ctxt) e + end + | None -> begin + match (x.pexp_desc,p.ppat_desc) with + | ( _ , Ppat_constraint( p ,ty)) -> (* special case for the first*) + begin match ty.ptyp_desc with + | Ptyp_poly _ -> + pp f "%a@;:@;%a@;=@;%a" (simple_pattern ctxt) p + (core_type ctxt) ty (expression ctxt) x + | _ -> + pp f "(%a@;:@;%a)@;=@;%a" (simple_pattern ctxt) p + (core_type ctxt) ty (expression ctxt) x + end + | (_, Ppat_var _) -> + pp f "%a@ %a" (simple_pattern ctxt) p pp_print_pexp_function x + | _ -> + pp f "%a@;=@;%a" (pattern ctxt) p (expression ctxt) x + end (* [in] is not printed *) and bindings ctxt f (rf,l) = diff --git a/parsing/printast.ml b/parsing/printast.ml index 673defb6..6e167b3e 100644 --- a/parsing/printast.ml +++ b/parsing/printast.ml @@ -165,7 +165,7 @@ let rec core_type i ppf x = let i = i + 1 in List.iter (fun (s, attrs, t) -> - line i ppf "method %s\n" s; + line i ppf "method %s\n" s.txt; attributes i ppf attrs; core_type (i + 1) ppf t ) @@ -178,7 +178,7 @@ let rec core_type i ppf x = core_type i ppf ct; | Ptyp_poly (sl, ct) -> line i ppf "Ptyp_poly%a\n" - (fun ppf -> List.iter (fun x -> fprintf ppf " '%s" x)) sl; + (fun ppf -> List.iter (fun x -> fprintf ppf " '%s" x.txt)) sl; core_type i ppf ct; | Ptyp_package (s, l) -> line i ppf "Ptyp_package %a\n" fmt_longident_loc s; @@ -331,7 +331,7 @@ and expression i ppf x = option i core_type ppf cto1; core_type i ppf cto2; | Pexp_send (e, s) -> - line i ppf "Pexp_send \"%s\"\n" s; + line i ppf "Pexp_send \"%s\"\n" s.txt; expression i ppf e; | Pexp_new (li) -> line i ppf "Pexp_new %a\n" fmt_longident_loc li; | Pexp_setinstvar (s, e) -> @@ -362,7 +362,7 @@ and expression i ppf x = line i ppf "Pexp_object\n"; class_structure i ppf s | Pexp_newtype (s, e) -> - line i ppf "Pexp_newtype \"%s\"\n" s; + line i ppf "Pexp_newtype \"%s\"\n" s.txt; expression i ppf e | Pexp_pack me -> line i ppf "Pexp_pack\n"; @@ -497,11 +497,11 @@ and class_type_field i ppf x = line i ppf "Pctf_inherit\n"; class_type i ppf ct; | Pctf_val (s, mf, vf, ct) -> - line i ppf "Pctf_val \"%s\" %a %a\n" s fmt_mutable_flag mf + line i ppf "Pctf_val \"%s\" %a %a\n" s.txt fmt_mutable_flag mf fmt_virtual_flag vf; core_type (i+1) ppf ct; | Pctf_method (s, pf, vf, ct) -> - line i ppf "Pctf_method \"%s\" %a %a\n" s fmt_private_flag pf + line i ppf "Pctf_method \"%s\" %a %a\n" s.txt fmt_private_flag pf fmt_virtual_flag vf; core_type (i+1) ppf ct; | Pctf_constraint (ct1, ct2) -> @@ -583,7 +583,7 @@ and class_field i ppf x = | Pcf_inherit (ovf, ce, so) -> line i ppf "Pcf_inherit %a\n" fmt_override_flag ovf; class_expr (i+1) ppf ce; - option (i+1) string ppf so; + option (i+1) string_loc ppf so; | Pcf_val (s, mf, k) -> line i ppf "Pcf_val %a\n" fmt_mutable_flag mf; line (i+1) ppf "%a\n" fmt_string_loc s; diff --git a/stdlib/.depend b/stdlib/.depend index 45827a92..961b1fd7 100644 --- a/stdlib/.depend +++ b/stdlib/.depend @@ -178,9 +178,9 @@ stringLabels.cmi : sys.cmo : sys.cmi sys.cmx : sys.cmi sys.cmi : -uchar.cmo : printf.cmi pervasives.cmi format.cmi char.cmi uchar.cmi -uchar.cmx : printf.cmx pervasives.cmx format.cmx char.cmx uchar.cmi -uchar.cmi : format.cmi +uchar.cmo : pervasives.cmi char.cmi uchar.cmi +uchar.cmx : pervasives.cmx char.cmx uchar.cmi +uchar.cmi : weak.cmo : sys.cmi obj.cmi hashtbl.cmi array.cmi weak.cmi weak.cmx : sys.cmx obj.cmx hashtbl.cmx array.cmx weak.cmi weak.cmi : hashtbl.cmi @@ -314,7 +314,7 @@ stringLabels.cmo : string.cmi stringLabels.cmi stringLabels.p.cmx : string.cmx stringLabels.cmi sys.cmo : sys.cmi sys.p.cmx : sys.cmi -uchar.cmo : printf.cmi pervasives.cmi format.cmi char.cmi uchar.cmi -uchar.p.cmx : printf.cmx pervasives.cmx format.cmx char.cmx uchar.cmi +uchar.cmo : pervasives.cmi char.cmi uchar.cmi +uchar.p.cmx : pervasives.cmx char.cmx uchar.cmi weak.cmo : sys.cmi obj.cmi hashtbl.cmi array.cmi weak.cmi weak.p.cmx : sys.cmx obj.cmx hashtbl.cmx array.cmx weak.cmi diff --git a/stdlib/Makefile b/stdlib/Makefile index 05ee26ab..004329a7 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -13,66 +13,238 @@ #* * #************************************************************************** -include Makefile.shared +include ../config/Makefile +CAMLRUN ?= ../boot/ocamlrun +CAMLYACC ?= ../boot/ocamlyacc +TARGET_BINDIR ?= $(BINDIR) -allopt: - $(MAKE) stdlib.cmxa std_exit.cmx - $(MAKE) allopt-$(PROFILING) +COMPILER=../ocamlc +CAMLC=$(CAMLRUN) $(COMPILER) +COMPFLAGS=-strict-sequence -absname -w +a-4-9-41-42-44-45-48 \ + -g -warn-error A -bin-annot -nostdlib \ + -safe-string -strict-formats +ifeq "$(FLAMBDA)" "true" +OPTCOMPFLAGS=-O3 +else +OPTCOMPFLAGS= +endif +OPTCOMPILER=../ocamlopt +CAMLOPT=$(CAMLRUN) $(OPTCOMPILER) +CAMLDEP=$(CAMLRUN) ../tools/ocamldep +OBJS=camlinternalFormatBasics.cmo pervasives.cmo $(OTHERS) +OTHERS=list.cmo char.cmo uchar.cmo bytes.cmo string.cmo sys.cmo \ + sort.cmo marshal.cmo obj.cmo array.cmo \ + int32.cmo int64.cmo nativeint.cmo \ + lexing.cmo parsing.cmo \ + set.cmo map.cmo stack.cmo queue.cmo \ + camlinternalLazy.cmo lazy.cmo stream.cmo \ + buffer.cmo camlinternalFormat.cmo printf.cmo \ + arg.cmo printexc.cmo gc.cmo \ + digest.cmo random.cmo hashtbl.cmo weak.cmo \ + format.cmo scanf.cmo callback.cmo \ + camlinternalOO.cmo oo.cmo camlinternalMod.cmo \ + genlex.cmo ephemeron.cmo \ + filename.cmo complex.cmo \ + arrayLabels.cmo listLabels.cmo bytesLabels.cmo \ + stringLabels.cmo moreLabels.cmo stdLabels.cmo \ + spacetime.cmo + +.PHONY: all +all: stdlib.cma std_exit.cmo camlheader target_camlheader camlheader_ur + +ifeq "$(RUNTIMED)" "true" +all: camlheaderd +endif + +ifeq "$(RUNTIMEI)" "true" +all: camlheaderi +endif + +ifeq "$(PROFILING)" "true" +PROFILINGTARGET = prof +else +PROFILINGTARGET = noprof +endif + +.PHONY: allopt +allopt: stdlib.cmxa std_exit.cmx allopt-$(PROFILINGTARGET) + +.PHONY: allopt-noprof allopt-noprof: +.PHONY: allopt-prof allopt-prof: stdlib.p.cmxa std_exit.p.cmx rm -f std_exit.p.cmi -installopt: installopt-default installopt-$(PROFILING) +INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) + +.PHONY: install +install:: + cp stdlib.cma std_exit.cmo *.cmi *.cmt *.cmti *.mli *.ml \ + camlheader_ur \ + "$(INSTALL_LIBDIR)" + cp target_camlheader "$(INSTALL_LIBDIR)/camlheader" + +ifeq "$(RUNTIMED)" "true" +install:: + cp target_camlheaderd $(INSTALL_LIBDIR) +endif + +ifeq "$(RUNTIMEI)" "true" +install:: + cp target_camlheaderi $(INSTALL_LIBDIR) +endif +.PHONY: installopt +installopt: installopt-default installopt-$(PROFILINGTARGET) + +.PHONY: installopt-default installopt-default: - cp stdlib.cmxa stdlib.a std_exit.o *.cmx "$(INSTALL_LIBDIR)" - cd "$(INSTALL_LIBDIR)"; $(RANLIB) stdlib.a + cp stdlib.cmxa stdlib.$(A) std_exit.$(O) *.cmx "$(INSTALL_LIBDIR)" + cd "$(INSTALL_LIBDIR)"; $(RANLIB) stdlib.$(A) +.PHONY: installopt-noprof installopt-noprof: - rm -f "$(INSTALL_LIBDIR)/stdlib.p.cmxa"; \ - ln -s stdlib.cmxa "$(INSTALL_LIBDIR)/stdlib.p.cmxa" - rm -f "$(INSTALL_LIBDIR)/stdlib.p.a"; \ - ln -s stdlib.a "$(INSTALL_LIBDIR)/stdlib.p.a" - rm -f "$(INSTALL_LIBDIR)/std_exit.p.cmx"; \ - ln -s std_exit.cmx "$(INSTALL_LIBDIR)/std_exit.p.cmx" - rm -f "$(INSTALL_LIBDIR)/std_exit.p.o"; \ - ln -s std_exit.o "$(INSTALL_LIBDIR)/std_exit.p.o" +.PHONY: installopt-prof installopt-prof: - cp stdlib.p.cmxa stdlib.p.a std_exit.p.cmx std_exit.p.o \ + cp stdlib.p.cmxa stdlib.p.$(A) std_exit.p.cmx std_exit.p.$(O) \ "$(INSTALL_LIBDIR)" - cd "$(INSTALL_LIBDIR)"; $(RANLIB) stdlib.p.a + cd "$(INSTALL_LIBDIR)"; $(RANLIB) stdlib.p.$(A) + +ifeq "$(UNIX_OR_WIN32)" "unix" +HEADERPROGRAM = header.c +else # Windows +HEADERPROGRAM = headernt.c +endif + +CAMLHEADERS =\ + camlheader target_camlheader camlheader_ur \ + camlheaderd target_camlheaderd \ + camlheaderi target_camlheaderi + +ifeq "$(HASHBANGSCRIPTS)" "true" +$(CAMLHEADERS): ../config/Makefile + for suff in '' d i; do \ + echo '#!$(BINDIR)/ocamlrun'$$suff > camlheader$$suff && \ + echo '#!$(TARGET_BINDIR)/ocamlrun'$$suff >target_camlheader$$suff; \ + done && \ + echo '#!' | tr -d '\012' > camlheader_ur; +else # Hashbang scripts not supported + +$(CAMLHEADERS): $(HEADERPROGRAM) ../config/Makefile + +ifeq "$(UNIX_OR_WIN32)" "unix" +$(CAMLHEADERS): + for suff in '' d i; do \ + $(BYTECC) $(BYTECCCOMPOPTS) $(BYTECCLINKOPTS) \ + -DRUNTIME_NAME='"$(BINDIR)/ocamlrun'$$suff'"' \ + header.c -o tmpheader$(EXE) && \ + strip tmpheader$(EXE) && \ + mv tmpheader$(EXE) camlheader$$suff && \ + $(BYTECC) $(BYTECCCOMPOPTS) $(BYTECCLINKOPTS) \ + -DRUNTIME_NAME='"$(TARGET_BINDIR)/ocamlrun'$$suff'"' \ + header.c -o tmpheader$(EXE) && \ + strip tmpheader$(EXE) && \ + mv tmpheader$(EXE) target_camlheader$$suff; \ + done && \ + cp camlheader camlheader_ur + +else # Windows + +# TODO: see whether there is a way to further merge the rules below +# with those above + +camlheader target_camlheader camlheader_ur: + $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \ + -DRUNTIME_NAME='"ocamlrun"' headernt.c + $(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS) + rm -f camlheader.exe + mv tmpheader.exe camlheader + cp camlheader target_camlheader + cp camlheader camlheader_ur + +camlheaderd target_camlheaderd: + $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \ + -DRUNTIME_NAME='"ocamlrund"' headernt.c + $(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS) + mv tmpheader.exe camlheaderd + cp camlheaderd target_camlheaderd + +camlheaderi: + $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \ + -DRUNTIME_NAME='"ocamlruni"' headernt.c + $(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS) + mv tmpheader.exe camlheaderi + +# TODO: do not call flexlink to build tmpheader.exe (we don't need +# the export table) + +endif # ifeq "$(UNIX_OR_WIN32)" "unix" + +endif # ifeq "$(HASHBANGSCRIPTS)" "true" + +stdlib.cma: $(OBJS) + $(CAMLC) -a -o $@ $^ + +stdlib.cmxa: $(OBJS:.cmo=.cmx) + $(CAMLOPT) -a -o $@ $^ stdlib.p.cmxa: $(OBJS:.cmo=.p.cmx) - $(CAMLOPT) -a -o stdlib.p.cmxa $(OBJS:.cmo=.p.cmx) - -camlheader target_camlheader camlheader_ur \ -camlheaderd target_camlheaderd \ -camlheaderi target_camlheaderi: \ - header.c ../config/Makefile - if $(HASHBANGSCRIPTS); then \ - for suff in '' d i; do \ - echo '#!$(BINDIR)/ocamlrun'$$suff > camlheader$$suff && \ - echo '#!$(TARGET_BINDIR)/ocamlrun'$$suff >target_camlheader$$suff; \ - done && \ - echo '#!' | tr -d '\012' > camlheader_ur; \ - else \ - for suff in '' d i; do \ - $(BYTECC) $(BYTECCCOMPOPTS) $(BYTECCLINKOPTS) \ - -DRUNTIME_NAME='"$(BINDIR)/ocamlrun'$$suff'"' \ - header.c -o tmpheader$(EXE) && \ - strip tmpheader$(EXE) && \ - mv tmpheader$(EXE) camlheader$$suff && \ - $(BYTECC) $(BYTECCCOMPOPTS) $(BYTECCLINKOPTS) \ - -DRUNTIME_NAME='"$(TARGET_BINDIR)/ocamlrun'$$suff'"' \ - header.c -o tmpheader$(EXE) && \ - strip tmpheader$(EXE) && \ - mv tmpheader$(EXE) target_camlheader$$suff; \ - done && \ - cp camlheader camlheader_ur; \ - fi - -.PHONY: all allopt allopt-noprof allopt-prof install installopt -.PHONY: installopt-default installopt-noprof installopt-prof clean depend + $(CAMLOPT) -a -o $@ $^ + +sys.ml: sys.mlp ../VERSION + sed -e "s|%%VERSION%%|`sed -e 1q ../VERSION | tr -d '\r'`|" sys.mlp > $@ + +.PHONY: clean +clean:: + rm -f sys.ml + +clean:: + rm -f $(CAMLHEADERS) + +.SUFFIXES: .mli .ml .cmi .cmo .cmx .p.cmx + +.mli.cmi: + $(CAMLC) $(COMPFLAGS) `sh ./Compflags $@` -c $< + +.ml.cmo: + $(CAMLC) $(COMPFLAGS) `sh ./Compflags $@` -c $< + +.ml.cmx: + $(CAMLOPT) $(COMPFLAGS) $(OPTCOMPFLAGS) `sh ./Compflags $@` -c $< + +.ml.p.cmx: + $(CAMLOPT) $(COMPFLAGS) $(OPTCOMPFLAGS) `sh ./Compflags $@` \ + -p -c -o $*.p.cmx $< + +# Dependencies on the compiler +COMPILER_DEPS=$(filter-out -use-prims, $(COMPILER)) +$(OBJS) std_exit.cmo: $(COMPILER_DEPS) +$(OBJS:.cmo=.cmi) std_exit.cmi: $(COMPILER_DEPS) +$(OBJS:.cmo=.cmx) std_exit.cmx: $(OPTCOMPILER) +$(OBJS:.cmo=.p.cmx) std_exit.p.cmx: $(OPTCOMPILER) + +# Dependencies on Pervasives (not tracked by ocamldep) +$(OTHERS) std_exit.cmo: pervasives.cmi +$(OTHERS:.cmo=.cmi) std_exit.cmi: pervasives.cmi +$(OBJS:.cmo=.cmx) std_exit.cmx: pervasives.cmi +$(OBJS:.cmo=.p.cmx) std_exit.p.cmx: pervasives.cmi +$(OTHERS:.cmo=.cmx) std_exit.cmx: pervasives.cmx +$(OTHERS:.cmo=.p.cmx) std_exit.p.cmx: pervasives.cmx + +clean:: + rm -f *.cm* *.$(O) *.$(A) + rm -f *~ + rm -f camlheader* + +include .depend + +# Note that .p.cmx targets do not depend (for compilation) upon other +# .p.cmx files. When the compiler imports another compilation unit, +# it looks for the .cmx file (not .p.cmx). +.PHONY: depend +depend: + $(CAMLDEP) -slash *.mli *.ml > .depend + $(CAMLDEP) -slash *.ml | sed -e 's/\.cmx : /.p.cmx : /g' >>.depend diff --git a/stdlib/Makefile.nt b/stdlib/Makefile.nt index 7b4ce68f..ed9900bb 100644 --- a/stdlib/Makefile.nt +++ b/stdlib/Makefile.nt @@ -13,34 +13,4 @@ #* * #************************************************************************** -include Makefile.shared - -allopt: stdlib.cmxa std_exit.cmx - -installopt: - cp stdlib.cmxa stdlib.$(A) std_exit.$(O) *.cmx "$(INSTALL_LIBDIR)" - -camlheader target_camlheader camlheader_ur: headernt.c ../config/Makefile - $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \ - -DRUNTIME_NAME='"ocamlrun"' headernt.c - $(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS) - rm -f camlheader.exe - mv tmpheader.exe camlheader - cp camlheader target_camlheader - cp camlheader camlheader_ur - -camlheaderd target_camlheaderd: headernt.c ../config/Makefile - $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \ - -DRUNTIME_NAME='"ocamlrund"' headernt.c - $(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS) - mv tmpheader.exe camlheaderd - cp camlheaderd target_camlheaderd - -camlheaderi: headernt.c ../config/Makefile - $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \ - -DRUNTIME_NAME='"ocamlruni"' headernt.c - $(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS) - mv tmpheader.exe camlheaderi - -# TODO: do not call flexlink to build tmpheader.exe (we don't need -# the export table) +include Makefile diff --git a/stdlib/Makefile.shared b/stdlib/Makefile.shared deleted file mode 100755 index 1956657a..00000000 --- a/stdlib/Makefile.shared +++ /dev/null @@ -1,138 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include ../config/Makefile -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc -TARGET_BINDIR ?= $(BINDIR) - -COMPILER=../ocamlc -CAMLC=$(CAMLRUN) $(COMPILER) -COMPFLAGS=-strict-sequence -absname -w +a-4-9-41-42-44-45-48 \ - -g -warn-error A -bin-annot -nostdlib \ - -safe-string -strict-formats -ifeq "$(FLAMBDA)" "true" -OPTCOMPFLAGS=-O3 -else -OPTCOMPFLAGS= -endif -OPTCOMPILER=../ocamlopt -CAMLOPT=$(CAMLRUN) $(OPTCOMPILER) -CAMLDEP=$(CAMLRUN) ../tools/ocamldep - -OBJS=camlinternalFormatBasics.cmo pervasives.cmo $(OTHERS) -OTHERS=list.cmo char.cmo bytes.cmo string.cmo sys.cmo \ - sort.cmo marshal.cmo obj.cmo array.cmo \ - int32.cmo int64.cmo nativeint.cmo \ - lexing.cmo parsing.cmo \ - set.cmo map.cmo stack.cmo queue.cmo \ - camlinternalLazy.cmo lazy.cmo stream.cmo \ - buffer.cmo camlinternalFormat.cmo printf.cmo \ - arg.cmo printexc.cmo gc.cmo \ - digest.cmo random.cmo hashtbl.cmo weak.cmo \ - format.cmo uchar.cmo scanf.cmo callback.cmo \ - camlinternalOO.cmo oo.cmo camlinternalMod.cmo \ - genlex.cmo ephemeron.cmo \ - filename.cmo complex.cmo \ - arrayLabels.cmo listLabels.cmo bytesLabels.cmo \ - stringLabels.cmo moreLabels.cmo stdLabels.cmo \ - spacetime.cmo - -all: stdlib.cma std_exit.cmo camlheader target_camlheader camlheader_ur - -ifeq "$(RUNTIMED)" "runtimed" -all: camlheaderd -endif - -ifeq "$(RUNTIMEI)" "true" -all: camlheaderi -endif - -INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) - -install:: - cp stdlib.cma std_exit.cmo *.cmi *.cmt *.cmti *.mli *.ml \ - camlheader_ur \ - "$(INSTALL_LIBDIR)" - cp target_camlheader "$(INSTALL_LIBDIR)/camlheader" - -ifeq "$(RUNTIMED)" "runtimed" -install:: - cp target_camlheaderd $(INSTALL_LIBDIR) -endif - -ifeq "$(RUNTIMEI)" "true" -install:: - cp target_camlheaderi $(INSTALL_LIBDIR) -endif - -stdlib.cma: $(OBJS) - $(CAMLC) -a -o stdlib.cma $(OBJS) - -stdlib.cmxa: $(OBJS:.cmo=.cmx) - $(CAMLOPT) -a -o stdlib.cmxa $(OBJS:.cmo=.cmx) - -sys.ml: sys.mlp ../VERSION - sed -e "s|%%VERSION%%|`sed -e 1q ../VERSION`|" sys.mlp >sys.ml - -clean:: - rm -f sys.ml - -clean:: - rm -f camlheader target_camlheader camlheader_ur target_camlheader[di] - -.SUFFIXES: .mli .ml .cmi .cmo .cmx .p.cmx - -.mli.cmi: - $(CAMLC) $(COMPFLAGS) `./Compflags $@` -c $< - -.ml.cmo: - $(CAMLC) $(COMPFLAGS) `./Compflags $@` -c $< - -.ml.cmx: - $(CAMLOPT) $(COMPFLAGS) $(OPTCOMPFLAGS) `./Compflags $@` -c $< - -.ml.p.cmx: - $(CAMLOPT) $(COMPFLAGS) $(OPTCOMPFLAGS) `./Compflags $@` \ - -p -c -o $*.p.cmx $< - -# Dependencies on the compiler -COMPILER_DEPS=$(filter-out -use-prims, $(COMPILER)) -$(OBJS) std_exit.cmo: $(COMPILER_DEPS) -$(OBJS:.cmo=.cmi) std_exit.cmi: $(COMPILER_DEPS) -$(OBJS:.cmo=.cmx) std_exit.cmx: $(OPTCOMPILER) -$(OBJS:.cmo=.p.cmx) std_exit.p.cmx: $(OPTCOMPILER) - -# Dependencies on Pervasives (not tracked by ocamldep) -$(OTHERS) std_exit.cmo: pervasives.cmi -$(OTHERS:.cmo=.cmi) std_exit.cmi: pervasives.cmi -$(OBJS:.cmo=.cmx) std_exit.cmx: pervasives.cmi -$(OBJS:.cmo=.p.cmx) std_exit.p.cmx: pervasives.cmi -$(OTHERS:.cmo=.cmx) std_exit.cmx: pervasives.cmx -$(OTHERS:.cmo=.p.cmx) std_exit.p.cmx: pervasives.cmx - -clean:: - rm -f *.cm* *.$(O) *.$(A) - rm -f *~ - rm -f camlheader* - -include .depend - -# Note that .p.cmx targets do not depend (for compilation) upon other -# .p.cmx files. When the compiler imports another compilation unit, -# it looks for the .cmx file (not .p.cmx). -depend: - $(CAMLDEP) -slash *.mli *.ml > .depend - $(CAMLDEP) -slash *.ml | sed -e 's/\.cmx : /.p.cmx : /g' >>.depend diff --git a/stdlib/StdlibModules b/stdlib/StdlibModules index b65e9deb..28207401 100644 --- a/stdlib/StdlibModules +++ b/stdlib/StdlibModules @@ -35,6 +35,7 @@ STDLIB_MODULES=\ char \ complex \ digest \ + ephemeron \ filename \ format \ gc \ diff --git a/stdlib/arg.ml b/stdlib/arg.ml index 9b0bce99..0f9095a7 100644 --- a/stdlib/arg.ml +++ b/stdlib/arg.ml @@ -36,6 +36,13 @@ type spec = call the function with the symbol. *) | Rest of (string -> unit) (* Stop interpreting keywords and call the function with each remaining argument *) + | Expand of (string -> string array) (* If the remaining arguments to process + are of the form + [["-foo"; "arg"] @ rest] where "foo" is + registered as [Expand f], then the + arguments [f "arg" @ rest] are + processed. Only allowed in + [parse_and_expand_argv_dynamic]. *) exception Bad of string exception Help of string @@ -122,12 +129,15 @@ let float_of_string_opt x = try Some (float_of_string x) with Failure _ -> None -let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg = - let l = Array.length argv in - let b = Buffer.create 200 in +let parse_and_expand_argv_dynamic_aux allow_expand current argv speclist anonfun errmsg = let initpos = !current in - let stop error = - let progname = if initpos < l then argv.(initpos) else "(?)" in + let convert_error error = + (* convert an internal error to a Bad/Help exception + *or* add the program name as a prefix and the usage message as a suffix + to an user-raised Bad exception. + *) + let b = Buffer.create 200 in + let progname = if initpos < (Array.length !argv) then !argv.(initpos) else "(?)" in begin match error with | Unknown "-help" -> () | Unknown "--help" -> () @@ -138,43 +148,43 @@ let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg = | Wrong (opt, arg, expected) -> bprintf b "%s: wrong argument '%s'; option '%s' expects %s.\n" progname arg opt expected - | Message s -> + | Message s -> (* user error message *) bprintf b "%s: %s.\n" progname s end; usage_b b !speclist errmsg; if error = Unknown "-help" || error = Unknown "--help" - then raise (Help (Buffer.contents b)) - else raise (Bad (Buffer.contents b)) + then Help (Buffer.contents b) + else Bad (Buffer.contents b) in incr current; - while !current < l do - let s = argv.(!current) in - if String.length s >= 1 && s.[0] = '-' then begin - let action, follow = - try assoc3 s !speclist, None - with Not_found -> + while !current < (Array.length !argv) do + begin try + let s = !argv.(!current) in + if String.length s >= 1 && s.[0] = '-' then begin + let action, follow = + try assoc3 s !speclist, None + with Not_found -> try let keyword, arg = split s in assoc3 keyword !speclist, Some arg - with Not_found -> stop (Unknown s) - in - let no_arg () = - match follow with - | None -> () - | Some arg -> stop (Wrong (s, arg, "no argument")) in - let get_arg () = - match follow with - | None -> - if !current + 1 < l then argv.(!current + 1) - else stop (Missing s) - | Some arg -> arg - in - let consume_arg () = - match follow with - | None -> incr current - | Some _ -> () - in - begin try + with Not_found -> raise (Stop (Unknown s)) + in + let no_arg () = + match follow with + | None -> () + | Some arg -> raise (Stop (Wrong (s, arg, "no argument"))) in + let get_arg () = + match follow with + | None -> + if !current + 1 < (Array.length !argv) then !argv.(!current + 1) + else raise (Stop (Missing s)) + | Some arg -> arg + in + let consume_arg () = + match follow with + | None -> incr current + | Some _ -> () + in let rec treat_action = function | Unit f -> f (); | Bool f -> @@ -233,22 +243,34 @@ let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg = | Tuple specs -> List.iter treat_action specs; | Rest f -> - while !current < l - 1 do - f argv.(!current + 1); + while !current < (Array.length !argv) - 1 do + f !argv.(!current + 1); consume_arg (); done; + | Expand f -> + if not allow_expand then + raise (Invalid_argument "Arg.Expand is is only allowed with Arg.parse_and_expand_argv_dynamic"); + let arg = get_arg () in + let newarg = f arg in + consume_arg (); + let before = Array.sub !argv 0 (!current + 1) + and after = Array.sub !argv (!current + 1) ((Array.length !argv) - !current - 1) in + argv:= Array.concat [before;newarg;after]; in - treat_action action - with Bad m -> stop (Message m); - | Stop e -> stop e; - end; - incr current; - end else begin - (try anonfun s with Bad m -> stop (Message m)); - incr current; + treat_action action end + else anonfun s + with | Bad m -> raise (convert_error (Message m)); + | Stop e -> raise (convert_error e); end; + incr current done +let parse_and_expand_argv_dynamic current argv speclist anonfun errmsg = + parse_and_expand_argv_dynamic_aux true current argv speclist anonfun errmsg + +let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg = + parse_and_expand_argv_dynamic_aux false current (ref argv) speclist anonfun errmsg + let parse_argv ?(current=current) argv speclist anonfun errmsg = parse_argv_dynamic ~current:current argv (ref speclist) anonfun errmsg @@ -269,6 +291,16 @@ let parse_dynamic l f msg = | Bad msg -> eprintf "%s" msg; exit 2 | Help msg -> printf "%s" msg; exit 0 +let parse_expand l f msg = + try + let argv = ref Sys.argv in + let spec = ref l in + let current = ref (!current) in + parse_and_expand_argv_dynamic current argv spec f msg + with + | Bad msg -> eprintf "%s" msg; exit 2 + | Help msg -> printf "%s" msg; exit 0 + let second_word s = let len = String.length s in @@ -315,3 +347,48 @@ let align ?(limit=max_int) speclist = let len = List.fold_left max_arg_len 0 completed in let len = min len limit in List.map (add_padding len) completed + +let trim_cr s = + let len = String.length s in + if len > 0 && String.get s (len - 1) = '\r' then + String.sub s 0 (len - 1) + else + s + +let read_aux trim sep file = + let ic = open_in_bin file in + let buf = Buffer.create 200 in + let words = ref [] in + let stash () = + let word = (Buffer.contents buf) in + let word = if trim then trim_cr word else word in + words := word :: !words; + Buffer.clear buf + in + let rec read () = + try + let c = input_char ic in + if c = sep then begin + stash (); read () + end else begin + Buffer.add_char buf c; read () + end + with End_of_file -> + if Buffer.length buf > 0 then + stash () in + read (); + close_in ic; + Array.of_list (List.rev !words) + +let read_arg = read_aux true '\n' + +let read_arg0 = read_aux false '\x00' + +let write_aux sep file args = + let oc = open_out_bin file in + Array.iter (fun s -> fprintf oc "%s%c" s sep) args; + close_out oc + +let write_arg = write_aux '\n' + +let write_arg0 = write_aux '\x00' diff --git a/stdlib/arg.mli b/stdlib/arg.mli index 3f263554..e7d942ed 100644 --- a/stdlib/arg.mli +++ b/stdlib/arg.mli @@ -59,6 +59,13 @@ type spec = call the function with the symbol *) | Rest of (string -> unit) (** Stop interpreting keywords and call the function with each remaining argument *) + | Expand of (string -> string array) (** If the remaining arguments to process + are of the form + [["-foo"; "arg"] @ rest] where "foo" is + registered as [Expand f], then the + arguments [f "arg" @ rest] are + processed. Only allowed in + [parse_and_expand_argv_dynamic]. *) (** The concrete type describing the behavior associated with a keyword. *) @@ -103,18 +110,19 @@ val parse_dynamic : is to parse command lines of the form: - command subcommand [options] where the list of options depends on the value of the subcommand argument. + @since 4.01.0 *) val parse_argv : ?current: int ref -> string array -> (key * spec * doc) list -> anon_fun -> usage_msg -> unit (** [Arg.parse_argv ~current args speclist anon_fun usage_msg] parses the array [args] as if it were the command line. It uses and updates - the value of [~current] (if given), or [Arg.current]. You must set + the value of [~current] (if given), or {!Arg.current}. You must set it before calling [parse_argv]. The initial value of [current] is the index of the program name (argument 0) in the array. - If an error occurs, [Arg.parse_argv] raises [Arg.Bad] with + If an error occurs, [Arg.parse_argv] raises {!Arg.Bad} with the error message as argument. If option [-help] or [--help] is - given, [Arg.parse_argv] raises [Arg.Help] with the help message + given, [Arg.parse_argv] raises {!Arg.Help} with the help message as argument. *) @@ -123,6 +131,22 @@ val parse_argv_dynamic : ?current:int ref -> string array -> (** Same as {!Arg.parse_argv}, except that the [speclist] argument is a reference and may be updated during the parsing. See {!Arg.parse_dynamic}. + @since 4.01.0 +*) + +val parse_and_expand_argv_dynamic : int ref -> string array ref -> + (key * spec * doc) list ref -> anon_fun -> string -> unit +(** Same as {!Arg.parse_argv_dynamic}, except that the [argv] argument is a + reference and may be updated during the parsing of [Expand] arguments. + See {!Arg.parse_argv_dynamic}. + @since 4.05.0 +*) + +val parse_expand: + (key * spec * doc) list -> anon_fun -> usage_msg -> unit +(** Same as {!Arg.parse}, except that the [Expand] arguments are allowed and + the {!current} reference is not updated. + @since 4.05.0 *) exception Help of string @@ -131,13 +155,13 @@ exception Help of string exception Bad of string (** Functions in [spec] or [anon_fun] can raise [Arg.Bad] with an error message to reject invalid arguments. - [Arg.Bad] is also raised by [Arg.parse_argv] in case of an error. *) + [Arg.Bad] is also raised by {!Arg.parse_argv} in case of an error. *) val usage : (key * spec * doc) list -> usage_msg -> unit (** [Arg.usage speclist usage_msg] prints to standard error an error message that includes the list of valid options. This is the same message that {!Arg.parse} prints in case of error. - [speclist] and [usage_msg] are the same as for [Arg.parse]. *) + [speclist] and [usage_msg] are the same as for {!Arg.parse}. *) val usage_string : (key * spec * doc) list -> usage_msg -> string (** Returns the message that would have been printed by {!Arg.usage}, @@ -159,3 +183,25 @@ val current : int ref {!Arg.parse} uses the initial value of {!Arg.current} as the index of argument 0 (the program name) and starts parsing arguments at the next element. *) + +val read_arg: string -> string array +(** [Arg.read_arg file] reads newline-terminated command line arguments from + file [file]. + @since 4.05.0 *) + +val read_arg0: string -> string array +(** Identical to {!Arg.read_arg} but assumes null character terminated command line + arguments. + @since 4.05.0 *) + + +val write_arg: string -> string array -> unit +(** [Arg.write_arg file args] writes the arguments [args] newline-terminated + into the file [file]. If the any of the arguments in [args] contains a + newline, use {!Arg.write_arg0} instead. + @since 4.05.0 *) + +val write_arg0: string -> string array -> unit +(** Identical to {!Arg.write_arg} but uses the null character for terminator + instead of newline. + @since 4.05.0 *) diff --git a/stdlib/array.mli b/stdlib/array.mli index f75b6137..b89cd6b6 100644 --- a/stdlib/array.mli +++ b/stdlib/array.mli @@ -80,7 +80,7 @@ val make_matrix : int -> int -> 'a -> 'a array array with the notation [m.(x).(y)]. Raise [Invalid_argument] if [dimx] or [dimy] is negative or - greater than [Sys.max_array_length]. + greater than {!Sys.max_array_length}. If the value of [e] is a floating-point number, then the maximum size is only [Sys.max_array_length / 2]. *) @@ -93,7 +93,7 @@ val append : 'a array -> 'a array -> 'a array concatenation of the arrays [v1] and [v2]. *) val concat : 'a array list -> 'a array -(** Same as [Array.append], but concatenates a list of arrays. *) +(** Same as {!Array.append}, but concatenates a list of arrays. *) val sub : 'a array -> int -> int -> 'a array (** [Array.sub a start len] returns a fresh array of length [len], diff --git a/stdlib/arrayLabels.mli b/stdlib/arrayLabels.mli index 02c24cc8..868f73a5 100644 --- a/stdlib/arrayLabels.mli +++ b/stdlib/arrayLabels.mli @@ -19,24 +19,24 @@ external length : 'a array -> int = "%array_length" (** Return the length (number of elements) of the given array. *) external get : 'a array -> int -> 'a = "%array_safe_get" -(** [ArrayLabels.get a n] returns the element number [n] of array [a]. +(** [Array.get a n] returns the element number [n] of array [a]. The first element has number 0. - The last element has number [ArrayLabels.length a - 1]. - You can also write [a.(n)] instead of [ArrayLabels.get a n]. + The last element has number [Array.length a - 1]. + You can also write [a.(n)] instead of [Array.get a n]. Raise [Invalid_argument "index out of bounds"] - if [n] is outside the range 0 to [(ArrayLabels.length a - 1)]. *) + if [n] is outside the range 0 to [(Array.length a - 1)]. *) external set : 'a array -> int -> 'a -> unit = "%array_safe_set" -(** [ArrayLabels.set a n x] modifies array [a] in place, replacing +(** [Array.set a n x] modifies array [a] in place, replacing element number [n] with [x]. - You can also write [a.(n) <- x] instead of [ArrayLabels.set a n x]. + You can also write [a.(n) <- x] instead of [Array.set a n x]. Raise [Invalid_argument "index out of bounds"] - if [n] is outside the range 0 to [ArrayLabels.length a - 1]. *) + if [n] is outside the range 0 to [Array.length a - 1]. *) external make : int -> 'a -> 'a array = "caml_make_vect" -(** [ArrayLabels.make n x] returns a fresh array of length [n], +(** [Array.make n x] returns a fresh array of length [n], initialized with [x]. All the elements of this new array are initially physically equal to [x] (in the sense of the [==] predicate). @@ -49,13 +49,13 @@ external make : int -> 'a -> 'a array = "caml_make_vect" size is only [Sys.max_array_length / 2].*) external create : int -> 'a -> 'a array = "caml_make_vect" - [@@ocaml.deprecated "Use ArrayLabels.make instead."] -(** @deprecated [ArrayLabels.create] is an alias for {!ArrayLabels.make}. *) + [@@ocaml.deprecated "Use Array.make instead."] +(** @deprecated [Array.create] is an alias for {!Array.make}. *) val init : int -> f:(int -> 'a) -> 'a array -(** [ArrayLabels.init n f] returns a fresh array of length [n], +(** [Array.init n f] returns a fresh array of length [n], with element number [i] initialized to the result of [f i]. - In other terms, [ArrayLabels.init n f] tabulates the results of [f] + In other terms, [Array.init n f] tabulates the results of [f] applied to the integers [0] to [n-1]. Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length]. @@ -63,7 +63,7 @@ val init : int -> f:(int -> 'a) -> 'a array size is only [Sys.max_array_length / 2].*) val make_matrix : dimx:int -> dimy:int -> 'a -> 'a array array -(** [ArrayLabels.make_matrix dimx dimy e] returns a two-dimensional array +(** [Array.make_matrix dimx dimy e] returns a two-dimensional array (an array of arrays) with first dimension [dimx] and second dimension [dimy]. All the elements of this new matrix are initially physically equal to [e]. @@ -71,37 +71,37 @@ val make_matrix : dimx:int -> dimy:int -> 'a -> 'a array array with the notation [m.(x).(y)]. Raise [Invalid_argument] if [dimx] or [dimy] is negative or - greater than [Sys.max_array_length]. + greater than {!Sys.max_array_length}. If the value of [e] is a floating-point number, then the maximum size is only [Sys.max_array_length / 2]. *) val create_matrix : dimx:int -> dimy:int -> 'a -> 'a array array - [@@ocaml.deprecated "Use ArrayLabels.make_matrix instead."] -(** @deprecated [ArrayLabels.create_matrix] is an alias for - {!ArrayLabels.make_matrix}. *) + [@@ocaml.deprecated "Use Array.make_matrix instead."] +(** @deprecated [Array.create_matrix] is an alias for + {!Array.make_matrix}. *) val append : 'a array -> 'a array -> 'a array -(** [ArrayLabels.append v1 v2] returns a fresh array containing the +(** [Array.append v1 v2] returns a fresh array containing the concatenation of the arrays [v1] and [v2]. *) val concat : 'a array list -> 'a array -(** Same as [ArrayLabels.append], but concatenates a list of arrays. *) +(** Same as {!Array.append}, but concatenates a list of arrays. *) val sub : 'a array -> pos:int -> len:int -> 'a array -(** [ArrayLabels.sub a start len] returns a fresh array of length [len], +(** [Array.sub a start len] returns a fresh array of length [len], containing the elements number [start] to [start + len - 1] of array [a]. Raise [Invalid_argument "Array.sub"] if [start] and [len] do not designate a valid subarray of [a]; that is, if - [start < 0], or [len < 0], or [start + len > ArrayLabels.length a]. *) + [start < 0], or [len < 0], or [start + len > Array.length a]. *) val copy : 'a array -> 'a array -(** [ArrayLabels.copy a] returns a copy of [a], that is, a fresh array +(** [Array.copy a] returns a copy of [a], that is, a fresh array containing the same elements as [a]. *) val fill : 'a array -> pos:int -> len:int -> 'a -> unit -(** [ArrayLabels.fill a ofs len x] modifies the array [a] in place, +(** [Array.fill a ofs len x] modifies the array [a] in place, storing [x] in elements number [ofs] to [ofs + len - 1]. Raise [Invalid_argument "Array.fill"] if [ofs] and [len] do not @@ -110,7 +110,7 @@ val fill : 'a array -> pos:int -> len:int -> 'a -> unit val blit : src:'a array -> src_pos:int -> dst:'a array -> dst_pos:int -> len:int -> unit -(** [ArrayLabels.blit v1 o1 v2 o2 len] copies [len] elements +(** [Array.blit v1 o1 v2 o2 len] copies [len] elements from array [v1], starting at element number [o1], to array [v2], starting at element number [o2]. It works correctly even if [v1] and [v2] are the same array, and the source and @@ -121,69 +121,94 @@ val blit : designate a valid subarray of [v2]. *) val to_list : 'a array -> 'a list -(** [ArrayLabels.to_list a] returns the list of all the elements of [a]. *) +(** [Array.to_list a] returns the list of all the elements of [a]. *) val of_list : 'a list -> 'a array -(** [ArrayLabels.of_list l] returns a fresh array containing the elements +(** [Array.of_list l] returns a fresh array containing the elements of [l]. *) val iter : f:('a -> unit) -> 'a array -> unit -(** [ArrayLabels.iter f a] applies function [f] in turn to all +(** [Array.iter f a] applies function [f] in turn to all the elements of [a]. It is equivalent to - [f a.(0); f a.(1); ...; f a.(ArrayLabels.length a - 1); ()]. *) + [f a.(0); f a.(1); ...; f a.(Array.length a - 1); ()]. *) val map : f:('a -> 'b) -> 'a array -> 'b array -(** [ArrayLabels.map f a] applies function [f] to all the elements of [a], +(** [Array.map f a] applies function [f] to all the elements of [a], and builds an array with the results returned by [f]: - [[| f a.(0); f a.(1); ...; f a.(ArrayLabels.length a - 1) |]]. *) + [[| f a.(0); f a.(1); ...; f a.(Array.length a - 1) |]]. *) val iteri : f:(int -> 'a -> unit) -> 'a array -> unit -(** Same as {!ArrayLabels.iter}, but the +(** Same as {!Array.iter}, but the function is applied to the index of the element as first argument, and the element itself as second argument. *) val mapi : f:(int -> 'a -> 'b) -> 'a array -> 'b array -(** Same as {!ArrayLabels.map}, but the +(** Same as {!Array.map}, but the function is applied to the index of the element as first argument, and the element itself as second argument. *) val fold_left : f:('a -> 'b -> 'a) -> init:'a -> 'b array -> 'a -(** [ArrayLabels.fold_left f x a] computes +(** [Array.fold_left f x a] computes [f (... (f (f x a.(0)) a.(1)) ...) a.(n-1)], where [n] is the length of the array [a]. *) val fold_right : f:('b -> 'a -> 'a) -> 'b array -> init:'a -> 'a -(** [ArrayLabels.fold_right f a x] computes +(** [Array.fold_right f a x] computes [f a.(0) (f a.(1) ( ... (f a.(n-1) x) ...))], where [n] is the length of the array [a]. *) + +(** {6 Iterators on two arrays} *) + + +val iter2 : f:('a -> 'b -> unit) -> 'a array -> 'b array -> unit +(** [Array.iter2 f a b] applies function [f] to all the elements of [a] + and [b]. + Raise [Invalid_argument] if the arrays are not the same size. + @since 4.05.0 *) + +val map2 : f:('a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array +(** [Array.map2 f a b] applies function [f] to all the elements of [a] + and [b], and builds an array with the results returned by [f]: + [[| f a.(0) b.(0); ...; f a.(Array.length a - 1) b.(Array.length b - 1)|]]. + Raise [Invalid_argument] if the arrays are not the same size. + @since 4.05.0 *) + + +(** {6 Array scanning} *) + + val exists : f:('a -> bool) -> 'a array -> bool -(** [ArrayLabels.exists p [|a1; ...; an|]] checks if at least one element of +(** [Array.exists p [|a1; ...; an|]] checks if at least one element of the array satisfies the predicate [p]. That is, it returns - [(p a1) || (p a2) || ... || (p an)]. *) + [(p a1) || (p a2) || ... || (p an)]. + @since 4.03.0 *) val for_all : f:('a -> bool) -> 'a array -> bool -(** [ArrayLabels.for_all p [|a1; ...; an|]] checks if all elements of the array +(** [Array.for_all p [|a1; ...; an|]] checks if all elements of the array satisfy the predicate [p]. That is, it returns - [(p a1) && (p a2) && ... && (p an)]. *) + [(p a1) && (p a2) && ... && (p an)]. + @since 4.03.0 *) val mem : 'a -> set:'a array -> bool (** [mem x a] is true if and only if [x] is equal - to an element of [a]. *) + to an element of [a]. + @since 4.03.0 *) val memq : 'a -> set:'a array -> bool -(** Same as {!ArrayLabels.mem}, but uses physical equality instead of structural - equality to compare list elements. *) +(** Same as {!Array.mem}, but uses physical equality instead of structural + equality to compare list elements. + @since 4.03.0 *) external create_float: int -> float array = "caml_make_float_vect" -(** [ArrayLabels.create_float n] returns a fresh float array of length [n], +(** [Array.create_float n] returns a fresh float array of length [n], with uninitialized data. @since 4.03 *) val make_float: int -> float array - [@@ocaml.deprecated "Use ArrayLabels.create_float instead."] -(** @deprecated [ArrayLabels.make_float] is an alias for - {!ArrayLabels.create_float}. *) + [@@ocaml.deprecated "Use Array.create_float instead."] +(** @deprecated [Array.make_float] is an alias for + {!Array.create_float}. *) (** {6 Sorting} *) @@ -196,9 +221,9 @@ val sort : cmp:('a -> 'a -> int) -> 'a array -> unit and a negative integer if the first is smaller (see below for a complete specification). For example, {!Pervasives.compare} is a suitable comparison function, provided there are no floating-point - NaN values in the data. After calling [ArrayLabels.sort], the + NaN values in the data. After calling [Array.sort], the array is sorted in place in increasing order. - [ArrayLabels.sort] is guaranteed to run in constant heap space + [Array.sort] is guaranteed to run in constant heap space and (at most) logarithmic stack space. The current implementation uses Heap Sort. It runs in constant @@ -210,23 +235,23 @@ val sort : cmp:('a -> 'a -> int) -> 'a array -> unit - [cmp x y] > 0 if and only if [cmp y x] < 0 - if [cmp x y] >= 0 and [cmp y z] >= 0 then [cmp x z] >= 0 - When [ArrayLabels.sort] returns, [a] contains the same elements as before, + When [Array.sort] returns, [a] contains the same elements as before, reordered in such a way that for all i and j valid indices of [a] : - [cmp a.(i) a.(j)] >= 0 if and only if i >= j *) val stable_sort : cmp:('a -> 'a -> int) -> 'a array -> unit -(** Same as {!ArrayLabels.sort}, but the sorting algorithm is stable (i.e. +(** Same as {!Array.sort}, but the sorting algorithm is stable (i.e. elements that compare equal are kept in their original order) and not guaranteed to run in constant heap space. The current implementation uses Merge Sort. It uses [n/2] words of heap space, where [n] is the length of the array. - It is usually faster than the current implementation of {!ArrayLabels.sort}. + It is usually faster than the current implementation of {!Array.sort}. *) val fast_sort : cmp:('a -> 'a -> int) -> 'a array -> unit -(** Same as {!ArrayLabels.sort} or {!ArrayLabels.stable_sort}, whichever is +(** Same as {!Array.sort} or {!Array.stable_sort}, whichever is faster on typical input. *) diff --git a/stdlib/buffer.ml b/stdlib/buffer.ml index 51ab6412..908909fa 100644 --- a/stdlib/buffer.ml +++ b/stdlib/buffer.ml @@ -188,3 +188,9 @@ let add_substitute b f s = end else if previous = '\\' then add_char b previous in subst ' ' 0 + +let truncate b len = + if len < 0 || len > length b then + invalid_arg "Buffer.truncate" + else + b.position <- len diff --git a/stdlib/buffer.mli b/stdlib/buffer.mli index 00e8c7b7..71d87970 100644 --- a/stdlib/buffer.mli +++ b/stdlib/buffer.mli @@ -131,3 +131,9 @@ val add_channel : t -> in_channel -> int -> unit val output_buffer : out_channel -> t -> unit (** [output_buffer oc b] writes the current contents of buffer [b] on the output channel [oc]. *) + +val truncate : t -> int -> unit +(** [truncate b len] truncates the length of [b] to [len] + Note: the internal byte sequence is not shortened. + Raise [Invalid_argument] if [len < 0] or [len > length b]. + @since 4.05.0 *) diff --git a/stdlib/bytes.ml b/stdlib/bytes.ml index 24e97cce..f048a951 100644 --- a/stdlib/bytes.ml +++ b/stdlib/bytes.ml @@ -72,8 +72,16 @@ let sub s ofs len = let sub_string b ofs len = unsafe_to_string (sub b ofs len) +(* addition with an overflow check *) +let (++) a b = + let c = a + b in + match a < 0, b < 0, c < 0 with + | true , true , false + | false, false, true -> invalid_arg "Bytes.extend" (* overflow *) + | _ -> c + let extend s left right = - let len = length s + left + right in + let len = length s ++ left ++ right in let r = create len in let (srcoff, dstoff) = if left < 0 then -left, 0 else 0, left in let cpylen = min (length s - srcoff) (len - dstoff) in @@ -124,7 +132,7 @@ let rec unsafe_blits dst pos sep seplen = function let concat sep = function [] -> empty | l -> let seplen = length sep in - unsafe_blits + unsafe_blits (create (sum_lengths 0 seplen l)) 0 sep seplen l @@ -236,12 +244,26 @@ let rec index_rec s lim i c = (* duplicated in string.ml *) let index s c = index_rec s (length s) 0 c +(* duplicated in string.ml *) +let rec index_rec_opt s lim i c = + if i >= lim then None else + if unsafe_get s i = c then Some i else index_rec_opt s lim (i + 1) c + +(* duplicated in string.ml *) +let index_opt s c = index_rec_opt s (length s) 0 c + (* duplicated in string.ml *) let index_from s i c = let l = length s in if i < 0 || i > l then invalid_arg "String.index_from / Bytes.index_from" else index_rec s l i c +(* duplicated in string.ml *) +let index_from_opt s i c = + let l = length s in + if i < 0 || i > l then invalid_arg "String.index_from_opt / Bytes.index_from_opt" else + index_rec_opt s l i c + (* duplicated in string.ml *) let rec rindex_rec s i c = if i < 0 then raise Not_found else @@ -257,6 +279,21 @@ let rindex_from s i c = else rindex_rec s i c +(* duplicated in string.ml *) +let rec rindex_rec_opt s i c = + if i < 0 then None else + if unsafe_get s i = c then Some i else rindex_rec_opt s (i - 1) c + +(* duplicated in string.ml *) +let rindex_opt s c = rindex_rec_opt s (length s - 1) c + +(* duplicated in string.ml *) +let rindex_from_opt s i c = + if i < -1 || i >= length s then + invalid_arg "String.rindex_from_opt / Bytes.rindex_from_opt" + else + rindex_rec_opt s i c + (* duplicated in string.ml *) let contains_from s i c = diff --git a/stdlib/bytes.mli b/stdlib/bytes.mli index a6172d85..dc530787 100644 --- a/stdlib/bytes.mli +++ b/stdlib/bytes.mli @@ -48,7 +48,7 @@ external length : bytes -> int = "%bytes_length" external get : bytes -> int -> char = "%bytes_safe_get" (** [get s n] returns the byte at index [n] in argument [s]. - Raise [Invalid_argument] if [n] not a valid index in [s]. *) + Raise [Invalid_argument] if [n] is not a valid index in [s]. *) external set : bytes -> int -> char -> unit = "%bytes_safe_set" (** [set s n c] modifies [s] in place, replacing the byte at index [n] @@ -193,12 +193,22 @@ val index : bytes -> char -> int Raise [Not_found] if [c] does not occur in [s]. *) +val index_opt: bytes -> char -> int option +(** [index_opt s c] returns the index of the first occurrence of byte [c] + in [s] or [None] if [c] does not occur in [s]. + @since 4.05 *) + val rindex : bytes -> char -> int (** [rindex s c] returns the index of the last occurrence of byte [c] in [s]. Raise [Not_found] if [c] does not occur in [s]. *) +val rindex_opt: bytes -> char -> int option +(** [rindex_opt s c] returns the index of the last occurrence of byte [c] + in [s] or [None] if [c] does not occur in [s]. + @since 4.05 *) + val index_from : bytes -> int -> char -> int (** [index_from s i c] returns the index of the first occurrence of byte [c] in [s] after position [i]. [Bytes.index s c] is @@ -207,6 +217,14 @@ val index_from : bytes -> int -> char -> int Raise [Invalid_argument] if [i] is not a valid position in [s]. Raise [Not_found] if [c] does not occur in [s] after position [i]. *) +val index_from_opt: bytes -> int -> char -> int option +(** [index_from _opts i c] returns the index of the first occurrence of + byte [c] in [s] after position [i] or [None] if [c] does not occur in [s] after position [i]. + [Bytes.index_opt s c] is equivalent to [Bytes.index_from_opt s 0 c]. + + Raise [Invalid_argument] if [i] is not a valid position in [s]. + @since 4.05 *) + val rindex_from : bytes -> int -> char -> int (** [rindex_from s i c] returns the index of the last occurrence of byte [c] in [s] before position [i+1]. [rindex s c] is equivalent @@ -215,6 +233,15 @@ val rindex_from : bytes -> int -> char -> int Raise [Invalid_argument] if [i+1] is not a valid position in [s]. Raise [Not_found] if [c] does not occur in [s] before position [i+1]. *) +val rindex_from_opt: bytes -> int -> char -> int option +(** [rindex_from_opt s i c] returns the index of the last occurrence + of byte [c] in [s] before position [i+1] or [None] if [c] does not + occur in [s] before position [i+1]. [rindex_opt s c] is equivalent to + [rindex_from s (Bytes.length s - 1) c]. + + Raise [Invalid_argument] if [i+1] is not a valid position in [s]. + @since 4.05 *) + val contains : bytes -> char -> bool (** [contains s c] tests if byte [c] appears in [s]. *) @@ -372,7 +399,7 @@ let bytes_length (s : bytes) = The caller may not mutate [s] while the string is borrowed (it has temporarily given up ownership). This affects concurrent programs, - but also higher-order functions: if [String.length] returned + but also higher-order functions: if {!String.length} returned a closure to be called later, [s] should not be mutated until this closure is fully applied and returns ownership. *) diff --git a/stdlib/bytesLabels.mli b/stdlib/bytesLabels.mli index fb9404b9..9848f32d 100644 --- a/stdlib/bytesLabels.mli +++ b/stdlib/bytesLabels.mli @@ -23,7 +23,7 @@ external length : bytes -> int = "%bytes_length" external get : bytes -> int -> char = "%bytes_safe_get" (** [get s n] returns the byte at index [n] in argument [s]. - Raise [Invalid_argument] if [n] not a valid index in [s]. *) + Raise [Invalid_argument] if [n] is not a valid index in [s]. *) external set : bytes -> int -> char -> unit = "%bytes_safe_set" @@ -76,6 +76,17 @@ val sub : bytes -> pos:int -> len:int -> bytes val sub_string : bytes -> int -> int -> string (** Same as [sub] but return a string instead of a byte sequence. *) +val extend : bytes -> left:int -> right:int -> bytes +(** [extend s left right] returns a new byte sequence that contains + the bytes of [s], with [left] uninitialized bytes prepended and + [right] uninitialized bytes appended to it. If [left] or [right] + is negative, then bytes are removed (instead of appended) from + the corresponding side of [s]. + + Raise [Invalid_argument] if the result length is negative or + longer than {!Sys.max_string_length} bytes. + @since 4.05.0 *) + val fill : bytes -> pos:int -> len:int -> char -> unit (** [fill s start len c] modifies [s] in place, replacing [len] characters with [c], starting at [start]. @@ -96,11 +107,31 @@ val blit : designate a valid range of [src], or if [dstoff] and [len] do not designate a valid range of [dst]. *) +val blit_string : + src:string -> src_pos:int -> dst:bytes -> dst_pos:int -> len:int + -> unit +(** [blit src srcoff dst dstoff len] copies [len] bytes from string + [src], starting at index [srcoff], to byte sequence [dst], + starting at index [dstoff]. + + Raise [Invalid_argument] if [srcoff] and [len] do not + designate a valid range of [src], or if [dstoff] and [len] + do not designate a valid range of [dst]. + @since 4.05.0 *) + val concat : sep:bytes -> bytes list -> bytes (** [concat sep sl] concatenates the list of byte sequences [sl], inserting the separator byte sequence [sep] between each, and returns the result as a new byte sequence. *) +val cat : bytes -> bytes -> bytes +(** [cat s1 s2] concatenates [s1] and [s2] and returns the result + as new byte sequence. + + Raise [Invalid_argument] if the result is longer than + {!Sys.max_string_length} bytes. + @since 4.05.0 *) + val iter : f:(char -> unit) -> bytes -> unit (** [iter f s] applies function [f] in turn to all the bytes of [s]. It is equivalent to [f (get s 0); f (get s 1); ...; f (get s @@ -136,12 +167,22 @@ val index : bytes -> char -> int Raise [Not_found] if [c] does not occur in [s]. *) +val index_opt: bytes -> char -> int option +(** [index_opt s c] returns the index of the first occurrence of byte [c] + in [s] or [None] if [c] does not occur in [s]. + @since 4.05 *) + val rindex : bytes -> char -> int (** [rindex s c] returns the index of the last occurrence of byte [c] in [s]. Raise [Not_found] if [c] does not occur in [s]. *) +val rindex_opt: bytes -> char -> int option +(** [rindex_opt s c] returns the index of the last occurrence of byte [c] + in [s] or [None] if [c] does not occur in [s]. + @since 4.05 *) + val index_from : bytes -> int -> char -> int (** [index_from s i c] returns the index of the first occurrence of byte [c] in [s] after position [i]. [Bytes.index s c] is @@ -150,6 +191,14 @@ val index_from : bytes -> int -> char -> int Raise [Invalid_argument] if [i] is not a valid position in [s]. Raise [Not_found] if [c] does not occur in [s] after position [i]. *) +val index_from_opt: bytes -> int -> char -> int option +(** [index_from _opts i c] returns the index of the first occurrence of + byte [c] in [s] after position [i] or [None] if [c] does not occur in [s] after position [i]. + [Bytes.index_opt s c] is equivalent to [Bytes.index_from_opt s 0 c]. + + Raise [Invalid_argument] if [i] is not a valid position in [s]. + @since 4.05 *) + val rindex_from : bytes -> int -> char -> int (** [rindex_from s i c] returns the index of the last occurrence of byte [c] in [s] before position [i+1]. [rindex s c] is equivalent @@ -158,6 +207,15 @@ val rindex_from : bytes -> int -> char -> int Raise [Invalid_argument] if [i+1] is not a valid position in [s]. Raise [Not_found] if [c] does not occur in [s] before position [i+1]. *) +val rindex_from_opt: bytes -> int -> char -> int option +(** [rindex_from_opt s i c] returns the index of the last occurrence + of byte [c] in [s] before position [i+1] or [None] if [c] does not + occur in [s] before position [i+1]. [rindex_opt s c] is equivalent to + [rindex_from s (Bytes.length s - 1) c]. + + Raise [Invalid_argument] if [i+1] is not a valid position in [s]. + @since 4.05 *) + val contains : bytes -> char -> bool (** [contains s c] tests if byte [c] appears in [s]. *) @@ -176,22 +234,50 @@ val rcontains_from : bytes -> int -> char -> bool position in [s]. *) val uppercase : bytes -> bytes + [@@ocaml.deprecated "Use Bytes.uppercase_ascii instead."] (** Return a copy of the argument, with all lowercase letters - translated to uppercase, including accented letters of the ISO - Latin-1 (8859-1) character set. *) + translated to uppercase, including accented letters of the ISO + Latin-1 (8859-1) character set. + @deprecated Functions operating on Latin-1 character set are deprecated. *) val lowercase : bytes -> bytes + [@@ocaml.deprecated "Use Bytes.lowercase_ascii instead."] (** Return a copy of the argument, with all uppercase letters - translated to lowercase, including accented letters of the ISO - Latin-1 (8859-1) character set. *) + translated to lowercase, including accented letters of the ISO + Latin-1 (8859-1) character set. + @deprecated Functions operating on Latin-1 character set are deprecated. *) val capitalize : bytes -> bytes -(** Return a copy of the argument, with the first byte set to - uppercase. *) + [@@ocaml.deprecated "Use Bytes.capitalize_ascii instead."] +(** Return a copy of the argument, with the first character set to uppercase, + using the ISO Latin-1 (8859-1) character set.. + @deprecated Functions operating on Latin-1 character set are deprecated. *) val uncapitalize : bytes -> bytes -(** Return a copy of the argument, with the first byte set to - lowercase. *) + [@@ocaml.deprecated "Use Bytes.uncapitalize_ascii instead."] +(** Return a copy of the argument, with the first character set to lowercase, + using the ISO Latin-1 (8859-1) character set.. + @deprecated Functions operating on Latin-1 character set are deprecated. *) + +val uppercase_ascii : bytes -> bytes +(** Return a copy of the argument, with all lowercase letters + translated to uppercase, using the US-ASCII character set. + @since 4.05.0 *) + +val lowercase_ascii : bytes -> bytes +(** Return a copy of the argument, with all uppercase letters + translated to lowercase, using the US-ASCII character set. + @since 4.05.0 *) + +val capitalize_ascii : bytes -> bytes +(** Return a copy of the argument, with the first character set to uppercase, + using the US-ASCII character set. + @since 4.05.0 *) + +val uncapitalize_ascii : bytes -> bytes +(** Return a copy of the argument, with the first character set to lowercase, + using the US-ASCII character set. + @since 4.05.0 *) type t = bytes (** An alias for the type of byte sequences. *) @@ -202,6 +288,10 @@ val compare: t -> t -> int this function [compare] allows the module [Bytes] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) +val equal: t -> t -> bool +(** The equality function for byte sequences. + @since 4.05.0 *) + (**/**) (* The following is for system use only. Do not call directly. *) diff --git a/stdlib/digest.ml b/stdlib/digest.ml index 9ad393cf..408194b5 100644 --- a/stdlib/digest.ml +++ b/stdlib/digest.ml @@ -50,6 +50,7 @@ let char_hex n = Char.unsafe_chr (n + if n < 10 then Char.code '0' else (Char.code 'a' - 10)) let to_hex d = + if String.length d <> 16 then invalid_arg "Digest.to_hex"; let result = Bytes.create 32 in for i = 0 to 15 do let x = Char.code d.[i] in @@ -59,7 +60,7 @@ let to_hex d = Bytes.unsafe_to_string result let from_hex s = - if String.length s <> 32 then raise (Invalid_argument "Digest.from_hex"); + if String.length s <> 32 then invalid_arg "Digest.from_hex"; let digit c = match c with | '0'..'9' -> Char.code c - Char.code '0' diff --git a/stdlib/digest.mli b/stdlib/digest.mli index c5e91f50..2c9bebc5 100644 --- a/stdlib/digest.mli +++ b/stdlib/digest.mli @@ -73,7 +73,9 @@ val input : in_channel -> t (** Read a digest from the given input channel. *) val to_hex : t -> string -(** Return the printable hexadecimal representation of the given digest. *) +(** Return the printable hexadecimal representation of the given digest. + Raise [Invalid_argument] if the argument is not exactly 16 bytes. + *) val from_hex : string -> t (** Convert a hexadecimal representation back into the corresponding digest. diff --git a/stdlib/ephemeron.ml b/stdlib/ephemeron.ml index 64b2529a..c2b3d05d 100644 --- a/stdlib/ephemeron.ml +++ b/stdlib/ephemeron.ml @@ -205,6 +205,31 @@ module GenHashTable = struct (* TODO inline 3 iterations *) find_rec key hkey (h.data.(key_index h hkey)) + let rec find_rec_opt key hkey = function + | Empty -> + None + | Cons(hk, c, rest) when hkey = hk -> + begin match H.equal c key with + | ETrue -> + begin match H.get_data c with + | None -> + (* This case is not impossible because the gc can run between + H.equal and H.get_data *) + find_rec_opt key hkey rest + | Some _ as d -> d + end + | EFalse -> find_rec_opt key hkey rest + | EDead -> + find_rec_opt key hkey rest + end + | Cons(_, _, rest) -> + find_rec_opt key hkey rest + + let find_opt h key = + let hkey = H.hash h.seed key in + (* TODO inline 3 iterations *) + find_rec_opt key hkey (h.data.(key_index h hkey)) + let find_all h key = let hkey = H.hash h.seed key in let rec find_in_bucket = function diff --git a/stdlib/ephemeron.mli b/stdlib/ephemeron.mli index a05306bf..46d3aad3 100644 --- a/stdlib/ephemeron.mli +++ b/stdlib/ephemeron.mli @@ -64,6 +64,7 @@ Ephemerons are defined in a language agnostic way in this paper: B. Hayes, Ephemerons: a New Finalization Mechanism, OOPSLA'9 + @since 4.03.0 *) module type S = sig @@ -116,6 +117,8 @@ module K1 : sig (** [Ephemeron.K1.get_key_copy eph] returns [None] if the key of [eph] is empty, [Some x] (where [x] is a (shallow) copy of the key) if it is full. This function has the same GC friendliness as {!Weak.get_copy} + + If the element is a custom block it is not copied. *) val set_key: ('k,'d) t -> 'k -> unit @@ -138,8 +141,8 @@ module K1 : sig val blit_key : ('k,_) t -> ('k,_) t -> unit (** [Ephemeron.K1.blit_key eph1 eph2] sets the key of [eph2] with - the key of [eph1]. Contrary to using [Ephemeron.K1.get_key] - followed by [Ephemeron.K1.set_key] or [Ephemeon.K1.unset_key] + the key of [eph1]. Contrary to using {!Ephemeron.K1.get_key} + followed by {!Ephemeron.K1.set_key} or {!Ephemeron.K1.unset_key} this function does not prevent the incremental GC from erasing the value in its current cycle. *) @@ -151,6 +154,8 @@ module K1 : sig (** [Ephemeron.K1.get_data_copy eph] returns [None] if the data of [eph] is empty, [Some x] (where [x] is a (shallow) copy of the data) if it is full. This function has the same GC friendliness as {!Weak.get_copy} + + If the element is a custom block it is not copied. *) val set_data: ('k,'d) t -> 'd -> unit @@ -159,7 +164,7 @@ module K1 : sig *) val unset_data: ('k,'d) t -> unit - (** [Ephemeron.K1.unset_key eph el] sets the key of [eph] to be an + (** [Ephemeron.K1.unset_data eph el] sets the key of [eph] to be an empty key. The ephemeron starts behaving like a weak pointer. *) @@ -172,8 +177,8 @@ module K1 : sig val blit_data : (_,'d) t -> (_,'d) t -> unit (** [Ephemeron.K1.blit_data eph1 eph2] sets the data of [eph2] with - the data of [eph1]. Contrary to using [Ephemeron.K1.get_data] - followed by [Ephemeron.K1.set_data] or [Ephemeon.K1.unset_data] + the data of [eph1]. Contrary to using {!Ephemeron.K1.get_data} + followed by {!Ephemeron.K1.set_data} or {!Ephemeron.K1.unset_data} this function does not prevent the incremental GC from erasing the value in its current cycle. *) @@ -214,7 +219,7 @@ module K2 : sig (** Same as {!Ephemeron.K1.get_key_copy} *) val set_key2: ('k1,'k2,'d) t -> 'k2 -> unit - (** Same as {!Ephemeron.K1.get_key} *) + (** Same as {!Ephemeron.K1.set_key} *) val unset_key2: ('k1,'k2,'d) t -> unit (** Same as {!Ephemeron.K1.unset_key} *) @@ -353,10 +358,10 @@ module GenHashTable: sig (** [get_key cont] returns the keys if they are all alive *) val get_data: 'a container -> 'a option - (** [get_data cont] return the data if it is alive *) + (** [get_data cont] returns the data if it is alive *) val set_key_data: 'a container -> t -> 'a -> unit - (** [set_key_data cont] modify the key and data *) + (** [set_key_data cont] modifies the key and data *) val check_key: 'a container -> bool (** [check_key cont] checks if all the keys contained in the data diff --git a/stdlib/format.mli b/stdlib/format.mli index 2f52dbe6..7ff5fda2 100644 --- a/stdlib/format.mli +++ b/stdlib/format.mli @@ -387,7 +387,7 @@ type formatter_out_functions = { out_flush : unit -> unit; out_newline : unit -> unit; out_spaces : int -> unit; -} +} (** @since 4.01.0 *) val set_formatter_out_functions : formatter_out_functions -> unit (** [set_formatter_out_functions f] @@ -404,12 +404,14 @@ val set_formatter_out_functions : formatter_out_functions -> unit application at hand). The two functions [f.out_spaces] and [f.out_newline] are normally connected to [f.out_string] and [f.out_flush]: respective default values for [f.out_space] and [f.out_newline] are - [f.out_string (String.make n ' ') 0 n] and [f.out_string "\n" 0 1]. *) + [f.out_string (String.make n ' ') 0 n] and [f.out_string "\n" 0 1]. + @since 4.01.0 *) val get_formatter_out_functions : unit -> formatter_out_functions (** Return the current output functions of the pretty-printer, including line splitting and indentation functions. Useful to record the - current setting and restore it afterwards. *) + current setting and restore it afterwards. + @since 4.01.0 *) (** {6:tagsmeaning Changing the meaning of printing semantic tags} *) @@ -457,7 +459,7 @@ type formatter margin, maximum indentation limit, maximum number of boxes simultaneously opened, ellipsis, and so on, are specific to each pretty-printer and may be fixed independently. - Given a [Pervasives.out_channel] output channel [oc], a new formatter + Given a {!Pervasives.out_channel} output channel [oc], a new formatter writing to that channel is simply obtained by calling [formatter_of_out_channel oc]. Alternatively, the [make_formatter] function allocates a new @@ -500,7 +502,7 @@ val make_formatter : (string -> int -> int -> unit) -> (unit -> unit) -> formatter (** [make_formatter out flush] returns a new formatter that writes according to the output function [out], and the flushing function [flush]. For - instance, a formatter to the [Pervasives.out_channel] [oc] is returned by + instance, a formatter to the {!Pervasives.out_channel} [oc] is returned by [make_formatter (Pervasives.output oc) (fun () -> Pervasives.flush oc)]. *) (** {6 Basic functions to use with formatters} *) @@ -557,13 +559,15 @@ val pp_get_formatter_tag_functions : val pp_set_formatter_out_functions : formatter -> formatter_out_functions -> unit +(** @since 4.01.0 *) val pp_get_formatter_out_functions : formatter -> unit -> formatter_out_functions (** These functions are the basic ones: usual functions operating on the standard formatter are defined via partial evaluation of these primitives. For instance, - [print_string] is equal to [pp_print_string std_formatter]. *) + [print_string] is equal to [pp_print_string std_formatter]. + @since 4.01.0 *) val pp_flush_formatter : formatter -> unit (** [pp_flush_formatter fmt] flushes [fmt]'s internal queue, ensuring that all @@ -571,7 +575,8 @@ val pp_flush_formatter : formatter -> unit operation will close all boxes and reset the state of the formatter. This will not flush [fmt]'s output. In most cases, the user may want to use - {!pp_print_flush} instead. *) + {!pp_print_flush} instead. + @since 4.04.0 *) (** {6 Convenience formatting functions.} *) @@ -604,7 +609,7 @@ val fprintf : formatter -> ('a, formatter, unit) format -> 'a The format [fmt] is a character string which contains three types of objects: plain characters and conversion specifications as specified in - the [Printf] module, and pretty-printing indications specific to the + the {!Printf} module, and pretty-printing indications specific to the [Format] module. The pretty-printing indication characters are introduced by diff --git a/stdlib/gc.ml b/stdlib/gc.ml index fc04b606..d3dd069b 100644 --- a/stdlib/gc.ml +++ b/stdlib/gc.ml @@ -47,7 +47,7 @@ external stat : unit -> stat = "caml_gc_stat" external quick_stat : unit -> stat = "caml_gc_quick_stat" external counters : unit -> (float * float * float) = "caml_gc_counters" external minor_words : unit -> (float [@unboxed]) - = "caml_gc_minor_words" "caml_gc_minor_words_unboxed" [@@noalloc] + = "caml_gc_minor_words" "caml_gc_minor_words_unboxed" external get : unit -> control = "caml_gc_get" external set : control -> unit = "caml_gc_set" external minor : unit -> unit = "caml_gc_minor" @@ -55,7 +55,7 @@ external major_slice : int -> int = "caml_gc_major_slice" external major : unit -> unit = "caml_gc_major" external full_major : unit -> unit = "caml_gc_full_major" external compact : unit -> unit = "caml_gc_compaction" -external get_minor_free : unit -> int = "caml_get_minor_free" [@@noalloc] +external get_minor_free : unit -> int = "caml_get_minor_free" external get_bucket : int -> int = "caml_get_major_bucket" [@@noalloc] external get_credit : unit -> int = "caml_get_major_credit" [@@noalloc] external huge_fallback_count : unit -> int = "caml_gc_huge_fallback_count" diff --git a/stdlib/gc.mli b/stdlib/gc.mli index 5a1e6272..80020379 100644 --- a/stdlib/gc.mli +++ b/stdlib/gc.mli @@ -171,7 +171,7 @@ external counters : unit -> float * float * float = "caml_gc_counters" is as fast as [quick_stat]. *) external minor_words : unit -> (float [@unboxed]) - = "caml_gc_minor_words" "caml_gc_minor_words_unboxed" [@@noalloc] + = "caml_gc_minor_words" "caml_gc_minor_words_unboxed" (** Number of words allocated in the minor heap since the program was started. This number is accurate in byte-code programs, but only an approximation in programs compiled to native code. @@ -219,7 +219,7 @@ val allocated_bytes : unit -> float started. It is returned as a [float] to avoid overflow problems with [int] on 32-bit machines. *) -external get_minor_free : unit -> int = "caml_get_minor_free" [@@noalloc] +external get_minor_free : unit -> int = "caml_get_minor_free" (** Return the current size of the free space inside the minor heap. @since 4.03.0 *) diff --git a/stdlib/genlex.mli b/stdlib/genlex.mli index 3ac4cc5f..47394926 100644 --- a/stdlib/genlex.mli +++ b/stdlib/genlex.mli @@ -67,7 +67,7 @@ val make_lexer : string list -> char Stream.t -> token Stream.t belongs to this list, and as [Ident s] otherwise. A special character [s] is returned as [Kwd s] if [s] belongs to this list, and cause a lexical error (exception - [Stream.Error] with the offending lexeme as its parameter) otherwise. + {!Stream.Error} with the offending lexeme as its parameter) otherwise. Blanks and newlines are skipped. Comments delimited by [(*] and [*)] - are skipped as well, and can be nested. A [Stream.Failure] exception + are skipped as well, and can be nested. A {!Stream.Failure} exception is raised if end of stream is unexpectedly reached.*) diff --git a/stdlib/hashtbl.ml b/stdlib/hashtbl.ml index 58e558e2..77e8b907 100644 --- a/stdlib/hashtbl.ml +++ b/stdlib/hashtbl.ml @@ -203,6 +203,26 @@ let find h key = | Cons{key=k3; data=d3; next=next3} -> if compare key k3 = 0 then d3 else find_rec key next3 +let rec find_rec_opt key = function + | Empty -> + None + | Cons{key=k; data; next} -> + if compare key k = 0 then Some data else find_rec_opt key next + +let find_opt h key = + match h.data.(key_index h key) with + | Empty -> None + | Cons{key=k1; data=d1; next=next1} -> + if compare key k1 = 0 then Some d1 else + match next1 with + | Empty -> None + | Cons{key=k2; data=d2; next=next2} -> + if compare key k2 = 0 then Some d2 else + match next2 with + | Empty -> None + | Cons{key=k3; data=d3; next=next3} -> + if compare key k3 = 0 then Some d3 else find_rec_opt key next3 + let find_all h key = let rec find_in_bucket = function | Empty -> @@ -361,6 +381,7 @@ module type S = val add: 'a t -> key -> 'a -> unit val remove: 'a t -> key -> unit val find: 'a t -> key -> 'a + val find_opt: 'a t -> key -> 'a option val find_all: 'a t -> key -> 'a list val replace : 'a t -> key -> 'a -> unit val mem : 'a t -> key -> bool @@ -382,6 +403,7 @@ module type SeededS = val add : 'a t -> key -> 'a -> unit val remove : 'a t -> key -> unit val find : 'a t -> key -> 'a + val find_opt: 'a t -> key -> 'a option val find_all : 'a t -> key -> 'a list val replace : 'a t -> key -> 'a -> unit val mem : 'a t -> key -> bool @@ -449,6 +471,26 @@ module MakeSeeded(H: SeededHashedType): (SeededS with type key = H.t) = | Cons{key=k3; data=d3; next=next3} -> if H.equal key k3 then d3 else find_rec key next3 + let rec find_rec_opt key = function + | Empty -> + None + | Cons{key=k; data; next} -> + if H.equal key k then Some data else find_rec_opt key next + + let find_opt h key = + match h.data.(key_index h key) with + | Empty -> None + | Cons{key=k1; data=d1; next=next1} -> + if H.equal key k1 then Some d1 else + match next1 with + | Empty -> None + | Cons{key=k2; data=d2; next=next2} -> + if H.equal key k2 then Some d2 else + match next2 with + | Empty -> None + | Cons{key=k3; data=d3; next=next3} -> + if H.equal key k3 then Some d3 else find_rec_opt key next3 + let find_all h key = let rec find_in_bucket = function | Empty -> diff --git a/stdlib/hashtbl.mli b/stdlib/hashtbl.mli index 6d9cd00d..d3c0ef3e 100644 --- a/stdlib/hashtbl.mli +++ b/stdlib/hashtbl.mli @@ -87,6 +87,11 @@ val find : ('a, 'b) t -> 'a -> 'b (** [Hashtbl.find tbl x] returns the current binding of [x] in [tbl], or raises [Not_found] if no such binding exists. *) +val find_opt : ('a, 'b) t -> 'a -> 'b option +(** [Hashtbl.find_opt tbl x] returns the current binding of [x] in [tbl], + or [None] if no such binding exists. + @since 4.05 *) + val find_all : ('a, 'b) t -> 'a -> 'b list (** [Hashtbl.find_all tbl x] returns the list of all data associated with [x] in [tbl]. @@ -188,8 +193,9 @@ val randomize : unit -> unit val is_randomized : unit -> bool (** return if the tables are currently created in randomized mode by default - @since 4.02.0 *) + @since 4.03.0 *) +(** @since 4.00.0 *) type statistics = { num_bindings: int; (** Number of bindings present in the table. @@ -271,19 +277,25 @@ module type S = type 'a t val create : int -> 'a t val clear : 'a t -> unit - val reset : 'a t -> unit + val reset : 'a t -> unit (** @since 4.00.0 *) + val copy : 'a t -> 'a t val add : 'a t -> key -> 'a -> unit val remove : 'a t -> key -> unit val find : 'a t -> key -> 'a + val find_opt : 'a t -> key -> 'a option + (** @since 4.05.0 *) + val find_all : 'a t -> key -> 'a list val replace : 'a t -> key -> 'a -> unit val mem : 'a t -> key -> bool val iter : (key -> 'a -> unit) -> 'a t -> unit val filter_map_inplace: (key -> 'a -> 'a option) -> 'a t -> unit + (** @since 4.03.0 *) + val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b val length : 'a t -> int - val stats: 'a t -> statistics + val stats: 'a t -> statistics (** @since 4.00.0 *) end (** The output signature of the functor {!Hashtbl.Make}. *) @@ -328,11 +340,15 @@ module type SeededS = val add : 'a t -> key -> 'a -> unit val remove : 'a t -> key -> unit val find : 'a t -> key -> 'a + val find_opt : 'a t -> key -> 'a option (** @since 4.05.0 *) + val find_all : 'a t -> key -> 'a list val replace : 'a t -> key -> 'a -> unit val mem : 'a t -> key -> bool val iter : (key -> 'a -> unit) -> 'a t -> unit val filter_map_inplace: (key -> 'a -> 'a option) -> 'a t -> unit + (** @since 4.03.0 *) + val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b val length : 'a t -> int val stats: 'a t -> statistics diff --git a/stdlib/int32.ml b/stdlib/int32.ml index 52e5c099..959c0424 100644 --- a/stdlib/int32.ml +++ b/stdlib/int32.ml @@ -57,6 +57,11 @@ let to_string n = format "%d" n external of_string : string -> int32 = "caml_int32_of_string" +let of_string_opt s = + (* TODO: expose a non-raising primitive directly. *) + try Some (of_string s) + with Failure _ -> None + type t = int32 let compare (x: t) (y: t) = Pervasives.compare x y diff --git a/stdlib/int32.mli b/stdlib/int32.mli index 249fa23d..19d7897a 100644 --- a/stdlib/int32.mli +++ b/stdlib/int32.mli @@ -135,6 +135,11 @@ external of_string : string -> int32 = "caml_int32_of_string" a valid representation of an integer, or if the integer represented exceeds the range of integers representable in type [int32]. *) +val of_string_opt: string -> int32 option +(** Same as [of_string], but return [None] instead of raising. + @since 4.05 *) + + val to_string : int32 -> string (** Return the string representation of its argument, in signed decimal. *) diff --git a/stdlib/int64.ml b/stdlib/int64.ml index d5b4610a..8bc95a03 100644 --- a/stdlib/int64.ml +++ b/stdlib/int64.ml @@ -55,6 +55,13 @@ let to_string n = format "%d" n external of_string : string -> int64 = "caml_int64_of_string" +let of_string_opt s = + (* TODO: expose a non-raising primitive directly. *) + try Some (of_string s) + with Failure _ -> None + + + external bits_of_float : float -> int64 = "caml_int64_bits_of_float" "caml_int64_bits_of_float_unboxed" [@@unboxed] [@@noalloc] diff --git a/stdlib/int64.mli b/stdlib/int64.mli index 85df21fe..d8aacd53 100644 --- a/stdlib/int64.mli +++ b/stdlib/int64.mli @@ -157,6 +157,10 @@ external of_string : string -> int64 = "caml_int64_of_string" a valid representation of an integer, or if the integer represented exceeds the range of integers representable in type [int64]. *) +val of_string_opt: string -> int64 option +(** Same as [of_string], but return [None] instead of raising. + @since 4.05 *) + val to_string : int64 -> string (** Return the string representation of its argument, in decimal. *) diff --git a/stdlib/lazy.mli b/stdlib/lazy.mli index e14e6bb4..ee10366e 100644 --- a/stdlib/lazy.mli +++ b/stdlib/lazy.mli @@ -48,7 +48,7 @@ external force : 'a t -> 'a = "%lazy_force" If [x] has already been forced, [Lazy.force x] returns the same value again without recomputing it. If it raised an exception, the same exception is raised again. - Raise [Undefined] if the forcing of [x] tries to force [x] itself + Raise {!Undefined} if the forcing of [x] tries to force [x] itself recursively. *) @@ -56,10 +56,10 @@ val force_val : 'a t -> 'a (** [force_val x] forces the suspension [x] and returns its result. If [x] has already been forced, [force_val x] returns the same value again without recomputing it. - Raise [Undefined] if the forcing of [x] tries to force [x] itself + Raise {!Undefined} if the forcing of [x] tries to force [x] itself recursively. If the computation of [x] raises an exception, it is unspecified - whether [force_val x] raises the same exception or [Undefined]. + whether [force_val x] raises the same exception or {!Undefined}. *) val from_fun : (unit -> 'a) -> 'a t diff --git a/stdlib/list.ml b/stdlib/list.ml index c02f5e86..73b7d834 100644 --- a/stdlib/list.ml +++ b/stdlib/list.ml @@ -39,6 +39,14 @@ let nth l n = | a::l -> if n = 0 then a else nth_aux l (n-1) in nth_aux l n +let nth_opt l n = + if n < 0 then invalid_arg "List.nth" else + let rec nth_aux l n = + match l with + | [] -> None + | a::l -> if n = 0 then Some a else nth_aux l (n-1) + in nth_aux l n + let append = (@) let rec rev_append l1 l2 = @@ -158,10 +166,18 @@ let rec assoc x = function [] -> raise Not_found | (a,b)::l -> if compare a x = 0 then b else assoc x l +let rec assoc_opt x = function + [] -> None + | (a,b)::l -> if compare a x = 0 then Some b else assoc_opt x l + let rec assq x = function [] -> raise Not_found | (a,b)::l -> if a == x then b else assq x l +let rec assq_opt x = function + [] -> None + | (a,b)::l -> if a == x then Some b else assq_opt x l + let rec mem_assoc x = function | [] -> false | (a, _) :: l -> compare a x = 0 || mem_assoc x l @@ -183,6 +199,10 @@ let rec find p = function | [] -> raise Not_found | x :: l -> if p x then x else find p l +let rec find_opt p = function + | [] -> None + | x :: l -> if p x then Some x else find_opt p l + let find_all p = let rec find accu = function | [] -> rev accu @@ -430,3 +450,19 @@ let sort_uniq cmp l = in let len = length l in if len < 2 then l else sort len l + +let rec compare_lengths l1 l2 = + match l1, l2 with + | [], [] -> 0 + | [], _ -> -1 + | _, [] -> 1 + | _ :: l1, _ :: l2 -> compare_lengths l1 l2 +;; + +let rec compare_length_with l n = + match l, n with + | [], 0 -> 0 + | [], _ -> if n > 0 then -1 else 1 + | _, 0 -> 1 + | _ :: l, n -> compare_length_with l (n-1) +;; diff --git a/stdlib/list.mli b/stdlib/list.mli index 7d12712a..e8d6d392 100644 --- a/stdlib/list.mli +++ b/stdlib/list.mli @@ -29,6 +29,20 @@ val length : 'a list -> int (** Return the length (number of elements) of the given list. *) +val compare_lengths : 'a list -> 'b list -> int +(** Compare the lengths of two lists. [compare_lengths l1 l2] is + equivalent to [compare (length l1) (length l2)], except that + the computation stops after itering on the shortest list. + @since 4.05.0 + *) + +val compare_length_with : 'a list -> int -> int +(** Compare the length of a list to an integer. [compare_length_with l n] is + equivalent to [compare (length l) n], except that + the computation stops after at most [n] iterations on the list. + @since 4.05.0 +*) + val cons : 'a -> 'a list -> 'a list (** [cons x xs] is [x :: xs] @since 4.03.0 @@ -40,14 +54,22 @@ val hd : 'a list -> 'a val tl : 'a list -> 'a list (** Return the given list without its first element. Raise - [Failure "tl"] if the list is empty. *) + [Failure "tl"] if the list is empty. *) -val nth : 'a list -> int -> 'a +val nth: 'a list -> int -> 'a (** Return the [n]-th element of the given list. The first element (head of the list) is at position 0. Raise [Failure "nth"] if the list is too short. Raise [Invalid_argument "List.nth"] if [n] is negative. *) +val nth_opt: 'a list -> int -> 'a option +(** Return the [n]-th element of the given list. + The first element (head of the list) is at position 0. + Return [None] if the list is too short. + Raise [Invalid_argument "List.nth"] if [n] is negative. + @since 4.05 +*) + val rev : 'a list -> 'a list (** List reversal. *) @@ -185,6 +207,12 @@ val find : ('a -> bool) -> 'a list -> 'a Raise [Not_found] if there is no value that satisfies [p] in the list [l]. *) +val find_opt: ('a -> bool) -> 'a list -> 'a option +(** [find_opt p l] returns the first element of the list [l] that + satisfies the predicate [p], or [None] if there is no value that + satisfies [p] in the list [l]. + @since 4.05 *) + val filter : ('a -> bool) -> 'a list -> 'a list (** [filter p l] returns all the elements of the list [l] that satisfy the predicate [p]. The order of the elements @@ -212,10 +240,24 @@ val assoc : 'a -> ('a * 'b) list -> 'b Raise [Not_found] if there is no value associated with [a] in the list [l]. *) +val assoc_opt: 'a -> ('a * 'b) list -> 'b option +(** [assoc_opt a l] returns the value associated with key [a] in the list of + pairs [l]. That is, + [assoc_opt a [ ...; (a,b); ...] = b] + if [(a,b)] is the leftmost binding of [a] in list [l]. + Returns [None] if there is no value associated with [a] in the + list [l]. + @since 4.05 *) + val assq : 'a -> ('a * 'b) list -> 'b (** Same as {!List.assoc}, but uses physical equality instead of structural equality to compare keys. *) +val assq_opt : 'a -> ('a * 'b) list -> 'b option +(** Same as {!List.assoc_opt}, but uses physical equality instead of structural + equality to compare keys. + @since 4.05 *) + val mem_assoc : 'a -> ('a * 'b) list -> bool (** Same as {!List.assoc}, but simply return true if a binding exists, and false if no bindings exist for the given key. *) diff --git a/stdlib/listLabels.mli b/stdlib/listLabels.mli index 50cf05ab..52ded3f9 100644 --- a/stdlib/listLabels.mli +++ b/stdlib/listLabels.mli @@ -33,6 +33,25 @@ val hd : 'a list -> 'a (** Return the first element of the given list. Raise [Failure "hd"] if the list is empty. *) +val compare_lengths : 'a list -> 'b list -> int +(** Compare the lengths of two lists. [compare_lengths l1 l2] is + equivalent to [compare (length l1) (length l2)], except that + the computation stops after itering on the shortest list. + @since 4.05.0 + *) + +val compare_length_with : 'a list -> len:int -> int +(** Compare the length of a list to an integer. [compare_length_with l n] is + equivalent to [compare (length l) n], except that + the computation stops after at most [n] iterations on the list. + @since 4.05.0 +*) + +val cons : 'a -> 'a list -> 'a list +(** [cons x xs] is [x :: xs] + @since 4.05.0 +*) + val tl : 'a list -> 'a list (** Return the given list without its first element. Raise [Failure "tl"] if the list is empty. *) @@ -43,6 +62,14 @@ val nth : 'a list -> int -> 'a Raise [Failure "nth"] if the list is too short. Raise [Invalid_argument "List.nth"] if [n] is negative. *) +val nth_opt: 'a list -> int -> 'a option +(** Return the [n]-th element of the given list. + The first element (head of the list) is at position 0. + Return [None] if the list is too short. + Raise [Invalid_argument "List.nth"] if [n] is negative. + @since 4.05 +*) + val rev : 'a list -> 'a list (** List reversal. *) @@ -52,8 +79,8 @@ val append : 'a list -> 'a list -> 'a list operator is not tail-recursive either. *) val rev_append : 'a list -> 'a list -> 'a list -(** [ListLabels.rev_append l1 l2] reverses [l1] and concatenates it to [l2]. - This is equivalent to {!ListLabels.rev}[ l1 @ l2], but [rev_append] is +(** [List.rev_append l1 l2] reverses [l1] and concatenates it to [l2]. + This is equivalent to {!List.rev}[ l1 @ l2], but [rev_append] is tail-recursive and more efficient. *) val concat : 'a list list -> 'a list @@ -71,40 +98,40 @@ val flatten : 'a list list -> 'a list val iter : f:('a -> unit) -> 'a list -> unit -(** [ListLabels.iter f [a1; ...; an]] applies function [f] in turn to +(** [List.iter f [a1; ...; an]] applies function [f] in turn to [a1; ...; an]. It is equivalent to [begin f a1; f a2; ...; f an; () end]. *) val iteri : f:(int -> 'a -> unit) -> 'a list -> unit -(** Same as {!ListLabels.iter}, but the function is applied to the index of +(** Same as {!List.iter}, but the function is applied to the index of the element as first argument (counting from 0), and the element itself as second argument. @since 4.00.0 *) val map : f:('a -> 'b) -> 'a list -> 'b list -(** [ListLabels.map f [a1; ...; an]] applies function [f] to [a1, ..., an], +(** [List.map f [a1; ...; an]] applies function [f] to [a1, ..., an], and builds the list [[f a1; ...; f an]] with the results returned by [f]. Not tail-recursive. *) val mapi : f:(int -> 'a -> 'b) -> 'a list -> 'b list -(** Same as {!ListLabels.map}, but the function is applied to the index of +(** Same as {!List.map}, but the function is applied to the index of the element as first argument (counting from 0), and the element itself as second argument. @since 4.00.0 *) val rev_map : f:('a -> 'b) -> 'a list -> 'b list -(** [ListLabels.rev_map f l] gives the same result as - {!ListLabels.rev}[ (]{!ListLabels.map}[ f l)], but is tail-recursive and +(** [List.rev_map f l] gives the same result as + {!List.rev}[ (]{!List.map}[ f l)], but is tail-recursive and more efficient. *) val fold_left : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a -(** [ListLabels.fold_left f a [b1; ...; bn]] is +(** [List.fold_left f a [b1; ...; bn]] is [f (... (f (f a b1) b2) ...) bn]. *) val fold_right : f:('a -> 'b -> 'b) -> 'a list -> init:'b -> 'b -(** [ListLabels.fold_right f [a1; ...; an] b] is +(** [List.fold_right f [a1; ...; an] b] is [f a1 (f a2 (... (f an b) ...))]. Not tail-recursive. *) @@ -112,32 +139,32 @@ val fold_right : f:('a -> 'b -> 'b) -> 'a list -> init:'b -> 'b val iter2 : f:('a -> 'b -> unit) -> 'a list -> 'b list -> unit -(** [ListLabels.iter2 f [a1; ...; an] [b1; ...; bn]] calls in turn +(** [List.iter2 f [a1; ...; an] [b1; ...; bn]] calls in turn [f a1 b1; ...; f an bn]. Raise [Invalid_argument] if the two lists are determined to have different lengths. *) val map2 : f:('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list -(** [ListLabels.map2 f [a1; ...; an] [b1; ...; bn]] is +(** [List.map2 f [a1; ...; an] [b1; ...; bn]] is [[f a1 b1; ...; f an bn]]. Raise [Invalid_argument] if the two lists are determined to have different lengths. Not tail-recursive. *) val rev_map2 : f:('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list -(** [ListLabels.rev_map2 f l1 l2] gives the same result as - {!ListLabels.rev}[ (]{!ListLabels.map2}[ f l1 l2)], but is tail-recursive and +(** [List.rev_map2 f l1 l2] gives the same result as + {!List.rev}[ (]{!List.map2}[ f l1 l2)], but is tail-recursive and more efficient. *) val fold_left2 : f:('a -> 'b -> 'c -> 'a) -> init:'a -> 'b list -> 'c list -> 'a -(** [ListLabels.fold_left2 f a [b1; ...; bn] [c1; ...; cn]] is +(** [List.fold_left2 f a [b1; ...; bn] [c1; ...; cn]] is [f (... (f (f a b1 c1) b2 c2) ...) bn cn]. Raise [Invalid_argument] if the two lists are determined to have different lengths. *) val fold_right2 : f:('a -> 'b -> 'c -> 'c) -> 'a list -> 'b list -> init:'c -> 'c -(** [ListLabels.fold_right2 f [a1; ...; an] [b1; ...; bn] c] is +(** [List.fold_right2 f [a1; ...; an] [b1; ...; bn] c] is [f a1 b1 (f a2 b2 (... (f an bn c) ...))]. Raise [Invalid_argument] if the two lists are determined to have different lengths. Not tail-recursive. *) @@ -157,12 +184,12 @@ val exists : f:('a -> bool) -> 'a list -> bool [(p a1) || (p a2) || ... || (p an)]. *) val for_all2 : f:('a -> 'b -> bool) -> 'a list -> 'b list -> bool -(** Same as {!ListLabels.for_all}, but for a two-argument predicate. +(** Same as {!List.for_all}, but for a two-argument predicate. Raise [Invalid_argument] if the two lists are determined to have different lengths. *) val exists2 : f:('a -> 'b -> bool) -> 'a list -> 'b list -> bool -(** Same as {!ListLabels.exists}, but for a two-argument predicate. +(** Same as {!List.exists}, but for a two-argument predicate. Raise [Invalid_argument] if the two lists are determined to have different lengths. *) @@ -171,7 +198,7 @@ val mem : 'a -> set:'a list -> bool to an element of [l]. *) val memq : 'a -> set:'a list -> bool -(** Same as {!ListLabels.mem}, but uses physical equality instead of structural +(** Same as {!List.mem}, but uses physical equality instead of structural equality to compare list elements. *) @@ -184,13 +211,20 @@ val find : f:('a -> bool) -> 'a list -> 'a Raise [Not_found] if there is no value that satisfies [p] in the list [l]. *) +val find_opt: f:('a -> bool) -> 'a list -> 'a option +(** [find p l] returns the first element of the list [l] + that satisfies the predicate [p]. + Returns [None] if there is no value that satisfies [p] in the + list [l]. + @since 4.05 *) + val filter : f:('a -> bool) -> 'a list -> 'a list (** [filter p l] returns all the elements of the list [l] that satisfy the predicate [p]. The order of the elements in the input list is preserved. *) val find_all : f:('a -> bool) -> 'a list -> 'a list -(** [find_all] is another name for {!ListLabels.filter}. *) +(** [find_all] is another name for {!List.filter}. *) val partition : f:('a -> bool) -> 'a list -> 'a list * 'a list (** [partition p l] returns a pair of lists [(l1, l2)], where @@ -211,16 +245,31 @@ val assoc : 'a -> ('a * 'b) list -> 'b Raise [Not_found] if there is no value associated with [a] in the list [l]. *) +val assoc_opt: 'a -> ('a * 'b) list -> 'b option +(** [assoc_opt a l] returns the value associated with key [a] in the list of + pairs [l]. That is, + [assoc a [ ...; (a,b); ...] = b] + if [(a,b)] is the leftmost binding of [a] in list [l]. + Returns [None] if there is no value associated with [a] in the + list [l]. + @since 4.05 +*) + val assq : 'a -> ('a * 'b) list -> 'b -(** Same as {!ListLabels.assoc}, but uses physical equality instead of +(** Same as {!List.assoc}, but uses physical equality instead of structural equality to compare keys. *) +val assq_opt: 'a -> ('a * 'b) list -> 'b option +(** Same as {!List.assoc_opt}, but uses physical equality instead of + structural equality to compare keys. + @since 4.05.0 *) + val mem_assoc : 'a -> map:('a * 'b) list -> bool -(** Same as {!ListLabels.assoc}, but simply return true if a binding exists, +(** Same as {!List.assoc}, but simply return true if a binding exists, and false if no bindings exist for the given key. *) val mem_assq : 'a -> map:('a * 'b) list -> bool -(** Same as {!ListLabels.mem_assoc}, but uses physical equality instead of +(** Same as {!List.mem_assoc}, but uses physical equality instead of structural equality to compare keys. *) val remove_assoc : 'a -> ('a * 'b) list -> ('a * 'b) list @@ -229,7 +278,7 @@ val remove_assoc : 'a -> ('a * 'b) list -> ('a * 'b) list Not tail-recursive. *) val remove_assq : 'a -> ('a * 'b) list -> ('a * 'b) list -(** Same as {!ListLabels.remove_assoc}, but uses physical equality instead +(** Same as {!List.remove_assoc}, but uses physical equality instead of structural equality to compare keys. Not tail-recursive. *) @@ -261,7 +310,7 @@ val sort : cmp:('a -> 'a -> int) -> 'a list -> 'a list a complete specification). For example, {!Pervasives.compare} is a suitable comparison function. The resulting list is sorted in increasing order. - [ListLabels.sort] is guaranteed to run in constant heap space + [List.sort] is guaranteed to run in constant heap space (in addition to the size of the result list) and logarithmic stack space. @@ -270,7 +319,7 @@ val sort : cmp:('a -> 'a -> int) -> 'a list -> 'a list *) val stable_sort : cmp:('a -> 'a -> int) -> 'a list -> 'a list -(** Same as {!ListLabels.sort}, but the sorting algorithm is guaranteed to +(** Same as {!List.sort}, but the sorting algorithm is guaranteed to be stable (i.e. elements that compare equal are kept in their original order) . @@ -279,12 +328,12 @@ val stable_sort : cmp:('a -> 'a -> int) -> 'a list -> 'a list *) val fast_sort : cmp:('a -> 'a -> int) -> 'a list -> 'a list -(** Same as {!ListLabels.sort} or {!ListLabels.stable_sort}, whichever is +(** Same as {!List.sort} or {!List.stable_sort}, whichever is faster on typical input. *) val sort_uniq : cmp:('a -> 'a -> int) -> 'a list -> 'a list -(** Same as {!ListLabels.sort}, but also remove duplicates. - @since 4.02.0 *) +(** Same as {!List.sort}, but also remove duplicates. + @since 4.03.0 *) val merge : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list (** Merge two lists: diff --git a/stdlib/map.ml b/stdlib/map.ml index 50ebdb3d..18659c49 100644 --- a/stdlib/map.ml +++ b/stdlib/map.ml @@ -43,10 +43,18 @@ module type S = val cardinal: 'a t -> int val bindings: 'a t -> (key * 'a) list val min_binding: 'a t -> (key * 'a) + val min_binding_opt: 'a t -> (key * 'a) option val max_binding: 'a t -> (key * 'a) + val max_binding_opt: 'a t -> (key * 'a) option val choose: 'a t -> (key * 'a) + val choose_opt: 'a t -> (key * 'a) option val split: key -> 'a t -> 'a t * 'a option * 'a t val find: key -> 'a t -> 'a + val find_opt: key -> 'a t -> 'a option + val find_first: (key -> bool) -> 'a t -> key * 'a + val find_first_opt: (key -> bool) -> 'a t -> (key * 'a) option + val find_last: (key -> bool) -> 'a t -> key * 'a + val find_last_opt: (key -> bool) -> 'a t -> (key * 'a) option val map: ('a -> 'b) -> 'a t -> 'b t val mapi: (key -> 'a -> 'b) -> 'a t -> 'b t end @@ -125,6 +133,86 @@ module Make(Ord: OrderedType) = struct if c = 0 then d else find x (if c < 0 then l else r) + let rec find_first_aux v0 d0 f = function + Empty -> + (v0, d0) + | Node(l, v, d, r, _) -> + if f v then + find_first_aux v d f l + else + find_first_aux v0 d0 f r + + let rec find_first f = function + Empty -> + raise Not_found + | Node(l, v, d, r, _) -> + if f v then + find_first_aux v d f l + else + find_first f r + + let rec find_first_opt_aux v0 d0 f = function + Empty -> + Some (v0, d0) + | Node(l, v, d, r, _) -> + if f v then + find_first_opt_aux v d f l + else + find_first_opt_aux v0 d0 f r + + let rec find_first_opt f = function + Empty -> + None + | Node(l, v, d, r, _) -> + if f v then + find_first_opt_aux v d f l + else + find_first_opt f r + + let rec find_last_aux v0 d0 f = function + Empty -> + (v0, d0) + | Node(l, v, d, r, _) -> + if f v then + find_last_aux v d f r + else + find_last_aux v0 d0 f l + + let rec find_last f = function + Empty -> + raise Not_found + | Node(l, v, d, r, _) -> + if f v then + find_last_aux v d f r + else + find_last f l + + let rec find_last_opt_aux v0 d0 f = function + Empty -> + Some (v0, d0) + | Node(l, v, d, r, _) -> + if f v then + find_last_opt_aux v d f r + else + find_last_opt_aux v0 d0 f l + + let rec find_last_opt f = function + Empty -> + None + | Node(l, v, d, r, _) -> + if f v then + find_last_opt_aux v d f r + else + find_last_opt f l + + let rec find_opt x = function + Empty -> + None + | Node(l, v, d, r, _) -> + let c = Ord.compare x v in + if c = 0 then Some d + else find_opt x (if c < 0 then l else r) + let rec mem x = function Empty -> false @@ -137,11 +225,21 @@ module Make(Ord: OrderedType) = struct | Node(Empty, x, d, _, _) -> (x, d) | Node(l, _, _, _, _) -> min_binding l + let rec min_binding_opt = function + Empty -> None + | Node(Empty, x, d, _, _) -> Some (x, d) + | Node(l, _, _, _, _) -> min_binding_opt l + let rec max_binding = function Empty -> raise Not_found | Node(_, x, d, Empty, _) -> (x, d) | Node(_, _, _, r, _) -> max_binding r + let rec max_binding_opt = function + Empty -> None + | Node(_, x, d, Empty, _) -> Some (x, d) + | Node(_, _, _, r, _) -> max_binding_opt r + let rec remove_min_binding = function Empty -> invalid_arg "Map.remove_min_elt" | Node(Empty, _, _, r, _) -> r @@ -356,4 +454,6 @@ module Make(Ord: OrderedType) = struct let choose = min_binding + let choose_opt = min_binding_opt + end diff --git a/stdlib/map.mli b/stdlib/map.mli index d8c68f8f..331e2a72 100644 --- a/stdlib/map.mli +++ b/stdlib/map.mli @@ -104,6 +104,9 @@ module type S = (** [merge f m1 m2] computes a map whose keys is a subset of keys of [m1] and of [m2]. The presence of each such binding, and the corresponding value, is determined with the function [f]. + In terms of the [find_opt] operation, we have + [find_opt x (merge f m1 m2) = f (find_opt x m1) (find_opt x m2)] + for any key [x], provided that [f None None = None]. @since 3.12.0 *) @@ -111,6 +114,13 @@ module type S = (** [union f m1 m2] computes a map whose keys is the union of keys of [m1] and of [m2]. When the same binding is defined in both arguments, the function [f] is used to combine them. + This is a special case of [merge]: [union f m1 m2] is equivalent + to [merge f' m1 m2], where + - [f' None None = None] + - [f' (Some v) None = Some v] + - [f' None (Some v) = Some v] + - [f' (Some v1) (Some v2) = f v1 v2] + @since 4.03.0 *) @@ -143,7 +153,7 @@ module type S = val exists: (key -> 'a -> bool) -> 'a t -> bool (** [exists p m] checks if at least one binding of the map - satisfy the predicate [p]. + satisfies the predicate [p]. @since 3.12.0 *) @@ -184,12 +194,25 @@ module type S = @since 3.12.0 *) + val min_binding_opt: 'a t -> (key * 'a) option + (** Return the smallest binding of the given map + (with respect to the [Ord.compare] ordering), or [None] + if the map is empty. + @since 4.05 + *) + val max_binding: 'a t -> (key * 'a) (** Same as {!Map.S.min_binding}, but returns the largest binding of the given map. @since 3.12.0 *) + val max_binding_opt: 'a t -> (key * 'a) option + (** Same as {!Map.S.min_binding_opt}, but returns the largest binding + of the given map. + @since 4.05 + *) + val choose: 'a t -> (key * 'a) (** Return one binding of the given map, or raise [Not_found] if the map is empty. Which binding is chosen is unspecified, @@ -197,6 +220,13 @@ module type S = @since 3.12.0 *) + val choose_opt: 'a t -> (key * 'a) option + (** Return one binding of the given map, or [None] if + the map is empty. Which binding is chosen is unspecified, + but equal bindings will be chosen for equal maps. + @since 4.05 + *) + val split: key -> 'a t -> 'a t * 'a option * 'a t (** [split x m] returns a triple [(l, data, r)], where [l] is the map with all the bindings of [m] whose key @@ -212,6 +242,46 @@ module type S = (** [find x m] returns the current binding of [x] in [m], or raises [Not_found] if no such binding exists. *) + val find_opt: key -> 'a t -> 'a option + (** [find_opt x m] returns [Some v] if the current binding of [x] + in [m] is [v], or [None] if no such binding exists. + @since 4.05 + *) + + val find_first: (key -> bool) -> 'a t -> key * 'a + (** [find_first f m], where [f] is a monotonically increasing function, + returns the binding of [m] with the lowest key [k] such that [f k], + or raises [Not_found] if no such key exists. + + For example, [find_first (fun k -> Ord.compare k x >= 0) m] will return + the first binding [k, v] of [m] where [Ord.compare k x >= 0] + (intuitively: [k >= x]), or raise [Not_found] if [x] is greater than any + element of [m]. + + @since 4.05 + *) + + val find_first_opt: (key -> bool) -> 'a t -> (key * 'a) option + (** [find_first_opt f m], where [f] is a monotonically increasing function, + returns an option containing the binding of [m] with the lowest key [k] + such that [f k], or [None] if no such key exists. + @since 4.05 + *) + + val find_last: (key -> bool) -> 'a t -> key * 'a + (** [find_last f m], where [f] is a monotonically decreasing function, + returns the binding of [m] with the highest key [k] such that [f k], + or raises [Not_found] if no such key exists. + @since 4.05 + *) + + val find_last_opt: (key -> bool) -> 'a t -> (key * 'a) option + (** [find_last_opt f m], where [f] is a monotonically decreasing function, + returns an option containing the binding of [m] with the highest key [k] + such that [f k], or [None] if no such key exists. + @since 4.05 + *) + val map: ('a -> 'b) -> 'a t -> 'b t (** [map f m] returns a map with same domain as [m], where the associated value [a] of all bindings of [m] has been diff --git a/stdlib/marshal.mli b/stdlib/marshal.mli index 671feed7..2473365f 100644 --- a/stdlib/marshal.mli +++ b/stdlib/marshal.mli @@ -90,7 +90,7 @@ val to_channel : out_channel -> 'a -> extern_flags list -> unit digest of the code transmitted along with the code position.) The exact definition of which free variables are captured in a - closure is not specified and can very between bytecode and native + closure is not specified and can vary between bytecode and native code (and according to optimization flags). In particular, a function value accessing a global reference may or may not include the reference in its closure. If it does, unmarshaling the diff --git a/stdlib/moreLabels.mli b/stdlib/moreLabels.mli index 9c5ab690..824c9a23 100644 --- a/stdlib/moreLabels.mli +++ b/stdlib/moreLabels.mli @@ -31,6 +31,7 @@ module Hashtbl : sig val copy : ('a, 'b) t -> ('a, 'b) t val add : ('a, 'b) t -> key:'a -> data:'b -> unit val find : ('a, 'b) t -> 'a -> 'b + val find_opt : ('a, 'b) t -> 'a -> 'b option val find_all : ('a, 'b) t -> 'a -> 'b list val mem : ('a, 'b) t -> 'a -> bool val remove : ('a, 'b) t -> 'a -> unit @@ -43,6 +44,7 @@ module Hashtbl : sig ('a, 'b) t -> init:'c -> 'c val length : ('a, 'b) t -> int val randomize : unit -> unit + val is_randomized : unit -> bool type statistics = Hashtbl.statistics val stats : ('a, 'b) t -> statistics module type HashedType = Hashtbl.HashedType @@ -58,6 +60,7 @@ module Hashtbl : sig val add : 'a t -> key:key -> data:'a -> unit val remove : 'a t -> key -> unit val find : 'a t -> key -> 'a + val find_opt: 'a t -> key -> 'a option val find_all : 'a t -> key -> 'a list val replace : 'a t -> key:key -> data:'a -> unit val mem : 'a t -> key -> bool @@ -81,6 +84,7 @@ module Hashtbl : sig val add : 'a t -> key:key -> data:'a -> unit val remove : 'a t -> key -> unit val find : 'a t -> key -> 'a + val find_opt : 'a t -> key -> 'a option val find_all : 'a t -> key -> 'a list val replace : 'a t -> key:key -> data:'a -> unit val mem : 'a t -> key -> bool @@ -129,10 +133,18 @@ module Map : sig val cardinal: 'a t -> int val bindings: 'a t -> (key * 'a) list val min_binding: 'a t -> (key * 'a) + val min_binding_opt: 'a t -> (key * 'a) option val max_binding: 'a t -> (key * 'a) + val max_binding_opt: 'a t -> (key * 'a) option val choose: 'a t -> (key * 'a) + val choose_opt: 'a t -> (key * 'a) option val split: key -> 'a t -> 'a t * 'a option * 'a t val find : key -> 'a t -> 'a + val find_opt: key -> 'a t -> 'a option + val find_first : f:(key -> bool) -> 'a t -> key * 'a + val find_first_opt : f:(key -> bool) -> 'a t -> (key * 'a) option + val find_last : f:(key -> bool) -> 'a t -> key * 'a + val find_last_opt : f:(key -> bool) -> 'a t -> (key * 'a) option val map : f:('a -> 'b) -> 'a t -> 'b t val mapi : f:(key -> 'a -> 'b) -> 'a t -> 'b t end @@ -167,10 +179,18 @@ module Set : sig val cardinal : t -> int val elements : t -> elt list val min_elt : t -> elt + val min_elt_opt: t -> elt option val max_elt : t -> elt + val max_elt_opt: t -> elt option val choose : t -> elt + val choose_opt: t -> elt option val split: elt -> t -> t * bool * t val find: elt -> t -> elt + val find_opt: elt -> t -> elt option + val find_first: f:(elt -> bool) -> t -> elt + val find_first_opt: f:(elt -> bool) -> t -> elt option + val find_last: f:(elt -> bool) -> t -> elt + val find_last_opt: f:(elt -> bool) -> t -> elt option val of_list: elt list -> t end module Make : functor (Ord : OrderedType) -> S with type elt = Ord.t diff --git a/stdlib/nativeint.ml b/stdlib/nativeint.ml index df2d1dd2..2f6fe780 100644 --- a/stdlib/nativeint.ml +++ b/stdlib/nativeint.ml @@ -54,6 +54,11 @@ let to_string n = format "%d" n external of_string: string -> nativeint = "caml_nativeint_of_string" +let of_string_opt s = + (* TODO: expose a non-raising primitive directly. *) + try Some (of_string s) + with Failure _ -> None + type t = nativeint let compare (x: t) (y: t) = Pervasives.compare x y diff --git a/stdlib/nativeint.mli b/stdlib/nativeint.mli index e23440c5..b733318d 100644 --- a/stdlib/nativeint.mli +++ b/stdlib/nativeint.mli @@ -85,7 +85,7 @@ val max_int : nativeint or 2{^63} - 1 on a 64-bit platform. *) val min_int : nativeint -(** The greatest representable native integer, +(** The smallest representable native integer, either -2{^31} on a 32-bit platform, or -2{^63} on a 64-bit platform. *) @@ -165,6 +165,10 @@ external of_string : string -> nativeint = "caml_nativeint_of_string" a valid representation of an integer, or if the integer represented exceeds the range of integers representable in type [nativeint]. *) +val of_string_opt: string -> nativeint option +(** Same as [of_string], but return [None] instead of raising. + @since 4.05 *) + val to_string : nativeint -> string (** Return the string representation of its argument, in decimal. *) @@ -178,7 +182,7 @@ val compare: t -> t -> int {!Set.Make} and {!Map.Make}. *) val equal: t -> t -> bool -(** The equal function for natives ints. +(** The equal function for native ints. @since 4.03.0 *) (**/**) diff --git a/stdlib/obj.mli b/stdlib/obj.mli index 31c2e45f..e76c7df9 100644 --- a/stdlib/obj.mli +++ b/stdlib/obj.mli @@ -50,7 +50,7 @@ external field : t -> int -> t = "%obj_field" For experts only: [set_field] et al can be made safe by first wrapping the block in - [Sys.opaque_identity], so any information about its contents will not + {!Sys.opaque_identity}, so any information about its contents will not be propagated. *) external set_field : t -> int -> t -> unit = "%obj_set_field" diff --git a/stdlib/pervasives.ml b/stdlib/pervasives.ml index a8c6310c..fc7d9218 100644 --- a/stdlib/pervasives.ml +++ b/stdlib/pervasives.ml @@ -159,7 +159,9 @@ external float : int -> float = "%floatofint" external float_of_int : int -> float = "%floatofint" external truncate : float -> int = "%intoffloat" external int_of_float : float -> int = "%intoffloat" -external float_of_bits : int64 -> float = "caml_int64_float_of_bits" +external float_of_bits : int64 -> float + = "caml_int64_float_of_bits" "caml_int64_float_of_bits_unboxed" + [@@unboxed] [@@noalloc] let infinity = float_of_bits 0x7F_F0_00_00_00_00_00_00L let neg_infinity = @@ -241,10 +243,22 @@ let bool_of_string = function | "false" -> false | _ -> invalid_arg "bool_of_string" +let bool_of_string_opt = function + | "true" -> Some true + | "false" -> Some false + | _ -> None + let string_of_int n = format_int "%d" n external int_of_string : string -> int = "caml_int_of_string" + +let int_of_string_opt s = + (* TODO: provide this directly as a non-raising primitive. *) + try Some (int_of_string s) + with Failure _ -> None + + external string_get : string -> int -> char = "%string_safe_get" let valid_float_lexem s = @@ -262,6 +276,11 @@ let string_of_float f = valid_float_lexem (format_float "%.12g" f) external float_of_string : string -> float = "caml_float_of_string" +let float_of_string_opt s = + (* TODO: provide this directly as a non-raising primitive. *) + try Some (float_of_string s) + with Failure _ -> None + (* List operations -- more in module List *) let rec ( @ ) l1 l2 = @@ -468,7 +487,9 @@ let prerr_newline () = output_char stderr '\n'; flush stderr let read_line () = flush stdout; input_line stdin let read_int () = int_of_string(read_line()) +let read_int_opt () = int_of_string_opt(read_line()) let read_float () = float_of_string(read_line()) +let read_float_opt () = float_of_string_opt(read_line()) (* Operations on large files *) diff --git a/stdlib/pervasives.mli b/stdlib/pervasives.mli index 1f5e3628..7bf88f88 100644 --- a/stdlib/pervasives.mli +++ b/stdlib/pervasives.mli @@ -571,6 +571,13 @@ val bool_of_string : string -> bool Raise [Invalid_argument "bool_of_string"] if the string is not ["true"] or ["false"]. *) +val bool_of_string_opt: string -> bool option +(** Convert the given string to a boolean. + Return [None] if the string is not + ["true"] or ["false"]. + @since 4.05 +*) + val string_of_int : int -> string (** Return the string representation of an integer, in decimal. *) @@ -585,6 +592,12 @@ external int_of_string : string -> int = "caml_int_of_string" a valid representation of an integer, or if the integer represented exceeds the range of integers representable in type [int]. *) + +val int_of_string_opt: string -> int option +(** Same as [int_of_string], but returs [None] instead of raising. + @since 4.05 +*) + val string_of_float : float -> string (** Return the string representation of a floating-point number. *) @@ -605,6 +618,11 @@ external float_of_string : string -> float = "caml_float_of_string" Raise [Failure "float_of_string"] if the given string is not a valid representation of a float. *) +val float_of_string_opt: string -> float option +(** Same as [float_of_string], but returns [None] instead of raising. + @since 4.05 +*) + (** {6 Pair operations} *) external fst : 'a * 'b -> 'a = "%field0" @@ -710,12 +728,24 @@ val read_int : unit -> int and convert it to an integer. Raise [Failure "int_of_string"] if the line read is not a valid representation of an integer. *) +val read_int_opt: unit -> int option +(** Same as [read_int_opt], but returs [None] instead of raising. + @since 4.05 +*) + val read_float : unit -> float (** Flush standard output, then read one line from standard input and convert it to a floating-point number. The result is unspecified if the line read is not a valid representation of a floating-point number. *) +val read_float_opt: unit -> float option +(** Flush standard output, then read one line from standard input + and convert it to a floating-point number. + Returns [None] if the line read is not a valid + representation of a floating-point number. + @since 4.05.0 *) + (** {7 General output functions} *) @@ -747,7 +777,7 @@ val open_out_bin : string -> out_channel val open_out_gen : open_flag list -> int -> string -> out_channel (** [open_out_gen mode perm filename] opens the named file for writing, as described above. The extra argument [mode] - specify the opening mode. The extra argument [perm] specifies + specifies the opening mode. The extra argument [perm] specifies the file permissions, in case the file must be created. {!Pervasives.open_out} and {!Pervasives.open_out_bin} are special cases of this function. *) @@ -1003,6 +1033,7 @@ external decr : int ref -> unit = "%decr" (** {6 Result type} *) +(** @since 4.03.0 *) type ('a,'b) result = Ok of 'a | Error of 'b (** {6 Operations on format strings} *) @@ -1049,12 +1080,12 @@ type ('a,'b) result = Ok of 'a | Error of 'b - ['b] is the type of input source for formatted input functions and the type of output target for formatted output functions. - For [printf]-style functions from module [Printf], ['b] is typically + For [printf]-style functions from module {!Printf}, ['b] is typically [out_channel]; - for [printf]-style functions from module [Format], ['b] is typically - [Format.formatter]; - for [scanf]-style functions from module [Scanf], ['b] is typically - [Scanf.Scanning.in_channel]. + for [printf]-style functions from module {!Format}, ['b] is typically + {!Format.formatter}; + for [scanf]-style functions from module {!Scanf}, ['b] is typically + {!Scanf.Scanning.in_channel}. Type argument ['b] is also the type of the first argument given to user's defined printing functions for [%a] and [%t] conversions, diff --git a/stdlib/printexc.ml b/stdlib/printexc.ml index 1e882f58..90214d9f 100644 --- a/stdlib/printexc.ml +++ b/stdlib/printexc.ml @@ -89,6 +89,9 @@ type raw_backtrace external get_raw_backtrace: unit -> raw_backtrace = "caml_get_exception_raw_backtrace" +external raise_with_backtrace: exn -> raw_backtrace -> 'a + = "%raise_with_backtrace" + type backtrace_slot = | Known_location of { is_raise : bool; @@ -237,8 +240,7 @@ external get_raw_backtrace_next_slot : (* confusingly named: returns the *string* corresponding to the global current backtrace *) -let get_backtrace () = - backtrace_to_string (convert_raw_backtrace (get_raw_backtrace ())) +let get_backtrace () = raw_backtrace_to_string (get_raw_backtrace ()) external record_backtrace: bool -> unit = "caml_record_backtrace" external backtrace_status: unit -> bool = "caml_backtrace_status" diff --git a/stdlib/printexc.mli b/stdlib/printexc.mli index 19bd39c3..cc865085 100644 --- a/stdlib/printexc.mli +++ b/stdlib/printexc.mli @@ -42,13 +42,20 @@ val print_backtrace: out_channel -> unit on the output channel [oc]. The backtrace lists the program locations where the most-recently raised exception was raised and where it was propagated through function calls. + + If the call is not inside an exception handler, the returned + backtrace is unspecified. If the call is after some + exception-catching code (before in the handler, or in a when-guard + during the matching of the exception handler), the backtrace may + correspond to a later exception than the handled one. + @since 3.11.0 *) val get_backtrace: unit -> string (** [Printexc.get_backtrace ()] returns a string containing the same exception backtrace that [Printexc.print_backtrace] would - print. + print. Same restriction usage than {!print_backtrace}. @since 3.11.0 *) @@ -106,7 +113,7 @@ type raw_backtrace val get_raw_backtrace: unit -> raw_backtrace (** [Printexc.get_raw_backtrace ()] returns the same exception backtrace that [Printexc.print_backtrace] would print, but in - a raw format. + a raw format. Same restriction usage than {!print_backtrace}. @since 4.01.0 *) @@ -125,6 +132,14 @@ val raw_backtrace_to_string: raw_backtrace -> string @since 4.01.0 *) +external raise_with_backtrace: exn -> raw_backtrace -> 'a + = "%raise_with_backtrace" +(** Reraise the exception using the given raw_backtrace for the + origin of the exception + + @since 4.05.0 +*) + (** {6 Current call stack} *) val get_callstack: int -> raw_backtrace @@ -200,6 +215,7 @@ type location = { @since 4.02 *) +(** @since 4.02.0 *) module Slot : sig type t = backtrace_slot @@ -271,7 +287,7 @@ val raw_backtrace_length : raw_backtrace -> int *) val get_raw_backtrace_slot : raw_backtrace -> int -> raw_backtrace_slot -(** [get_slot bckt pos] returns the slot in position [pos] in the +(** [get_raw_backtrace_slot bckt pos] returns the slot in position [pos] in the backtrace [bckt]. @since 4.02 @@ -289,6 +305,22 @@ val get_raw_backtrace_next_slot : raw_backtrace_slot -> raw_backtrace_slot option (** [get_raw_backtrace_next_slot slot] returns the next slot inlined, if any. + Sample code to iterate over all frames (inlined and non-inlined): + {[ + (* Iterate over inlined frames *) + let rec iter_raw_backtrace_slot f slot = + f slot; + match get_raw_backtrace_next_slot slot with + | None -> () + | Some slot' -> iter_raw_backtrace_slot f slot' + + (* Iterate over stack frames *) + let iter_raw_backtrace f bt = + for i = 0 to raw_backtrace_length bt - 1 do + iter_raw_backtrace_slot f (get_raw_backtrace_slot bt i) + done + ]} + @since 4.04.0 *) @@ -303,7 +335,7 @@ val exn_slot_id: exn -> int *) val exn_slot_name: exn -> string -(** [Printexc.exn_slot_id exn] returns the internal name of the constructor +(** [Printexc.exn_slot_name exn] returns the internal name of the constructor used to create the exception value [exn]. @since 4.02.0 diff --git a/stdlib/printf.mli b/stdlib/printf.mli index c10f0c6c..92a3b16e 100644 --- a/stdlib/printf.mli +++ b/stdlib/printf.mli @@ -150,7 +150,7 @@ val kfprintf : (out_channel -> 'd) -> out_channel -> val ikfprintf : ('b -> 'd) -> 'b -> ('a, 'b, 'c, 'd) format4 -> 'a (** Same as [kfprintf] above, but does not print anything. Useful to ignore some material when conditionally printing. - @since 4.0 + @since 4.01.0 *) val ksprintf : (string -> 'd) -> ('a, unit, string, 'd) format4 -> 'a diff --git a/stdlib/queue.mli b/stdlib/queue.mli index 33c13e61..46e48fd0 100644 --- a/stdlib/queue.mli +++ b/stdlib/queue.mli @@ -41,14 +41,14 @@ val push : 'a -> 'a t -> unit val take : 'a t -> 'a (** [take q] removes and returns the first element in queue [q], - or raises [Empty] if the queue is empty. *) + or raises {!Empty} if the queue is empty. *) val pop : 'a t -> 'a (** [pop] is a synonym for [take]. *) val peek : 'a t -> 'a (** [peek q] returns the first element in queue [q], without removing - it from the queue, or raises [Empty] if the queue is empty. *) + it from the queue, or raises {!Empty} if the queue is empty. *) val top : 'a t -> 'a (** [top] is a synonym for [peek]. *) diff --git a/stdlib/random.mli b/stdlib/random.mli index 9e97cce2..0cbaace3 100644 --- a/stdlib/random.mli +++ b/stdlib/random.mli @@ -66,7 +66,7 @@ val bool : unit -> bool (** {6 Advanced functions} *) -(** The functions from module [State] manipulate the current state +(** The functions from module {!State} manipulate the current state of the random generator explicitly. This allows using one or several deterministic PRNGs, even in a multi-threaded program, without interference from diff --git a/stdlib/scanf.mli b/stdlib/scanf.mli index ab3c054c..ea0d4ce7 100644 --- a/stdlib/scanf.mli +++ b/stdlib/scanf.mli @@ -19,7 +19,7 @@ (** {7 Functional input with format strings} *) -(** The module [Scanf] provides formatted input functions or {e scanners}. +(** The module {!Scanf} provides formatted input functions or {e scanners}. The formatted input functions can read from any kind of input, including strings, files, or anything that can return characters. The more general @@ -86,12 +86,12 @@ module Scanning : sig type in_channel -(** The notion of input channel for the [Scanf] module: +(** The notion of input channel for the {!Scanf} module: those channels provide all the machinery necessary to read from any source - of characters, including a [!Pervasives.in_channel] value. - A [Scanf.Scanning.in_channel] value is also called a {i formatted input + of characters, including a {!Pervasives.in_channel} value. + A Scanf.Scanning.in_channel value is also called a {i formatted input channel} or equivalently a {i scanning buffer}. - The type [Scanning.scanbuf] below is an alias for [Scanning.in_channel]. + The type {!Scanning.scanbuf} below is an alias for [Scanning.in_channel]. @since 3.12.0 *) @@ -108,12 +108,12 @@ type scanbuf = in_channel *) val stdin : in_channel -(** The standard input notion for the [Scanf] module. - [Scanning.stdin] is the [Scanning.in_channel] formatted input channel - attached to [!Pervasives.stdin]. +(** The standard input notion for the {!Scanf} module. + [Scanning.stdin] is the {!Scanning.in_channel} formatted input channel + attached to {!Pervasives.stdin}. Note: in the interactive system, when input is read from - [!Pervasives.stdin], the newline character that triggers evaluation is + {!Pervasives.stdin}, the newline character that triggers evaluation is part of the input; thus, the scanning specifications must properly skip this additional newline character (for instance, simply add a ['\n'] as the last character of the format string). @@ -126,7 +126,7 @@ type file_name = string *) val open_in : file_name -> in_channel -(** [Scanning.open_in fname] returns a [!Scanning.in_channel] formatted input +(** [Scanning.open_in fname] returns a {!Scanning.in_channel} formatted input channel for bufferized reading in text mode from file [fname]. Note: @@ -138,32 +138,32 @@ val open_in : file_name -> in_channel *) val open_in_bin : file_name -> in_channel -(** [Scanning.open_in_bin fname] returns a [!Scanning.in_channel] formatted +(** [Scanning.open_in_bin fname] returns a {!Scanning.in_channel} formatted input channel for bufferized reading in binary mode from file [fname]. @since 3.12.0 *) val close_in : in_channel -> unit -(** Closes the [!Pervasives.in_channel] associated with the given - [!Scanning.in_channel] formatted input channel. +(** Closes the {!Pervasives.in_channel} associated with the given + {!Scanning.in_channel} formatted input channel. @since 3.12.0 *) val from_file : file_name -> in_channel -(** An alias for [!Scanning.open_in] above. *) +(** An alias for {!Scanning.open_in} above. *) val from_file_bin : string -> in_channel -(** An alias for [!Scanning.open_in_bin] above. *) +(** An alias for {!Scanning.open_in_bin} above. *) val from_string : string -> in_channel -(** [Scanning.from_string s] returns a [!Scanning.in_channel] formatted +(** [Scanning.from_string s] returns a {!Scanning.in_channel} formatted input channel which reads from the given string. Reading starts from the first character in the string. The end-of-input condition is set when the end of the string is reached. *) val from_function : (unit -> char) -> in_channel -(** [Scanning.from_function f] returns a [!Scanning.in_channel] formatted +(** [Scanning.from_function f] returns a {!Scanning.in_channel} formatted input channel with the given function as its reading method. When scanning needs one more character, the given function is called. @@ -173,32 +173,32 @@ val from_function : (unit -> char) -> in_channel *) val from_channel : Pervasives.in_channel -> in_channel -(** [Scanning.from_channel ic] returns a [!Scanning.in_channel] formatted - input channel which reads from the regular [!Pervasives.in_channel] input +(** [Scanning.from_channel ic] returns a {!Scanning.in_channel} formatted + input channel which reads from the regular {!Pervasives.in_channel} input channel [ic] argument. Reading starts at current reading position of [ic]. *) val end_of_input : in_channel -> bool (** [Scanning.end_of_input ic] tests the end-of-input condition of the given - [!Scanning.in_channel] formatted input channel. + {!Scanning.in_channel} formatted input channel. *) val beginning_of_input : in_channel -> bool (** [Scanning.beginning_of_input ic] tests the beginning of input condition - of the given [!Scanning.in_channel] formatted input channel. + of the given {!Scanning.in_channel} formatted input channel. *) val name_of_input : in_channel -> string (** [Scanning.name_of_input ic] returns the name of the character source - for the given [!Scanning.in_channel] formatted input channel. + for the given {!Scanning.in_channel} formatted input channel. @since 3.09.0 *) val stdib : in_channel [@@ocaml.deprecated "Use Scanf.Scanning.stdin instead."] -(** A deprecated alias for [!Scanning.stdin], the scanning buffer reading from - [!Pervasives.stdin]. +(** A deprecated alias for {!Scanning.stdin}, the scanning buffer reading from + {!Pervasives.stdin}. *) end @@ -213,11 +213,11 @@ type ('a, 'b, 'c, 'd) scanner = precisely, if [scan] is some formatted input function, then [scan ic fmt f] applies [f] to all the arguments specified by format string [fmt], when [scan] has read those arguments from the - [!Scanning.in_channel] formatted input channel [ic]. + {!Scanning.in_channel} formatted input channel [ic]. - For instance, the [!Scanf.scanf] function below has type + For instance, the {!Scanf.scanf} function below has type [('a, 'b, 'c, 'd) scanner], since it is a formatted input function that - reads from [!Scanning.stdin]: [scanf fmt f] applies [f] to the arguments + reads from {!Scanning.stdin}: [scanf fmt f] applies [f] to the arguments specified by [fmt], reading those arguments from [!Pervasives.stdin] as expected. @@ -240,7 +240,7 @@ exception Scan_failure of string val bscanf : Scanning.in_channel -> ('a, 'b, 'c, 'd) scanner (** [bscanf ic fmt r1 ... rN f] reads characters from the - [!Scanning.in_channel] formatted input channel [ic] and converts them to + {!Scanning.in_channel} formatted input channel [ic] and converts them to values according to format string [fmt]. As a final step, receiver function [f] is applied to the values read and gives the result of the [bscanf] call. @@ -410,7 +410,7 @@ val bscanf : Scanning.in_channel -> ('a, 'b, 'c, 'd) scanner - the [scanf] facility is not intended for heavy duty lexical analysis and parsing. If it appears not expressive enough for your needs, several alternative exists: regular expressions (module - [Str]), stream parsers, [ocamllex]-generated lexers, + {!Str}), stream parsers, [ocamllex]-generated lexers, [ocamlyacc]-generated parsers. *) @@ -434,11 +434,11 @@ val bscanf : Scanning.in_channel -> ('a, 'b, 'c, 'd) scanner For instance, format ["%s@%%"] reads a string up to the next [%] character, and format ["%s@%@"] reads a string up to the next [@]. - The scanning indications introduce slight differences in the syntax of - [Scanf] format strings, compared to those used for the [Printf] + {!Scanf} format strings, compared to those used for the {!Printf} module. However, the scanning indications are similar to those used in - the [Format] module; hence, when producing formatted text to be scanned - by [!Scanf.bscanf], it is wise to use printing functions from the - [Format] module (or, if you need to use functions from [Printf], banish + the {!Format} module; hence, when producing formatted text to be scanned + by {!Scanf.bscanf}, it is wise to use printing functions from the + {!Format} module (or, if you need to use functions from {!Printf}, banish or carefully double check the format strings that contain ['@'] characters). *) @@ -448,7 +448,7 @@ val bscanf : Scanning.in_channel -> ('a, 'b, 'c, 'd) scanner (** Scanners may raise the following exceptions when the input cannot be read according to the format string: - - Raise [Scanf.Scan_failure] if the input does not match the format. + - Raise {!Scanf.Scan_failure} if the input does not match the format. - Raise [Failure] if a conversion to a number is not possible. @@ -471,7 +471,7 @@ val sscanf : string -> ('a, 'b, 'c, 'd) scanner val scanf : ('a, 'b, 'c, 'd) scanner (** Same as {!Scanf.bscanf}, but reads from the predefined formatted input - channel {!Scanf.Scanning.stdin} that is connected to [!Pervasives.stdin]. + channel {!Scanf.Scanning.stdin} that is connected to {!Pervasives.stdin}. *) val kscanf : @@ -498,7 +498,7 @@ val bscanf_format : (** [bscanf_format ic fmt f] reads a format string token from the formatted input channel [ic], according to the given format string [fmt], and applies [f] to the resulting format string value. - Raise [Scan_failure] if the format string value read does not have the + Raise {!Scan_failure} if the format string value read does not have the same type as [fmt]. @since 3.09.0 *) @@ -515,7 +515,7 @@ val format_from_string : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> ('a, 'b, 'c, 'd, 'e, 'f) format6 (** [format_from_string s fmt] converts a string argument to a format string, according to the given format string [fmt]. - Raise [Scan_failure] if [s], considered as a format string, does not + Raise {!Scan_failure} if [s], considered as a format string, does not have the same type as [fmt]. @since 3.10.0 *) @@ -529,7 +529,7 @@ val unescaped : string -> string Always return a copy of the argument, even if there is no escape sequence in the argument. - Raise [Scan_failure] if [s] is not properly escaped (i.e. [s] has invalid + Raise {!Scan_failure} if [s] is not properly escaped (i.e. [s] has invalid escape sequences or special characters that are not properly escaped). For instance, [String.unescaped "\""] will fail. @since 4.00.0 @@ -541,15 +541,15 @@ val fscanf : Pervasives.in_channel -> ('a, 'b, 'c, 'd) scanner [@@ocaml.deprecated "Use Scanning.from_channel then Scanf.bscanf."] (** @deprecated [Scanf.fscanf] is error prone and deprecated since 4.03.0. - This function violates the following invariant of the [Scanf] module: - To preserve scanning semantics, all scanning functions defined in [Scanf] - must read from a user defined [Scanning.in_channel] formatted input + This function violates the following invariant of the {!Scanf} module: + To preserve scanning semantics, all scanning functions defined in {!Scanf} + must read from a user defined {!Scanning.in_channel} formatted input channel. - If you need to read from a [!Pervasives.in_channel] input channel - [ic], simply define a [!Scanning.in_channel] formatted input channel as in + If you need to read from a {!Pervasives.in_channel} input channel + [ic], simply define a {!Scanning.in_channel} formatted input channel as in [let ib = Scanning.from_channel ic], - then use [!Scanf.bscanf ib] as usual. + then use [Scanf.bscanf ib] as usual. *) val kfscanf : diff --git a/stdlib/set.ml b/stdlib/set.ml index ac10e564..abfa41ed 100644 --- a/stdlib/set.ml +++ b/stdlib/set.ml @@ -47,10 +47,18 @@ module type S = val cardinal: t -> int val elements: t -> elt list val min_elt: t -> elt + val min_elt_opt: t -> elt option val max_elt: t -> elt + val max_elt_opt: t -> elt option val choose: t -> elt + val choose_opt: t -> elt option val split: elt -> t -> t * bool * t val find: elt -> t -> elt + val find_opt: elt -> t -> elt option + val find_first: (elt -> bool) -> t -> elt + val find_first_opt: (elt -> bool) -> t -> elt option + val find_last: (elt -> bool) -> t -> elt + val find_last_opt: (elt -> bool) -> t -> elt option val of_list: elt list -> t end @@ -163,11 +171,21 @@ module Make(Ord: OrderedType) = | Node(Empty, v, _, _) -> v | Node(l, _, _, _) -> min_elt l + let rec min_elt_opt = function + Empty -> None + | Node(Empty, v, _, _) -> Some v + | Node(l, _, _, _) -> min_elt_opt l + let rec max_elt = function Empty -> raise Not_found | Node(_, v, Empty, _) -> v | Node(_, _, r, _) -> max_elt r + let rec max_elt_opt = function + Empty -> None + | Node(_, v, Empty, _) -> Some v + | Node(_, _, r, _) -> max_elt_opt r + (* Remove the smallest element of the given set *) let rec remove_min_elt = function @@ -368,6 +386,8 @@ module Make(Ord: OrderedType) = let choose = min_elt + let choose_opt = min_elt_opt + let rec find x = function Empty -> raise Not_found | Node(l, v, r, _) -> @@ -375,6 +395,94 @@ module Make(Ord: OrderedType) = if c = 0 then v else find x (if c < 0 then l else r) + let rec find_first_aux v0 f = function + Empty -> + v0 + | Node(l, v, r, _) -> + if f v then + find_first_aux v f l + else + find_first_aux v0 f r + + let rec find_first f = function + Empty -> + raise Not_found + | Node(l, v, r, _) -> + if f v then + find_first_aux v f l + else + find_first f r + + let rec find_first_opt_aux v0 f = function + Empty -> + Some v0 + | Node(l, v, r, _) -> + if f v then + find_first_opt_aux v f l + else + find_first_opt_aux v0 f r + + let rec find_first_opt f = function + Empty -> + None + | Node(l, v, r, _) -> + if f v then + find_first_opt_aux v f l + else + find_first_opt f r + + let rec find_last_aux v0 f = function + Empty -> + v0 + | Node(l, v, r, _) -> + if f v then + find_last_aux v f r + else + find_last_aux v0 f l + + let rec find_last f = function + Empty -> + raise Not_found + | Node(l, v, r, _) -> + if f v then + find_last_aux v f r + else + find_last f l + + let rec find_last_opt_aux v0 f = function + Empty -> + Some v0 + | Node(l, v, r, _) -> + if f v then + find_last_opt_aux v f r + else + find_last_opt_aux v0 f l + + let rec find_last_opt f = function + Empty -> + None + | Node(l, v, r, _) -> + if f v then + find_last_opt_aux v f r + else + find_last_opt f l + + let rec find_opt x = function + Empty -> None + | Node(l, v, r, _) -> + let c = Ord.compare x v in + if c = 0 then Some v + else find_opt x (if c < 0 then l else r) + + let try_join l v r = + (* [join l v r] can only be called when (elements of l < v < + elements of r); use [try_join l v r] when this property may + not hold, but you hope it does hold in the common case *) + if (l = Empty || Ord.compare (max_elt l) v < 0) + && (r = Empty || Ord.compare v (min_elt r) < 0) + then join l v r + else union l (add v r) + let rec map f = function | Empty -> Empty | Node (l, v, r, _) as t -> @@ -383,12 +491,7 @@ module Make(Ord: OrderedType) = let v' = f v in let r' = map f r in if l == l' && v == v' && r == r' then t - else begin - if (l' = Empty || Ord.compare (max_elt l') v < 0) - && (r' = Empty || Ord.compare v (min_elt r') < 0) - then join l' v' r' - else union l' (add v' r') - end + else try_join l' v' r' let of_sorted_list l = let rec sub n l = diff --git a/stdlib/set.mli b/stdlib/set.mli index f57999eb..ef61e1a7 100644 --- a/stdlib/set.mli +++ b/stdlib/set.mli @@ -22,7 +22,7 @@ reasonably efficient: insertion and membership take time logarithmic in the size of the set, for instance. - The [Make] functor constructs implementations for any type, given a + The {!Make} functor constructs implementations for any type, given a [compare] function. For instance: {[ @@ -127,7 +127,8 @@ module type S = If no element of [s] is changed by [f], [s] is returned unchanged. (If each output of [f] is physically equal to its - input, the returned set is physically equal to [s].) *) + input, the returned set is physically equal to [s].) + @since 4.04.0 *) val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a (** [fold f s a] computes [(f xN ... (f x2 (f x1 a))...)], @@ -168,15 +169,35 @@ module type S = (with respect to the [Ord.compare] ordering), or raise [Not_found] if the set is empty. *) + val min_elt_opt: t -> elt option + (** Return the smallest element of the given set + (with respect to the [Ord.compare] ordering), or [None] + if the set is empty. + @since 4.05 + *) + val max_elt: t -> elt (** Same as {!Set.S.min_elt}, but returns the largest element of the given set. *) + val max_elt_opt: t -> elt option + (** Same as {!Set.S.min_elt_opt}, but returns the largest element of the + given set. + @since 4.05 + *) + val choose: t -> elt (** Return one element of the given set, or raise [Not_found] if the set is empty. Which element is chosen is unspecified, but equal elements will be chosen for equal sets. *) + val choose_opt: t -> elt option + (** Return one element of the given set, or [None] if + the set is empty. Which element is chosen is unspecified, + but equal elements will be chosen for equal sets. + @since 4.05 + *) + val split: elt -> t -> t * bool * t (** [split x s] returns a triple [(l, present, r)], where [l] is the set of elements of [s] that are @@ -192,6 +213,46 @@ module type S = exists. @since 4.01.0 *) + val find_opt: elt -> t -> elt option + (** [find_opt x s] returns the element of [s] equal to [x] (according + to [Ord.compare]), or [None] if no such element + exists. + @since 4.05 *) + + val find_first: (elt -> bool) -> t -> elt + (** [find_first f s], where [f] is a monotonically increasing function, + returns the lowest element [e] of [s] such that [f e], + or raises [Not_found] if no such element exists. + + For example, [find_first (fun e -> Ord.compare e x >= 0) s] will return + the first element [e] of [s] where [Ord.compare e x >= 0] (intuitively: + [e >= x]), or raise [Not_found] if [x] is greater than any element of + [s]. + + @since 4.05 + *) + + val find_first_opt: (elt -> bool) -> t -> elt option + (** [find_first_opt f s], where [f] is a monotonically increasing function, + returns an option containing the lowest element [e] of [s] such that + [f e], or [None] if no such element exists. + @since 4.05 + *) + + val find_last: (elt -> bool) -> t -> elt + (** [find_last f s], where [f] is a monotonically decreasing function, + returns the highest element [e] of [s] such that [f e], + or raises [Not_found] if no such element exists. + @since 4.05 + *) + + val find_last_opt: (elt -> bool) -> t -> elt option + (** [find_last_opt f s], where [f] is a monotonically decreasing function, + returns an option containing the highest element [e] of [s] such that + [f e], or [None] if no such element exists. + @since 4.05 + *) + val of_list: elt list -> t (** [of_list l] creates a set from a list of elements. This is usually more efficient than folding [add] over the list, diff --git a/stdlib/spacetime.ml b/stdlib/spacetime.ml index 56dde7c5..3e8abe1d 100644 --- a/stdlib/spacetime.ml +++ b/stdlib/spacetime.ml @@ -15,8 +15,10 @@ external spacetime_enabled : unit -> bool = "caml_spacetime_enabled" [@@noalloc] +let enabled = spacetime_enabled () + let if_spacetime_enabled f = - if spacetime_enabled () then f () else () + if enabled then f () else () module Series = struct type t = { diff --git a/stdlib/spacetime.mli b/stdlib/spacetime.mli index 5f3b51e6..d0bbac8b 100644 --- a/stdlib/spacetime.mli +++ b/stdlib/spacetime.mli @@ -50,6 +50,10 @@ For functions to decode the information recorded by the profiler, see the Spacetime offline library in otherlibs/. *) +(** [enabled] is [true] if the compiler is configured with spacetime and [false] + otherwise *) +val enabled : bool + module Series : sig (** Type representing a file that will hold a series of heap snapshots together with additional information required to interpret those @@ -62,7 +66,7 @@ module Series : sig (** [save_event] writes an event, which is an arbitrary string, into the given series file. This may be used for identifying particular points during program execution when analysing the profile. - The optional [time] parameter is as for [Snapshot.take]. + The optional [time] parameter is as for {!Snapshot.take}. *) val save_event : ?time:float -> t -> event_name:string -> unit @@ -70,7 +74,7 @@ module Series : sig interpeting the snapshots that [series] contains and then closes the [series] file. This function must be called to produce a valid series file. - The optional [time] parameter is as for [Snapshot.take]. + The optional [time] parameter is as for {!Snapshot.take}. *) val save_and_close : ?time:float -> t -> unit end @@ -81,7 +85,7 @@ module Snapshot : sig result to the [series] file. This function triggers a minor GC but does not allocate any memory itself. If the optional [time] is specified, it will be used instead of the - result of [Sys.time] as the timestamp of the snapshot. Such [time]s + result of {!Sys.time} as the timestamp of the snapshot. Such [time]s should start from zero and be monotonically increasing. This parameter is intended to be used so that snapshots can be correlated against wall clock time (which is not supported in the standard library) rather than @@ -90,6 +94,6 @@ module Snapshot : sig val take : ?time:float -> Series.t -> unit end -(** Like [Series.save_event], but writes to the automatic snapshot file. +(** Like {!Series.save_event}, but writes to the automatic snapshot file. This function is a no-op if OCAML_SPACETIME_INTERVAL was not set. *) val save_event_for_automatic_snapshots : event_name:string -> unit diff --git a/stdlib/stack.mli b/stdlib/stack.mli index c057186c..4ce89953 100644 --- a/stdlib/stack.mli +++ b/stdlib/stack.mli @@ -33,11 +33,11 @@ val push : 'a -> 'a t -> unit val pop : 'a t -> 'a (** [pop s] removes and returns the topmost element in stack [s], - or raises [Empty] if the stack is empty. *) + or raises {!Empty} if the stack is empty. *) val top : 'a t -> 'a (** [top s] returns the topmost element in stack [s], - or raises [Empty] if the stack is empty. *) + or raises {!Empty} if the stack is empty. *) val clear : 'a t -> unit (** Discard all elements from a stack. *) diff --git a/stdlib/stream.mli b/stdlib/stream.mli index 157c9f63..03b34a04 100644 --- a/stdlib/stream.mli +++ b/stdlib/stream.mli @@ -67,10 +67,10 @@ val iter : ('a -> unit) -> 'a t -> unit val next : 'a t -> 'a (** Return the first element of the stream and remove it from the - stream. Raise Stream.Failure if the stream is empty. *) + stream. Raise {!Stream.Failure} if the stream is empty. *) val empty : 'a t -> unit -(** Return [()] if the stream is empty, else raise [Stream.Failure]. *) +(** Return [()] if the stream is empty, else raise {!Stream.Failure}. *) (** {6 Useful functions} *) diff --git a/stdlib/string.ml b/stdlib/string.ml index 9c4a97f2..1d382274 100644 --- a/stdlib/string.ml +++ b/stdlib/string.ml @@ -69,7 +69,7 @@ let rec unsafe_blits dst pos sep seplen = function let concat sep = function [] -> "" | l -> let seplen = length sep in bts @@ - unsafe_blits + unsafe_blits (B.create (sum_lengths 0 seplen l)) 0 sep seplen l @@ -121,12 +121,26 @@ let rec index_rec s lim i c = (* duplicated in bytes.ml *) let index s c = index_rec s (length s) 0 c +(* duplicated in bytes.ml *) +let rec index_rec_opt s lim i c = + if i >= lim then None else + if unsafe_get s i = c then Some i else index_rec_opt s lim (i + 1) c + +(* duplicated in bytes.ml *) +let index_opt s c = index_rec_opt s (length s) 0 c + (* duplicated in bytes.ml *) let index_from s i c = let l = length s in if i < 0 || i > l then invalid_arg "String.index_from / Bytes.index_from" else index_rec s l i c +(* duplicated in bytes.ml *) +let index_from_opt s i c = + let l = length s in + if i < 0 || i > l then invalid_arg "String.index_from_opt / Bytes.index_from_opt" else + index_rec_opt s l i c + (* duplicated in bytes.ml *) let rec rindex_rec s i c = if i < 0 then raise Not_found else @@ -142,6 +156,21 @@ let rindex_from s i c = else rindex_rec s i c +(* duplicated in bytes.ml *) +let rec rindex_rec_opt s i c = + if i < 0 then None else + if unsafe_get s i = c then Some i else rindex_rec_opt s (i - 1) c + +(* duplicated in bytes.ml *) +let rindex_opt s c = rindex_rec_opt s (length s - 1) c + +(* duplicated in bytes.ml *) +let rindex_from_opt s i c = + if i < -1 || i >= length s then + invalid_arg "String.rindex_from_opt / Bytes.rindex_from_opt" + else + rindex_rec_opt s i c + (* duplicated in bytes.ml *) let contains_from s i c = let l = length s in diff --git a/stdlib/string.mli b/stdlib/string.mli index 5c66cd00..6c250ef7 100644 --- a/stdlib/string.mli +++ b/stdlib/string.mli @@ -181,12 +181,24 @@ val index : string -> char -> int Raise [Not_found] if [c] does not occur in [s]. *) +val index_opt: string -> char -> int option +(** [String.index_opt s c] returns the index of the first + occurrence of character [c] in string [s], or + [None] if [c] does not occur in [s]. + @since 4.05 *) + val rindex : string -> char -> int (** [String.rindex s c] returns the index of the last occurrence of character [c] in string [s]. Raise [Not_found] if [c] does not occur in [s]. *) +val rindex_opt: string -> char -> int option +(** [String.rindex_opt s c] returns the index of the last occurrence + of character [c] in string [s], or [None] if [c] does not occur in + [s]. + @since 4.05 *) + val index_from : string -> int -> char -> int (** [String.index_from s i c] returns the index of the first occurrence of character [c] in string [s] after position [i]. @@ -195,6 +207,17 @@ val index_from : string -> int -> char -> int Raise [Invalid_argument] if [i] is not a valid position in [s]. Raise [Not_found] if [c] does not occur in [s] after position [i]. *) +val index_from_opt: string -> int -> char -> int option +(** [String.index_from_opt s i c] returns the index of the + first occurrence of character [c] in string [s] after position [i] + or [None] if [c] does not occur in [s] after position [i]. + + [String.index_opt s c] is equivalent to [String.index_from_opt s 0 c]. + Raise [Invalid_argument] if [i] is not a valid position in [s]. + + @since 4.05 +*) + val rindex_from : string -> int -> char -> int (** [String.rindex_from s i c] returns the index of the last occurrence of character [c] in string [s] before position [i+1]. @@ -204,6 +227,19 @@ val rindex_from : string -> int -> char -> int Raise [Invalid_argument] if [i+1] is not a valid position in [s]. Raise [Not_found] if [c] does not occur in [s] before position [i+1]. *) +val rindex_from_opt: string -> int -> char -> int option +(** [String.rindex_from_opt s i c] returns the index of the + last occurrence of character [c] in string [s] before position [i+1] + or [None] if [c] does not occur in [s] before position [i+1]. + + [String.rindex_opt s c] is equivalent to + [String.rindex_from_opt s (String.length s - 1) c]. + + Raise [Invalid_argument] if [i+1] is not a valid position in [s]. + + @since 4.05 +*) + val contains : string -> char -> bool (** [String.contains s c] tests if character [c] appears in the string [s]. *) diff --git a/stdlib/stringLabels.mli b/stdlib/stringLabels.mli index 7f9a5e53..41c5951d 100644 --- a/stdlib/stringLabels.mli +++ b/stdlib/stringLabels.mli @@ -53,7 +53,8 @@ val init : int -> f:(int -> char) -> string (** [init n f] returns a string of length [n], with character [i] initialized to the result of [f i]. - Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *) + Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. + @since 4.02.0 *) val copy : string -> string (** Return a copy of the given string. *) @@ -135,12 +136,24 @@ val index : string -> char -> int Raise [Not_found] if [c] does not occur in [s]. *) +val index_opt: string -> char -> int option +(** [String.index_opt s c] returns the index of the first + occurrence of character [c] in string [s], or + [None] if [c] does not occur in [s]. + @since 4.05 *) + val rindex : string -> char -> int (** [String.rindex s c] returns the index of the last occurrence of character [c] in string [s]. Raise [Not_found] if [c] does not occur in [s]. *) +val rindex_opt: string -> char -> int option +(** [String.rindex_opt s c] returns the index of the last occurrence + of character [c] in string [s], or [None] if [c] does not occur in + [s]. + @since 4.05 *) + val index_from : string -> int -> char -> int (** [String.index_from s i c] returns the index of the first occurrence of character [c] in string [s] after position [i]. @@ -149,6 +162,17 @@ val index_from : string -> int -> char -> int Raise [Invalid_argument] if [i] is not a valid position in [s]. Raise [Not_found] if [c] does not occur in [s] after position [i]. *) +val index_from_opt: string -> int -> char -> int option +(** [String.index_from_opt s i c] returns the index of the + first occurrence of character [c] in string [s] after position [i] + or [None] if [c] does not occur in [s] after position [i]. + + [String.index_opt s c] is equivalent to [String.index_from_opt s 0 c]. + Raise [Invalid_argument] if [i] is not a valid position in [s]. + + @since 4.05 +*) + val rindex_from : string -> int -> char -> int (** [String.rindex_from s i c] returns the index of the last occurrence of character [c] in string [s] before position [i+1]. @@ -158,6 +182,19 @@ val rindex_from : string -> int -> char -> int Raise [Invalid_argument] if [i+1] is not a valid position in [s]. Raise [Not_found] if [c] does not occur in [s] before position [i+1]. *) +val rindex_from_opt: string -> int -> char -> int option +(** [String.rindex_from_opt s i c] returns the index of the + last occurrence of character [c] in string [s] before position [i+1] + or [None] if [c] does not occur in [s] before position [i+1]. + + [String.rindex_opt s c] is equivalent to + [String.rindex_from_opt s (String.length s - 1) c]. + + Raise [Invalid_argument] if [i+1] is not a valid position in [s]. + + @since 4.05 +*) + val contains : string -> char -> bool (** [String.contains s c] tests if character [c] appears in the string [s]. *) @@ -178,20 +215,50 @@ val rcontains_from : string -> int -> char -> bool position in [s]. *) val uppercase : string -> string + [@@ocaml.deprecated "Use String.uppercase_ascii instead."] (** Return a copy of the argument, with all lowercase letters translated to uppercase, including accented letters of the ISO - Latin-1 (8859-1) character set. *) + Latin-1 (8859-1) character set. + @deprecated Functions operating on Latin-1 character set are deprecated. *) val lowercase : string -> string + [@@ocaml.deprecated "Use String.lowercase_ascii instead."] (** Return a copy of the argument, with all uppercase letters translated to lowercase, including accented letters of the ISO - Latin-1 (8859-1) character set. *) + Latin-1 (8859-1) character set. + @deprecated Functions operating on Latin-1 character set are deprecated. *) val capitalize : string -> string -(** Return a copy of the argument, with the first character set to uppercase. *) + [@@ocaml.deprecated "Use String.capitalize_ascii instead."] +(** Return a copy of the argument, with the first character set to uppercase, + using the ISO Latin-1 (8859-1) character set.. + @deprecated Functions operating on Latin-1 character set are deprecated. *) val uncapitalize : string -> string -(** Return a copy of the argument, with the first character set to lowercase. *) + [@@ocaml.deprecated "Use String.uncapitalize_ascii instead."] +(** Return a copy of the argument, with the first character set to lowercase, + using the ISO Latin-1 (8859-1) character set.. + @deprecated Functions operating on Latin-1 character set are deprecated. *) + +val uppercase_ascii : string -> string +(** Return a copy of the argument, with all lowercase letters + translated to uppercase, using the US-ASCII character set. + @since 4.05.0 *) + +val lowercase_ascii : string -> string +(** Return a copy of the argument, with all uppercase letters + translated to lowercase, using the US-ASCII character set. + @since 4.05.0 *) + +val capitalize_ascii : string -> string +(** Return a copy of the argument, with the first character set to uppercase, + using the US-ASCII character set. + @since 4.05.0 *) + +val uncapitalize_ascii : string -> string +(** Return a copy of the argument, with the first character set to lowercase, + using the US-ASCII character set. + @since 4.05.0 *) type t = string (** An alias for the type of strings. *) @@ -202,6 +269,25 @@ val compare: t -> t -> int allows the module [String] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) +val equal: t -> t -> bool +(** The equal function for strings. + @since 4.05.0 *) + +val split_on_char: sep:char -> string -> string list +(** [String.split_on_char sep s] returns the list of all (possibly empty) + substrings of [s] that are delimited by the [sep] character. + + The function's output is specified by the following invariants: + + - The list is not empty. + - Concatenating its elements using [sep] as a separator returns a + string equal to the input ([String.concat (String.make 1 sep) + (String.split_on_char sep s) = s]). + - No string in the result contains the [sep] character. + + @since 4.05.0 +*) + (**/**) (* The following is for system use only. Do not call directly. *) diff --git a/stdlib/sys.mli b/stdlib/sys.mli index d2061341..2359d41b 100644 --- a/stdlib/sys.mli +++ b/stdlib/sys.mli @@ -52,6 +52,12 @@ external getenv : string -> string = "caml_sys_getenv" (** Return the value associated to a variable in the process environment. Raise [Not_found] if the variable is unbound. *) +val getenv_opt: string -> string option +(** Return the value associated to a variable in the process + environment or [None] if the variable is unbound. + @since 4.05 +*) + external command : string -> int = "caml_sys_system_command" (** Execute the given shell command and return its exit code. *) @@ -99,7 +105,7 @@ type backend_type = val backend_type : backend_type (** Backend type currently executing the OCaml program. - @ since 4.04.0 + @since 4.04.0 *) val unix : bool diff --git a/stdlib/sys.mlp b/stdlib/sys.mlp index 7e79cbd9..62c84fb1 100644 --- a/stdlib/sys.mlp +++ b/stdlib/sys.mlp @@ -54,6 +54,12 @@ external is_directory : string -> bool = "caml_sys_is_directory" external remove: string -> unit = "caml_sys_remove" external rename : string -> string -> unit = "caml_sys_rename" external getenv: string -> string = "caml_sys_getenv" + +let getenv_opt s = + (* TODO: expose a non-raising primitive directly. *) + try Some (getenv s) + with Not_found -> None + external command: string -> int = "caml_sys_system_command" external time: unit -> (float [@unboxed]) = "caml_sys_time" "caml_sys_time_unboxed" [@@noalloc] diff --git a/stdlib/uchar.ml b/stdlib/uchar.ml index 69d48ecf..a2b7fe3a 100644 --- a/stdlib/uchar.ml +++ b/stdlib/uchar.ml @@ -13,10 +13,12 @@ (* *) (**************************************************************************) +external format_int : string -> int -> string = "caml_format_int" + let err_no_pred = "U+0000 has no predecessor" let err_no_succ = "U+10FFFF has no successor" -let err_not_sv i = Printf.sprintf "%X is not an Unicode scalar value" i -let err_not_latin1 u = Printf.sprintf "U+%04X is not a latin1 character" u +let err_not_sv i = format_int "%X" i ^ " is not an Unicode scalar value" +let err_not_latin1 u = "U+" ^ format_int "%04X" u ^ " is not a latin1 character" type t = int @@ -51,5 +53,3 @@ let unsafe_to_char = Char.unsafe_chr let equal : int -> int -> bool = ( = ) let compare : int -> int -> int = Pervasives.compare let hash = to_int - -let dump ppf u = Format.fprintf ppf "U+%04X" u diff --git a/stdlib/uchar.mli b/stdlib/uchar.mli index 690a291a..5ea47c9d 100644 --- a/stdlib/uchar.mli +++ b/stdlib/uchar.mli @@ -82,9 +82,3 @@ val compare : t -> t -> int val hash : t -> int (** [hash u] associates a non-negative integer to [u]. *) - -val dump : Format.formatter -> t -> unit -(** [dump ppf u] prints a representation of [u] on [ppf] using - only US-ASCII encoded characters according to the Unicode - {{:http://www.unicode.org/versions/latest/appA.pdf}notational - convention for code points}. *) diff --git a/stdlib/weak.ml b/stdlib/weak.ml index 631c73e0..4ade095a 100644 --- a/stdlib/weak.ml +++ b/stdlib/weak.ml @@ -52,6 +52,7 @@ module type S = sig val add : t -> data -> unit val remove : t -> data -> unit val find : t -> data -> data + val find_opt : t -> data -> data option val find_all : t -> data -> data list val mem : t -> data -> bool val iter : (data -> unit) -> t -> unit @@ -259,6 +260,26 @@ module Make (H : Hashtbl.HashedType) : (S with type data = H.t) = struct let find t d = find_or t d (fun _h _index -> raise Not_found) + let find_opt t d = + let h = H.hash d in + let index = get_index t h in + let bucket = t.table.(index) in + let hashes = t.hashes.(index) in + let sz = length bucket in + let rec loop i = + if i >= sz then None + else if h = hashes.(i) then begin + match get_copy bucket i with + | Some v when H.equal v d + -> begin match get bucket i with + | Some _ as v -> v + | None -> loop (i + 1) + end + | _ -> loop (i + 1) + end else loop (i + 1) + in + loop 0 + let find_shadow t d iffound ifnotfound = let h = H.hash d in diff --git a/stdlib/weak.mli b/stdlib/weak.mli index 95249444..951cd9c0 100644 --- a/stdlib/weak.mli +++ b/stdlib/weak.mli @@ -66,7 +66,11 @@ val get_copy : 'a t -> int -> 'a option the incremental GC from erasing the value in its current cycle ([get] may delay the erasure to the next GC cycle). Raise [Invalid_argument "Weak.get"] if [n] is not in the range - 0 to {!Weak.length}[ a - 1].*) + 0 to {!Weak.length}[ a - 1]. + + If the element is a custom block it is not copied. + +*) val check : 'a t -> int -> bool @@ -137,6 +141,12 @@ module type S = sig (** [find t x] returns an instance of [x] found in [t]. Raise [Not_found] if there is no such element. *) + val find_opt: t -> data -> data option + (** [find_opt t x] returns an instance of [x] found in [t] + or [None] if there is no such element. + @since 4.05 + *) + val find_all : t -> data -> data list (** [find_all t x] returns a list of all the instances of [x] found in [t]. *) diff --git a/testsuite/HACKING.adoc b/testsuite/HACKING.adoc new file mode 100644 index 00000000..71259057 --- /dev/null +++ b/testsuite/HACKING.adoc @@ -0,0 +1,11 @@ +== Running the testsuite + +== Creating a new test + +== Useful Makefile targets + +`make parallel`:: runs the tests in parallel using the link:https://www.gnu.org/software/parallel/[GNU parallel] tool: tests run twice as fast with no difference in output order. + +`make all-foo`, `make parallel-foo`:: runs only the tests in the directories whose name starts with `foo`: `parallel-typing`, `all-lib`, etc. + +`make one DIR=tests/foo`:: runs only the tests in the directory `tests/foo`. This is often equivalent to `cd tests/foo && make`, but sometimes the latter breaks the test makefile if it contains fragile relative filesystem paths. Such errors should be fixed if you find them, but `make one DIR=...` is the more reliable option as it runs exactly as `make all` which is heavily tested. \ No newline at end of file diff --git a/testsuite/makefiles/Makefile.common b/testsuite/makefiles/Makefile.common index 91ab0146..0a85f959 100644 --- a/testsuite/makefiles/Makefile.common +++ b/testsuite/makefiles/Makefile.common @@ -58,9 +58,8 @@ defaultclean: .mll.ml: @$(OCAMLLEX) -q $< > /dev/null -.cmm.o: - @$(OCAMLRUN) ./codegen $*.cmm > $*.s - @$(ASM) -o $*.o $*.s +.cmm.s: + @$(OCAMLRUN) ./codegen -S $*.cmm .cmm.obj: @$(OCAMLRUN) ./codegen $*.cmm \ @@ -72,6 +71,7 @@ defaultclean: .S.o: @$(ASPP) $(ASPPFLAGS) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) -o $*.o $*.S +.PRECIOUS: %.s .s.o: @$(ASPP) $(ASPPFLAGS) -DSYS_$(SYSTEM) -o $*.o $*.s diff --git a/testsuite/makefiles/Makefile.several b/testsuite/makefiles/Makefile.several index f24aff91..e29378c7 100644 --- a/testsuite/makefiles/Makefile.several +++ b/testsuite/makefiles/Makefile.several @@ -23,12 +23,12 @@ O_FILES=$(F_FILES:=.o) $(C_FILES:=.o) CUSTOM_FLAG=`if [ -n "$(C_FILES)" ]; then echo '-custom'; fi` ADD_CFLAGS+=$(CUSTOM_FLAG) -MYRUNTIME=`if [ -z "$(C_FILES)$(CUSTOM)" ]; then echo '$(OCAMLRUN)'; fi` +MYRUNTIME=`if [ -z "$(C_FILES)$(CUSTOM)" ]; then echo '$(OCAMLRUN)'; echo '$(ADD_BYTERUN_FLAGS)'; fi` FORTRAN_LIB=`if [ -n "$(F_FILES)" ]; then echo $(FORTRAN_LIBRARY); fi` ADD_CFLAGS+=$(FORTRAN_LIB) ADD_OPTFLAGS+=$(FORTRAN_LIB) -C_INCLUDES+=-I $(CTOPDIR)/byterun -I$(CTOPDIR)/otherlibs/bigarray +C_INCLUDES+=-I $(CTOPDIR)/byterun -I $(CTOPDIR)/otherlibs/bigarray GENERATED_SOURCES= @@ -119,7 +119,7 @@ run-file: if [ -f $$F.runner ]; then \ RUNTIME="$(RUNTIME)" sh $$F.runner; \ else \ - $(RUNTIME) ./program$(EXE) $(PROGRAM_ARGS) >$$F.result; \ + $(SET_LD_PATH) $(RUNTIME) ./program$(EXE) $(PROGRAM_ARGS) >$$F.result; \ fi \ && \ if [ -f $$F.checker ]; then \ diff --git a/testsuite/tests/asmcomp/Makefile b/testsuite/tests/asmcomp/Makefile index abcb8729..5ef5a2e3 100644 --- a/testsuite/tests/asmcomp/Makefile +++ b/testsuite/tests/asmcomp/Makefile @@ -16,6 +16,7 @@ BASEDIR=../.. INCLUDES=\ + -I $(OTOPDIR)/parsing \ -I $(OTOPDIR)/utils \ -I $(OTOPDIR)/typing \ -I $(OTOPDIR)/middle_end \ @@ -39,6 +40,8 @@ all: @$(MAKE) arch codegen @$(MAKE) tests +main.cmo: parsecmm.cmo + codegen: parsecmm.ml lexcmm.ml $(OBJS:.cmo=.cmi) $(OBJS) main.cmo @$(OCAMLC) $(LINKFLAGS) -o codegen $(OTHEROBJS) $(OBJS) main.cmo @@ -50,6 +53,7 @@ lexcmm.ml: lexcmm.mll MLCASES=optargs staticalloc bind_tuples is_static register_typing \ register_typing_switch +ARGS_optargs=-g ARGS_is_static=-I $(OTOPDIR)/byterun is_in_static_data.c MLCASES_FLAMBDA=is_static_flambda unrolling_flambda unrolling_flambda2 \ static_float_array_flambda static_float_array_flambda_opaque @@ -61,7 +65,8 @@ ARGS_static_float_array_flambda_opaque=\ -I $(OTOPDIR)/byterun is_in_static_data.c -opaque simple_float_const_opaque.ml CASES=fib tak quicksort quicksort2 soli \ - arith checkbound tagged-fib tagged-integr tagged-quicksort tagged-tak + arith checkbound tagged-fib tagged-integr tagged-quicksort tagged-tak \ + catch-try catch-rec even-odd even-odd-spill pgcd ARGS_fib=-DINT_INT -DFUN=fib main.c ARGS_tak=-DUNIT_INT -DFUN=takmain main.c ARGS_quicksort=-DSORT -DFUN=quicksort main.c @@ -75,6 +80,11 @@ ARGS_tagged-integr=-DINT_FLOAT -DFUN=test main.c ARGS_tagged-quicksort=-DSORT -DFUN=quicksort main.c ARGS_tagged-tak=-DUNIT_INT -DFUN=takmain main.c ARGS_staticalloc=-I $(OTOPDIR)/utils config.cmx +ARGS_catch-try=-DINT_INT -DFUN=catch_exit main.c +ARGS_catch-rec=-DINT_INT -DFUN=catch_fact main.c +ARGS_even-odd=-DINT_INT -DFUN=is_even main.c +ARGS_even-odd-spill=-DINT_INT -DFUN=is_even main.c +ARGS_pgcd=-DINT_INT -DFUN=pgcd_30030 main.c skips: @for c in $(CASES) $(MLCASES) $(MLCASES_FLAMBDA); do \ diff --git a/testsuite/tests/asmcomp/catch-rec.cmm b/testsuite/tests/asmcomp/catch-rec.cmm new file mode 100644 index 00000000..69208f5f --- /dev/null +++ b/testsuite/tests/asmcomp/catch-rec.cmm @@ -0,0 +1,5 @@ +(function "catch_fact" (b:int) + (catch (exit fact b 1) + with (fact c acc) + (if (== c 0) acc + (exit fact (- c 1) ( * c acc))))) diff --git a/testsuite/tests/asmcomp/catch-try.cmm b/testsuite/tests/asmcomp/catch-try.cmm new file mode 100644 index 00000000..bbbdc387 --- /dev/null +++ b/testsuite/tests/asmcomp/catch-try.cmm @@ -0,0 +1,7 @@ + +(function "catch_exit" (b:int) + (+ 33 + (catch + (try (exit lbl 12) + with var 456) + with (lbl x) (+ x 789)))) diff --git a/testsuite/tests/asmcomp/even-odd-spill.cmm b/testsuite/tests/asmcomp/even-odd-spill.cmm new file mode 100644 index 00000000..0c5f0558 --- /dev/null +++ b/testsuite/tests/asmcomp/even-odd-spill.cmm @@ -0,0 +1,19 @@ +("format_odd": string "odd %d\n\000") +("format_even": string "even %d\n\000") + +(function "force_spill" (a:int) 0) + +(function "is_even" (b:int) + (catch (exit even b) + with (odd v) + (if (== v 0) 0 + (seq + (extcall "printf_int" "format_odd" v unit) + (let v2 (- v 1) + (app "force_spill" 0 int) + (exit even v2)))) + and (even v) + (if (== v 0) 1 + (seq + (extcall "printf_int" "format_even" v unit) + (exit odd (- v 1)))))) diff --git a/testsuite/tests/asmcomp/even-odd.cmm b/testsuite/tests/asmcomp/even-odd.cmm new file mode 100644 index 00000000..db79f1ca --- /dev/null +++ b/testsuite/tests/asmcomp/even-odd.cmm @@ -0,0 +1,8 @@ +(function "is_even" (b:int) + (catch (exit even b) + with (odd v) + (if (== v 0) 0 + (exit even (- v 1))) + and (even v) + (if (== v 0) 1 + (exit odd (- v 1))))) \ No newline at end of file diff --git a/testsuite/tests/asmcomp/lexcmm.mll b/testsuite/tests/asmcomp/lexcmm.mll index d3c0d394..a946f6aa 100644 --- a/testsuite/tests/asmcomp/lexcmm.mll +++ b/testsuite/tests/asmcomp/lexcmm.mll @@ -27,6 +27,7 @@ let keyword_table = "case", CASE; "catch", CATCH; "checkbound", CHECKBOUND; + "data", DATA; "exit", EXIT; "extcall", EXTCALL; "float", FLOAT; @@ -34,6 +35,7 @@ let keyword_table = "float64", FLOAT64; "floatofint", FLOATOFINT; "function", FUNCTION; + "global", GLOBAL; "half", HALF; "if", IF; "int", INT; @@ -121,8 +123,12 @@ let report_error lexbuf msg = } +let newline = ('\013'* '\010') + rule token = parse - [' ' '\010' '\013' '\009' '\012'] + + newline + { Lexing.new_line lexbuf; token lexbuf } + | [' ' '\009' '\012'] + { token lexbuf } | "+a" { ADDA } | "+v" { ADDV } @@ -153,13 +159,12 @@ rule token = parse | " + (file, line, start, end_)) + in + let loc_start = + Lexing.{ pos_fname; pos_lnum; pos_bol = 0; pos_cnum = start } + in + let loc_end = + Lexing.{ pos_fname; pos_lnum; pos_bol = 0; pos_cnum = end_ } + in + let location = Location.{ loc_start; loc_end; loc_ghost = false } in + LOCATION location } | _ { raise(Error(Illegal_character)) } and comment = parse @@ -196,6 +217,8 @@ and comment = parse if !comment_depth > 0 then comment lexbuf } | eof { raise (Error(Unterminated_comment)) } + | newline + { Lexing.new_line lexbuf; comment lexbuf } | _ { comment lexbuf } @@ -215,3 +238,4 @@ and string = parse | _ { store_string_char(Lexing.lexeme_char lexbuf 0); string lexbuf } + diff --git a/testsuite/tests/asmcomp/main.ml b/testsuite/tests/asmcomp/main.ml index c094bd09..284f7fbc 100644 --- a/testsuite/tests/asmcomp/main.ml +++ b/testsuite/tests/asmcomp/main.ml @@ -1,11 +1,17 @@ open Clflags +let write_asm_file = ref false let compile_file filename = + if !write_asm_file then begin + let out_name = Filename.chop_extension filename ^ ".s" in + Emitaux.output_channel := open_out out_name + end; (* otherwise, stdout *) Clflags.dlcode := false; Compilenv.reset ~source_provenance:(Timings.File filename) "test"; Emit.begin_assembly(); let ic = open_in filename in let lb = Lexing.from_channel ic in + lb.Lexing.lex_curr_p <- { lb.Lexing.lex_curr_p with pos_fname = filename }; try while true do Asmgen.compile_phrase Format.std_formatter @@ -13,14 +19,20 @@ let compile_file filename = done with End_of_file -> - close_in ic; Emit.end_assembly() + close_in ic; Emit.end_assembly(); + if !write_asm_file then close_out !Emitaux.output_channel | Lexcmm.Error msg -> close_in ic; Lexcmm.report_error lb msg | Parsing.Parse_error -> close_in ic; - prerr_string "Syntax error near character "; - prerr_int (Lexing.lexeme_start lb); - prerr_newline() + let start_p = Lexing.lexeme_start_p lb in + let end_p = Lexing.lexeme_end_p lb in + Printf.eprintf "File \"%s\", line %i, characters %i-%i:\n\ + Syntax error.\n%!" + filename + start_p.Lexing.pos_lnum + (start_p.Lexing.pos_cnum - start_p.Lexing.pos_bol) + (end_p.Lexing.pos_cnum - start_p.Lexing.pos_bol) | Parsecmmaux.Error msg -> close_in ic; Parsecmmaux.report_error msg | x -> @@ -30,7 +42,11 @@ let usage = "Usage: codegen \noptions are:" let main() = Arg.parse [ + "-S", Arg.Set write_asm_file, + " Output file to filename.s (default is stdout)"; + "-g", Arg.Set Clflags.debug, ""; "-dcmm", Arg.Set dump_cmm, ""; + "-dcse", Arg.Set dump_cse, ""; "-dsel", Arg.Set dump_selection, ""; "-dlive", Arg.Unit(fun () -> dump_live := true; Printmach.print_live := true), ""; @@ -41,7 +57,10 @@ let main() = "-dalloc", Arg.Set dump_regalloc, ""; "-dreload", Arg.Set dump_reload, ""; "-dscheduling", Arg.Set dump_scheduling, ""; - "-dlinear", Arg.Set dump_linear, "" + "-dlinear", Arg.Set dump_linear, ""; + "-dtimings", Arg.Set print_timings, ""; ] compile_file usage -let _ = (*Printexc.catch*) main (); exit 0 +let _ = (*Printexc.catch*) Timings.(time All) main (); + if !Clflags.print_timings then Timings.print Format.std_formatter; + exit 0 diff --git a/testsuite/tests/asmcomp/parsecmm.mly b/testsuite/tests/asmcomp/parsecmm.mly index a1eea39f..52a6dfad 100644 --- a/testsuite/tests/asmcomp/parsecmm.mly +++ b/testsuite/tests/asmcomp/parsecmm.mly @@ -20,14 +20,16 @@ let make_switch n selector caselist = List.iter (fun pos -> index.(pos) <- i) posl; actv.(i) <- e done; - Cswitch(selector, index, actv) + Cswitch(selector, index, actv, Debuginfo.none) let access_array base numelt size = match numelt with Cconst_int 0 -> base - | Cconst_int n -> Cop(Cadda, [base; Cconst_int(n * size)]) + | Cconst_int n -> Cop(Cadda, [base; Cconst_int(n * size)], Debuginfo.none) | _ -> Cop(Cadda, [base; - Cop(Clsl, [numelt; Cconst_int(Misc.log2 size)])]) + Cop(Clsl, [numelt; Cconst_int(Misc.log2 size)], + Debuginfo.none)], + Debuginfo.none) %} @@ -48,6 +50,7 @@ let access_array base numelt size = %token CATCH %token CHECKBOUND %token COLON +%token DATA %token DIVF %token DIVI %token EOF @@ -65,6 +68,7 @@ let access_array base numelt size = %token GEA %token GEF %token GEI +%token GLOBAL %token GTA %token GTF %token GTI @@ -82,6 +86,7 @@ let access_array base numelt size = %token LEI %token LET %token LOAD +%token LOCATION %token LPAREN %token LSL %token LSR @@ -135,11 +140,14 @@ phrase: | EOF { raise End_of_file } ; fundecl: - LPAREN FUNCTION STRING LPAREN params RPAREN sequence RPAREN + LPAREN FUNCTION fun_name LPAREN params RPAREN sequence RPAREN { List.iter (fun (id, ty) -> unbind_ident id) $5; {fun_name = $3; fun_args = $5; fun_body = $7; fun_fast = true; - fun_dbg = Debuginfo.none} } + fun_dbg = debuginfo ()} } ; +fun_name: + STRING { $1 } + | IDENT { $1 } params: oneparam params { $1 :: $2 } | /**/ { [] } @@ -170,14 +178,15 @@ expr: | LBRACKET RBRACKET { Ctuple [] } | LPAREN LET letdef sequence RPAREN { make_letdef $3 $4 } | LPAREN ASSIGN IDENT expr RPAREN { Cassign(find_ident $3, $4) } - | LPAREN APPLY expr exprlist machtype RPAREN - { Cop(Capply($5, Debuginfo.none), $3 :: List.rev $4) } + | LPAREN APPLY location expr exprlist machtype RPAREN + { Cop(Capply $6, $4 :: List.rev $5, debuginfo ?loc:$3 ()) } | LPAREN EXTCALL STRING exprlist machtype RPAREN - {Cop(Cextcall($3, $5, false, Debuginfo.none, None), List.rev $4)} - | LPAREN SUBF expr RPAREN { Cop(Cnegf, [$3]) } - | LPAREN SUBF expr expr RPAREN { Cop(Csubf, [$3; $4]) } - | LPAREN unaryop expr RPAREN { Cop($2, [$3]) } - | LPAREN binaryop expr expr RPAREN { Cop($2, [$3; $4]) } + {Cop(Cextcall($3, $5, false, None), List.rev $4, debuginfo ())} + | LPAREN ALLOC exprlist RPAREN { Cop(Calloc, List.rev $3, debuginfo ()) } + | LPAREN SUBF expr RPAREN { Cop(Cnegf, [$3], debuginfo ()) } + | LPAREN SUBF expr expr RPAREN { Cop(Csubf, [$3; $4], debuginfo ()) } + | LPAREN unaryop expr RPAREN { Cop($2, [$3], debuginfo ()) } + | LPAREN binaryop expr expr RPAREN { Cop($2, [$3; $4], debuginfo ()) } | LPAREN SEQ sequence RPAREN { $3 } | LPAREN IF expr expr expr RPAREN { Cifthenelse($3, $4, $5) } | LPAREN SWITCH INTCONST expr caselist RPAREN { make_switch $3 $4 $5 } @@ -186,26 +195,37 @@ expr: match $3 with Cconst_int x when x <> 0 -> $4 | _ -> Cifthenelse($3, $4, (Cexit(0,[]))) in - Ccatch(0, [], Cloop body, Ctuple []) } - | LPAREN CATCH sequence WITH sequence RPAREN { Ccatch(0, [], $3, $5) } + Ccatch(Recursive, [0, [], Cloop body], Ctuple []) } + | LPAREN EXIT IDENT exprlist RPAREN + { Cexit(find_label $3, List.rev $4) } + | LPAREN CATCH sequence WITH catch_handlers RPAREN + { let handlers = $5 in + List.iter (fun (_, l, _) -> List.iter unbind_ident l) handlers; + Ccatch(Recursive, handlers, $3) } | EXIT { Cexit(0,[]) } | LPAREN TRY sequence WITH bind_ident sequence RPAREN { unbind_ident $5; Ctrywith($3, $5, $6) } + | LPAREN VAL expr expr RPAREN + { Cop(Cload (Word_val, Mutable), [access_array $3 $4 Arch.size_addr], + debuginfo ()) } | LPAREN ADDRAREF expr expr RPAREN - { Cop(Cload Word_val, [access_array $3 $4 Arch.size_addr]) } + { Cop(Cload (Word_val, Mutable), [access_array $3 $4 Arch.size_addr], + Debuginfo.none) } | LPAREN INTAREF expr expr RPAREN - { Cop(Cload Word_int, [access_array $3 $4 Arch.size_int]) } + { Cop(Cload (Word_int, Mutable), [access_array $3 $4 Arch.size_int], + Debuginfo.none) } | LPAREN FLOATAREF expr expr RPAREN - { Cop(Cload Double_u, [access_array $3 $4 Arch.size_float]) } + { Cop(Cload (Double_u, Mutable), [access_array $3 $4 Arch.size_float], + Debuginfo.none) } | LPAREN ADDRASET expr expr expr RPAREN { Cop(Cstore (Word_val, Assignment), - [access_array $3 $4 Arch.size_addr; $5]) } + [access_array $3 $4 Arch.size_addr; $5], Debuginfo.none) } | LPAREN INTASET expr expr expr RPAREN { Cop(Cstore (Word_int, Assignment), - [access_array $3 $4 Arch.size_int; $5]) } + [access_array $3 $4 Arch.size_int; $5], Debuginfo.none) } | LPAREN FLOATASET expr expr expr RPAREN { Cop(Cstore (Double_u, Assignment), - [access_array $3 $4 Arch.size_float; $5]) } + [access_array $3 $4 Arch.size_float; $5], Debuginfo.none) } ; exprlist: exprlist expr { $2 :: $1 } @@ -234,21 +254,20 @@ chunk: | FLOAT32 { Single } | FLOAT64 { Double } | FLOAT { Double_u } - + | VAL { Word_val } ; unaryop: - LOAD chunk { Cload $2 } - | ALLOC { Calloc Debuginfo.none } + LOAD chunk { Cload ($2, Mutable) } | FLOATOFINT { Cfloatofint } | INTOFFLOAT { Cintoffloat } - | RAISE { Craise ($1, Debuginfo.none) } + | RAISE { Craise $1 } | ABSF { Cabsf } ; binaryop: STORE chunk { Cstore ($2, Assignment) } | ADDI { Caddi } | SUBI { Csubi } - | MULI { Cmuli } + | STAR { Cmuli } | DIVI { Cdivi } | MODI { Cmodi } | AND { Cand } @@ -280,7 +299,7 @@ binaryop: | LEF { Ccmpf Cle } | GTF { Ccmpf Cgt } | GEF { Ccmpf Cge } - | CHECKBOUND { Ccheckbound Debuginfo.none } + | CHECKBOUND { Ccheckbound } | MULH { Cmulhi } ; sequence: @@ -300,6 +319,7 @@ bind_ident: ; datadecl: LPAREN datalist RPAREN { List.rev $2 } + | LPAREN DATA datalist RPAREN { List.rev $3 } ; datalist: datalist dataitem { $2 :: $1 } @@ -316,4 +336,24 @@ dataitem: | KSTRING STRING { Cstring $2 } | SKIP INTCONST { Cskip $2 } | ALIGN INTCONST { Calign $2 } + | GLOBAL STRING { Cglobal_symbol $2 } ; +catch_handlers: + | catch_handler + { [$1] } + | catch_handler AND catch_handlers + { $1 :: $3 } + +catch_handler: + | sequence + { 0, [], $1 } + | LPAREN IDENT bind_identlist RPAREN sequence + { find_label $2, $3, $5 } + +bind_identlist: + /**/ { [] } + | bind_ident bind_identlist { $1 :: $2 } + +location: + /**/ { None } + | LOCATION { Some $1 } diff --git a/testsuite/tests/asmcomp/parsecmmaux.ml b/testsuite/tests/asmcomp/parsecmmaux.ml index d2199cbe..db555273 100644 --- a/testsuite/tests/asmcomp/parsecmmaux.ml +++ b/testsuite/tests/asmcomp/parsecmmaux.ml @@ -6,9 +6,15 @@ type error = exception Error of error let tbl_ident = (Hashtbl.create 57 : (string, Ident.t) Hashtbl.t) +let tbl_label = (Hashtbl.create 57 : (string, int) Hashtbl.t) + +let ident_name s = + match String.index s '/' with + | exception Not_found -> s + | n -> String.sub s 0 n let bind_ident s = - let id = Ident.create s in + let id = Ident.create (ident_name s) in Hashtbl.add tbl_ident s id; id @@ -21,6 +27,17 @@ let find_ident s = let unbind_ident id = Hashtbl.remove tbl_ident (Ident.name id) +let find_label s = + try + Hashtbl.find tbl_label s + with Not_found -> + let lbl = Lambda.next_raise_count () in + Hashtbl.add tbl_label s lbl; + lbl + let report_error = function Unbound s -> prerr_string "Unbound identifier "; prerr_string s; prerr_endline "." + +let debuginfo ?(loc=Location.symbol_rloc ()) () = + Debuginfo.(from_location loc) diff --git a/testsuite/tests/asmcomp/parsecmmaux.mli b/testsuite/tests/asmcomp/parsecmmaux.mli index c7920803..f5478579 100644 --- a/testsuite/tests/asmcomp/parsecmmaux.mli +++ b/testsuite/tests/asmcomp/parsecmmaux.mli @@ -4,6 +4,10 @@ val bind_ident: string -> Ident.t val find_ident: string -> Ident.t val unbind_ident: Ident.t -> unit +val find_label: string -> int + +val debuginfo: ?loc:Location.t -> unit -> Debuginfo.t + type error = Unbound of string diff --git a/testsuite/tests/asmcomp/pgcd.cmm b/testsuite/tests/asmcomp/pgcd.cmm new file mode 100644 index 00000000..e75a149a --- /dev/null +++ b/testsuite/tests/asmcomp/pgcd.cmm @@ -0,0 +1,9 @@ +(function "pgcd_30030" (a:int) + (catch (exit pgcd a 30030) + with (pgcd n m) + (if (> n m) + (exit pgcd m n) + (if (== n 0) + m + (let (r (mod m n)) + (exit pgcd r n)))))) \ No newline at end of file diff --git a/testsuite/tests/backtrace/backtrace2.byte.reference b/testsuite/tests/backtrace/backtrace2.byte.reference index 82833fd9..aef38381 100644 --- a/testsuite/tests/backtrace/backtrace2.byte.reference +++ b/testsuite/tests/backtrace/backtrace2.byte.reference @@ -2,26 +2,57 @@ a No exception b Uncaught exception Backtrace2.Error("b") -Raised at file "backtrace2.ml", line 7, characters 21-32 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 11, characters 4-11 -Re-raised at file "backtrace2.ml", line 13, characters 68-71 -Called from file "backtrace2.ml", line 18, characters 11-23 +Raised at file "backtrace2.ml", line 8, characters 23-34 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 13, characters 4-11 +Re-raised at file "backtrace2.ml", line 15, characters 68-71 +Called from file "backtrace2.ml", line 58, characters 11-23 Uncaught exception Backtrace2.Error("c") -Raised at file "backtrace2.ml", line 14, characters 26-37 -Called from file "backtrace2.ml", line 18, characters 11-23 +Raised at file "backtrace2.ml", line 16, characters 26-37 +Called from file "backtrace2.ml", line 58, characters 11-23 Uncaught exception Backtrace2.Error("d") -Raised at file "backtrace2.ml", line 7, characters 21-32 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 11, characters 4-11 -Called from file "backtrace2.ml", line 18, characters 11-23 +Raised at file "backtrace2.ml", line 8, characters 23-34 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 13, characters 4-11 +Called from file "backtrace2.ml", line 58, characters 11-23 +e +Uncaught exception Backtrace2.Error("e") +Raised at file "backtrace2.ml", line 22, characters 56-59 +Called from file "backtrace2.ml", line 58, characters 11-23 +f +Uncaught exception Backtrace2.Error("f") +Raised at file "backtrace2.ml", line 28, characters 68-71 +Called from file "backtrace2.ml", line 58, characters 11-23 Uncaught exception Invalid_argument("index out of bounds") -Raised by primitive operation at file "backtrace2.ml", line 18, characters 14-22 +Raised by primitive operation at file "backtrace2.ml", line 58, characters 14-22 +test_Not_found +Uncaught exception Not_found +Raised at file "hashtbl.ml", line 194, characters 19-28 +Called from file "backtrace2.ml", line 39, characters 9-42 +Re-raised at file "backtrace2.ml", line 39, characters 67-70 +Called from file "backtrace2.ml", line 58, characters 11-23 +Uncaught exception Not_found +Raised at file "backtrace2.ml", line 43, characters 24-33 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "camlinternalLazy.ml", line 27, characters 17-27 +Re-raised at file "camlinternalLazy.ml", line 34, characters 10-11 +Called from file "backtrace2.ml", line 58, characters 11-23 +Uncaught exception Not_found +Raised at file "hashtbl.ml", line 194, characters 19-28 +Called from file "backtrace2.ml", line 46, characters 8-41 +Re-raised at file "camlinternalLazy.ml", line 33, characters 62-63 +Called from file "camlinternalLazy.ml", line 27, characters 17-27 +Re-raised at file "camlinternalLazy.ml", line 34, characters 10-11 +Called from file "backtrace2.ml", line 58, characters 11-23 diff --git a/testsuite/tests/backtrace/backtrace2.ml b/testsuite/tests/backtrace/backtrace2.ml index fa0f2119..07cf5ccc 100644 --- a/testsuite/tests/backtrace/backtrace2.ml +++ b/testsuite/tests/backtrace/backtrace2.ml @@ -3,17 +3,57 @@ exception Error of string -let rec f msg n = - if n = 0 then raise(Error msg) else 1 + f msg (n-1) - -let g msg = +let test_Error msg = + let rec f msg n = + if n = 0 then raise(Error msg) else 1 + f msg (n-1) in + let exception_raised_internally () = + try Hashtbl.find (Hashtbl.create 3) 0 + with Not_found -> false in try f msg 5 with Error "a" -> print_string "a"; print_newline(); 0 | Error "b" as exn -> print_string "b"; print_newline(); raise exn | Error "c" -> raise (Error "c") + (** [Error "d"] not caught *) + (** Test reraise when an exception is used in the middle of the exception + handler. Currently the wrong backtrace is used. *) + | Error "e" as exn -> + print_string "e"; print_newline (); + ignore (exception_raised_internally ()); raise exn + (** Test reraise of backtrace when a `when` clause use exceptions. + Currently the wrong backtrace is used. + *) + | Error "f" when exception_raised_internally () -> + assert false (** absurd: when false *) + | Error "f" as exn -> print_string "f"; print_newline(); raise exn + +let test_Not_found () = + let rec aux n = + if n = 0 then raise Not_found else 1 + aux (n-1) + in + try aux 5 + (** Test the raise to reraise heuristic with included try_with. + Currently the wrong backtrace is used. *) + with exn -> + print_string "test_Not_found"; print_newline(); + (try Hashtbl.find (Hashtbl.create 3) 0 with Not_found -> raise exn) + +let test_lazy = + let rec aux n = + if n = 0 then raise Not_found else 1 + aux (n-1) + in + let exception_raised_internally () = + try Hashtbl.find (Hashtbl.create 3) 0 + with Not_found -> () in + let l = lazy (aux 5) in + (** Test the backtrace obtained from a lazy value. + Currently the second time the value is forced the + wrong backtrace is used. *) + fun () -> + exception_raised_internally (); + Lazy.force l -let run args = +let run g args = try ignore (g args.(0)); print_string "No exception\n" with exn -> @@ -22,8 +62,14 @@ let run args = let _ = Printexc.record_backtrace true; - run [| "a" |]; - run [| "b" |]; - run [| "c" |]; - run [| "d" |]; - run [| |] + run test_Error [| "a" |]; + run test_Error [| "b" |]; + run test_Error [| "c" |]; + run test_Error [| "d" |]; + run test_Error [| "e" |]; + run test_Error [| "f" |]; + run test_Error [| |]; + run test_Not_found [| () |]; + run test_lazy [| () |]; + run test_lazy [| () |]; + () diff --git a/testsuite/tests/backtrace/backtrace2.native.reference b/testsuite/tests/backtrace/backtrace2.native.reference index 5c75a66b..978bc937 100644 --- a/testsuite/tests/backtrace/backtrace2.native.reference +++ b/testsuite/tests/backtrace/backtrace2.native.reference @@ -2,26 +2,57 @@ a No exception b Uncaught exception Backtrace2.Error("b") -Raised at file "backtrace2.ml", line 7, characters 16-32 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 11, characters 4-11 -Re-raised at file "backtrace2.ml", line 13, characters 62-71 -Called from file "backtrace2.ml", line 18, characters 11-23 +Raised at file "backtrace2.ml", line 8, characters 18-34 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 13, characters 4-11 +Re-raised at file "backtrace2.ml", line 15, characters 62-71 +Called from file "backtrace2.ml", line 58, characters 11-23 Uncaught exception Backtrace2.Error("c") -Raised at file "backtrace2.ml", line 14, characters 20-37 -Called from file "backtrace2.ml", line 18, characters 11-23 +Raised at file "backtrace2.ml", line 16, characters 20-37 +Called from file "backtrace2.ml", line 58, characters 11-23 Uncaught exception Backtrace2.Error("d") -Raised at file "backtrace2.ml", line 7, characters 16-32 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 7, characters 42-53 -Called from file "backtrace2.ml", line 11, characters 4-11 -Called from file "backtrace2.ml", line 18, characters 11-23 +Raised at file "backtrace2.ml", line 8, characters 18-34 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 8, characters 44-55 +Called from file "backtrace2.ml", line 13, characters 4-11 +Called from file "backtrace2.ml", line 58, characters 11-23 +e +Uncaught exception Backtrace2.Error("e") +Raised at file "backtrace2.ml", line 22, characters 50-59 +Called from file "backtrace2.ml", line 58, characters 11-23 +f +Uncaught exception Backtrace2.Error("f") +Raised at file "backtrace2.ml", line 28, characters 62-71 +Called from file "backtrace2.ml", line 58, characters 11-23 Uncaught exception Invalid_argument("index out of bounds") -Raised by primitive operation at file "backtrace2.ml", line 18, characters 14-22 +Raised by primitive operation at file "backtrace2.ml", line 58, characters 14-22 +test_Not_found +Uncaught exception Not_found +Raised at file "hashtbl.ml", line 194, characters 13-28 +Called from file "backtrace2.ml", line 39, characters 9-42 +Re-raised at file "backtrace2.ml", line 39, characters 61-70 +Called from file "backtrace2.ml", line 58, characters 11-23 +Uncaught exception Not_found +Raised at file "backtrace2.ml", line 43, characters 18-33 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "backtrace2.ml", line 43, characters 43-52 +Called from file "camlinternalLazy.ml", line 27, characters 17-27 +Re-raised at file "camlinternalLazy.ml", line 34, characters 4-11 +Called from file "backtrace2.ml", line 58, characters 11-23 +Uncaught exception Not_found +Raised at file "hashtbl.ml", line 194, characters 13-28 +Called from file "backtrace2.ml", line 46, characters 8-41 +Re-raised at file "camlinternalLazy.ml", line 33, characters 56-63 +Called from file "camlinternalLazy.ml", line 27, characters 17-27 +Re-raised at file "camlinternalLazy.ml", line 34, characters 4-11 +Called from file "backtrace2.ml", line 58, characters 11-23 diff --git a/testsuite/tests/backtrace/raw_backtrace.byte.reference b/testsuite/tests/backtrace/raw_backtrace.byte.reference index b9365231..ba437e33 100644 --- a/testsuite/tests/backtrace/raw_backtrace.byte.reference +++ b/testsuite/tests/backtrace/raw_backtrace.byte.reference @@ -8,12 +8,12 @@ Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 -Called from file "raw_backtrace.ml", line 11, characters 4-11 -Re-raised at file "raw_backtrace.ml", line 13, characters 68-71 -Called from file "raw_backtrace.ml", line 18, characters 11-23 +Called from file "raw_backtrace.ml", line 16, characters 4-11 +Re-raised at file "raw_backtrace.ml", line 18, characters 68-71 +Called from file "raw_backtrace.ml", line 33, characters 11-23 Uncaught exception Raw_backtrace.Error("c") -Raised at file "raw_backtrace.ml", line 14, characters 26-37 -Called from file "raw_backtrace.ml", line 18, characters 11-23 +Raised at file "raw_backtrace.ml", line 19, characters 26-37 +Called from file "raw_backtrace.ml", line 33, characters 11-23 Uncaught exception Raw_backtrace.Error("d") Raised at file "raw_backtrace.ml", line 7, characters 21-32 Called from file "raw_backtrace.ml", line 7, characters 42-53 @@ -21,7 +21,29 @@ Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 -Called from file "raw_backtrace.ml", line 11, characters 4-11 -Called from file "raw_backtrace.ml", line 18, characters 11-23 +Called from file "raw_backtrace.ml", line 16, characters 4-11 +Called from file "raw_backtrace.ml", line 33, characters 11-23 +e +Uncaught exception Raw_backtrace.Error("e") +Raised at file "raw_backtrace.ml", line 7, characters 21-32 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 16, characters 4-11 +Re-raised at file "raw_backtrace.ml", line 25, characters 39-42 +Called from file "raw_backtrace.ml", line 33, characters 11-23 +f +Uncaught exception Raw_backtrace.Localized(_) +Raised at file "raw_backtrace.ml", line 7, characters 21-32 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 16, characters 4-11 +Re-raised at file "raw_backtrace.ml", line 29, characters 39-54 +Called from file "raw_backtrace.ml", line 33, characters 11-23 Uncaught exception Invalid_argument("index out of bounds") -Raised by primitive operation at file "raw_backtrace.ml", line 18, characters 14-22 +Raised by primitive operation at file "raw_backtrace.ml", line 33, characters 14-22 diff --git a/testsuite/tests/backtrace/raw_backtrace.ml b/testsuite/tests/backtrace/raw_backtrace.ml index 594a7c56..45822751 100644 --- a/testsuite/tests/backtrace/raw_backtrace.ml +++ b/testsuite/tests/backtrace/raw_backtrace.ml @@ -6,12 +6,27 @@ exception Error of string let rec f msg n = if n = 0 then raise(Error msg) else 1 + f msg (n-1) +exception Localized of exn + let g msg = + let exception_raised_internally () = + try Hashtbl.find (Hashtbl.create 3) 0 + with Not_found -> false in try f msg 5 with Error "a" -> print_string "a"; print_newline(); 0 | Error "b" as exn -> print_string "b"; print_newline(); raise exn | Error "c" -> raise (Error "c") + (** [Error "d"] not caught *) + | Error "e" as exn -> + let bt = Printexc.get_raw_backtrace () in + print_string "e"; print_newline (); + ignore (exception_raised_internally ()); + Printexc.raise_with_backtrace exn bt + | Error "f" as exn -> + let bt = Printexc.get_raw_backtrace () in + print_string "f"; print_newline (); + Printexc.raise_with_backtrace (Localized exn) bt let backtrace args = try @@ -30,7 +45,8 @@ let run args = try ignore (f "c" 5); assert false with Error _ -> (); end; Printf.printf "Uncaught exception %s\n" exn; - Printexc.print_raw_backtrace stdout trace + Printexc.print_raw_backtrace stdout trace; + flush stdout let _ = Printexc.record_backtrace true; @@ -38,4 +54,6 @@ let _ = run [| "b" |]; run [| "c" |]; run [| "d" |]; + run [| "e" |]; + run [| "f" |]; run [| |] diff --git a/testsuite/tests/backtrace/raw_backtrace.native.reference b/testsuite/tests/backtrace/raw_backtrace.native.reference index b1ff607c..06f4f164 100644 --- a/testsuite/tests/backtrace/raw_backtrace.native.reference +++ b/testsuite/tests/backtrace/raw_backtrace.native.reference @@ -8,12 +8,12 @@ Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 -Called from file "raw_backtrace.ml", line 11, characters 4-11 -Re-raised at file "raw_backtrace.ml", line 13, characters 62-71 -Called from file "raw_backtrace.ml", line 18, characters 11-23 +Called from file "raw_backtrace.ml", line 16, characters 4-11 +Re-raised at file "raw_backtrace.ml", line 18, characters 62-71 +Called from file "raw_backtrace.ml", line 33, characters 11-23 Uncaught exception Raw_backtrace.Error("c") -Raised at file "raw_backtrace.ml", line 14, characters 20-37 -Called from file "raw_backtrace.ml", line 18, characters 11-23 +Raised at file "raw_backtrace.ml", line 19, characters 20-37 +Called from file "raw_backtrace.ml", line 33, characters 11-23 Uncaught exception Raw_backtrace.Error("d") Raised at file "raw_backtrace.ml", line 7, characters 16-32 Called from file "raw_backtrace.ml", line 7, characters 42-53 @@ -21,7 +21,29 @@ Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 Called from file "raw_backtrace.ml", line 7, characters 42-53 -Called from file "raw_backtrace.ml", line 11, characters 4-11 -Called from file "raw_backtrace.ml", line 18, characters 11-23 +Called from file "raw_backtrace.ml", line 16, characters 4-11 +Called from file "raw_backtrace.ml", line 33, characters 11-23 +e +Uncaught exception Raw_backtrace.Error("e") +Raised at file "raw_backtrace.ml", line 7, characters 16-32 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 16, characters 4-11 +Re-raised at file "raw_backtrace.ml", line 25, characters 9-45 +Called from file "raw_backtrace.ml", line 33, characters 11-23 +f +Uncaught exception Raw_backtrace.Localized(_) +Raised at file "raw_backtrace.ml", line 7, characters 16-32 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 7, characters 42-53 +Called from file "raw_backtrace.ml", line 16, characters 4-11 +Re-raised at file "raw_backtrace.ml", line 29, characters 9-57 +Called from file "raw_backtrace.ml", line 33, characters 11-23 Uncaught exception Invalid_argument("index out of bounds") -Raised by primitive operation at file "raw_backtrace.ml", line 18, characters 14-22 +Raised by primitive operation at file "raw_backtrace.ml", line 33, characters 14-22 diff --git a/testsuite/tests/basic-float/zero_sized_float_arrays.ml b/testsuite/tests/basic-float/zero_sized_float_arrays.ml new file mode 100644 index 00000000..cc959b47 --- /dev/null +++ b/testsuite/tests/basic-float/zero_sized_float_arrays.ml @@ -0,0 +1,15 @@ +let non_float_array : int array = [| |] + +let float_array : float array = [| |] + +let non_float_array_from_runtime : int array = + Array.make 0 0 + +let float_array_from_runtime : float array = + Array.make 0 0.0 + +let () = + assert (Pervasives.compare non_float_array non_float_array_from_runtime = 0); + assert (Pervasives.compare non_float_array non_float_array_from_runtime = 0); + assert (Pervasives.compare float_array float_array_from_runtime = 0); + assert (Pervasives.compare float_array float_array_from_runtime = 0) diff --git a/testsuite/tests/basic-float/zero_sized_float_arrays.reference b/testsuite/tests/basic-float/zero_sized_float_arrays.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/basic-modules/Makefile b/testsuite/tests/basic-modules/Makefile index d2c0c963..1feb55aa 100644 --- a/testsuite/tests/basic-modules/Makefile +++ b/testsuite/tests/basic-modules/Makefile @@ -15,7 +15,7 @@ BASEDIR=../.. -MODULES=offset pr6726 +MODULES=offset pr6726 pr7427 MAIN_MODULE=main include $(BASEDIR)/makefiles/Makefile.one diff --git a/testsuite/tests/basic-modules/main.ml b/testsuite/tests/basic-modules/main.ml index 7f3f44d7..b9a7df8d 100644 --- a/testsuite/tests/basic-modules/main.ml +++ b/testsuite/tests/basic-modules/main.ml @@ -12,3 +12,11 @@ module M = F (Offset) let () = M.test (Offset.M.Set.singleton "42") let v = Pr6726.Test.v + +(* PR#7427 *) + +let () = + try + let module M = Pr7427.F () in + failwith "Test failed" + with Assert_failure _ -> () diff --git a/testsuite/tests/basic-modules/pr7427.ml b/testsuite/tests/basic-modules/pr7427.ml new file mode 100644 index 00000000..bb00ce93 --- /dev/null +++ b/testsuite/tests/basic-modules/pr7427.ml @@ -0,0 +1,7 @@ +module F() = struct + module M = struct + let aaa = assert false + let bbb () = assert false + end + let ccc () = M.bbb () +end diff --git a/testsuite/tests/basic/divint.ml b/testsuite/tests/basic/divint.ml index 77c165ba..c007edae 100644 --- a/testsuite/tests/basic/divint.ml +++ b/testsuite/tests/basic/divint.ml @@ -138,3 +138,8 @@ let _ = (* PR#6879 *) let f n = assert (1 mod n = 0) let () = f 1 + + +type t = {x: int; y:int} +let f x = {x; y = x/0}.x +let () = try ignore (f 1); assert false with Division_by_zero -> () diff --git a/testsuite/tests/basic/eval_order_1.ml b/testsuite/tests/basic/eval_order_1.ml new file mode 100644 index 00000000..7c20be3f --- /dev/null +++ b/testsuite/tests/basic/eval_order_1.ml @@ -0,0 +1,4 @@ +let f x y = Printf.printf "%d %d\n" x y + +let i = ref 0 +let () = f (incr i; !i) !i diff --git a/testsuite/tests/basic/eval_order_1.reference b/testsuite/tests/basic/eval_order_1.reference new file mode 100644 index 00000000..80c0cc79 --- /dev/null +++ b/testsuite/tests/basic/eval_order_1.reference @@ -0,0 +1 @@ +1 0 diff --git a/testsuite/tests/basic/eval_order_2.ml b/testsuite/tests/basic/eval_order_2.ml new file mode 100644 index 00000000..378398b3 --- /dev/null +++ b/testsuite/tests/basic/eval_order_2.ml @@ -0,0 +1,24 @@ +(* PR#6136 *) + +exception Ok + +let first () = + let f g x = ignore (failwith "called f"); g in + let g x = x in + f g 2 (raise Ok) + +let second () = + let f g x = ignore (failwith "called f"); g in + let g x = x in + let h f = f g 2 (raise Ok) in + ignore (h f) + +let () = + try + ignore (first ()); + assert false + with Ok -> + try + ignore (second ()); + assert false + with Ok -> () diff --git a/testsuite/tests/basic/eval_order_2.reference b/testsuite/tests/basic/eval_order_2.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/basic/eval_order_3.ml b/testsuite/tests/basic/eval_order_3.ml new file mode 100644 index 00000000..07c5367e --- /dev/null +++ b/testsuite/tests/basic/eval_order_3.ml @@ -0,0 +1,22 @@ +let i = ref 0 + +let f x y = + Printf.printf "%d %d\n" x y; + 0 +[@@inline never] + +let foo _ = () + +let foobar baz = + let incr_i _ = + incr i; + !i + in + let b = !i in + let z = foo 42 in + let a = (incr_i [@inlined never]) z in + let x = f a b in + x + 1 + +let () = + ignore ((foobar 0) : int) diff --git a/testsuite/tests/basic/eval_order_3.reference b/testsuite/tests/basic/eval_order_3.reference new file mode 100644 index 00000000..80c0cc79 --- /dev/null +++ b/testsuite/tests/basic/eval_order_3.reference @@ -0,0 +1 @@ +1 0 diff --git a/testsuite/tests/basic/eval_order_4.ml b/testsuite/tests/basic/eval_order_4.ml new file mode 100644 index 00000000..8e29f455 --- /dev/null +++ b/testsuite/tests/basic/eval_order_4.ml @@ -0,0 +1,17 @@ +(* PR#7531 *) + +let f = + (let _i = print_endline "first" + in fun q -> fun i -> "") (print_endline "x") + +let _ = + let k = + (let _i = print_int 1 + in fun q -> fun i -> "") () + in k (print_int 0) + +let () = + print_endline "foo"; + ignore ((f ()) : string); + ignore ((f ()) : string); + print_endline "bar" diff --git a/testsuite/tests/basic/eval_order_4.reference b/testsuite/tests/basic/eval_order_4.reference new file mode 100644 index 00000000..426ddfda --- /dev/null +++ b/testsuite/tests/basic/eval_order_4.reference @@ -0,0 +1,4 @@ +x +first +10foo +bar diff --git a/testsuite/tests/basic/includestruct.ml b/testsuite/tests/basic/includestruct.ml index 15708bf9..a9c4e91b 100644 --- a/testsuite/tests/basic/includestruct.ml +++ b/testsuite/tests/basic/includestruct.ml @@ -89,3 +89,19 @@ module G = let _ = begin try raise (G.Exn "foo") with G.Exn s -> print_string s end; print_int ((new G.c)#m); print_newline() + + + +include (struct + let a = 10 + module X = struct let x = 1 let z = 42 let y = 2 end + exception XXX +end : sig + module X : sig val y: int val x: int end + exception XXX + val a: int +end) + +let () = + Printf.printf "%i / %i / %i \n%!" X.x X.y a; + Printf.printf "%s\n%!" (Printexc.to_string XXX) diff --git a/testsuite/tests/basic/includestruct.reference b/testsuite/tests/basic/includestruct.reference index a7756837..70af2e3d 100644 --- a/testsuite/tests/basic/includestruct.reference +++ b/testsuite/tests/basic/includestruct.reference @@ -13,3 +13,5 @@ A 42 foo1 foo1 +1 / 2 / 10 +XXX diff --git a/testsuite/tests/basic/opt_variants.ml b/testsuite/tests/basic/opt_variants.ml new file mode 100755 index 00000000..16966be2 --- /dev/null +++ b/testsuite/tests/basic/opt_variants.ml @@ -0,0 +1,114 @@ +let () = + assert(Sys.getenv_opt "FOOBAR_UNLIKELY_TO_EXIST_42" = None); + + assert(int_of_string_opt "foo" = None); + assert(int_of_string_opt "42" = Some 42); + assert(int_of_string_opt (String.make 100 '9') = None); + + assert(Nativeint.of_string_opt "foo" = None); + assert(Nativeint.of_string_opt "42" = Some 42n); + assert(Nativeint.of_string_opt (String.make 100 '9') = None); + + assert(Int32.of_string_opt "foo" = None); + assert(Int32.of_string_opt "42" = Some 42l); + assert(Int32.of_string_opt (String.make 100 '9') = None); + + assert(Int64.of_string_opt "foo" = None); + assert(Int64.of_string_opt "42" = Some 42L); + assert(Int64.of_string_opt (String.make 100 '9') = None); + + assert(bool_of_string_opt "" = None); + assert(bool_of_string_opt "true" = Some true); + assert(bool_of_string_opt "false" = Some false); + + assert(float_of_string_opt "foo" = None); + assert(float_of_string_opt "42." = Some 42.); + assert(float_of_string_opt (String.make 1000 '9') = Some infinity); + + assert(List.nth_opt [] 0 = None); + assert(List.nth_opt [42] 0 = Some 42); + assert(List.nth_opt [42] 1 = None); + + assert(List.find_opt (fun _ -> true) [] = None); + assert(List.find_opt (fun x -> x > 10) [4; 42] = Some 42); + + assert(List.assoc_opt 42 [] = None); + assert(List.assoc_opt 42 [41, false; 42, true] = Some true); + + assert(List.assq_opt 42 [] = None); + assert(List.assq_opt 42 [41, false; 42, true] = Some true); + + let h = Hashtbl.create 5 in + assert(Hashtbl.find_opt h 42 = None); + Hashtbl.add h 42 (); + assert(Hashtbl.find_opt h 42 = Some ()); + + + let module IntSet = Set.Make(struct + type t = int + let compare = compare + end) + in + let set = IntSet.of_list [42; 43] in + assert(IntSet.min_elt_opt IntSet.empty = None); + assert(IntSet.min_elt_opt set = Some 42); + + assert(IntSet.max_elt_opt IntSet.empty = None); + assert(IntSet.max_elt_opt set = Some 43); + + assert(IntSet.choose_opt IntSet.empty = None); + assert(IntSet.choose_opt set <> None); + + assert(IntSet.find_opt 42 IntSet.empty = None); + assert(IntSet.find_opt 42 set = Some 42); + assert(IntSet.find_opt 0 set = None); + + + let module IntMap = Map.Make(struct + type t = int + let compare = compare + end) + in + let map = IntMap.add 42 "42" (IntMap.add 43 "43" IntMap.empty) in + assert(IntMap.min_binding_opt IntMap.empty = None); + assert(IntMap.min_binding_opt map = Some (42, "42")); + + assert(IntMap.max_binding_opt IntMap.empty = None); + assert(IntMap.max_binding_opt map = Some (43, "43")); + + assert(IntMap.choose_opt IntMap.empty = None); + assert(IntMap.choose_opt map <> None); + + assert(IntMap.find_opt 42 IntMap.empty = None); + assert(IntMap.find_opt 42 map = Some "42"); + assert(IntMap.find_opt 0 map = None); + + + let s = "Hello world !" in + assert(String.index_opt s 'x' = None); + assert(String.index_opt s ' ' = Some 5); + + assert(String.rindex_opt s 'x' = None); + assert(String.rindex_opt s ' ' = Some 11); + + assert(String.index_from_opt s 0 'x' = None); + assert(String.index_from_opt s 6 ' ' = Some 11); + + assert(String.rindex_from_opt s 0 'x' = None); + assert(String.rindex_from_opt s 6 ' ' = Some 5); + + + let module W = Weak.Make(struct + type t = int ref + let equal = (=) + let hash = Hashtbl.hash + end) + in + let w = W.create 10 in + let x = Random.int 42 in + let r = ref x in + assert (W.find_opt w r = None); + W.add w r; + assert (W.find_opt w r = Some r); + + () diff --git a/testsuite/tests/basic/opt_variants.reference b/testsuite/tests/basic/opt_variants.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/basic/pr7533.ml b/testsuite/tests/basic/pr7533.ml new file mode 100644 index 00000000..47bbeeea --- /dev/null +++ b/testsuite/tests/basic/pr7533.ml @@ -0,0 +1,19 @@ +(* PR#7533 *) + +exception Foo + +let f x = + if x > 42 then 1 + else raise Foo + +let () = + let f = Sys.opaque_identity f in + match (f 0) / (List.hd (Sys.opaque_identity [0])) with + | exception Foo -> () + | _ -> assert false + +let () = + let f = Sys.opaque_identity f in + match (f 0) mod (List.hd (Sys.opaque_identity [0])) with + | exception Foo -> () + | _ -> assert false diff --git a/testsuite/tests/basic/pr7533.reference b/testsuite/tests/basic/pr7533.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/basic/switch_opts.ml b/testsuite/tests/basic/switch_opts.ml new file mode 100644 index 00000000..67034de3 --- /dev/null +++ b/testsuite/tests/basic/switch_opts.ml @@ -0,0 +1,63 @@ +(* Test for optimisation of jump tables to arrays of constants *) + +let p = Printf.printf + +type test = + Test : 'b * 'a * ('b -> 'a) -> test + +type t = A | B | C + +(* These test functions need to have at least three cases. + Functions with fewer cases don't trigger the optimisation, + as they are compiled to if-then-else, not switch *) +let testcases = [ + Test (3, 3, function 1 -> 1 | 2 -> 2 | 3 -> 3 | _ -> 0); + Test (3, -3, function 1 -> 1 | 2 -> 2 | 3 -> -3 | _ -> 0); + Test (3, min_int, function 1 -> 1 | 2 -> 2 | 3 -> min_int | _ -> 0); + Test (3, max_int, function 1 -> 1 | 2 -> 2 | 3 -> max_int | _ -> 0); + Test (3, 3., function 1 -> 1. | 2 -> 2. | 3 -> 3. | _ -> 0.); + Test (3, Sys.opaque_identity "c" ^ Sys.opaque_identity "c", + function 1 -> "a" | 2 -> "b" | 3 -> "cc" | _ -> ""); + Test (3, List.rev [3;2;1], function 1 -> [] | 2 -> [42] | 3 -> [1;2;3] | _ -> [415]); + + Test (C, 3, function A -> 1 | B -> 2 | C -> 3); + Test (C, -3, function A -> 1 | B -> 2 | C -> -3); + Test (C, min_int, function A -> 1 | B -> 2 | C -> min_int); + Test (C, max_int, function A -> 1 | B -> 2 | C -> max_int); + Test (C, 3., function A -> 1. | B -> 2. | C -> 3.); + Test (C, "c", function A -> "a" | B -> "b" | C -> "c"); + Test (C, List.rev [3;2;1], function A -> [] | B -> [42] | C -> [1;2;3]); + + Test (42, 42, function + | 1 -> 1 | 2 -> 2 | 3 -> 3 | 4 -> 4 | 5 -> 5 | 6 -> 6 | 7 -> 7 | 8 -> 8 + | 9 -> 9 | 10 -> 10 | 11 -> 11 | 12 -> 12 | 13 -> 13 | 14 -> 14 | 15 -> 15 + | 16 -> 16 | 17 -> 17 | 18 -> 18 | 19 -> 19 | 20 -> 20 | 21 -> 21 | 22 -> 22 + | 23 -> 23 | 24 -> 24 | 25 -> 25 | 26 -> 26 | 27 -> 27 | 28 -> 28 | 29 -> 29 + | 30 -> 30 | 31 -> 31 | 32 -> 32 | 33 -> 33 | 34 -> 34 | 35 -> 35 | 36 -> 36 + | 37 -> 37 | 38 -> 38 | 39 -> 39 | 40 -> 40 | 41 -> 41 | 42 -> 42 | 43 -> 43 + | 44 -> 44 | 45 -> 45 | 46 -> 46 | 47 -> 47 | 48 -> 48 | 49 -> 49 | 50 -> 50 + | 51 -> 51 | 52 -> 52 | 53 -> 53 | 54 -> 54 | 55 -> 55 | 56 -> 56 | 57 -> 57 + | 58 -> 58 | 59 -> 59 | 60 -> 60 | 61 -> 61 | 62 -> 62 | 63 -> 63 | 64 -> 64 + | 65 -> 65 | 66 -> 66 | 67 -> 67 | 68 -> 68 | 69 -> 69 | 70 -> 70 | 71 -> 71 + | 72 -> 72 | 73 -> 73 | 74 -> 74 | 75 -> 75 | 76 -> 76 | 77 -> 77 | 78 -> 78 + | 79 -> 79 | 80 -> 80 | 81 -> 81 | 82 -> 82 | 83 -> 83 | 84 -> 84 | 85 -> 85 + | 86 -> 86 | 87 -> 87 | 88 -> 88 | 89 -> 89 | 90 -> 90 | 91 -> 91 | 92 -> 92 + | 93 -> 93 | 94 -> 94 | 95 -> 95 | 96 -> 96 | 97 -> 97 | 98 -> 98 | 99 -> 99 + | _ -> 0); + + Test (3, `Tertiary, function + | 1 -> `Primary + | 2 -> `Secondary + | 3 -> `Tertiary + | n -> invalid_arg "test") + ] + +let passes = ref 0 +let run_test (Test (a, b, f)) = + assert (f a = b); + incr passes + +let () = + List.iter run_test testcases; + Printf.printf "%d tests passed\n" !passes + diff --git a/testsuite/tests/basic/switch_opts.reference b/testsuite/tests/basic/switch_opts.reference new file mode 100644 index 00000000..48a00459 --- /dev/null +++ b/testsuite/tests/basic/switch_opts.reference @@ -0,0 +1 @@ +16 tests passed diff --git a/testsuite/tests/basic/zero_divided_by_n.ml b/testsuite/tests/basic/zero_divided_by_n.ml new file mode 100644 index 00000000..1523d962 --- /dev/null +++ b/testsuite/tests/basic/zero_divided_by_n.ml @@ -0,0 +1,17 @@ +(* Mantis 7201 *) + +let f () = 0 [@@inline never] + +let () = + try + ignore ((0 / f ()) : int); + assert false + with Division_by_zero -> () + +(* Not in Mantis 7201, but related: *) + +let () = + try + ignore ((0 mod f ()) : int); + assert false + with Division_by_zero -> () diff --git a/testsuite/tests/basic/zero_divided_by_n.reference b/testsuite/tests/basic/zero_divided_by_n.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/embedded/cmstub.c b/testsuite/tests/embedded/cmstub.c index 4eea82a6..a83ad61e 100644 --- a/testsuite/tests/embedded/cmstub.c +++ b/testsuite/tests/embedded/cmstub.c @@ -20,11 +20,11 @@ int fib(int n) { value * fib_closure = caml_named_value("fib"); - return Int_val(callback(*fib_closure, Val_int(n))); + return Int_val(caml_callback(*fib_closure, Val_int(n))); } char * format_result(int n) { value * format_result_closure = caml_named_value("format_result"); - return strdup(String_val(callback(*format_result_closure, Val_int(n)))); + return strdup(String_val(caml_callback(*format_result_closure, Val_int(n)))); } diff --git a/testsuite/tests/exotic-syntax/exotic.ml b/testsuite/tests/exotic-syntax/exotic.ml index 51b968aa..18280e68 100644 --- a/testsuite/tests/exotic-syntax/exotic.ml +++ b/testsuite/tests/exotic-syntax/exotic.ml @@ -76,6 +76,13 @@ let set_int contents = { contents : int } let set_int2 c = { contents : int = c } ;; +(* applying a functor to the unpacking of a first-class module *) +module M() = struct + module type String = module type of String + let string = (module String : String) + module M = Set.Make(val string) +end ;; + (* More exotic: not even found in the manual (up to version 4.00), but used in some programs found in the wild. *) diff --git a/otherlibs/bigarray/Makefile.shared b/testsuite/tests/flambda/Makefile similarity index 67% rename from otherlibs/bigarray/Makefile.shared rename to testsuite/tests/flambda/Makefile index 0d515ed0..cbf581ad 100644 --- a/otherlibs/bigarray/Makefile.shared +++ b/testsuite/tests/flambda/Makefile @@ -1,10 +1,10 @@ #************************************************************************** #* * -#* OCaml * +#* OCaml * #* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* Xavier Clerc, SED, INRIA Rocquencourt * #* * -#* Copyright 1999 Institut National de Recherche en Informatique et * +#* Copyright 2010 Institut National de Recherche en Informatique et * #* en Automatique. * #* * #* All rights reserved. This file is distributed under the terms of * @@ -13,11 +13,9 @@ #* * #************************************************************************** -LIBNAME=bigarray -EXTRACFLAGS=-I../$(UNIXLIB) -DIN_OCAML_BIGARRAY -DCAML_NAME_SPACE -EXTRACAMLFLAGS=-I ../$(UNIXLIB) -COBJS=bigarray_stubs.$(O) mmap_$(UNIX_OR_WIN32).$(O) -CAMLOBJS=bigarray.cmo -HEADERS=bigarray.h +BASEDIR=../.. -include ../Makefile +ADD_OPTFLAGS=-unbox-closures + +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/flambda/gpr998.ml b/testsuite/tests/flambda/gpr998.ml new file mode 100644 index 00000000..9f16185d --- /dev/null +++ b/testsuite/tests/flambda/gpr998.ml @@ -0,0 +1,39 @@ +(* This test attempts to check that unused closures are not deleted + during conversion from flambda to clambda. The idea is that there is + a direct call to [foo] in [bar] even though the closure for [foo] is + not used. This requires [bar] to be have a specialised parameter that + would be [foo]'s closure were there any calls to [bar], and for [bar] + to not be deleted even though there are no calls to it. Creating such + a situation is difficult, and the fact that the following code does so + is very fragile. This means two things: + + 1. This code only tests the appropriate property on amd64 + architectures. Since the code conversion from flambda to + clambda is architecture independent, this should be fine + as long as the test is run on such an architecture as part + of CI. + + 2. It is likely that future changes to flambda will silently cause + this test to stop testing the desired property. It would be worth + periodically examining the flambda output for the code to check + that this test is still worth using. +*) + +let main x = + let[@inline never] inner () = + let[@inline never] foo y () () () () () () () = x + y in + let x1, x2, x3 = x + 1, x + 2, x + 3 in + let bar p y () () () = + if p then foo y () () () () () () () + else x1 + x2 + x3 + in + let[@inline never] baz0 y () () () () () () () = + let y1 = y + 1 in + let[@inline never] baz1 () () () () () = + bar false y1 () () () + in + baz1 () () () () () + in + baz0 1 () () () () () () () + in + inner () diff --git a/testsuite/tests/flambda/gpr998.reference b/testsuite/tests/flambda/gpr998.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/float-unboxing/float_subst_boxed_number.ml b/testsuite/tests/float-unboxing/float_subst_boxed_number.ml index 209b6a4f..672b3ff8 100644 --- a/testsuite/tests/float-unboxing/float_subst_boxed_number.ml +++ b/testsuite/tests/float-unboxing/float_subst_boxed_number.ml @@ -139,6 +139,15 @@ let unbox_minor_words () = ignore (Gc.minor_words () = 0.) done +let ignore_useless_args () = + let f x _y = int_of_float (cos x) in + let rec g a n x = + if n = 0 + then a + else g (a + (f [@inlined always]) x (x +. 1.)) (n - 1) x + in + ignore (g 0 10 5.) + let () = let flambda = match Sys.getenv "FLAMBDA" with @@ -153,6 +162,7 @@ let () = check_noalloc "float refs" unbox_float_refs; check_noalloc "unbox let float" unbox_let_float; check_noalloc "unbox only if useful" unbox_only_if_useful; + check_noalloc "ignore useless args" ignore_useless_args; if flambda then begin check_noalloc "float and int32 record" unbox_record; diff --git a/testsuite/tests/formats-transition/ignored_scan_counters.ml b/testsuite/tests/formats-transition/ignored_scan_counters.ml index 307f8a59..2186a82d 100644 --- a/testsuite/tests/formats-transition/ignored_scan_counters.ml +++ b/testsuite/tests/formats-transition/ignored_scan_counters.ml @@ -1,5 +1,8 @@ (* Benoit's patch did not support %_[nlNL]; test their behavior *) +(* Ignore OCAMLRUNPARAM=b to be reproducible *) +Printexc.record_backtrace false;; + (* not supported by Printf or Format: fails at runtime *) let () = Printf.printf "%_n" ;; diff --git a/testsuite/tests/formats-transition/ignored_scan_counters.ml.reference b/testsuite/tests/formats-transition/ignored_scan_counters.ml.reference index 6d8d098b..55f8ee68 100644 --- a/testsuite/tests/formats-transition/ignored_scan_counters.ml.reference +++ b/testsuite/tests/formats-transition/ignored_scan_counters.ml.reference @@ -1,5 +1,6 @@ -# Exception: Invalid_argument "Printf: bad conversion %_". +# - : unit = () +# Exception: Invalid_argument "Printf: bad conversion %_". # Exception: Invalid_argument "Printf: bad conversion %_". # Exception: Invalid_argument "Printf: bad conversion %_". # Exception: Invalid_argument "Printf: bad conversion %_". diff --git a/testsuite/tests/lib-arg/Makefile b/testsuite/tests/lib-arg/Makefile index bc447a37..dd488d43 100644 --- a/testsuite/tests/lib-arg/Makefile +++ b/testsuite/tests/lib-arg/Makefile @@ -14,7 +14,6 @@ #************************************************************************** BASEDIR=../.. -MAIN_MODULE=testarg -include $(BASEDIR)/makefiles/Makefile.one +include $(BASEDIR)/makefiles/Makefile.several include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-arg/testarg.ml b/testsuite/tests/lib-arg/testarg.ml index 1994ba88..380f420c 100644 --- a/testsuite/tests/lib-arg/testarg.ml +++ b/testsuite/tests/lib-arg/testarg.ml @@ -81,7 +81,7 @@ let args2 = [| let error s = Printf.printf "error (%s)\n" s;; let check r v msg = if !r <> v then error msg;; -let test argv = +let test spec argv = current := 0; r_set := false; r_clear := true; @@ -89,7 +89,7 @@ let test argv = r_int := 0; r_float := 0.0; accum := []; - Arg.parse_argv ~current argv spec f_anon "usage"; + Arg.parse_and_expand_argv_dynamic current argv (ref spec) f_anon "usage"; let result = List.rev !accum in let reference = [ "anon(anon1)"; @@ -119,5 +119,71 @@ let test argv = check r_float 2.72 "Set_float"; ;; -test args1;; -test args2;; +let test_arg args = test spec (ref args);; + +test_arg args1;; +test_arg args2;; + + +let safe_rm file = + try + Sys.remove file + with _ -> () + +let test_rw argv = + safe_rm "test_rw"; + safe_rm "test_rw0"; + Arg.write_arg "test_rw" argv; + Arg.write_arg0 "test_rw0" argv; + let argv' = Arg.read_arg "test_rw" in + let argv0 = Arg.read_arg0 "test_rw0" in + let f x y = + if x <> y then + Printf.printf "%20s %c %-20s\n%!" x (if x = y then '=' else '#') y + in + Array.iter2 f argv argv'; + Array.iter2 f argv argv0; + safe_rm "test_rw"; + safe_rm "test_rw0"; +;; + +test_rw args1;; +test_rw args2;; +test_rw (Array.make 0 "");; +test_rw [|"";""|];; + +let f_expand r msg arg s = + if s <> r then error msg; + arg; +;; + +let expand1,args1,expected1 = + let l = Array.length args1 - 1 in + let args = Array.sub args1 1 l in + let args1 = [|"prog";"-expand";"expand_arg1"|] in + Arg.["-expand", Expand (f_expand "expand_arg1" "Expand" args), "Expand (1)";], + args1, + Array.append args1 args +;; + +let expand2,args2,expected2 = + let l = Array.length args2 - 1 in + let args = Array.sub args2 1 l in + let args2 = [|"prog";"-expand";"expand_arg2"|] in + Arg.["-expand", Expand (f_expand "expand_arg2" "Expand" args), "Expand (1)";], + args2, + Array.append args2 args +;; + +let test_expand spec argv reference = + let result = ref argv in + test spec result; + let f x y = + if x <> y then + Printf.printf "%20s %c %-20s\n%!" x (if x = y then '=' else '#') y + in + Array.iter2 f !result reference; +;; + +test_expand (expand1@spec) args1 expected1;; +test_expand (expand2@spec) args2 expected2;; diff --git a/testsuite/tests/lib-arg/testerror.ml b/testsuite/tests/lib-arg/testerror.ml new file mode 100644 index 00000000..d4b433ee --- /dev/null +++ b/testsuite/tests/lib-arg/testerror.ml @@ -0,0 +1,41 @@ +(** Test that the right message errors are emitted by Arg *) + + +let usage= "Arg module testing" + +let test total i (spec,anon,argv) = + let argv = Array.of_list ("testerror" :: argv) in + try Arg.parse_argv ~current:(ref 0) argv spec anon usage with + | Arg.Bad s-> Printf.printf "(%d/%d) Bad:\n%s\n" (i+1) total s + | Arg.Help s -> Printf.printf "(%d/%d) Help:\n%s\n" (i+1) total s + + +let tests = [ +(** missing argument error *) + ["-s", Arg.String ignore, "missing arg"], ignore, ["-s"] + +(** No argument expected *) +; ["-set", Arg.Set (ref false), "no argument expected"], ignore, ["-set=true"] + +(** help message *) +; [], ignore, ["-help" ] + +(** wrong argument type *) +; ["-int", Arg.Int ignore, "wrong argument type" ], ignore, ["-int"; "not_an_int" ] + +(** unknown option *) +; [], ignore, [ "-an-unknown-option" ] + +(** user-error in anon fun *) +; [], (fun _ -> raise @@ Arg.Bad("User-raised error")), [ "argument" ] + +(** user-error in anon fun *) +; ["-error", + Arg.Unit (fun () -> raise @@ Arg.Bad("User-raised error bis")), + "user raised error"] +, ignore, [ "-error" ] +] + +let () = + let n = List.length tests in + List.iteri (test n) tests diff --git a/testsuite/tests/lib-arg/testerror.reference b/testsuite/tests/lib-arg/testerror.reference new file mode 100644 index 00000000..3608e11c --- /dev/null +++ b/testsuite/tests/lib-arg/testerror.reference @@ -0,0 +1,45 @@ +(1/7) Bad: +testerror: option '-s' needs an argument. +Arg module testing + -s missing arg + -help Display this list of options + --help Display this list of options + +(2/7) Bad: +testerror: wrong argument 'true'; option '-set=true' expects no argument. +Arg module testing + -set no argument expected + -help Display this list of options + --help Display this list of options + +(3/7) Help: +Arg module testing + -help Display this list of options + --help Display this list of options + +(4/7) Bad: +testerror: wrong argument 'not_an_int'; option '-int' expects an integer. +Arg module testing + -int wrong argument type + -help Display this list of options + --help Display this list of options + +(5/7) Bad: +testerror: unknown option '-an-unknown-option'. +Arg module testing + -help Display this list of options + --help Display this list of options + +(6/7) Bad: +testerror: User-raised error. +Arg module testing + -help Display this list of options + --help Display this list of options + +(7/7) Bad: +testerror: User-raised error bis. +Arg module testing + -error user raised error + -help Display this list of options + --help Display this list of options + diff --git a/testsuite/tests/lib-bigarray-file/Makefile b/testsuite/tests/lib-bigarray-file/Makefile new file mode 100644 index 00000000..09ee70fa --- /dev/null +++ b/testsuite/tests/lib-bigarray-file/Makefile @@ -0,0 +1,23 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Clerc, SED, INRIA Rocquencourt * +#* * +#* Copyright 2010 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +BASEDIR=../.. +LIBRARIES=unix bigarray +ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix \ + -I $(OTOPDIR)/otherlibs/bigarray +LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix:$(TOPDIR)/otherlibs/bigarray + +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-bigarray-file/mapfile.ml b/testsuite/tests/lib-bigarray-file/mapfile.ml new file mode 100644 index 00000000..c69ca459 --- /dev/null +++ b/testsuite/tests/lib-bigarray-file/mapfile.ml @@ -0,0 +1,109 @@ +open Bigarray + +(* Test harness *) + +let error_occurred = ref false + +let function_tested = ref "" + +let testing_function s = + function_tested := s; + print_newline(); + print_string s; + print_newline() + +let test test_number answer correct_answer = + flush stdout; + flush stderr; + if answer <> correct_answer then begin + Printf.eprintf "*** Bad result (%s, test %d)\n" !function_tested test_number; + flush stderr; + error_occurred := true + end else begin + Printf.printf " %d..." test_number + end + +(* Tests *) + +let tests () = + testing_function "map_file"; + let mapped_file = Filename.temp_file "bigarray" ".data" in + begin + let fd = + Unix.openfile mapped_file + [Unix.O_RDWR; Unix.O_TRUNC; Unix.O_CREAT] 0o666 in + let a = + array1_of_genarray (Genarray.map_file fd float64 c_layout true [|10000|]) + in + Unix.close fd; + for i = 0 to 9999 do a.{i} <- float i done; + let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in + let b = + array2_of_genarray + (Genarray.map_file fd float64 fortran_layout false [|100; -1|]) + in + Unix.close fd; + let ok = ref true in + for i = 0 to 99 do + for j = 0 to 99 do + if b.{j+1,i+1} <> float (100 * i + j) then ok := false + done + done; + test 1 !ok true; + b.{50,50} <- (-1.0); + let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in + let c = + array2_of_genarray (Genarray.map_file fd float64 c_layout false [|-1; 100|]) + in + Unix.close fd; + let ok = ref true in + for i = 0 to 99 do + for j = 0 to 99 do + if c.{i,j} <> float (100 * i + j) then ok := false + done + done; + test 2 !ok true; + let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in + let c = + array2_of_genarray + (Genarray.map_file fd ~pos:800L float64 c_layout false [|-1; 100|]) + in + Unix.close fd; + let ok = ref true in + for i = 1 to 99 do + for j = 0 to 99 do + if c.{i-1,j} <> float (100 * i + j) then ok := false + done + done; + test 3 !ok true; + let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in + let c = + array2_of_genarray + (Genarray.map_file fd ~pos:79200L float64 c_layout false [|-1; 100|]) + in + Unix.close fd; + let ok = ref true in + for j = 0 to 99 do + if c.{0,j} <> float (100 * 99 + j) then ok := false + done; + test 4 !ok true + end; + (* Force garbage collection of the mapped bigarrays above, otherwise + Win32 doesn't let us erase the file. Notice the begin...end above + so that the VM doesn't keep stack references to the mapped bigarrays. *) + Gc.full_major(); + Sys.remove mapped_file; + + () + [@@inline never] + + +(********* End of test *********) + +let _ = + tests (); + print_newline(); + if !error_occurred then begin + prerr_endline "************* TEST FAILED ****************"; exit 2 + end else + exit 0 diff --git a/testsuite/tests/lib-bigarray-file/mapfile.reference b/testsuite/tests/lib-bigarray-file/mapfile.reference new file mode 100644 index 00000000..4b66315c --- /dev/null +++ b/testsuite/tests/lib-bigarray-file/mapfile.reference @@ -0,0 +1,3 @@ + +map_file + 1... 2... 3... 4... diff --git a/testsuite/tests/lib-bigarray/bigarrays.ml b/testsuite/tests/lib-bigarray/bigarrays.ml index 9f8afc41..d229ae09 100644 --- a/testsuite/tests/lib-bigarray/bigarrays.ml +++ b/testsuite/tests/lib-bigarray/bigarrays.ml @@ -476,6 +476,16 @@ let tests () = Complex.i 1 1); test 12 true (test_blit_fill complex64 [Complex.zero; Complex.one; Complex.i] Complex.i 1 1); + testing_function "slice"; + let a = Array1.of_array int c_layout [| 5; 4; 3 |] in + test 1 (Array1.slice a 0) (Array0.of_value int c_layout 5); + test 2 (Array1.slice a 1) (Array0.of_value int c_layout 4); + test 3 (Array1.slice a 2) (Array0.of_value int c_layout 3); + let a = Array1.of_array int fortran_layout [| 5; 4; 3 |] in + test 6 (Array1.slice a 1) (Array0.of_value int fortran_layout 5); + test 7 (Array1.slice a 2) (Array0.of_value int fortran_layout 4); + test 8 (Array1.slice a 3) (Array0.of_value int fortran_layout 3); + (* Bi-dimensional arrays *) @@ -769,6 +779,111 @@ let tests () = let a = Genarray.create int c_layout [|2;2;2;2;2|] in test 1 (Genarray.size_in_bytes a) (32 * (kind_size_in_bytes int)); +(* Zero-dimensional arrays *) + testing_function "------ Array0 --------"; + testing_function "create/set/get"; + let test_setget kind vals = + List.for_all (fun (v1, v2) -> + let ca = Array0.create kind c_layout in + let fa = Array0.create kind fortran_layout in + Array0.set ca v1; + Array0.set fa v1; + Array0.get ca = v2 && Array0.get fa = v2) vals in + test 1 true + (test_setget int8_signed + [0, 0; + 123, 123; + -123, -123; + 456, -56; + 0x101, 1]); + test 2 true + (test_setget int8_unsigned + [0, 0; + 123, 123; + -123, 133; + 456, 0xc8; + 0x101, 1]); + test 3 true + (test_setget int16_signed + [0, 0; + 123, 123; + -123, -123; + 31456, 31456; + -31456, -31456; + 65432, -104; + 0x10001, 1]); + test 4 true + (test_setget int16_unsigned + [0, 0; + 123, 123; + -123, 65413; + 31456, 31456; + -31456, 34080; + 65432, 65432; + 0x10001, 1]); + test 5 true + (test_setget int + [0, 0; + 123, 123; + -456, -456; + max_int, max_int; + min_int, min_int; + 0x12345678, 0x12345678; + -0x12345678, -0x12345678]); + test 6 true + (test_setget int32 + [Int32.zero, Int32.zero; + Int32.of_int 123, Int32.of_int 123; + Int32.of_int (-456), Int32.of_int (-456); + Int32.max_int, Int32.max_int; + Int32.min_int, Int32.min_int; + Int32.of_string "0x12345678", Int32.of_string "0x12345678"]); + test 7 true + (test_setget int64 + [Int64.zero, Int64.zero; + Int64.of_int 123, Int64.of_int 123; + Int64.of_int (-456), Int64.of_int (-456); + Int64.max_int, Int64.max_int; + Int64.min_int, Int64.min_int; + Int64.of_string "0x123456789ABCDEF0", + Int64.of_string "0x123456789ABCDEF0"]); + test 8 true + (test_setget nativeint + [Nativeint.zero, Nativeint.zero; + Nativeint.of_int 123, Nativeint.of_int 123; + Nativeint.of_int (-456), Nativeint.of_int (-456); + Nativeint.max_int, Nativeint.max_int; + Nativeint.min_int, Nativeint.min_int; + Nativeint.of_string "0x12345678", + Nativeint.of_string "0x12345678"]); + test 9 true + (test_setget float32 + [0.0, 0.0; + 4.0, 4.0; + -0.5, -0.5; + 655360.0, 655360.0]); + test 10 true + (test_setget float64 + [0.0, 0.0; + 4.0, 4.0; + -0.5, -0.5; + 1.2345678, 1.2345678; + 3.1415e10, 3.1415e10]); + test 11 true + (test_setget complex32 + [Complex.zero, Complex.zero; + Complex.one, Complex.one; + Complex.i, Complex.i; + {im = 0.5; re = -2.0}, {im = 0.5; re = -2.0}]); + test 12 true + (test_setget complex64 + [Complex.zero, Complex.zero; + Complex.one, Complex.one; + Complex.i, Complex.i; + {im=0.5;re= -2.0}, {im=0.5;re= -2.0}; + {im=3.1415;re=1.2345678}, {im=3.1415;re=1.2345678}]); + + (* Kind size *) testing_function "kind_size_in_bytes"; let arr1 = Array1.create Float32 c_layout 1 in @@ -819,6 +934,13 @@ let tests () = test 5 (Array2.slice_right d 1) (from_list_fortran int [1001;2001;3001;1002]); test 6 (Array2.slice_right d 2) (from_list_fortran int [2002;3002;1003;2003]); test 7 (Array2.slice_right d 3) (from_list_fortran int [3003;1004;2004;3004]); + testing_function "reshape"; + let a = make_array2 int c_layout 0 1 1 (fun i -> i + 3) in + let b = reshape_0 (genarray_of_array2 a) in + let c = reshape (genarray_of_array0 b) [|1|] in + test 8 (Array0.get b) 3; + test 9 (Genarray.get c [|0|]) 3; + test 10 (Genarray.get (Genarray.slice_left c [|0|]) [||]) 3; (* I/O *) diff --git a/testsuite/tests/lib-bigarray/bigarrays.reference b/testsuite/tests/lib-bigarray/bigarrays.reference index 40ab1ec4..e96d0114 100644 --- a/testsuite/tests/lib-bigarray/bigarrays.reference +++ b/testsuite/tests/lib-bigarray/bigarrays.reference @@ -19,6 +19,8 @@ sub 1... 2... 3... 4... 5... 6... 7... 8... 9... blit, fill 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... +slice + 1... 2... 3... 6... 7... 8... ------ Array2 -------- @@ -53,6 +55,10 @@ slice1 1... 2... 3... 4... 5... 6... 7... size_in_bytes_general 1... +------ Array0 -------- + +create/set/get + 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... kind_size_in_bytes 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... @@ -62,6 +68,8 @@ reshape_1 1... 2... reshape_2 1... 2... 3... 4... 5... 6... 7... +reshape + 8... 9... 10... ------ I/O -------- diff --git a/testsuite/tests/lib-bigarray/weak_bigarray.ml b/testsuite/tests/lib-bigarray/weak_bigarray.ml new file mode 100644 index 00000000..62f9b99f --- /dev/null +++ b/testsuite/tests/lib-bigarray/weak_bigarray.ml @@ -0,0 +1,28 @@ + + +(** check that custom block are not copied by Weak.get_copy *) + +open Bigarray +open Bigarray.Array1 + +let () = + let a = ref (create float64 c_layout 10) in + Gc.compact (); + set !a 0 42.; + + let w = Weak.create 1 in + Weak.set w 0 (Some !a); + + let b = + match Weak.get_copy w 0 with + | None -> assert false + | Some b -> b + in + Printf.printf "a.(0) = %f\n" (get !a 0); + Printf.printf "b.(0) = %f\n" (get b 0); + a := create float64 c_layout 10; + Gc.compact (); + + let c = create float64 c_layout 10 in + set c 0 33.; + Printf.printf "b.(0) = %f\n" (get b 0); diff --git a/testsuite/tests/lib-bigarray/weak_bigarray.reference b/testsuite/tests/lib-bigarray/weak_bigarray.reference new file mode 100644 index 00000000..38901efc --- /dev/null +++ b/testsuite/tests/lib-bigarray/weak_bigarray.reference @@ -0,0 +1,3 @@ +a.(0) = 42.000000 +b.(0) = 42.000000 +b.(0) = 42.000000 diff --git a/tools/make-opcodes b/testsuite/tests/lib-buffer/Makefile similarity index 74% rename from tools/make-opcodes rename to testsuite/tests/lib-buffer/Makefile index 6dba377a..c11a415f 100644 --- a/tools/make-opcodes +++ b/testsuite/tests/lib-buffer/Makefile @@ -1,10 +1,10 @@ #************************************************************************** #* * -#* OCaml * +#* OCaml * #* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* Xavier Clerc, SED, INRIA Rocquencourt * #* * -#* Copyright 1995 Institut National de Recherche en Informatique et * +#* Copyright 2010 Institut National de Recherche en Informatique et * #* en Automatique. * #* * #* All rights reserved. This file is distributed under the terms of * @@ -13,5 +13,6 @@ #* * #************************************************************************** -$1=="enum" {n=0; next; } - {for (i = 1; i <= NF; i++) {printf("let op%s = %d\n", $i, n++);}} +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-buffer/test.ml b/testsuite/tests/lib-buffer/test.ml new file mode 100644 index 00000000..0fd32a6c --- /dev/null +++ b/testsuite/tests/lib-buffer/test.ml @@ -0,0 +1,86 @@ +open Printf +;; + +(* Set up*) +let n = 10 +;; + +let buf = Buffer.create n +;; + +let () = + for i = 1 to 10 do + Buffer.add_char buf 'a' + done +;; + +assert (Buffer.length buf = n) +;; + +(* Helpers *) + +let output result str = + print_string ("Buffer " ^ str ^ " " ^ result ^ "\n") +;; + +let passed = output "passed" +;; + +let failed = output "failed" +;; + +(* Tests *) +let () = print_string "Standard Library: Module Buffer\n" +;; + +let truncate_neg : unit = + let msg = "truncate: negative" in + try + Buffer.truncate buf (-1); + failed msg + with + Invalid_argument "Buffer.truncate" -> + passed msg +;; + +let truncate_large : unit = + let msg = "truncate: large" in + try + Buffer.truncate buf (n+1); + failed msg + with + Invalid_argument "Buffer.truncate" -> + passed msg +;; + +let truncate_correct : unit = + let n' = n - 1 + and msg = "truncate: in-range" in + try + Buffer.truncate buf n'; + if Buffer.length buf = n' then + passed msg + else + failed msg + with + Invalid_argument "Buffer.truncate" -> + failed msg +;; + +let reset_non_zero : unit = + let msg = "reset: non-zero" in + Buffer.reset buf; + if Buffer.length buf = 0 then + passed msg + else + failed msg +;; + +let reset_zero : unit = + let msg = "reset: zero" in + Buffer.reset buf; + if Buffer.length buf = 0 then + passed msg + else + failed msg +;; diff --git a/testsuite/tests/lib-buffer/test.reference b/testsuite/tests/lib-buffer/test.reference new file mode 100644 index 00000000..3e63c335 --- /dev/null +++ b/testsuite/tests/lib-buffer/test.reference @@ -0,0 +1,6 @@ +Standard Library: Module Buffer +Buffer truncate: negative passed +Buffer truncate: large passed +Buffer truncate: in-range passed +Buffer reset: non-zero passed +Buffer reset: zero passed diff --git a/testsuite/tests/lib-bytes/Makefile b/testsuite/tests/lib-bytes/Makefile new file mode 100644 index 00000000..77b26912 --- /dev/null +++ b/testsuite/tests/lib-bytes/Makefile @@ -0,0 +1,19 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Clerc, SED, INRIA Rocquencourt * +#* * +#* Copyright 2010 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +BASEDIR=../.. +MODULES=testing +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-bytes/test_bytes.ml b/testsuite/tests/lib-bytes/test_bytes.ml new file mode 100644 index 00000000..49725a5b --- /dev/null +++ b/testsuite/tests/lib-bytes/test_bytes.ml @@ -0,0 +1,122 @@ +let test_raises_invalid_argument f x = + ignore + (Testing.test_raises_exc_p (function Invalid_argument _ -> true | _ -> false) + f x) + +let check b offset s = + let rec loop i = + i = String.length s || + Bytes.get b (i + offset) = String.get s i && loop (i+1) + in + loop 0 + +let () = + let abcde = Bytes.of_string "abcde" in + let open Bytes in + begin + (* + abcde + ????? + *) + Testing.test + (length (extend abcde 7 (-7)) = 5); + + (* + abcde + ????? + *) + Testing.test + (length (extend abcde (-7) 7) = 5); + + (* + abcde + abcde + *) + Testing.test + (let r = extend abcde 0 0 in + length r = 5 && check r 0 "abcde" + && r != abcde); + + (* + abcde + ??abc + *) + Testing.test + (let r = extend abcde 2 (-2) in + length r = 5 && check r 2 "abc"); + + (* + abcde + bcd + *) + Testing.test + (let r = extend abcde (-1) (-1) in + length r = 3 && check r 0 "bcd"); + + (* + abcde + de?? + *) + Testing.test + (let r = extend abcde (-3) 2 in + length r = 4 && check r 0 "de"); + + (* + abcde + abc + *) + Testing.test + (let r = extend abcde 0 (-2) in + length r = 3 && check r 0 "abc"); + + (* + abcde + cde + *) + Testing.test + (let r = extend abcde (-2) 0 in + length r = 3 && check r 0 "cde"); + + (* + abcde + abcde?? + *) + Testing.test + (let r = extend abcde 0 2 in + length r = 7 + && check r 0 "abcde"); + + (* + abcde + ??abcde + *) + Testing.test + (let r = extend abcde 2 0 in + length r = 7 + && check r 2 "abcde"); + + (* + abcde + ?abcde? + *) + Testing.test + (let r = extend abcde 1 1 in + length r = 7 + && check r 1 "abcde"); + + (* length + left + right < 0 *) + test_raises_invalid_argument + (fun () -> extend abcde (-3) (-3)) (); + + (* length + left > max_int *) + test_raises_invalid_argument + (fun () -> extend abcde max_int 0) (); + + (* length + right > max_int *) + test_raises_invalid_argument + (fun () -> extend abcde 0 max_int) (); + + (* length + left + right > max_int *) + test_raises_invalid_argument + (fun () -> extend abcde max_int max_int) (); + end diff --git a/testsuite/tests/lib-bytes/test_bytes.reference b/testsuite/tests/lib-bytes/test_bytes.reference new file mode 100644 index 00000000..d2a3171e --- /dev/null +++ b/testsuite/tests/lib-bytes/test_bytes.reference @@ -0,0 +1,2 @@ + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 +All tests succeeded. diff --git a/testsuite/tests/lib-dynlink-csharp/Makefile b/testsuite/tests/lib-dynlink-csharp/Makefile index e3acc6b7..ae98ca0b 100644 --- a/testsuite/tests/lib-dynlink-csharp/Makefile +++ b/testsuite/tests/lib-dynlink-csharp/Makefile @@ -14,7 +14,8 @@ #************************************************************************** BASEDIR=../.. -CSC_COMMAND=csc +# Only run this test for TOOLCHAIN=msvc +CSC_COMMAND=$(filter csc,$(subst msvc,csc,$(TOOLCHAIN))) CSC=$(CSC_COMMAND) $(CSC_FLAGS) COMPFLAGS=-I $(OTOPDIR)/otherlibs/bigarray -I $(OTOPDIR)/otherlibs/dynlink \ @@ -31,7 +32,9 @@ all: prepare bytecode bytecode-dll native native-dll prepare: @if $(SUPPORTS_SHARED_LIBRARIES); then \ $(OCAMLC) -c plugin.ml && \ - $(OCAMLOPT) -o plugin.cmxs -shared plugin.ml; \ + if $(BYTECODE_ONLY) ; then : ; else \ + $(OCAMLOPT) -o plugin.cmxs -shared plugin.ml; \ + fi; \ fi .PHONY: bytecode diff --git a/testsuite/tests/lib-dynlink-native/Makefile b/testsuite/tests/lib-dynlink-native/Makefile index 6346532f..13e1a4a9 100644 --- a/testsuite/tests/lib-dynlink-native/Makefile +++ b/testsuite/tests/lib-dynlink-native/Makefile @@ -69,7 +69,7 @@ plugin2.cmx: api.cmx plugin.cmi plugin.cmx @mv plugin.cmx.bak plugin.cmx sub/api.so: sub/api.cmi sub/api.ml - @cd sub; $(OCAMLOPT) -c $(SHARED) api.ml + @cd sub; $(OCAMLOPT) -c $(SUPPORTS_SHARED_LIBRARIES) api.ml sub/api.cmi: sub/api.mli @cd sub; $(OCAMLOPT) -c -opaque api.mli diff --git a/testsuite/tests/lib-hashtbl/htbl.ml b/testsuite/tests/lib-hashtbl/htbl.ml index 106ee793..0a8001f7 100644 --- a/testsuite/tests/lib-hashtbl/htbl.ml +++ b/testsuite/tests/lib-hashtbl/htbl.ml @@ -106,6 +106,7 @@ module HofM (M: Map.S) : Hashtbl.S with type key = M.key = let add = Hashtbl.add let remove = Hashtbl.remove let find = Hashtbl.find + let find_opt = Hashtbl.find_opt let find_all = Hashtbl.find_all let replace = Hashtbl.replace let mem = Hashtbl.mem diff --git a/testsuite/tests/lib-marshal/intextaux.c b/testsuite/tests/lib-marshal/intextaux.c index f8df141e..183343d6 100644 --- a/testsuite/tests/lib-marshal/intextaux.c +++ b/testsuite/tests/lib-marshal/intextaux.c @@ -20,11 +20,11 @@ value marshal_to_block(value vbuf, value vlen, value v, value vflags) { - return Val_long(output_value_to_block(v, vflags, + return Val_long(caml_output_value_to_block(v, vflags, (char *) vbuf, Long_val(vlen))); } value marshal_from_block(value vbuf, value vlen) { - return input_value_from_block((char *) vbuf, Long_val(vlen)); + return caml_input_value_from_block((char *) vbuf, Long_val(vlen)); } diff --git a/testsuite/tests/lib-set/testmap.ml b/testsuite/tests/lib-set/testmap.ml index bbf4b06a..307c7f8d 100644 --- a/testsuite/tests/lib-set/testmap.ml +++ b/testsuite/tests/lib-set/testmap.ml @@ -101,6 +101,58 @@ let test x v s1 s2 = with Not_found -> M.is_empty s1); + checkbool "find_first" + (let (l, p, r) = M.split x s1 in + if p = None && M.is_empty r then + try + let _ = M.find_first (fun k -> k >= x) s1 in + false + with Not_found -> + true + else + let (k, v) = M.find_first (fun k -> k >= x) s1 in + match p with + None -> (k, v) = M.min_binding r + | Some v1 -> (k, v) = (x, v1)); + + checkbool "find_first_opt" + (let (l, p, r) = M.split x s1 in + if p = None && M.is_empty r then + match M.find_first_opt (fun k -> k >= x) s1 with + None -> true + | _ -> false + else + let Some (k, v) = M.find_first_opt (fun k -> k >= x) s1 in + match p with + None -> (k, v) = M.min_binding r + | Some v1 -> (k, v) = (x, v1)); + + checkbool "find_last" + (let (l, p, r) = M.split x s1 in + if p = None && M.is_empty l then + try + let _ = M.find_last (fun k -> k <= x) s1 in + false + with Not_found -> + true + else + let (k, v) = M.find_last (fun k -> k <= x) s1 in + match p with + None -> (k, v) = M.max_binding l + | Some v1 -> (k, v) = (x, v1)); + + checkbool "find_last_opt" + (let (l, p, r) = M.split x s1 in + if p = None && M.is_empty l then + match M.find_last_opt (fun k -> k <= x) s1 with + None -> true + | _ -> false + else + let Some (k, v) = M.find_last_opt (fun k -> k <= x) s1 in + match p with + None -> (k, v) = M.max_binding l + | Some v1 -> (k, v) = (x, v1)); + check "split" (let (l, p, r) = M.split x s1 in fun i -> diff --git a/testsuite/tests/lib-set/testset.ml b/testsuite/tests/lib-set/testset.ml index 4417c36a..35878ea0 100644 --- a/testsuite/tests/lib-set/testset.ml +++ b/testsuite/tests/lib-set/testset.ml @@ -112,6 +112,62 @@ let test x s1 s2 = with Not_found -> S.is_empty s1); + checkbool "find_first" + (let (l, p, r) = S.split x s1 in + if not p && S.is_empty r then + try + let _ = S.find_first (fun k -> k >= x) s1 in + false + with Not_found -> + true + else + let e = S.find_first (fun k -> k >= x) s1 in + if p then + e = x + else + e = S.min_elt r); + + checkbool "find_first_opt" + (let (l, p, r) = S.split x s1 in + if not p && S.is_empty r then + match S.find_first_opt (fun k -> k >= x) s1 with + None -> true + | _ -> false + else + let Some e = S.find_first_opt (fun k -> k >= x) s1 in + if p then + e = x + else + e = S.min_elt r); + + checkbool "find_last" + (let (l, p, r) = S.split x s1 in + if not p && S.is_empty l then + try + let _ = S.find_last (fun k -> k <= x) s1 in + false + with Not_found -> + true + else + let e = S.find_last (fun k -> k <= x) s1 in + if p then + e = x + else + e = S.max_elt l); + + checkbool "find_last_opt" + (let (l, p, r) = S.split x s1 in + if not p && S.is_empty l then + match S.find_last_opt (fun k -> k <= x) s1 with + None -> true + | _ -> false + else + let Some e = S.find_last_opt (fun k -> k <= x) s1 in + if p then + e = x + else + e = S.max_elt l); + check "split" (let (l, p, r) = S.split x s1 in fun i -> @@ -167,3 +223,21 @@ let () = for i = 1 to 10 do s1 := S.add i !s1 done; let s2 = S.filter (fun e -> e >= 0) !s1 in assert (s2 == !s1) + +let valid_structure s = + (* this test should return 'true' for all set, + but it can detect sets that are ill-structured, + for example incorrectly ordered, as the S.mem + function will make assumptions about the set ordering. + + (This trick was used to exhibit the bug in PR#7403) + *) + List.for_all (fun n -> S.mem n s) (S.elements s) + +let () = + (* PR#7403: map buggily orders elements according to the input + set order, not the output set order. Mapping functions that + change the value ordering thus break the set structure. *) + let test = S.of_list [1; 3; 5] in + let f = function 3 -> 8 | n -> n in + assert (valid_structure (S.map f test)) diff --git a/testsuite/tests/lib-stdlabels/Makefile b/testsuite/tests/lib-stdlabels/Makefile new file mode 100644 index 00000000..fe35955c --- /dev/null +++ b/testsuite/tests/lib-stdlabels/Makefile @@ -0,0 +1,19 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Clerc, SED, INRIA Rocquencourt * +#* * +#* Copyright 2010 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** +ADD_COMPFLAGS=-nolabels +BASEDIR=../.. + +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-stdlabels/test_stdlabels.ml b/testsuite/tests/lib-stdlabels/test_stdlabels.ml new file mode 100644 index 00000000..5e9770d8 --- /dev/null +++ b/testsuite/tests/lib-stdlabels/test_stdlabels.ml @@ -0,0 +1,40 @@ +module A : module type of Array = ArrayLabels +module B : module type of Bytes = BytesLabels +module L : module type of List = ListLabels +module S : module type of String = StringLabels + +module M : module type of Map = MoreLabels.Map +module Se : module type of Set = MoreLabels.Set + + +(* For *) +(* module H : module type of Hashtbl = MoreLabels.Hashtbl *) +(* we will have following error: *) +(* Error: Signature mismatch: *) +(* ... *) +(* Type declarations do not match: *) +(* type statistics = Hashtbl.statistics *) +(* is not included in *) +(* type statistics = { *) +(* num_bindings : int; *) +(* num_buckets : int; *) +(* max_bucket_length : int; *) +(* bucket_histogram : int array; *) +(* } *) +(* Their kinds differ. *) +(* This is workaround:*) +module Indirection = struct + type t = Hashtbl.statistics = { num_bindings: int; + num_buckets: int; + max_bucket_length: int; + bucket_histogram: int array} +end +module type HS = sig + type statistics = Indirection.t + include module type of Hashtbl + with type statistics := Indirection.t +end +module H : HS = MoreLabels.Hashtbl + +let () = + () diff --git a/testsuite/tests/lib-stdlabels/test_stdlabels.reference b/testsuite/tests/lib-stdlabels/test_stdlabels.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/lib-threads/backtrace_threads.ml b/testsuite/tests/lib-threads/backtrace_threads.ml new file mode 100644 index 00000000..348a5f7f --- /dev/null +++ b/testsuite/tests/lib-threads/backtrace_threads.ml @@ -0,0 +1,18 @@ + +let () = Printexc.record_backtrace true + +let () = + let bt = + try + Hashtbl.find (Hashtbl.create 1) 1; + assert false + with Not_found -> + Printexc.get_raw_backtrace () + in + let t = Thread.create (fun () -> + try + Printexc.raise_with_backtrace Not_found bt + with Not_found -> () + ) () in + Thread.join t; + flush stdout diff --git a/testsuite/tests/lib-threads/backtrace_threads.reference b/testsuite/tests/lib-threads/backtrace_threads.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/lib-uchar/test.ml b/testsuite/tests/lib-uchar/test.ml index a2b7ec1d..3895c545 100644 --- a/testsuite/tests/lib-uchar/test.ml +++ b/testsuite/tests/lib-uchar/test.ml @@ -67,16 +67,6 @@ let test_compare () = assert (Uchar.(compare max min) = 1); () -let test_dump () = - let str u = Format.asprintf "%a" Uchar.dump u in - assert (str Uchar.min = "U+0000"); - assert (str Uchar.(succ min) = "U+0001"); - assert (str Uchar.(of_int 0xFFFF) = "U+FFFF"); - assert (str Uchar.(succ (of_int 0xFFFF)) = "U+10000"); - assert (str Uchar.(pred max) = "U+10FFFE"); - assert (str Uchar.max = "U+10FFFF"); - () - let tests () = test_constants (); test_succ (); @@ -87,7 +77,6 @@ let tests () = test_to_char (); test_equal (); test_compare (); - test_dump (); () let () = diff --git a/testsuite/tests/lib-unix/Makefile b/testsuite/tests/lib-unix/Makefile new file mode 100644 index 00000000..789c5091 --- /dev/null +++ b/testsuite/tests/lib-unix/Makefile @@ -0,0 +1,36 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Clerc, SED, INRIA Rocquencourt * +#* * +#* Copyright 2010 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +BASEDIR=../.. +LIBRARIES=unix +ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix +LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix + +ifeq ($(OS),Windows_NT) +ADD_BYTERUN_FLAGS="-I $(OTOPDIR)/otherlibs/win32unix" +endif + +default: reflector.exe fdstatus.exe cmdline_prog.exe + @$(MAKE) check + +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common + +%.exe: %.c +ifeq ($(CCOMPTYPE),msvc) + @set -o pipefail ; $(BYTECC) /Fe$*.exe $*.c | tail -n +2 +else + @$(BYTECC) -o $*.exe $*.c +endif diff --git a/testsuite/tests/lib-unix/cloexec.ml b/testsuite/tests/lib-unix/cloexec.ml new file mode 100644 index 00000000..d7e1e292 --- /dev/null +++ b/testsuite/tests/lib-unix/cloexec.ml @@ -0,0 +1,51 @@ +(* This is a terrible hack that plays on the internal representation + of file descriptors. The result is a number (as a string) + that the fdstatus.exe auxiliary program can use to check whether + the fd is open. *) + +let string_of_fd (fd: Unix.file_descr) : string = + match Sys.os_type with + | "Unix" | "Cygwin" -> string_of_int (Obj.magic fd : int) + | "Win32" -> + if Sys.word_size = 32 then + Int32.to_string (Obj.magic fd : int32) + else + Int64.to_string (Obj.magic fd : int64) + | _ -> assert false + +let _ = + let f0 = Unix.(openfile "tmp.txt" [O_WRONLY; O_CREAT; O_TRUNC] 0o600) in + let f1 = Unix.(openfile "tmp.txt" [O_RDONLY; O_KEEPEXEC] 0) in + let f2 = Unix.(openfile "tmp.txt" [O_RDONLY; O_CLOEXEC] 0) in + let d0 = Unix.dup f0 in + let d1 = Unix.dup ~cloexec:false f1 in + let d2 = Unix.dup ~cloexec:true f2 in + let (p0, p0') = Unix.pipe () in + let (p1, p1') = Unix.pipe ~cloexec:false () in + let (p2, p2') = Unix.pipe ~cloexec:true () in + let s0 = Unix.(socket PF_INET SOCK_STREAM 0) in + let s1 = Unix.(socket ~cloexec:false PF_INET SOCK_STREAM 0) in + let s2 = Unix.(socket ~cloexec:true PF_INET SOCK_STREAM 0) in + let (x0, x0') = + try Unix.(socketpair PF_UNIX SOCK_STREAM 0) + with Invalid_argument _ -> (p0, p0') in + (* socketpair not available under Win32; keep the same output *) + let (x1, x1') = + try Unix.(socketpair ~cloexec:false PF_UNIX SOCK_STREAM 0) + with Invalid_argument _ -> (p1, p1') in + let (x2, x2') = + try Unix.(socketpair ~cloexec:true PF_UNIX SOCK_STREAM 0) + with Invalid_argument _ -> (p2, p2') in + + let fds = [| f0;f1;f2; d0;d1;d2; + p0;p0';p1;p1';p2;p2'; + s0;s1;s2; + x0;x0';x1;x1';x2;x2' |] in + let pid = + Unix.create_process + (Filename.concat Filename.current_dir_name "fdstatus.exe") + (Array.append [| "fdstatus" |] (Array.map string_of_fd fds)) + Unix.stdin Unix.stdout Unix.stderr in + ignore (Unix.waitpid [] pid); + Array.iter (fun fd -> try Unix.close fd with Unix.Unix_error _ -> ()) fds; + Sys.remove "tmp.txt" diff --git a/testsuite/tests/lib-unix/cloexec.reference b/testsuite/tests/lib-unix/cloexec.reference new file mode 100644 index 00000000..c6270172 --- /dev/null +++ b/testsuite/tests/lib-unix/cloexec.reference @@ -0,0 +1,21 @@ +#1: open +#2: open +#3: closed +#4: open +#5: open +#6: closed +#7: open +#8: open +#9: open +#10: open +#11: closed +#12: closed +#13: open +#14: open +#15: closed +#16: open +#17: open +#18: open +#19: open +#20: closed +#21: closed diff --git a/testsuite/tests/lib-unix/cmdline_prog.c b/testsuite/tests/lib-unix/cmdline_prog.c new file mode 100644 index 00000000..c67a7563 --- /dev/null +++ b/testsuite/tests/lib-unix/cmdline_prog.c @@ -0,0 +1,10 @@ +#include + +int main (int argc, char *argv[]) +{ + int i; + for (i = 1; i < argc; i ++) { + printf ("%s\n", argv[i]); + } + return 0; +} diff --git a/testsuite/tests/lib-unix/dup.ml b/testsuite/tests/lib-unix/dup.ml new file mode 100644 index 00000000..d296cb97 --- /dev/null +++ b/testsuite/tests/lib-unix/dup.ml @@ -0,0 +1,5 @@ +let _ = + let f = Unix.dup ~cloexec:true Unix.stdout in + let txt = "Some output\n" in + ignore (Unix.write_substring f txt 0 (String.length txt)); + Unix.close f diff --git a/testsuite/tests/lib-unix/dup.reference b/testsuite/tests/lib-unix/dup.reference new file mode 100644 index 00000000..85cc16f5 --- /dev/null +++ b/testsuite/tests/lib-unix/dup.reference @@ -0,0 +1 @@ +Some output diff --git a/testsuite/tests/lib-unix/dup2.ml b/testsuite/tests/lib-unix/dup2.ml new file mode 100644 index 00000000..055d7e5f --- /dev/null +++ b/testsuite/tests/lib-unix/dup2.ml @@ -0,0 +1,24 @@ +let cat file = + let fd = Unix.openfile file [Unix.O_RDONLY] 0 in + let buf = Bytes.create 1024 in + let rec cat () = + let n = Unix.read fd buf 0 (Bytes.length buf) in + if n > 0 then (ignore(Unix.write Unix.stdout buf 0 n); cat ()) + in cat (); Unix.close fd + +let out fd txt = + ignore (Unix.write_substring fd txt 0 (String.length txt)) + +let _ = + let fd = + Unix.(openfile "./tmp.txt" + [O_WRONLY;O_TRUNC;O_CREAT;O_SHARE_DELETE] + 0o600) in + out fd "---\n"; + Unix.dup2 ~cloexec:true fd Unix.stderr; + Unix.close fd; + out Unix.stderr "Some output\n"; + cat "./tmp.txt"; + Sys.remove "./tmp.txt" + + diff --git a/testsuite/tests/lib-unix/dup2.reference b/testsuite/tests/lib-unix/dup2.reference new file mode 100644 index 00000000..2f5a485d --- /dev/null +++ b/testsuite/tests/lib-unix/dup2.reference @@ -0,0 +1,2 @@ +--- +Some output diff --git a/testsuite/tests/lib-unix/fdstatus.c b/testsuite/tests/lib-unix/fdstatus.c new file mode 100644 index 00000000..be8c6e5c --- /dev/null +++ b/testsuite/tests/lib-unix/fdstatus.c @@ -0,0 +1,73 @@ +/* Check if file descriptors are open or not */ + +#include +#include + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +void process_fd(char * s) +{ + int fd; + HANDLE h; + DWORD flags; + +#ifdef _WIN64 + h = (HANDLE) _atoi64(s); +#else + h = (HANDLE) atoi(s); +#endif + if (GetHandleInformation(h, &flags)) { + printf("open\n"); + } else if (GetLastError() == ERROR_INVALID_HANDLE) { + printf("closed\n"); + } else { + printf("error %d\n", GetLastError()); + } +} + +#else + +#include +#include +#include +#include +#include +#include + +void process_fd(char * s) +{ + long n; + int fd; + char * endp; + struct stat st; + n = strtol(s, &endp, 0); + if (*endp != 0 || n < 0 || n > (long) INT_MAX) { + printf("parsing error\n"); + return; + } + fd = (int) n; + if (fstat(fd, &st) != -1) { + printf("open\n"); + } else if (errno == EBADF) { + printf("closed\n"); + } else { + printf("error %s\n", strerror(errno)); + } +} + +#endif + +int main(int argc, char ** argv) +{ + int i; + for (i = 1; i < argc; i++) { + printf("#%d: ", i); + process_fd(argv[i]); + } + return 0; +} diff --git a/testsuite/tests/lib-unix/pipe_eof.ml b/testsuite/tests/lib-unix/pipe_eof.ml new file mode 100644 index 00000000..19f5258e --- /dev/null +++ b/testsuite/tests/lib-unix/pipe_eof.ml @@ -0,0 +1,34 @@ +let drain pipe = + let max = 2048 in + let buf = Buffer.create 2048 in + let tmp = Bytes.create max in + while begin + try + let len = Unix.read pipe tmp 0 max in + Buffer.add_subbytes buf tmp 0 len; + len > 0 + with Unix.Unix_error (Unix.EPIPE, _, _) when false -> + false + end do () done; + Buffer.contents buf +;; + +let run exe args = + let out_in, out_out = Unix.pipe () in + let err_in, err_out = Unix.pipe () in + let args = Array.append [| exe |] args in + let pid = Unix.create_process exe args Unix.stdin out_out err_out in + Unix.close out_out; + Unix.close err_out; + let output = drain out_in in + let error = drain err_in in + Unix.close out_in; + Unix.close err_in; + let _pid, status = Unix.waitpid [ ] pid in + status, output, error +;; + +let _ = + ignore (run "cp" [||]); + print_endline "success" +;; diff --git a/testsuite/tests/lib-unix/pipe_eof.reference b/testsuite/tests/lib-unix/pipe_eof.reference new file mode 100644 index 00000000..2e9ba477 --- /dev/null +++ b/testsuite/tests/lib-unix/pipe_eof.reference @@ -0,0 +1 @@ +success diff --git a/testsuite/tests/lib-unix/redirections.ml b/testsuite/tests/lib-unix/redirections.ml new file mode 100644 index 00000000..ed1712a4 --- /dev/null +++ b/testsuite/tests/lib-unix/redirections.ml @@ -0,0 +1,113 @@ +let cat file = + let fd = Unix.openfile file [Unix.O_RDONLY] 0 in + let buf = Bytes.create 1024 in + let rec cat () = + let n = Unix.read fd buf 0 (Bytes.length buf) in + if n > 0 then (ignore(Unix.write Unix.stdout buf 0 n); cat ()) + in cat (); Unix.close fd + +let out fd txt = + ignore (Unix.write_substring fd txt 0 (String.length txt)) + +let refl = + Filename.concat Filename.current_dir_name "reflector.exe" + +let test_createprocess () = + let f_out = + Unix.(openfile "./tmpout.txt" [O_WRONLY;O_TRUNC;O_CREAT;O_CLOEXEC] 0o600) in + let f_err = + Unix.(openfile "./tmperr.txt" [O_WRONLY;O_TRUNC;O_CREAT;O_CLOEXEC] 0o600) in + let (p_exit, p_entrance) = + Unix.pipe ~cloexec:true () in + let pid = + Unix.create_process_env + refl + [| refl; "i2o"; "i2e"; "o"; "123"; "e"; "456"; "i2o"; "v"; "XVAR" |] + [| "XVAR=xvar" |] + p_exit f_out f_err in + out p_entrance "aaaa\n"; + out p_entrance "bbbb\n"; + Unix.close p_entrance; + let (_, status) = Unix.waitpid [] pid in + Unix.close p_exit; Unix.close f_out; Unix.close f_err; + if status <> Unix.WEXITED 0 then + out Unix.stdout "!!! reflector exited with an error\n"; + out Unix.stdout "---- File tmpout.txt\n"; + cat "./tmpout.txt"; + out Unix.stdout "---- File tmperr.txt\n"; + cat "./tmperr.txt"; + Sys.remove "./tmpout.txt"; + Sys.remove "./tmperr.txt" + +let test_2ampsup1 () = (* 2>&1 redirection, cf. GPR#1105 *) + let pid = + Unix.create_process + refl + [| refl; "o"; "123"; "e"; "456"; "o"; "789" |] + Unix.stdin Unix.stdout Unix.stdout in + let (_, status) = Unix.waitpid [] pid in + if status <> Unix.WEXITED 0 then + out Unix.stdout "!!! reflector exited with an error\n" + +let test_swap12 () = (* swapping stdout and stderr *) + (* The test harness doesn't let us check contents of stderr, + so just output on stdout (after redirection) *) + let pid = + Unix.create_process + refl + [| refl; "e"; "123" |] + Unix.stdin Unix.stderr Unix.stdout in + let (_, status) = Unix.waitpid [] pid in + if status <> Unix.WEXITED 0 then + out Unix.stdout "!!! reflector exited with an error\n" + +let test_open_process_in () = + let ic = Unix.open_process_in (refl ^ " o 123 o 456") in + out Unix.stdout (input_line ic ^ "\n"); + out Unix.stdout (input_line ic ^ "\n"); + let status = Unix.close_process_in ic in + if status <> Unix.WEXITED 0 then + out Unix.stdout "!!! reflector exited with an error\n" + +let test_open_process_out () = + let oc = Unix.open_process_out (refl ^ " i2o i2o i2o") in + output_string oc "aa\nbbbb\n"; close_out oc; + let status = Unix.close_process_out oc in + if status <> Unix.WEXITED 0 then + out Unix.stdout "!!! reflector exited with an error\n" + +let test_open_process_full () = + let ((o, i, e) as res) = + Unix.open_process_full + (refl ^ " o 123 i2o e 456 i2e v XVAR") + [|"XVAR=xvar"|] in + output_string i "aa\nbbbb\n"; close_out i; + for _i = 1 to 3 do + out Unix.stdout (input_line o ^ "\n") + done; + for _i = 1 to 2 do + out Unix.stdout (input_line e ^ "\n") + done; + let status = Unix.close_process_full res in + if status <> Unix.WEXITED 0 then + out Unix.stdout "!!! reflector exited with an error\n" + +let _ = + (* The following 'close' makes things more difficult. + Under Unix it works fine, but under Win32 create_process + gives an error if one of the standard handles is closed. *) + (* Unix.close Unix.stdin; *) + out Unix.stdout "** create_process\n"; + test_createprocess(); + out Unix.stdout "** create_process 2>&1 redirection\n"; + test_2ampsup1(); + out Unix.stdout "** create_process swap 1-2\n"; + test_swap12(); + out Unix.stdout "** open_process_in\n"; + test_open_process_in(); + out Unix.stdout "** open_process_out\n"; + test_open_process_out(); + out Unix.stdout "** open_process_full\n"; + test_open_process_full() + + diff --git a/testsuite/tests/lib-unix/redirections.reference b/testsuite/tests/lib-unix/redirections.reference new file mode 100644 index 00000000..c0da174c --- /dev/null +++ b/testsuite/tests/lib-unix/redirections.reference @@ -0,0 +1,28 @@ +** create_process +---- File tmpout.txt +aaaa +123 + +xvar +---- File tmperr.txt +bbbb +456 +** create_process 2>&1 redirection +123 +456 +789 +** create_process swap 1-2 +123 +** open_process_in +123 +456 +** open_process_out +aa +bbbb + +** open_process_full +123 +aa +xvar +456 +bbbb diff --git a/testsuite/tests/lib-unix/reflector.c b/testsuite/tests/lib-unix/reflector.c new file mode 100644 index 00000000..f8bbbf31 --- /dev/null +++ b/testsuite/tests/lib-unix/reflector.c @@ -0,0 +1,74 @@ +#include +#include +#include +#if defined(_WIN32) +#include +#include +#endif + +/* A tool to read data from standard input and send it to standard + output or standard error. */ + +void copyline(FILE * in, FILE * out) +{ + int c; + do { + c = getc(in); + if (c == EOF) { + fputs("\n", out); + break; + } + putc(c, out); + } while (c != '\n'); + fflush(out); +} + +/* Command language: + i2o copy one line from stdin to stdout + i2e copy one line from stdin to stderr + o write plus newline to stdout + e write plus newline to stderr + v write value of environment variable to stdout +*/ + +int main(int argc, char ** argv) +{ + int i; + char * cmd; +#if defined(_WIN32) + _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdout), _O_BINARY); + _setmode(_fileno(stderr), _O_BINARY); +#endif + i = 1; + while (i < argc) { + cmd = argv[i]; + if (strcmp(cmd, "i2o") == 0) { + copyline(stdin, stdout); + i++; + } else if (strcmp(cmd, "i2e") == 0) { + copyline(stdin, stderr); + i++; + } else if (strcmp(cmd, "o") == 0 && i + 1 < argc) { + fputs(argv[i + 1], stdout); + fputc('\n', stdout); + fflush(stdout); + i += 2; + } else if (strcmp(cmd, "e") == 0 && i + 1 < argc) { + fputs(argv[i + 1], stderr); + fputc('\n', stderr); + fflush(stderr); + i += 2; + } else if (strcmp(cmd, "v") == 0 && i + 1 < argc) { + char * v = getenv(argv[i + 1]); + fputs((v == NULL ? "" : v), stdout); + fputc('\n', stdout); + fflush(stdout); + i += 2; + } else { + fputs("\n", stderr); + return 2; + } + } + return 0; +} diff --git a/testsuite/tests/lib-unix/test_unix_cmdline.ml b/testsuite/tests/lib-unix/test_unix_cmdline.ml new file mode 100644 index 00000000..f0f7679b --- /dev/null +++ b/testsuite/tests/lib-unix/test_unix_cmdline.ml @@ -0,0 +1,28 @@ +open Unix + +let prog_name = "cmdline_prog.exe" + +let run args = + let out, inp = pipe () in + let in_chan = in_channel_of_descr out in + set_binary_mode_in in_chan false; + let pid = create_process ("./" ^ prog_name) (Array.of_list (prog_name :: args)) Unix.stdin inp Unix.stderr in + List.iter (fun arg -> + let s = input_line in_chan in + Printf.printf "%S -> %S [%s]\n" arg s (if s = arg then "OK" else "FAIL") + ) args; + close_in in_chan; + let _, exit = waitpid [] pid in + assert (exit = WEXITED 0) + +let () = + List.iter run + [ + [""; ""; "\t \011"]; + ["a"; "b"; "c.txt@!"]; + ["\""]; + [" "; " a "; " \" \\\" "]; + [" \\ \\ \\\\\\"]; + [" \"hola \""]; + ["a\tb"]; + ] diff --git a/testsuite/tests/lib-unix/test_unix_cmdline.reference b/testsuite/tests/lib-unix/test_unix_cmdline.reference new file mode 100644 index 00000000..7d2f2c2a --- /dev/null +++ b/testsuite/tests/lib-unix/test_unix_cmdline.reference @@ -0,0 +1,13 @@ +"" -> "" [OK] +"" -> "" [OK] +"\t \011" -> "\t \011" [OK] +"a" -> "a" [OK] +"b" -> "b" [OK] +"c.txt@!" -> "c.txt@!" [OK] +"\"" -> "\"" [OK] +" " -> " " [OK] +" a " -> " a " [OK] +" \" \\\" " -> " \" \\\" " [OK] +" \\ \\ \\\\\\" -> " \\ \\ \\\\\\" [OK] +" \"hola \"" -> " \"hola \"" [OK] +"a\tb" -> "a\tb" [OK] diff --git a/testsuite/tests/link-test/Makefile b/testsuite/tests/link-test/Makefile index 8ac2e18b..ffef5988 100644 --- a/testsuite/tests/link-test/Makefile +++ b/testsuite/tests/link-test/Makefile @@ -14,7 +14,13 @@ #* * #************************************************************************** -default: byte native +default: + @$(MAKE) byte + @if $(BYTECODE_ONLY) ; then \ + echo " ... testing native 'test.reference': => skipped"; \ + else \ + $(MAKE) native; \ + fi native: @printf " ... testing native 'test.reference':" diff --git a/testsuite/tests/messages/Makefile b/testsuite/tests/messages/Makefile new file mode 100644 index 00000000..07f67998 --- /dev/null +++ b/testsuite/tests/messages/Makefile @@ -0,0 +1,3 @@ +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.expect +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/messages/precise_locations.ml b/testsuite/tests/messages/precise_locations.ml new file mode 100644 index 00000000..997cb86e --- /dev/null +++ b/testsuite/tests/messages/precise_locations.ml @@ -0,0 +1,93 @@ +type t = (unit, unit, unit, unit) bar +;; +(* PR#7315: we expect the error location on "bar" instead of "(...) bar" *) +[%%expect{| +Line _, characters 34-37: +Error: Unbound type constructor bar +|}];; + +function (x : +#bar) -> ();; +(* we expect the location on "bar" instead of "#bar" *) +[%%expect{| +Line _, characters 1-4: +Error: Unbound class bar +|}];; + +function +#bar -> () +;; +(* we expect the location on "bar" instead of "#bar" *) +[%%expect{| +Line _, characters 1-4: +Error: Unbound type constructor bar +|}];; + +new bar;; +(* we expect the location on "bar" instead of "new bar" *) +[%%expect{| +Line _, characters 4-7: +Error: Unbound class bar +|}];; + +type t = + | Foo of unit [@deprecated] + | Bar;; +#warnings "@3";; +let x = +Foo ();; +(* "Foo ()": the whole construct, with arguments, is deprecated *) +[%%expect{| +type t = Foo of unit | Bar +Line _, characters 0-6: +Warning 3: deprecated: Foo +Line _: +Error: Some fatal warnings were triggered (1 occurrences) +|}];; +function +Foo _ -> () | Bar -> ();; +(* "Foo _", the whole construct is deprecated *) +[%%expect{| +Line _, characters 0-5: +Warning 3: deprecated: Foo +Line _: +Error: Some fatal warnings were triggered (1 occurrences) +|}];; + + +open Foo;; +(* the error location should be on "Foo" *) +[%%expect{| +Line _, characters 5-8: +Error: Unbound module Foo +|}];; + +#warnings "@33";; (* unused open statement *) +include (struct +open List +end);; +(* here we expect the error location to be + on "open List" as whole rather than "List" *) +[%%expect{| +Line _, characters 0-9: +Warning 33: unused open List. +Line _: +Error: Some fatal warnings were triggered (1 occurrences) +|}];; + +type unknown += Foo;; +(* unknown, not the whole line *) +[%%expect{| +Line _, characters 5-12: +Error: Unbound type constructor unknown +|}];; + +type t = ..;; +type t += +Foo = Foobar;; +(* Foobar, not the whole line *) +[%%expect{| +type t = .. +Line _, characters 6-12: +Error: Unbound constructor Foobar +|}];; diff --git a/testsuite/tests/misc/gcwords.ml b/testsuite/tests/misc/gcwords.ml new file mode 100644 index 00000000..80ecd34e --- /dev/null +++ b/testsuite/tests/misc/gcwords.ml @@ -0,0 +1,24 @@ +type t = Leaf of int | Branch of t * t + +let a = [| 0.0 |] + +let rec allocate_lots m = function + | 0 -> Leaf m + | n -> Branch (allocate_lots m (n-1), allocate_lots (m+1) (n-1)) + +let measure f = + let a = Gc.minor_words () in + f (); + let c = Gc.minor_words () in + c -. a + +let () = + let n = measure (fun () -> a.(0) <- Gc.minor_words ()) in + (* Gc.minor_words should not allocate, although bytecode + generally boxes the floats *) + assert (n < 10.); + if Sys.backend_type = Sys.Native then assert (n = 0.); + let n = measure (fun () -> Sys.opaque_identity (allocate_lots 42 10)) in + (* This should allocate > 3k words (varying slightly by unboxing) *) + assert (n > 3000.); + print_endline "ok" diff --git a/testsuite/tests/misc/gcwords.reference b/testsuite/tests/misc/gcwords.reference new file mode 100644 index 00000000..9766475a --- /dev/null +++ b/testsuite/tests/misc/gcwords.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/parsetree/source.ml b/testsuite/tests/parsetree/source.ml index be2d5b9d..7742c599 100644 --- a/testsuite/tests/parsetree/source.ml +++ b/testsuite/tests/parsetree/source.ml @@ -7238,13 +7238,11 @@ class id = [%exp] let _ = fun (x : < x : int >) y z -> (y :> 'a), (x :> 'a), (z :> 'a);; (* - : (< x : int > as 'a) -> 'a -> 'a * 'a = *) -(* class ['a] c () = object method f = (new c (): int c) end and ['a] d () = object inherit ['a] c () end;; -*) (* PR#7329 Pattern open *) let _ = @@ -7254,3 +7252,25 @@ let _ = let h = function M.[] | M.[a] | M.(a::q) -> () in let i = function M.[||] | M.[|x|] -> true | _ -> false in () + +class ['a] c () = object + constraint 'a = < .. > -> unit + method m = (fun x -> () : 'a) +end + +let f: type a'.a' = assert false +let foo : type a' b'. a' -> b' = fun a -> assert false +let foo : type t' . t' = fun (type t') -> (assert false : t') +let foo : 't . 't = fun (type t) -> (assert false : t) +let foo : type a' b' c' t. a' -> b' -> c' -> t = fun a b c -> assert false + +let f x = + x.contents <- (print_string "coucou" ; x.contents) + +let ( ~$ ) x = Some x +let g x = + ~$ (x.contents) + +let ( ~$ ) x y = (x, y) +let g x y = + ~$ (x.contents) (y.contents) diff --git a/testsuite/tests/parsetree/test.ml b/testsuite/tests/parsetree/test.ml index ba8819db..86ed3c8c 100644 --- a/testsuite/tests/parsetree/test.ml +++ b/testsuite/tests/parsetree/test.ml @@ -1,5 +1,11 @@ (* (c) Alain Frisch / Lexifi *) (* cf. PR#7200 *) + +let diff = + match Array.to_list Sys.argv with + | [_; diff] -> diff + | _ -> "diff -u" + let report_err exn = match exn with | Sys_error msg -> @@ -69,7 +75,7 @@ let test parse_fun pprint print map filename = Printf.printf "%s: FAIL, REPARSED AST IS DIFFERENT\n%!" filename; let f1 = to_tmp_file print ast in let f2 = to_tmp_file print ast2 in - let cmd = Printf.sprintf "diff -u %s %s" + let cmd = Printf.sprintf "%s %s %s" diff (Filename.quote f1) (Filename.quote f2) in let _ret = Sys.command cmd in print_endline"=====================================================" diff --git a/testsuite/tests/regression/missing_set_of_closures/Makefile b/testsuite/tests/regression/missing_set_of_closures/Makefile new file mode 100644 index 00000000..9a1ba941 --- /dev/null +++ b/testsuite/tests/regression/missing_set_of_closures/Makefile @@ -0,0 +1,45 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Clerc, SED, INRIA Rocquencourt * +#* * +#* Copyright 2010 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +BASEDIR=../.. + +.PHONY: default +default: + @if $(BYTECODE_ONLY); then $(MAKE) skip ; else \ + $(MAKE) compile; \ + fi + +.PHONY: skip +skip: + @echo " ... testing 'missing_set_of_closures' => skipped" + +.PHONY: compile +compile: + @$(OCAMLOPT) -c a.ml + @$(OCAMLOPT) -c b.ml + @$(OCAMLOPT) -c b2.ml + @cp b.cmx b.cmi b2.cmx b2.cmi dir/ + @cd dir; printf " ... testing 'missing_set_of_closures'"; \ + $(OCAMLOPT) -w -58 -c c.ml \ + && echo " => passed" || echo " => failed"; \ + +.PHONY: promote +promote: + +.PHONY: clean +clean: defaultclean + @rm -f *.cmi *.cmx *.$(O) dir/*.cmi dir/*.cmx dir/*.$(O) + +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/regression/missing_set_of_closures/a.ml b/testsuite/tests/regression/missing_set_of_closures/a.ml new file mode 100644 index 00000000..c675669d --- /dev/null +++ b/testsuite/tests/regression/missing_set_of_closures/a.ml @@ -0,0 +1,9 @@ +module type Ret = sig + val g : int -> int -> int +end + +module F() : Ret = struct + let n = Sys.opaque_identity 42 + let rec f = ((fun x -> x + n) [@inline never]) + and g = ((fun x -> f) [@inline]) +end [@@inline never] diff --git a/testsuite/tests/regression/missing_set_of_closures/b.ml b/testsuite/tests/regression/missing_set_of_closures/b.ml new file mode 100644 index 00000000..e510a50c --- /dev/null +++ b/testsuite/tests/regression/missing_set_of_closures/b.ml @@ -0,0 +1,4 @@ + +let g = + let module X = A.F() in + X.g diff --git a/testsuite/tests/regression/missing_set_of_closures/b2.ml b/testsuite/tests/regression/missing_set_of_closures/b2.ml new file mode 100644 index 00000000..5436467a --- /dev/null +++ b/testsuite/tests/regression/missing_set_of_closures/b2.ml @@ -0,0 +1,2 @@ + +let f = B.g 3 diff --git a/testsuite/tests/regression/missing_set_of_closures/dir/c.ml b/testsuite/tests/regression/missing_set_of_closures/dir/c.ml new file mode 100644 index 00000000..e2ce54fe --- /dev/null +++ b/testsuite/tests/regression/missing_set_of_closures/dir/c.ml @@ -0,0 +1,2 @@ + +let f = B2.f diff --git a/otherlibs/str/Makefile.shared b/testsuite/tests/regression/pr7426/Makefile similarity index 65% rename from otherlibs/str/Makefile.shared rename to testsuite/tests/regression/pr7426/Makefile index b5010308..8b245519 100644 --- a/otherlibs/str/Makefile.shared +++ b/testsuite/tests/regression/pr7426/Makefile @@ -1,10 +1,10 @@ #************************************************************************** #* * -#* OCaml * +#* OCaml * #* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * #* * -#* Copyright 1999 Institut National de Recherche en Informatique et * +#* Copyright 2013 Institut National de Recherche en Informatique et * #* en Automatique. * #* * #* All rights reserved. This file is distributed under the terms of * @@ -13,20 +13,8 @@ #* * #************************************************************************** -# Makefile for the str library +MAIN_MODULE=pr7426 -LIBNAME=str -COBJS=strstubs.$(O) -CLIBNAME=camlstr -CAMLOBJS=str.cmo - -include ../Makefile - -str.cmo: str.cmi -str.cmx: str.cmi - -depend: - $(CC) -MM $(CFLAGS) *.c > .depend - $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend - -include .depend +BASEDIR=../../.. +include $(BASEDIR)/makefiles/Makefile.one +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/regression/pr7426/pr7426.ml b/testsuite/tests/regression/pr7426/pr7426.ml new file mode 100644 index 00000000..55aa4bfa --- /dev/null +++ b/testsuite/tests/regression/pr7426/pr7426.ml @@ -0,0 +1 @@ +class some_class = object val some_val = 0.0 end diff --git a/testsuite/tests/regression/pr7426/pr7426.reference b/testsuite/tests/regression/pr7426/pr7426.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/runtime-C-exceptions/Makefile b/testsuite/tests/runtime-C-exceptions/Makefile new file mode 100644 index 00000000..da534b75 --- /dev/null +++ b/testsuite/tests/runtime-C-exceptions/Makefile @@ -0,0 +1,7 @@ +BASEDIR=../.. +#MODULES= +MAIN_MODULE=test +C_FILES=stub_test + +include $(BASEDIR)/makefiles/Makefile.one +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/runtime-C-exceptions/stub_test.c b/testsuite/tests/runtime-C-exceptions/stub_test.c new file mode 100644 index 00000000..b7ffd242 --- /dev/null +++ b/testsuite/tests/runtime-C-exceptions/stub_test.c @@ -0,0 +1,20 @@ +#include +#include "caml/memory.h" +#include "caml/alloc.h" +#include "caml/mlvalues.h" +#include "caml/fail.h" + +char *some_dynamic_string_that_should_be_freed() +{ + return strdup("bar"); +} + +CAMLexport value dynamic_invalid_argument(value unit) +{ + CAMLparam1(unit); + char *dynamic_msg = some_dynamic_string_that_should_be_freed(); + value msg = caml_copy_string(dynamic_msg); + free(dynamic_msg); + caml_invalid_argument_value(msg); + CAMLnoreturn; +} diff --git a/testsuite/tests/runtime-C-exceptions/test.ml b/testsuite/tests/runtime-C-exceptions/test.ml new file mode 100644 index 00000000..794e27cb --- /dev/null +++ b/testsuite/tests/runtime-C-exceptions/test.ml @@ -0,0 +1,11 @@ +external failwith_from_ocaml : string -> 'a = "caml_failwith_value" + +external dynamic_invalid_argument : unit -> 'a = "dynamic_invalid_argument" + +let () = + try failwith_from_ocaml ("fo" ^ "o") + with Failure foo -> print_endline foo + +let () = + try dynamic_invalid_argument () + with Invalid_argument bar -> print_endline bar diff --git a/testsuite/tests/runtime-C-exceptions/test.reference b/testsuite/tests/runtime-C-exceptions/test.reference new file mode 100644 index 00000000..3bd1f0e2 --- /dev/null +++ b/testsuite/tests/runtime-C-exceptions/test.reference @@ -0,0 +1,2 @@ +foo +bar diff --git a/testsuite/tests/tool-command-line/Makefile b/testsuite/tests/tool-command-line/Makefile new file mode 100644 index 00000000..148dafa2 --- /dev/null +++ b/testsuite/tests/tool-command-line/Makefile @@ -0,0 +1,54 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Bernhard Schommer * +#* * +#* Copyright 2010 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +BASEDIR=../.. + + +default: + @$(MAKE) byte + @if $(BYTECODE_ONLY); then $(MAKE) opt-skipped ; else \ + $(MAKE) opt; \ + fi + +byte: + @$(OCAMLC) unknown-file 2>&1 | grep "don't know what to do with unknown-file" \ + > unknown-file.byte.result || true + @for file in *.byte.reference; do \ + printf " ... testing '$$file':"; \ + $(DIFF) $$file `basename $$file reference`result >/dev/null \ + && echo " => passed" || echo " => failed"; \ + done + +opt: + @$(OCAMLOPT) unknown-file 2>&1 | grep "don't know what to do with unknown-file"\ + > unknown-file.opt.result || true + @for file in *.opt.reference; do \ + printf " ... testing '$$file':"; \ + $(DIFF) $$file `basename $$file reference`result >/dev/null \ + && echo " => passed" || echo " => failed"; \ + done + +opt-skipped: + @for file in *.opt.reference; do \ + printf " ... testing '$$file':"; \ + echo " => skipped"; \ + done + +promote: defaultpromote + +clean: defaultclean + @rm -f *.result + +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/tool-command-line/unknown-file b/testsuite/tests/tool-command-line/unknown-file new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/tool-command-line/unknown-file.byte.reference b/testsuite/tests/tool-command-line/unknown-file.byte.reference new file mode 100644 index 00000000..9182c8a7 --- /dev/null +++ b/testsuite/tests/tool-command-line/unknown-file.byte.reference @@ -0,0 +1 @@ +don't know what to do with unknown-file diff --git a/testsuite/tests/tool-command-line/unknown-file.opt.reference b/testsuite/tests/tool-command-line/unknown-file.opt.reference new file mode 100644 index 00000000..9182c8a7 --- /dev/null +++ b/testsuite/tests/tool-command-line/unknown-file.opt.reference @@ -0,0 +1 @@ +don't know what to do with unknown-file diff --git a/testsuite/tests/tool-debugger/find-artifacts/Makefile b/testsuite/tests/tool-debugger/find-artifacts/Makefile index 84201111..13fe316a 100644 --- a/testsuite/tests/tool-debugger/find-artifacts/Makefile +++ b/testsuite/tests/tool-debugger/find-artifacts/Makefile @@ -53,7 +53,7 @@ run: program.byte$(EXE) >$(MAIN_MODULE).raw.result 2>&1 \ && sed -e '/Debugger version/d' -e '/^Time:/d' \ -e '/Breakpoint [0-9]* at [0-9]*:/d' -e '$$d' \ - $(MAIN_MODULE).raw.result >$(MAIN_MODULE).result \ + $(MAIN_MODULE).raw.result | tr -d '\r' >$(MAIN_MODULE).result \ && $(DIFF) $(MAIN_MODULE).reference $(MAIN_MODULE).result >/dev/null \ && echo " => passed" || echo " => failed" diff --git a/testsuite/tests/tool-ocamlc-open/Makefile b/testsuite/tests/tool-ocamlc-open/Makefile new file mode 100644 index 00000000..4e2c52d3 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-open/Makefile @@ -0,0 +1,14 @@ +BASEDIR=../.. + +compile: + @printf " ... testing 'foo.ml'" + @$(OCAMLC) -c a.ml + @$(OCAMLC) -open A.M -c b.ml \ + && echo " => passed" || echo " => failed" + +promote: + +clean: + @rm -f a.cmi a.cmo b.cmi b.cmo + +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/tool-ocamlc-open/a.ml b/testsuite/tests/tool-ocamlc-open/a.ml new file mode 100644 index 00000000..4ae15f14 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-open/a.ml @@ -0,0 +1,3 @@ +module M = struct + let f x = x +1 +end diff --git a/testsuite/tests/tool-ocamlc-open/b.ml b/testsuite/tests/tool-ocamlc-open/b.ml new file mode 100644 index 00000000..6c781576 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-open/b.ml @@ -0,0 +1 @@ +let g = f diff --git a/testsuite/tests/tool-ocamldoc-2/Makefile b/testsuite/tests/tool-ocamldoc-2/Makefile index ff155cf1..863c72c5 100644 --- a/testsuite/tests/tool-ocamldoc-2/Makefile +++ b/testsuite/tests/tool-ocamldoc-2/Makefile @@ -33,11 +33,12 @@ default: fi .PHONY: run -run: *.ml *.mli - @for file in *.mli *.ml; do \ +run: *.ml *.mli *.txt + @for file in *.mli *.ml *.txt; do \ printf " ... testing '$$file'"; \ F="`basename $$file .mli`"; \ F="`basename $$F .ml`"; \ + F="`basename $$F .txt`"; \ $(OCAMLDOC) $(DOCFLAGS) -hide-warnings -latex $ \ -o $$F.result $$file; \ $(DIFF) $$F.reference $$F.result >/dev/null \ diff --git a/testsuite/tests/tool-ocamldoc-2/inline_records.reference b/testsuite/tests/tool-ocamldoc-2/inline_records.reference index 84cfb9af..ff444001 100644 --- a/testsuite/tests/tool-ocamldoc-2/inline_records.reference +++ b/testsuite/tests/tool-ocamldoc-2/inline_records.reference @@ -33,7 +33,6 @@ A nice exception \begin{ocamldoccode} exception Less of int - \end{ocamldoccode} \index{Less@\verb`Less`} \begin{ocamldocdescription} @@ -221,7 +220,6 @@ Error field documentation {\tt{name:string}} \end{ocamldoccomment} \begin{ocamldoccode} {\char125} - \end{ocamldoccode} \index{Error@\verb`Error`} @@ -241,7 +239,6 @@ Field documentation for {\tt{E}} in ext \end{ocamldoccomment} \begin{ocamldoccode} {\char125} - \end{ocamldoccode} \begin{ocamldoccomment} Constructor E documentation @@ -258,7 +255,6 @@ Some field documentations for {\tt{F}} \end{ocamldoccomment} \begin{ocamldoccode} {\char125} - \end{ocamldoccode} \begin{ocamldoccomment} Constructor F documentation @@ -275,7 +271,6 @@ The last and least field documentation \end{ocamldoccomment} \begin{ocamldoccode} {\char125} - \end{ocamldoccode} \begin{ocamldoccomment} Constructor G documentation diff --git a/testsuite/tests/tool-ocamldoc-2/inline_records_bis.reference b/testsuite/tests/tool-ocamldoc-2/inline_records_bis.reference index 6524f488..091b0f0e 100644 --- a/testsuite/tests/tool-ocamldoc-2/inline_records_bis.reference +++ b/testsuite/tests/tool-ocamldoc-2/inline_records_bis.reference @@ -33,7 +33,6 @@ A nice exception \begin{ocamldoccode} exception Less of int - \end{ocamldoccode} \index{Less@\verb`Less`} \begin{ocamldocdescription} @@ -221,7 +220,6 @@ Error field documentation {\tt{name:string}} \end{ocamldoccomment} \begin{ocamldoccode} {\char125} - \end{ocamldoccode} \index{Error@\verb`Error`} @@ -241,7 +239,6 @@ Field documentation for {\tt{E}} in ext \end{ocamldoccomment} \begin{ocamldoccode} {\char125} - \end{ocamldoccode} \begin{ocamldoccomment} Constructor E documentation @@ -258,7 +255,6 @@ Some field documentations for {\tt{F}} \end{ocamldoccomment} \begin{ocamldoccode} {\char125} - \end{ocamldoccode} \begin{ocamldoccomment} Constructor F documentation @@ -275,7 +271,6 @@ The last and least field documentation \end{ocamldoccomment} \begin{ocamldoccode} {\char125} - \end{ocamldoccode} \begin{ocamldoccomment} Constructor G documentation diff --git a/testsuite/tests/tool-ocamldoc-2/loop.ml b/testsuite/tests/tool-ocamldoc-2/loop.ml new file mode 100644 index 00000000..b0306b76 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/loop.ml @@ -0,0 +1,3 @@ + +module rec A : sig type t end = B and B : sig type t = A.t end = A;; + diff --git a/testsuite/tests/tool-ocamldoc-2/loop.reference b/testsuite/tests/tool-ocamldoc-2/loop.reference new file mode 100644 index 00000000..f9d6b437 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/loop.reference @@ -0,0 +1,36 @@ +\documentclass[11pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{textcomp} +\usepackage{fullpage} +\usepackage{url} +\usepackage{ocamldoc} +\begin{document} +\tableofcontents +\section{Module {\tt{Loop}}} +\label{Loop}\index{Loop@\verb`Loop`} + + +\ocamldocvspace{0.5cm} + + + +\begin{ocamldoccode} +{\tt{module }}{\tt{A}}{\tt{ : }}\end{ocamldoccode} +\label{Loop.A}\index{A@\verb`A`} + +{\tt{B}} + + + + + +\begin{ocamldoccode} +{\tt{module }}{\tt{B}}{\tt{ : }}\end{ocamldoccode} +\label{Loop.B}\index{B@\verb`B`} + +{\tt{A}} + + + +\end{document} \ No newline at end of file diff --git a/testsuite/tests/tool-ocamldoc-2/short_description.reference b/testsuite/tests/tool-ocamldoc-2/short_description.reference new file mode 100644 index 00000000..5ffb6075 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/short_description.reference @@ -0,0 +1,21 @@ +\documentclass[11pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{textcomp} +\usepackage{fullpage} +\usepackage{url} +\usepackage{ocamldoc} +\begin{document} +\tableofcontents +\section{Short\_description : Short global description in text mode} +\label{Short-underscoredescription}\index{Short-underscoredescription@\verb`Short_description`} + + + +This file tests that documentation in text mode are given +a short description in the global description of modules. + + + + +\end{document} \ No newline at end of file diff --git a/testsuite/tests/tool-ocamldoc-2/short_description.txt b/testsuite/tests/tool-ocamldoc-2/short_description.txt new file mode 100644 index 00000000..7241f875 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/short_description.txt @@ -0,0 +1,4 @@ +Short global description in text mode + +This file tests that documentation in text mode are given +a short description in the global description of modules. diff --git a/testsuite/tests/tool-ocamldoc-2/variants.mli b/testsuite/tests/tool-ocamldoc-2/variants.mli new file mode 100644 index 00000000..7562a0b8 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/variants.mli @@ -0,0 +1,38 @@ +(** This test is here to check the latex code generated for variants *) + +type s = A | B (** only B is documented here *) | C + +type t = + | A + (** doc for A *) + | B + (** doc for B *) + +(** Some documentation for u*) +type u = +| A (** doc for A *) | B of unit (** doc for B *) + + +(** With records *) +type w = +| A of { x: int } + (** doc for A *) +| B of { y:int } + (** doc for B *) + +(** With args *) +type z = +| A of int + (** doc for A *) +| B of int + (** doc for B *) + +(** Gadt notation *) +type a = + A: a (** doc for A*) + +(** Lonely constructor *) +type b = + B (** doc for B *) + +type no_documentation = A | B | C diff --git a/testsuite/tests/tool-ocamldoc-2/variants.reference b/testsuite/tests/tool-ocamldoc-2/variants.reference new file mode 100644 index 00000000..bb9e7601 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/variants.reference @@ -0,0 +1,190 @@ +\documentclass[11pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{textcomp} +\usepackage{fullpage} +\usepackage{url} +\usepackage{ocamldoc} +\begin{document} +\tableofcontents +\section{Module {\tt{Variants}} : This test is here to check the latex code generated for variants} +\label{Variants}\index{Variants@\verb`Variants`} + + + + +\ocamldocvspace{0.5cm} + + + +\label{TYPVariants.s}\begin{ocamldoccode} +type s = + | A + | B +\end{ocamldoccode} +\begin{ocamldoccomment} +only B is documented here + + +\end{ocamldoccomment} +\begin{ocamldoccode} + | C +\end{ocamldoccode} +\index{s@\verb`s`} + + + + +\label{TYPVariants.t}\begin{ocamldoccode} +type t = + | A +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for A + + +\end{ocamldoccomment} +\begin{ocamldoccode} + | B +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for B + + +\end{ocamldoccomment} +\index{t@\verb`t`} + + + + +\label{TYPVariants.u}\begin{ocamldoccode} +type u = + | A +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for A + + +\end{ocamldoccomment} +\begin{ocamldoccode} + | B of unit +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for B + + +\end{ocamldoccomment} +\index{u@\verb`u`} +\begin{ocamldocdescription} +Some documentation for u + + +\end{ocamldocdescription} + + + + +\label{TYPVariants.w}\begin{ocamldoccode} +type w = + | A of {\char123} x : int ; +{\char125} +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for A + + +\end{ocamldoccomment} +\begin{ocamldoccode} + | B of {\char123} y : int ; +{\char125} +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for B + + +\end{ocamldoccomment} +\index{w@\verb`w`} +\begin{ocamldocdescription} +With records + + +\end{ocamldocdescription} + + + + +\label{TYPVariants.z}\begin{ocamldoccode} +type z = + | A of int +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for A + + +\end{ocamldoccomment} +\begin{ocamldoccode} + | B of int +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for B + + +\end{ocamldoccomment} +\index{z@\verb`z`} +\begin{ocamldocdescription} +With args + + +\end{ocamldocdescription} + + + + +\label{TYPVariants.a}\begin{ocamldoccode} +type a = + | A : a +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for A + + +\end{ocamldoccomment} +\index{a@\verb`a`} +\begin{ocamldocdescription} +Gadt notation + + +\end{ocamldocdescription} + + + + +\label{TYPVariants.b}\begin{ocamldoccode} +type b = + | B +\end{ocamldoccode} +\begin{ocamldoccomment} +doc for B + + +\end{ocamldoccomment} +\index{b@\verb`b`} +\begin{ocamldocdescription} +Lonely constructor + + +\end{ocamldocdescription} + + + + +\label{TYPVariants.no-underscoredocumentation}\begin{ocamldoccode} +type no_documentation = + | A + | B + | C +\end{ocamldoccode} +\index{no-underscoredocumentation@\verb`no_documentation`} + + +\end{document} \ No newline at end of file diff --git a/testsuite/tests/tool-ocamldoc-html/Loop.ml b/testsuite/tests/tool-ocamldoc-html/Loop.ml new file mode 100644 index 00000000..b0306b76 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-html/Loop.ml @@ -0,0 +1,3 @@ + +module rec A : sig type t end = B and B : sig type t = A.t end = A;; + diff --git a/testsuite/tests/tool-ocamldoc-html/Loop.reference b/testsuite/tests/tool-ocamldoc-html/Loop.reference new file mode 100644 index 00000000..235b4775 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-html/Loop.reference @@ -0,0 +1,20 @@ + + + + + + + + + +Loop + + + +

Module Loop

+ +
module Loop: sig .. end

+ +
module A: B
+
module B: A
\ No newline at end of file diff --git a/testsuite/tests/tool-ocamldoc-html/Makefile b/testsuite/tests/tool-ocamldoc-html/Makefile index c9160b4a..116b580b 100644 --- a/testsuite/tests/tool-ocamldoc-html/Makefile +++ b/testsuite/tests/tool-ocamldoc-html/Makefile @@ -33,10 +33,12 @@ default: fi .PHONY: run -run: *.mli - @for file in *.mli; do \ +run: *.mli *.ml +# Note that we strip both .ml and .mli extensions + @for file in *.ml *.mli; do \ printf " ... testing '$$file'"; \ F="`basename $$file .mli`"; \ + F="`basename $$F .ml`"; \ $(OCAMLDOC) $(DOCFLAGS) -colorize-code -hide-warnings -html $ \ -o index $$file; \ cp $$F.html $$F.result; \ @@ -44,7 +46,7 @@ run: *.mli && echo " => passed" || echo " => failed"; \ done;\ # For linebreaks.mli, we also compare type_Linebreaks.html and not only -# themain html file +# the main html file @cp type_Linebreaks.html type_Linebreaks.result;\ printf " ... testing 'type_Linebreak.html'";\ $(DIFF) type_Linebreaks.reference type_Linebreaks.result\ diff --git a/testsuite/tests/tool-ocamldoc-html/Module_whitespace.ml b/testsuite/tests/tool-ocamldoc-html/Module_whitespace.ml new file mode 100644 index 00000000..d9ddee7b --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-html/Module_whitespace.ml @@ -0,0 +1,4 @@ +module M = Set.Make(struct + type t = int + let compare = compare +end) diff --git a/testsuite/tests/tool-ocamldoc-html/Module_whitespace.reference b/testsuite/tests/tool-ocamldoc-html/Module_whitespace.reference new file mode 100644 index 00000000..4691b2d4 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-html/Module_whitespace.reference @@ -0,0 +1,24 @@ + + + + + + + + + +Module_whitespace + + + +

Module Module_whitespace

+ +
module Module_whitespace: sig .. end

+ +
module M: Set.Make(sig
+
type t = int 
+ + +
val compare : 'a -> 'a -> int
+
end)
\ No newline at end of file diff --git a/testsuite/tests/tool-ocamldoc-html/Variants.mli b/testsuite/tests/tool-ocamldoc-html/Variants.mli new file mode 100644 index 00000000..7562a0b8 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-html/Variants.mli @@ -0,0 +1,38 @@ +(** This test is here to check the latex code generated for variants *) + +type s = A | B (** only B is documented here *) | C + +type t = + | A + (** doc for A *) + | B + (** doc for B *) + +(** Some documentation for u*) +type u = +| A (** doc for A *) | B of unit (** doc for B *) + + +(** With records *) +type w = +| A of { x: int } + (** doc for A *) +| B of { y:int } + (** doc for B *) + +(** With args *) +type z = +| A of int + (** doc for A *) +| B of int + (** doc for B *) + +(** Gadt notation *) +type a = + A: a (** doc for A*) + +(** Lonely constructor *) +type b = + B (** doc for B *) + +type no_documentation = A | B | C diff --git a/testsuite/tests/tool-ocamldoc-html/Variants.reference b/testsuite/tests/tool-ocamldoc-html/Variants.reference new file mode 100644 index 00000000..12bd44e7 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-html/Variants.reference @@ -0,0 +1,232 @@ + + + + + + + + + + +Variants + + + +

Module Variants

+ +
module Variants: sig .. end
+This test is here to check the latex code generated for variants
+
+
+ +
type s = 
+ + + + + + + + + + + + + + +
+| +A
+| +B(*
+only B is documented here
+
+
*)
+| +C
+ + + +
type t = 
+ + + + + + + + + +
+| +A(*
+doc for A
+
+
*)
+| +B(*
+doc for B
+
+
*)
+ + + +
type u = 
+ + + + + + + + + +
+| +A(*
+doc for A
+
+
*)
+| +B of unit(*
+doc for B
+
+
*)
+ +
+Some documentation for u
+
+ + +
type w = 
+ + + + + + + + + +
+| +A of { + + + + +
+   +x : int;
+} +
(*
+doc for A
+
+
*)
+| +B of { + + + + +
+   +y : int;
+} +
(*
+doc for B
+
+
*)
+ +
+With records
+
+ + +
type z = 
+ + + + + + + + + +
+| +A of int(*
+doc for A
+
+
*)
+| +B of int(*
+doc for B
+
+
*)
+ +
+With args
+
+ + +
type a = 
+ + + + +
+| +A : a(*
+doc for A
+
+
*)
+ +
+Gadt notation
+
+ + +
type b = 
+ + + + +
+| +B(*
+doc for B
+
+
*)
+ +
+Lonely constructor
+
+ + +
type no_documentation = 
+ + + + + + + + + + + + + + +
+| +A
+| +B
+| +C
+ + + \ No newline at end of file diff --git a/testsuite/tests/tool-ocamldoc-open/Makefile b/testsuite/tests/tool-ocamldoc-open/Makefile index f54566af..92f09a1d 100644 --- a/testsuite/tests/tool-ocamldoc-open/Makefile +++ b/testsuite/tests/tool-ocamldoc-open/Makefile @@ -33,7 +33,7 @@ alias.odoc: inner.cmi alias.ml main.odoc: alias.cmi main.ml @$(OCAMLDOC) $(DOCFLAGS) -hide-warnings \ - -open Alias -open Aliased_inner -dump main.odoc main.ml + -open Alias.Container -open Aliased_inner -dump main.odoc main.ml alias.cmi:inner.cmi diff --git a/testsuite/tests/tool-ocamldoc-open/alias.ml b/testsuite/tests/tool-ocamldoc-open/alias.ml index 50a8f4fa..e3e81842 100644 --- a/testsuite/tests/tool-ocamldoc-open/alias.ml +++ b/testsuite/tests/tool-ocamldoc-open/alias.ml @@ -1 +1,3 @@ -module Aliased_inner = Inner +module Container = struct + module Aliased_inner = Inner +end diff --git a/testsuite/tests/tool-ocamldoc-open/doc.reference b/testsuite/tests/tool-ocamldoc-open/doc.reference index c372d156..19419f9b 100644 --- a/testsuite/tests/tool-ocamldoc-open/doc.reference +++ b/testsuite/tests/tool-ocamldoc-open/doc.reference @@ -16,11 +16,20 @@ \begin{ocamldoccode} -{\tt{module }}{\tt{Aliased\_inner}}{\tt{ : }}\end{ocamldoccode} -\label{module:Alias.Aliased-underscoreinner}\index{Aliased-underscoreinner@\verb`Aliased_inner`} +{\tt{module }}{\tt{Container}}{\tt{ : }}\end{ocamldoccode} +\label{module:Alias.Container}\index{Container@\verb`Container`} + +\begin{ocamldocsigend} + +\begin{ocamldoccode} +{\tt{module }}{\tt{Aliased\_inner}}{\tt{ : }}\end{ocamldoccode} +\label{module:Alias.Container.Aliased-underscoreinner}\index{Aliased-underscoreinner@\verb`Aliased_inner`} {\tt{Inner}} +\end{ocamldocsigend} + + \section{Module {\tt{Inner}}} @@ -48,7 +57,7 @@ type a = int \label{type:Main.t}\begin{ocamldoccode} -type t = Alias.Aliased_inner.a +type t = Alias.Container.Aliased_inner.a \end{ocamldoccode} \index{t@\verb`t`} \begin{ocamldocdescription} diff --git a/testsuite/tests/tool-ocamldoc/t05.ml b/testsuite/tests/tool-ocamldoc/t05.ml new file mode 100644 index 00000000..b0306b76 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc/t05.ml @@ -0,0 +1,3 @@ + +module rec A : sig type t end = B and B : sig type t = A.t end = A;; + diff --git a/testsuite/tests/tool-ocamldoc/t05.reference b/testsuite/tests/tool-ocamldoc/t05.reference new file mode 100644 index 00000000..4a043e39 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc/t05.reference @@ -0,0 +1,6 @@ +# +# module T05: +# +# module T05.A: +# +# module T05.B: diff --git a/testsuite/tests/tool-toplevel-invocation/Makefile b/testsuite/tests/tool-toplevel-invocation/Makefile new file mode 100644 index 00000000..31db2c3f --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/Makefile @@ -0,0 +1,36 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Bernhard Schommer * +#* * +#* Copyright 2010 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +BASEDIR=../.. + + +default: + @for file in *.txt; do \ + TERM=dumb $(OCAML) -args $$file < test.ml 2>&1 \ + | grep -v '^ OCaml version' > $$file.result; \ + done + @for file in *.reference; do \ + printf " ... testing '$$file':"; \ + $(DIFF) $$file `basename $$file reference`result >/dev/null \ + && echo " => passed" || echo " => failed"; \ + done + + +promote: defaultpromote + +clean: defaultclean + @rm -f *.result + +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/tool-toplevel-invocation/first_arg_fail.txt b/testsuite/tests/tool-toplevel-invocation/first_arg_fail.txt new file mode 100644 index 00000000..740a834a --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/first_arg_fail.txt @@ -0,0 +1,3 @@ +test.ml +-I +../ diff --git a/testsuite/tests/tool-toplevel-invocation/first_arg_fail.txt.reference b/testsuite/tests/tool-toplevel-invocation/first_arg_fail.txt.reference new file mode 100644 index 00000000..b49ea22c --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/first_arg_fail.txt.reference @@ -0,0 +1 @@ +For implementation reasons, the toplevel does not support having script files (here "test.ml") inside expanded arguments passed through the -args{,0} command-line option. diff --git a/testsuite/tests/tool-toplevel-invocation/indirect_first_arg_fail.txt b/testsuite/tests/tool-toplevel-invocation/indirect_first_arg_fail.txt new file mode 100644 index 00000000..25ac50da --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/indirect_first_arg_fail.txt @@ -0,0 +1,2 @@ +-args +first_arg_fail.txt diff --git a/testsuite/tests/tool-toplevel-invocation/indirect_first_arg_fail.txt.reference b/testsuite/tests/tool-toplevel-invocation/indirect_first_arg_fail.txt.reference new file mode 100644 index 00000000..b49ea22c --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/indirect_first_arg_fail.txt.reference @@ -0,0 +1 @@ +For implementation reasons, the toplevel does not support having script files (here "test.ml") inside expanded arguments passed through the -args{,0} command-line option. diff --git a/testsuite/tests/tool-toplevel-invocation/indirect_last_arg_fail.txt b/testsuite/tests/tool-toplevel-invocation/indirect_last_arg_fail.txt new file mode 100644 index 00000000..7847f963 --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/indirect_last_arg_fail.txt @@ -0,0 +1,2 @@ +-args +last_arg_fail.txt diff --git a/testsuite/tests/tool-toplevel-invocation/indirect_last_arg_fail.txt.reference b/testsuite/tests/tool-toplevel-invocation/indirect_last_arg_fail.txt.reference new file mode 100644 index 00000000..b49ea22c --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/indirect_last_arg_fail.txt.reference @@ -0,0 +1 @@ +For implementation reasons, the toplevel does not support having script files (here "test.ml") inside expanded arguments passed through the -args{,0} command-line option. diff --git a/testsuite/tests/tool-toplevel-invocation/last_arg_fail.txt b/testsuite/tests/tool-toplevel-invocation/last_arg_fail.txt new file mode 100644 index 00000000..764d630e --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/last_arg_fail.txt @@ -0,0 +1,3 @@ +-I +../ +test.ml diff --git a/testsuite/tests/tool-toplevel-invocation/last_arg_fail.txt.reference b/testsuite/tests/tool-toplevel-invocation/last_arg_fail.txt.reference new file mode 100644 index 00000000..b49ea22c --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/last_arg_fail.txt.reference @@ -0,0 +1 @@ +For implementation reasons, the toplevel does not support having script files (here "test.ml") inside expanded arguments passed through the -args{,0} command-line option. diff --git a/testsuite/tests/tool-toplevel-invocation/test.ml b/testsuite/tests/tool-toplevel-invocation/test.ml new file mode 100644 index 00000000..03b03d71 --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/test.ml @@ -0,0 +1 @@ +printf "Test succeeds\n";; diff --git a/testsuite/tests/tool-toplevel-invocation/working_arg.txt b/testsuite/tests/tool-toplevel-invocation/working_arg.txt new file mode 100644 index 00000000..7c42c092 --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/working_arg.txt @@ -0,0 +1,2 @@ +-open +Printf diff --git a/testsuite/tests/tool-toplevel-invocation/working_arg.txt.reference b/testsuite/tests/tool-toplevel-invocation/working_arg.txt.reference new file mode 100644 index 00000000..2438811a --- /dev/null +++ b/testsuite/tests/tool-toplevel-invocation/working_arg.txt.reference @@ -0,0 +1,4 @@ + +# Test succeeds +- : unit = () +# diff --git a/testsuite/tests/tool-toplevel/Makefile b/testsuite/tests/tool-toplevel/Makefile index 7fc00661..17a9c8e3 100644 --- a/testsuite/tests/tool-toplevel/Makefile +++ b/testsuite/tests/tool-toplevel/Makefile @@ -16,3 +16,4 @@ BASEDIR=../.. include $(BASEDIR)/makefiles/Makefile.toplevel include $(BASEDIR)/makefiles/Makefile.common +TOPFLAGS+=-I $(OTOPDIR)/toplevel diff --git a/testsuite/tests/tool-toplevel/pr7060.ml b/testsuite/tests/tool-toplevel/pr7060.ml new file mode 100644 index 00000000..67c11a47 --- /dev/null +++ b/testsuite/tests/tool-toplevel/pr7060.ml @@ -0,0 +1,6 @@ +type t = A | B;; +type u = C of t;; +let print_t out = function A -> Format.fprintf out "A";; +#install_printer print_t;; +B;; +C B;; diff --git a/testsuite/tests/tool-toplevel/pr7060.ml.reference b/testsuite/tests/tool-toplevel/pr7060.ml.reference new file mode 100644 index 00000000..bdfca395 --- /dev/null +++ b/testsuite/tests/tool-toplevel/pr7060.ml.reference @@ -0,0 +1,16 @@ + +# type t = A | B +# type u = C of t +# Characters 18-54: + let print_t out = function A -> Format.fprintf out "A";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +B +val print_t : Format.formatter -> t -> unit = +# # - : t = + +# - : u = +C + +# diff --git a/testsuite/tests/translprim/array_spec.ml.reference b/testsuite/tests/translprim/array_spec.ml.reference index 7b48cfdd..83fe0c4c 100644 --- a/testsuite/tests/translprim/array_spec.ml.reference +++ b/testsuite/tests/translprim/array_spec.ml.reference @@ -22,60 +22,60 @@ (function a x (array.unsafe_set[gen] a 0 x)) (let (eta_gen_len = - (function prim (array.length[gen] prim)) + (function prim stub (array.length[gen] prim)) eta_gen_safe_get = - (function prim prim + (function prim prim stub (array.get[gen] prim prim)) eta_gen_unsafe_get = - (function prim prim + (function prim prim stub (array.unsafe_get[gen] prim prim)) eta_gen_safe_set = - (function prim prim prim + (function prim prim prim stub (array.set[gen] prim prim prim)) eta_gen_unsafe_set = - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[gen] prim prim prim)) eta_int_len = - (function prim (array.length[int] prim)) + (function prim stub (array.length[int] prim)) eta_int_safe_get = - (function prim prim + (function prim prim stub (array.get[int] prim prim)) eta_int_unsafe_get = - (function prim prim + (function prim prim stub (array.unsafe_get[int] prim prim)) eta_int_safe_set = - (function prim prim prim + (function prim prim prim stub (array.set[int] prim prim prim)) eta_int_unsafe_set = - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[int] prim prim prim)) eta_float_len = - (function prim (array.length[float] prim)) + (function prim stub (array.length[float] prim)) eta_float_safe_get = - (function prim prim + (function prim prim stub (array.get[float] prim prim)) eta_float_unsafe_get = - (function prim prim + (function prim prim stub (array.unsafe_get[float] prim prim)) eta_float_safe_set = - (function prim prim prim + (function prim prim prim stub (array.set[float] prim prim prim)) eta_float_unsafe_set = - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[float] prim prim prim)) eta_addr_len = - (function prim (array.length[addr] prim)) + (function prim stub (array.length[addr] prim)) eta_addr_safe_get = - (function prim prim + (function prim prim stub (array.get[addr] prim prim)) eta_addr_unsafe_get = - (function prim prim + (function prim prim stub (array.unsafe_get[addr] prim prim)) eta_addr_safe_set = - (function prim prim prim + (function prim prim prim stub (array.set[addr] prim prim prim)) eta_addr_unsafe_set = - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[addr] prim prim prim))) (makeblock 0 int_a float_a addr_a eta_gen_len eta_gen_safe_get eta_gen_unsafe_get eta_gen_safe_set diff --git a/testsuite/tests/translprim/comparison_table.ml.reference b/testsuite/tests/translprim/comparison_table.ml.reference index 525ff898..e0401632 100644 --- a/testsuite/tests/translprim/comparison_table.ml.reference +++ b/testsuite/tests/translprim/comparison_table.ml.reference @@ -81,139 +81,150 @@ nativeint_ge = (function x y (Nativeint.>= x y)) eta_gen_cmp = - (function prim prim (caml_compare prim prim)) + (function prim prim stub (caml_compare prim prim)) eta_int_cmp = - (function prim prim (caml_int_compare prim prim)) + (function prim prim stub + (caml_int_compare prim prim)) eta_bool_cmp = - (function prim prim (caml_int_compare prim prim)) + (function prim prim stub + (caml_int_compare prim prim)) eta_intlike_cmp = - (function prim prim (caml_int_compare prim prim)) + (function prim prim stub + (caml_int_compare prim prim)) eta_float_cmp = - (function prim prim + (function prim prim stub (caml_float_compare prim prim)) eta_string_cmp = - (function prim prim + (function prim prim stub (caml_string_compare prim prim)) eta_int32_cmp = - (function prim prim + (function prim prim stub (caml_int32_compare prim prim)) eta_int64_cmp = - (function prim prim + (function prim prim stub (caml_int64_compare prim prim)) eta_nativeint_cmp = - (function prim prim + (function prim prim stub (caml_nativeint_compare prim prim)) eta_gen_eq = - (function prim prim (caml_equal prim prim)) + (function prim prim stub (caml_equal prim prim)) eta_int_eq = - (function prim prim (== prim prim)) + (function prim prim stub (== prim prim)) eta_bool_eq = - (function prim prim (== prim prim)) + (function prim prim stub (== prim prim)) eta_intlike_eq = - (function prim prim (== prim prim)) + (function prim prim stub (== prim prim)) eta_float_eq = - (function prim prim (==. prim prim)) + (function prim prim stub (==. prim prim)) eta_string_eq = - (function prim prim (caml_string_equal prim prim)) + (function prim prim stub + (caml_string_equal prim prim)) eta_int32_eq = - (function prim prim (Int32.== prim prim)) + (function prim prim stub (Int32.== prim prim)) eta_int64_eq = - (function prim prim (Int64.== prim prim)) + (function prim prim stub (Int64.== prim prim)) eta_nativeint_eq = - (function prim prim (Nativeint.== prim prim)) + (function prim prim stub (Nativeint.== prim prim)) eta_gen_ne = - (function prim prim (caml_notequal prim prim)) + (function prim prim stub + (caml_notequal prim prim)) eta_int_ne = - (function prim prim (!= prim prim)) + (function prim prim stub (!= prim prim)) eta_bool_ne = - (function prim prim (!= prim prim)) + (function prim prim stub (!= prim prim)) eta_intlike_ne = - (function prim prim (!= prim prim)) + (function prim prim stub (!= prim prim)) eta_float_ne = - (function prim prim (!=. prim prim)) + (function prim prim stub (!=. prim prim)) eta_string_ne = - (function prim prim + (function prim prim stub (caml_string_notequal prim prim)) eta_int32_ne = - (function prim prim (Int32.!= prim prim)) + (function prim prim stub (Int32.!= prim prim)) eta_int64_ne = - (function prim prim (Int64.!= prim prim)) + (function prim prim stub (Int64.!= prim prim)) eta_nativeint_ne = - (function prim prim (Nativeint.!= prim prim)) + (function prim prim stub (Nativeint.!= prim prim)) eta_gen_lt = - (function prim prim (caml_lessthan prim prim)) - eta_int_lt = (function prim prim (< prim prim)) + (function prim prim stub + (caml_lessthan prim prim)) + eta_int_lt = + (function prim prim stub (< prim prim)) eta_bool_lt = - (function prim prim (< prim prim)) + (function prim prim stub (< prim prim)) eta_intlike_lt = - (function prim prim (< prim prim)) + (function prim prim stub (< prim prim)) eta_float_lt = - (function prim prim (<. prim prim)) + (function prim prim stub (<. prim prim)) eta_string_lt = - (function prim prim + (function prim prim stub (caml_string_lessthan prim prim)) eta_int32_lt = - (function prim prim (Int32.< prim prim)) + (function prim prim stub (Int32.< prim prim)) eta_int64_lt = - (function prim prim (Int64.< prim prim)) + (function prim prim stub (Int64.< prim prim)) eta_nativeint_lt = - (function prim prim (Nativeint.< prim prim)) + (function prim prim stub (Nativeint.< prim prim)) eta_gen_gt = - (function prim prim (caml_greaterthan prim prim)) - eta_int_gt = (function prim prim (> prim prim)) + (function prim prim stub + (caml_greaterthan prim prim)) + eta_int_gt = + (function prim prim stub (> prim prim)) eta_bool_gt = - (function prim prim (> prim prim)) + (function prim prim stub (> prim prim)) eta_intlike_gt = - (function prim prim (> prim prim)) + (function prim prim stub (> prim prim)) eta_float_gt = - (function prim prim (>. prim prim)) + (function prim prim stub (>. prim prim)) eta_string_gt = - (function prim prim + (function prim prim stub (caml_string_greaterthan prim prim)) eta_int32_gt = - (function prim prim (Int32.> prim prim)) + (function prim prim stub (Int32.> prim prim)) eta_int64_gt = - (function prim prim (Int64.> prim prim)) + (function prim prim stub (Int64.> prim prim)) eta_nativeint_gt = - (function prim prim (Nativeint.> prim prim)) + (function prim prim stub (Nativeint.> prim prim)) eta_gen_le = - (function prim prim (caml_lessequal prim prim)) + (function prim prim stub + (caml_lessequal prim prim)) eta_int_le = - (function prim prim (<= prim prim)) + (function prim prim stub (<= prim prim)) eta_bool_le = - (function prim prim (<= prim prim)) + (function prim prim stub (<= prim prim)) eta_intlike_le = - (function prim prim (<= prim prim)) + (function prim prim stub (<= prim prim)) eta_float_le = - (function prim prim (<=. prim prim)) + (function prim prim stub (<=. prim prim)) eta_string_le = - (function prim prim + (function prim prim stub (caml_string_lessequal prim prim)) eta_int32_le = - (function prim prim (Int32.<= prim prim)) + (function prim prim stub (Int32.<= prim prim)) eta_int64_le = - (function prim prim (Int64.<= prim prim)) + (function prim prim stub (Int64.<= prim prim)) eta_nativeint_le = - (function prim prim (Nativeint.<= prim prim)) + (function prim prim stub (Nativeint.<= prim prim)) eta_gen_ge = - (function prim prim (caml_greaterequal prim prim)) + (function prim prim stub + (caml_greaterequal prim prim)) eta_int_ge = - (function prim prim (>= prim prim)) + (function prim prim stub (>= prim prim)) eta_bool_ge = - (function prim prim (>= prim prim)) + (function prim prim stub (>= prim prim)) eta_intlike_ge = - (function prim prim (>= prim prim)) + (function prim prim stub (>= prim prim)) eta_float_ge = - (function prim prim (>=. prim prim)) + (function prim prim stub (>=. prim prim)) eta_string_ge = - (function prim prim + (function prim prim stub (caml_string_greaterequal prim prim)) eta_int32_ge = - (function prim prim (Int32.>= prim prim)) + (function prim prim stub (Int32.>= prim prim)) eta_int64_ge = - (function prim prim (Int64.>= prim prim)) + (function prim prim stub (Int64.>= prim prim)) eta_nativeint_ge = - (function prim prim (Nativeint.>= prim prim)) + (function prim prim stub (Nativeint.>= prim prim)) int_vec = [0: [0: 1 1] [0: [0: 1 2] [0: [0: 2 1] 0a]]] bool_vec = [0: [0: 0a 0a] [0: [0: 0a 1a] [0: [0: 1a 0a] 0a]]] intlike_vec = [0: [0: 0a 0a] [0: [0: 0a 1a] [0: [0: 1a 0a] 0a]]] @@ -232,7 +243,7 @@ (apply f (field 0 param) (field 1 param))) map = (function f l - (apply (field 12 (global List!)) (apply uncurry f) + (apply (field 15 (global List!)) (apply uncurry f) l))) (makeblock 0 (makeblock 0 (apply map gen_cmp vec) @@ -280,7 +291,7 @@ (apply f (field 0 param) (field 1 param))) map = (function f l - (apply (field 12 (global List!)) + (apply (field 15 (global List!)) (apply uncurry f) l))) (makeblock 0 (makeblock 0 (apply map eta_gen_cmp vec) diff --git a/testsuite/tests/translprim/module_coercion.ml.reference b/testsuite/tests/translprim/module_coercion.ml.reference index b84637f4..ca771020 100644 --- a/testsuite/tests/translprim/module_coercion.ml.reference +++ b/testsuite/tests/translprim/module_coercion.ml.reference @@ -1,104 +1,115 @@ (setglobal Module_coercion! (let (M = (makeblock 0)) (makeblock 0 M - (makeblock 0 (function prim (array.length[int] prim)) - (function prim prim (array.get[int] prim prim)) - (function prim prim + (makeblock 0 (function prim stub (array.length[int] prim)) + (function prim prim stub + (array.get[int] prim prim)) + (function prim prim stub (array.unsafe_get[int] prim prim)) - (function prim prim prim + (function prim prim prim stub (array.set[int] prim prim prim)) - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[int] prim prim prim)) - (function prim prim (caml_int_compare prim prim)) - (function prim prim (== prim prim)) - (function prim prim (!= prim prim)) - (function prim prim (< prim prim)) - (function prim prim (> prim prim)) - (function prim prim (<= prim prim)) - (function prim prim (>= prim prim))) - (makeblock 0 (function prim (array.length[float] prim)) - (function prim prim (array.get[float] prim prim)) - (function prim prim + (function prim prim stub + (caml_int_compare prim prim)) + (function prim prim stub (== prim prim)) + (function prim prim stub (!= prim prim)) + (function prim prim stub (< prim prim)) + (function prim prim stub (> prim prim)) + (function prim prim stub (<= prim prim)) + (function prim prim stub (>= prim prim))) + (makeblock 0 (function prim stub (array.length[float] prim)) + (function prim prim stub + (array.get[float] prim prim)) + (function prim prim stub (array.unsafe_get[float] prim prim)) - (function prim prim prim + (function prim prim prim stub (array.set[float] prim prim prim)) - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[float] prim prim prim)) - (function prim prim + (function prim prim stub (caml_float_compare prim prim)) - (function prim prim (==. prim prim)) - (function prim prim (!=. prim prim)) - (function prim prim (<. prim prim)) - (function prim prim (>. prim prim)) - (function prim prim (<=. prim prim)) - (function prim prim (>=. prim prim))) - (makeblock 0 (function prim (array.length[addr] prim)) - (function prim prim (array.get[addr] prim prim)) - (function prim prim + (function prim prim stub (==. prim prim)) + (function prim prim stub (!=. prim prim)) + (function prim prim stub (<. prim prim)) + (function prim prim stub (>. prim prim)) + (function prim prim stub (<=. prim prim)) + (function prim prim stub (>=. prim prim))) + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub + (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim + (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[addr] prim prim prim)) - (function prim prim + (function prim prim stub (caml_string_compare prim prim)) - (function prim prim + (function prim prim stub (caml_string_equal prim prim)) - (function prim prim + (function prim prim stub (caml_string_notequal prim prim)) - (function prim prim + (function prim prim stub (caml_string_lessthan prim prim)) - (function prim prim + (function prim prim stub (caml_string_greaterthan prim prim)) - (function prim prim + (function prim prim stub (caml_string_lessequal prim prim)) - (function prim prim + (function prim prim stub (caml_string_greaterequal prim prim))) - (makeblock 0 (function prim (array.length[addr] prim)) - (function prim prim (array.get[addr] prim prim)) - (function prim prim + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub + (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim + (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[addr] prim prim prim)) - (function prim prim + (function prim prim stub (caml_int32_compare prim prim)) - (function prim prim (Int32.== prim prim)) - (function prim prim (Int32.!= prim prim)) - (function prim prim (Int32.< prim prim)) - (function prim prim (Int32.> prim prim)) - (function prim prim (Int32.<= prim prim)) - (function prim prim (Int32.>= prim prim))) - (makeblock 0 (function prim (array.length[addr] prim)) - (function prim prim (array.get[addr] prim prim)) - (function prim prim + (function prim prim stub (Int32.== prim prim)) + (function prim prim stub (Int32.!= prim prim)) + (function prim prim stub (Int32.< prim prim)) + (function prim prim stub (Int32.> prim prim)) + (function prim prim stub (Int32.<= prim prim)) + (function prim prim stub (Int32.>= prim prim))) + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub + (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim + (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[addr] prim prim prim)) - (function prim prim + (function prim prim stub (caml_int64_compare prim prim)) - (function prim prim (Int64.== prim prim)) - (function prim prim (Int64.!= prim prim)) - (function prim prim (Int64.< prim prim)) - (function prim prim (Int64.> prim prim)) - (function prim prim (Int64.<= prim prim)) - (function prim prim (Int64.>= prim prim))) - (makeblock 0 (function prim (array.length[addr] prim)) - (function prim prim (array.get[addr] prim prim)) - (function prim prim + (function prim prim stub (Int64.== prim prim)) + (function prim prim stub (Int64.!= prim prim)) + (function prim prim stub (Int64.< prim prim)) + (function prim prim stub (Int64.> prim prim)) + (function prim prim stub (Int64.<= prim prim)) + (function prim prim stub (Int64.>= prim prim))) + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub + (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim + (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim + (function prim prim prim stub (array.unsafe_set[addr] prim prim prim)) - (function prim prim + (function prim prim stub (caml_nativeint_compare prim prim)) - (function prim prim (Nativeint.== prim prim)) - (function prim prim (Nativeint.!= prim prim)) - (function prim prim (Nativeint.< prim prim)) - (function prim prim (Nativeint.> prim prim)) - (function prim prim (Nativeint.<= prim prim)) - (function prim prim (Nativeint.>= prim prim)))))) + (function prim prim stub + (Nativeint.== prim prim)) + (function prim prim stub + (Nativeint.!= prim prim)) + (function prim prim stub (Nativeint.< prim prim)) + (function prim prim stub (Nativeint.> prim prim)) + (function prim prim stub + (Nativeint.<= prim prim)) + (function prim prim stub + (Nativeint.>= prim prim)))))) diff --git a/testsuite/tests/typing-extensions/cast.ml b/testsuite/tests/typing-extensions/cast.ml index 855f4df7..1efcfd50 100644 --- a/testsuite/tests/typing-extensions/cast.ml +++ b/testsuite/tests/typing-extensions/cast.ml @@ -1,3 +1,5 @@ +(* Ignore OCAMLRUNPARAM=b to be reproducible *) +Printexc.record_backtrace false;; (* By using two types we can have a recursive constraint *) type 'a class_name = .. constraint 'a = < cast: 'a. 'a name -> 'a; ..> diff --git a/testsuite/tests/typing-extensions/cast.ml.reference b/testsuite/tests/typing-extensions/cast.ml.reference index 468a7c94..3478d60f 100644 --- a/testsuite/tests/typing-extensions/cast.ml.reference +++ b/testsuite/tests/typing-extensions/cast.ml.reference @@ -1,4 +1,5 @@ +# - : unit = () # type 'b class_name = .. constraint 'b = < cast : 'a. 'a name -> 'a; .. > and 'a name = Class : 'a class_name -> (< cast : 'a0. 'a0 name -> 'a0; .. > as 'a) name diff --git a/testsuite/tests/typing-extensions/extensions.ml b/testsuite/tests/typing-extensions/extensions.ml index edb14c8b..f6d6c900 100644 --- a/testsuite/tests/typing-extensions/extensions.ml +++ b/testsuite/tests/typing-extensions/extensions.ml @@ -1,3 +1,5 @@ +(* Ignore OCAMLRUNPARAM=b to be reproducible *) +Printexc.record_backtrace false;; type foo = .. ;; diff --git a/testsuite/tests/typing-extensions/extensions.ml.reference b/testsuite/tests/typing-extensions/extensions.ml.reference index 2a9183f7..ea2cfb8c 100644 --- a/testsuite/tests/typing-extensions/extensions.ml.reference +++ b/testsuite/tests/typing-extensions/extensions.ml.reference @@ -1,4 +1,5 @@ +# - : unit = () # type foo = .. # type foo += A | B of int # val is_a : foo -> bool = @@ -70,9 +71,9 @@ Error: The constructor M.A1 has type foo but was expected to be of type bar type foo += B3 = M.B1 (* Error: rebind private extension *) ^^^^ Error: The constructor M.B1 is private -# Characters 13-24: +# Characters 17-24: type foo += C = Unknown (* Error: unbound extension *) - ^^^^^^^^^^^ + ^^^^^^^ Error: Unbound constructor Unknown # module M : sig type foo type foo += A1 of int end type M.foo += A2 of int diff --git a/testsuite/tests/typing-gadts/pr7421.ml b/testsuite/tests/typing-gadts/pr7421.ml new file mode 100644 index 00000000..5bee9bc1 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7421.ml @@ -0,0 +1,26 @@ +type (_, _) eq = Refl : ('a, 'a) eq;; +type empty = (int, unit) eq;; +[%%expect{| +type (_, _) eq = Refl : ('a, 'a) eq +type empty = (int, unit) eq +|}] +let f (x : ('a, empty Lazy.t) result) = + match x with + | Ok x -> x + | Error (lazy _) -> .;; +[%%expect{| +Line _, characters 4-18: +Error: This match case could not be refuted. + Here is an example of a value that would reach it: Error lazy _ +|}] +let f (x : ('a, empty Lazy.t) result) = + match x with + | Ok x -> x + | Error (lazy Refl) -> .;; +[%%expect{| +Line _, characters 16-20: +Error: This pattern matches values of type (int, int) eq + but a pattern was expected which matches values of type + empty = (int, unit) eq + Type int is not compatible with type unit +|}] diff --git a/testsuite/tests/typing-gadts/pr7432.ml b/testsuite/tests/typing-gadts/pr7432.ml new file mode 100644 index 00000000..6b83f48e --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7432.ml @@ -0,0 +1,27 @@ +#labels false;; +type (_,_) eql = Refl : ('a, 'a) eql +type s = x:int -> y:float -> unit +type t = y:int -> x:float -> unit +type silly = {silly: 'a.'a};; +let eql : (s, t) eql = Refl;; +[%%expect{| +type (_, _) eql = Refl : ('a, 'a) eql +type s = x:int -> y:float -> unit +type t = y:int -> x:float -> unit +type silly = { silly : 'a. 'a; } +val eql : (s, t) eql = Refl +|}] + +#labels true;; +let f : [`L of (s, t) eql | `R of silly] -> 'a = + function `R {silly} -> silly +;; +[%%expect{| +Line _, characters 2-30: +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +`L Refl +val f : [ `L of (s, t) eql | `R of silly ] -> 'a = +|}] + +(* Segfault: let () = print_endline (f (`L eql)) *) diff --git a/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml.reference b/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml.reference index 8f2d22b3..50e54a07 100644 --- a/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml.reference +++ b/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml.reference @@ -98,10 +98,18 @@ module type MapT = val cardinal : 'a t -> int val bindings : 'a t -> (key * 'a) list val min_binding : 'a t -> key * 'a + val min_binding_opt : 'a t -> (key * 'a) option val max_binding : 'a t -> key * 'a + val max_binding_opt : 'a t -> (key * 'a) option val choose : 'a t -> key * 'a + val choose_opt : 'a t -> (key * 'a) option val split : key -> 'a t -> 'a t * 'a option * 'a t val find : key -> 'a t -> 'a + val find_opt : key -> 'a t -> 'a option + val find_first : (key -> bool) -> 'a t -> key * 'a + val find_first_opt : (key -> bool) -> 'a t -> (key * 'a) option + val find_last : (key -> bool) -> 'a t -> key * 'a + val find_last_opt : (key -> bool) -> 'a t -> (key * 'a) option val map : ('a -> 'b) -> 'a t -> 'b t val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t type data @@ -136,10 +144,18 @@ module SSMap : val cardinal : 'a t -> int val bindings : 'a t -> (key * 'a) list val min_binding : 'a t -> key * 'a + val min_binding_opt : 'a t -> (key * 'a) option val max_binding : 'a t -> key * 'a + val max_binding_opt : 'a t -> (key * 'a) option val choose : 'a t -> key * 'a + val choose_opt : 'a t -> (key * 'a) option val split : key -> 'a t -> 'a t * 'a option * 'a t val find : key -> 'a t -> 'a + val find_opt : key -> 'a t -> 'a option + val find_first : (key -> bool) -> 'a t -> key * 'a + val find_first_opt : (key -> bool) -> 'a t -> (key * 'a) option + val find_last : (key -> bool) -> 'a t -> key * 'a + val find_last_opt : (key -> bool) -> 'a t -> (key * 'a) option val map : ('a -> 'b) -> 'a t -> 'b t val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t type data = string diff --git a/testsuite/tests/typing-misc/records.ml b/testsuite/tests/typing-misc/records.ml index f6d9100c..b87361e8 100644 --- a/testsuite/tests/typing-misc/records.ml +++ b/testsuite/tests/typing-misc/records.ml @@ -94,19 +94,19 @@ Line _, characters 26-35: Error: Unbound record field Complex.z |}];; - (* PR#6608 *) -{ "reference" with contents = 0 } +{ true with contents = 0 };; [%%expect{| -Line _, characters 0-33: -Warning 23: all the fields are explicitly listed in this record: -the 'with' clause is useless. -- : int ref = {contents = 0} +Line _, characters 2-6: +Error: This expression has type bool but an expression was expected of type + 'a ref |}];; -{ true with contents = 0 } + +type ('a, 'b) t = { fst : 'a; snd : 'b };; +let with_fst r fst = { r with fst };; +with_fst { fst=""; snd="" } 2;; [%%expect{| -Line _, characters 0-26: -Warning 23: all the fields are explicitly listed in this record: -the 'with' clause is useless. -- : int ref = {contents = 0} +type ('a, 'b) t = { fst : 'a; snd : 'b; } +val with_fst : ('a, 'b) t -> 'c -> ('c, 'b) t = +- : (int, string) t = {fst = 2; snd = ""} |}];; diff --git a/testsuite/tests/typing-modules-bugs/pr7414_bad.ml b/testsuite/tests/typing-modules-bugs/pr7414_bad.ml new file mode 100644 index 00000000..38ecfa13 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr7414_bad.ml @@ -0,0 +1,55 @@ +module type T = sig + type t + val x : t + val show : t -> string +end + +module Int = struct + type t = int + let x = 0 + let show x = string_of_int x +end + +module String = struct + type t = string + let x = "Hello" + let show x = x +end + +let switch = ref true + +module Choose () = struct + module Choice = + (val if !switch then (module Int : T) + else (module String : T)) + let r = ref (ref []) +end + +module type S = sig + module Choice : T + val r : Choice.t list ref ref +end + +module Force (X : functor () -> S) = struct end + +module M = Choose () + +let () = switch := false + +module N = Choose () + +let () = N.r := !M.r +;; + +module Ignore = Force(Choose) +;; (* fail *) + +(* would cause segfault +module M' = (M : S) + +let () = (!M'.r) := [M'.Choice.x] + +module N' = (N : S) + +let () = List.iter (fun x -> print_string (N'.Choice.show x)) !(!N'.r) +*) diff --git a/testsuite/tests/typing-modules/aliases.ml b/testsuite/tests/typing-modules/aliases.ml index b318543e..f20a3eff 100644 --- a/testsuite/tests/typing-modules/aliases.ml +++ b/testsuite/tests/typing-modules/aliases.ml @@ -297,10 +297,18 @@ module StringSet : val cardinal : t -> int val elements : t -> elt list val min_elt : t -> elt + val min_elt_opt : t -> elt option val max_elt : t -> elt + val max_elt_opt : t -> elt option val choose : t -> elt + val choose_opt : t -> elt option val split : elt -> t -> t * bool * t val find : elt -> t -> elt + val find_opt : elt -> t -> elt option + val find_first : (elt -> bool) -> t -> elt + val find_first_opt : (elt -> bool) -> t -> elt option + val find_last : (elt -> bool) -> t -> elt + val find_last_opt : (elt -> bool) -> t -> elt option val of_list : elt list -> t end module SSet : @@ -329,10 +337,18 @@ module SSet : val cardinal : t -> int val elements : t -> elt list val min_elt : t -> elt + val min_elt_opt : t -> elt option val max_elt : t -> elt + val max_elt_opt : t -> elt option val choose : t -> elt + val choose_opt : t -> elt option val split : elt -> t -> t * bool * t val find : elt -> t -> elt + val find_opt : elt -> t -> elt option + val find_first : (elt -> bool) -> t -> elt + val find_first_opt : (elt -> bool) -> t -> elt option + val find_last : (elt -> bool) -> t -> elt + val find_last_opt : (elt -> bool) -> t -> elt option val of_list : elt list -> t end val f : StringSet.t -> SSet.t = @@ -393,10 +409,18 @@ module A : val cardinal : t -> int val elements : t -> elt list val min_elt : t -> elt + val min_elt_opt : t -> elt option val max_elt : t -> elt + val max_elt_opt : t -> elt option val choose : t -> elt + val choose_opt : t -> elt option val split : elt -> t -> t * bool * t val find : elt -> t -> elt + val find_opt : elt -> t -> elt option + val find_first : (elt -> bool) -> t -> elt + val find_first_opt : (elt -> bool) -> t -> elt option + val find_last : (elt -> bool) -> t -> elt + val find_last_opt : (elt -> bool) -> t -> elt option val of_list : elt list -> t end val empty : S.t @@ -497,10 +521,18 @@ module SInt : val cardinal : t -> int val elements : t -> elt list val min_elt : t -> elt + val min_elt_opt : t -> elt option val max_elt : t -> elt + val max_elt_opt : t -> elt option val choose : t -> elt + val choose_opt : t -> elt option val split : elt -> t -> t * bool * t val find : elt -> t -> elt + val find_opt : elt -> t -> elt option + val find_first : (elt -> bool) -> t -> elt + val find_first_opt : (elt -> bool) -> t -> elt option + val find_last : (elt -> bool) -> t -> elt + val find_last_opt : (elt -> bool) -> t -> elt option val of_list : elt list -> t end type (_, _) eq = Eq : ('a, 'a) eq diff --git a/testsuite/tests/typing-modules/pr7348.ml b/testsuite/tests/typing-modules/pr7348.ml new file mode 100644 index 00000000..eac11e81 --- /dev/null +++ b/testsuite/tests/typing-modules/pr7348.ml @@ -0,0 +1,37 @@ +module F (X : sig type t = private < foo:int; ..> val x : t end) = struct + let x : < foo: int; ..> = X.x +end;; +[%%expect{| +module F : + functor (X : sig type t = private < foo : int; .. > val x : t end) -> + sig val x : X.t end +|}] + +module M = struct + type t = < foo: int; bar: int> + let x = object + method foo = 0 + method bar = 0 + end +end;; +[%%expect{| +module M : + sig type t = < bar : int; foo : int > val x : < bar : int; foo : int > end +|}] + +module N = F(M);; +[%%expect{| +module N : sig val x : M.t end +|}] + +module A : sig end = struct + module F (X : sig type t = private < foo:int; ..> val x : t end) = struct + let x : < foo: int; ..> = X.x + end + + module N = F(M) + let _ = (N.x = M.x) +end;; +[%%expect{| +module A : sig end +|}] diff --git a/testsuite/tests/typing-objects/Tests.ml.principal.reference b/testsuite/tests/typing-objects/Tests.ml.principal.reference index c4c59562..7b1164e6 100644 --- a/testsuite/tests/typing-objects/Tests.ml.principal.reference +++ b/testsuite/tests/typing-objects/Tests.ml.principal.reference @@ -35,7 +35,7 @@ Error: This pattern cannot match self: it only matches values of type method f x = (x : bool c) end.. Error: The abbreviation c is used with parameters bool c - wich are incompatible with constraints int c + which are incompatible with constraints int c # class ['a, 'b] c : unit -> object diff --git a/testsuite/tests/typing-objects/Tests.ml.reference b/testsuite/tests/typing-objects/Tests.ml.reference index c4c59562..7b1164e6 100644 --- a/testsuite/tests/typing-objects/Tests.ml.reference +++ b/testsuite/tests/typing-objects/Tests.ml.reference @@ -35,7 +35,7 @@ Error: This pattern cannot match self: it only matches values of type method f x = (x : bool c) end.. Error: The abbreviation c is used with parameters bool c - wich are incompatible with constraints int c + which are incompatible with constraints int c # class ['a, 'b] c : unit -> object diff --git a/testsuite/tests/typing-objects/pr6383.ml.reference b/testsuite/tests/typing-objects/pr6383.ml.reference index 01b6141d..6c92acc3 100644 --- a/testsuite/tests/typing-objects/pr6383.ml.reference +++ b/testsuite/tests/typing-objects/pr6383.ml.reference @@ -1,6 +1,6 @@ -# Characters 10-16: +# Characters 11-16: let f (x: #M.foo) = 0;; - ^^^^^^ + ^^^^^ Error: Unbound module M # diff --git a/testsuite/tests/typing-poly/poly.ml b/testsuite/tests/typing-poly/poly.ml index 4b3d9e5d..0073f0ec 100644 --- a/testsuite/tests/typing-poly/poly.ml +++ b/testsuite/tests/typing-poly/poly.ml @@ -1425,6 +1425,33 @@ Error: This expression has type M.t but an expression was expected of type 'x The type constructor M.t would escape its scope |}];; + +(* PR#6987 *) +type 'a t = V1 of 'a + +type ('c,'t) pvariant = [ `V of ('c * 't t) ] + +class ['c] clss = + object + method mthod : 't . 'c -> 't t -> ('c, 't) pvariant = fun c x -> + `V (c, x) + end;; + +let f2 = fun o c x -> match x with | V1 _ -> x + +let rec f1 o c x = + match (o :> _ clss)#mthod c x with + | `V c -> f2 o c x;; +[%%expect{| +type 'a t = V1 of 'a +type ('c, 't) pvariant = [ `V of 'c * 't t ] +class ['c] clss : object method mthod : 'c -> 't t -> ('c, 't) pvariant end +val f2 : 'a -> 'b -> 'c t -> 'c t = +val f1 : + < mthod : 't. 'a -> 't t -> [< ('a, 't) pvariant ]; .. > -> + 'a -> 'b t -> 'b t = +|}] + (* PR#7285 *) type (+'a,-'b) foo = private int;; let f (x : int) : ('a,'a) foo = Obj.magic x;; diff --git a/testsuite/tests/typing-private/private.ml b/testsuite/tests/typing-private/private.ml index bab86eb8..fd3b7bd7 100644 --- a/testsuite/tests/typing-private/private.ml +++ b/testsuite/tests/typing-private/private.ml @@ -111,3 +111,8 @@ type t = private < x : int > as 'a;; type t = private (< x : int > as 'a) as 'b;; type 'a t = private < x : int; .. > as 'a;; type 'a t = private 'a constraint 'a = < x : int; .. >;; + +(* PR#7437 *) +type t = [` Closed ];; +type nonrec t = private [> t];; + diff --git a/testsuite/tests/typing-private/private.ml.principal.reference b/testsuite/tests/typing-private/private.ml.principal.reference index db933583..39b9440f 100644 --- a/testsuite/tests/typing-private/private.ml.principal.reference +++ b/testsuite/tests/typing-private/private.ml.principal.reference @@ -122,4 +122,6 @@ Error: Type declarations do not match: type 'a t Their constraints differ. # type 'a t = private 'a constraint 'a = < x : int; .. > -# +# type t = [ `Closed ] +# type nonrec t = private [> t ] +# diff --git a/testsuite/tests/typing-private/private.ml.reference b/testsuite/tests/typing-private/private.ml.reference index 341bc936..ace6cbdb 100644 --- a/testsuite/tests/typing-private/private.ml.reference +++ b/testsuite/tests/typing-private/private.ml.reference @@ -122,4 +122,6 @@ Error: Type declarations do not match: type 'a t Their constraints differ. # type 'a t = private 'a constraint 'a = < x : int; .. > -# +# type t = [ `Closed ] +# type nonrec t = private [> t ] +# diff --git a/testsuite/tests/typing-short-paths/pr6836.ml.reference b/testsuite/tests/typing-short-paths/pr6836.ml.reference index 3f8c6dbd..cc77356e 100644 --- a/testsuite/tests/typing-short-paths/pr6836.ml.reference +++ b/testsuite/tests/typing-short-paths/pr6836.ml.reference @@ -1,7 +1,7 @@ # type t = [ `A | `B ] # type 'a u = t -# val a : [< int u > `A ] = `A +# val a : [< t > `A ] = `A # type 'a s = 'a # val b : [< t > `B ] = `B # diff --git a/testsuite/tests/typing-short-paths/short-paths.ml.reference b/testsuite/tests/typing-short-paths/short-paths.ml.reference index df8f2c10..64651566 100644 --- a/testsuite/tests/typing-short-paths/short-paths.ml.reference +++ b/testsuite/tests/typing-short-paths/short-paths.ml.reference @@ -38,10 +38,18 @@ val cardinal : 'a t -> key val bindings : 'a t -> (key * 'a) list val min_binding : 'a t -> key * 'a + val min_binding_opt : 'a t -> (key * 'a) option val max_binding : 'a t -> key * 'a + val max_binding_opt : 'a t -> (key * 'a) option val choose : 'a t -> key * 'a + val choose_opt : 'a t -> (key * 'a) option val split : key -> 'a t -> 'a t * 'a option * 'a t val find : key -> 'a t -> 'a + val find_opt : key -> 'a t -> 'a option + val find_first : (key -> bool) -> 'a t -> key * 'a + val find_first_opt : (key -> bool) -> 'a t -> (key * 'a) option + val find_last : (key -> bool) -> 'a t -> key * 'a + val find_last_opt : (key -> bool) -> 'a t -> (key * 'a) option val map : ('a -> 'b) -> 'a t -> 'b t val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t end diff --git a/testsuite/tests/typing-unboxed-types/test.ml b/testsuite/tests/typing-unboxed-types/test.ml index f187b76d..8e0b337b 100644 --- a/testsuite/tests/typing-unboxed-types/test.ml +++ b/testsuite/tests/typing-unboxed-types/test.ml @@ -119,3 +119,38 @@ module T : sig end = struct type t = A of int [@@ocaml.unboxed] end;; + +(* regression test for PR#7511 (wrong determination of unboxability for GADTs) +*) +type 'a s = S : 'a -> 'a s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; + +(* regression test for GPR#1133 (follow-up to PR#7511) *) +type 'a s = S : 'a -> 'a option s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; + +(* Another test for GPR#1133: abstract types *) +module M : sig + type 'a r constraint 'a = unit -> 'b + val inj : 'b -> (unit -> 'b) r +end = struct + type 'a r = 'b constraint 'a = unit -> 'b + let inj x = x +end;; + +(* reject *) +type t = T : (unit -> _) M.r -> t [@@unboxed];; + +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed];; + +(* reject *) +type t = T : _ s -> t [@@unboxed];; + +(* accept *) +type 'a t = T : 'a s -> 'a t [@@unboxed];; + + +(* Another corner case from GPR#1133 *) +type _ s = S : 'a t -> _ s [@@unboxed] + and _ t = T : 'a -> 'a s t +;; diff --git a/testsuite/tests/typing-unboxed-types/test.ml.reference b/testsuite/tests/typing-unboxed-types/test.ml.reference index b555db8d..10a118d8 100644 --- a/testsuite/tests/typing-unboxed-types/test.ml.reference +++ b/testsuite/tests/typing-unboxed-types/test.ml.reference @@ -144,7 +144,12 @@ Error: Signature mismatch: Error: This type cannot be unboxed because it might contain both float and non-float values. You should annotate it with [@@ocaml.boxed]. -# type t18 = A : 'a list abs -> t18 [@@unboxed] +# Characters 19-69: + type t18 = A : _ list abs -> t18 [@@ocaml.unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. # * Characters 176-256: ......struct type t = A of float [@@ocaml.unboxed] @@ -159,4 +164,40 @@ Error: Signature mismatch: Their internal representations differ: the first declaration uses unboxed float representation. # * * module T : sig type t [@@immediate] end +# * type 'a s = S : 'a -> 'a s [@@unboxed] +# Characters 0-33: + type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +# type 'a s = S : 'a -> 'a option s [@@unboxed] +# Characters 0-33: + type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +# module M : + sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end +# Characters 14-59: + type t = T : (unit -> _) M.r -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +# type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed] +# Characters 14-47: + type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +# type 'a t = T : 'a s -> 'a t [@@unboxed] +# Characters 42-81: + type _ s = S : 'a t -> _ s [@@unboxed] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. # diff --git a/testsuite/tests/typing-unboxed/test.ml b/testsuite/tests/typing-unboxed/test.ml index bb265c44..85265c1f 100644 --- a/testsuite/tests/typing-unboxed/test.ml +++ b/testsuite/tests/typing-unboxed/test.ml @@ -124,3 +124,6 @@ external q : (int[@untagged]) -> float = "q";; external r : int -> (int[@untagged]) = "r";; external s : int -> int = "s" [@@untagged];; external t : float -> float = "t" [@@unboxed];; + +(* PR#7424 *) +type 'a b = B of 'a b b [@@unboxed];; diff --git a/testsuite/tests/typing-unboxed/test.ml.reference b/testsuite/tests/typing-unboxed/test.ml.reference index c76b8af4..803bf571 100644 --- a/testsuite/tests/typing-unboxed/test.ml.reference +++ b/testsuite/tests/typing-unboxed/test.ml.reference @@ -188,4 +188,5 @@ Error: The native code version of the primitive is mandatory when attributes [@u external t : float -> float = "t" [@@unboxed];; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present +# type 'a b = B of 'a b b [@@unboxed] # diff --git a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml index 78557072..2b52368e 100644 --- a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml +++ b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml @@ -1,3 +1,6 @@ +(* Ignore OCAMLRUNPARAM=b to be reproducible *) +Printexc.record_backtrace false;; + let () = print_endline "\n\ <----------------------------------------------------------------------\n\ To check the result file for this test, it suffices to look for \"val\"\n\ diff --git a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml.reference b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml.reference index 2b9d4c2b..ece388aa 100644 --- a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml.reference +++ b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml.reference @@ -1,5 +1,6 @@ -# +# - : unit = () +# <---------------------------------------------------------------------- To check the result file for this test, it suffices to look for "val" lines corresponding to toplevel answers. If they start with @@ -22,7 +23,7 @@ Warning 57: Ambiguous or-pattern variables under guard; variable x may match different arguments. (See manual section 8.5) val ambiguous_typical_example : expr * expr -> unit = # Note that an Assert_failure is expected just below. -# Exception: Assert_failure ("//toplevel//", 23, 6). +# Exception: Assert_failure ("//toplevel//", 25, 6). # val not_ambiguous__no_orpat : int option -> unit = # val not_ambiguous__no_guard : [< `A | `B | `C ] -> unit = # val not_ambiguous__no_patvar_in_guard : diff --git a/testsuite/tests/typing-warnings/application.ml b/testsuite/tests/typing-warnings/application.ml index a0c42061..8948dc8c 100644 --- a/testsuite/tests/typing-warnings/application.ml +++ b/testsuite/tests/typing-warnings/application.ml @@ -1,2 +1,5 @@ +(* Ignore OCAMLRUNPARAM=b to be reproducible *) +Printexc.record_backtrace false;; + let _ = ignore (+);; let _ = raise Exit 3;; diff --git a/testsuite/tests/typing-warnings/application.ml.reference b/testsuite/tests/typing-warnings/application.ml.reference index da825fd0..d35fd40e 100644 --- a/testsuite/tests/typing-warnings/application.ml.reference +++ b/testsuite/tests/typing-warnings/application.ml.reference @@ -1,5 +1,6 @@ -# Characters 15-18: +# - : unit = () +# Characters 16-19: let _ = ignore (+);; ^^^ Warning 5: this function application is partial, diff --git a/testsuite/tests/typing-warnings/exhaustiveness.ml b/testsuite/tests/typing-warnings/exhaustiveness.ml index d3d9bc05..c1e78a2a 100644 --- a/testsuite/tests/typing-warnings/exhaustiveness.ml +++ b/testsuite/tests/typing-warnings/exhaustiveness.ml @@ -108,3 +108,6 @@ let f x = match x with _ -> () | None -> .;; (* do not warn *) (* #7059, all clauses guarded *) let f x y = match 1 with 1 when x = y -> 1;; + +(* #7504, Example with no constraints on a record *) +let f = function {contents=_}, 0 -> 0;; diff --git a/testsuite/tests/typing-warnings/exhaustiveness.ml.reference b/testsuite/tests/typing-warnings/exhaustiveness.ml.reference index 4935f690..0bb5b0b8 100644 --- a/testsuite/tests/typing-warnings/exhaustiveness.ml.reference +++ b/testsuite/tests/typing-warnings/exhaustiveness.ml.reference @@ -133,4 +133,11 @@ Error: This match case could not be refuted. Warning 8: this pattern-matching is not exhaustive. All clauses in this pattern-matching are guarded. val f : 'a -> 'a -> int = +# Characters 62-91: + let f = function {contents=_}, 0 -> 0;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +(_, 1) +val f : 'a ref * int -> int = # diff --git a/testsuite/tests/typing-warnings/pr6872.ml b/testsuite/tests/typing-warnings/pr6872.ml index 283af4cc..73870a02 100644 --- a/testsuite/tests/typing-warnings/pr6872.ml +++ b/testsuite/tests/typing-warnings/pr6872.ml @@ -1,3 +1,6 @@ +(* Ignore OCAMLRUNPARAM=b to be reproducible *) +Printexc.record_backtrace false;; + exception A;; type a = A;; diff --git a/testsuite/tests/typing-warnings/pr6872.ml.principal.reference b/testsuite/tests/typing-warnings/pr6872.ml.principal.reference index eaebf225..616b4548 100644 --- a/testsuite/tests/typing-warnings/pr6872.ml.principal.reference +++ b/testsuite/tests/typing-warnings/pr6872.ml.principal.reference @@ -1,5 +1,6 @@ -# exception A +# - : unit = () +# exception A # type a = A # Characters 1-2: A;; diff --git a/testsuite/tests/typing-warnings/pr6872.ml.reference b/testsuite/tests/typing-warnings/pr6872.ml.reference index 7c0b3503..5cd4291f 100644 --- a/testsuite/tests/typing-warnings/pr6872.ml.reference +++ b/testsuite/tests/typing-warnings/pr6872.ml.reference @@ -1,5 +1,6 @@ -# exception A +# - : unit = () +# exception A # type a = A # Characters 1-2: A;; diff --git a/testsuite/tests/typing-warnings/pr7297.ml b/testsuite/tests/typing-warnings/pr7297.ml index 64b6fd5a..f55c0a32 100644 --- a/testsuite/tests/typing-warnings/pr7297.ml +++ b/testsuite/tests/typing-warnings/pr7297.ml @@ -1 +1,4 @@ +(* Ignore OCAMLRUNPARAM=b to be reproducible *) +Printexc.record_backtrace false;; + let () = raise Exit; () ;; (* warn *) diff --git a/testsuite/tests/typing-warnings/pr7297.ml.reference b/testsuite/tests/typing-warnings/pr7297.ml.reference index 9c9dbdd0..bc8580fc 100644 --- a/testsuite/tests/typing-warnings/pr7297.ml.reference +++ b/testsuite/tests/typing-warnings/pr7297.ml.reference @@ -1,5 +1,6 @@ -# Characters 9-19: +# - : unit = () +# Characters 10-20: let () = raise Exit; () ;; (* warn *) ^^^^^^^^^^ Warning 21: this statement never returns (or has an unsound type.) diff --git a/testsuite/tests/typing-warnings/unused_types.ml b/testsuite/tests/typing-warnings/unused_types.ml index a8333abb..791d9fd8 100644 --- a/testsuite/tests/typing-warnings/unused_types.ml +++ b/testsuite/tests/typing-warnings/unused_types.ml @@ -68,3 +68,9 @@ end = struct type t += Private_ext end ;; + +module Pr7438 : sig +end = struct + module type S = sig type t = private [> `Foo] end + module type X = sig type t = private [> `Foo | `Bar] include S with type t := t end +end;; diff --git a/testsuite/tests/typing-warnings/unused_types.ml.reference b/testsuite/tests/typing-warnings/unused_types.ml.reference index 9451ee69..1d318192 100644 --- a/testsuite/tests/typing-warnings/unused_types.ml.reference +++ b/testsuite/tests/typing-warnings/unused_types.ml.reference @@ -54,4 +54,5 @@ Warning 38: extension constructor Private_ext is never used to build values. It is exported or rebound as a private extension. module Unused_private_extension : sig type t = .. type t += private Private_ext end +# module Pr7438 : sig end # diff --git a/testsuite/tests/unwind/Makefile b/testsuite/tests/unwind/Makefile index 18b39ea3..614808b0 100644 --- a/testsuite/tests/unwind/Makefile +++ b/testsuite/tests/unwind/Makefile @@ -31,7 +31,7 @@ unwind_test: @$(OCAMLOPT) -c -opaque mylib.mli @$(OCAMLOPT) -c driver.ml @$(OCAMLOPT) -c mylib.ml - @$(OCAMLOPT) -c stack_walker.c + @$(OCAMLOPT) -ccopt "-I$(CTOPDIR)/byterun" -c stack_walker.c @$(OCAMLOPT) -cclib -Wl,-keep_dwarf_unwind -o unwind_test mylib.cmx \ driver.cmx stack_walker.o diff --git a/testsuite/tests/warnings/Makefile b/testsuite/tests/warnings/Makefile index 58a8eae9..7bf93ad2 100644 --- a/testsuite/tests/warnings/Makefile +++ b/testsuite/tests/warnings/Makefile @@ -19,6 +19,7 @@ FLAGS=-w A run-all: @$(OCAMLC) $(FLAGS) -c deprecated_module.mli @$(OCAMLC) $(FLAGS) -c module_without_cmx.mli + @$(OCAMLC) $(FLAGS) -c w60.mli @for file in *.ml; do \ printf " ... testing '$$file':"; \ F="`basename $$file .ml`"; \ diff --git a/testsuite/tests/warnings/w04.ml b/testsuite/tests/warnings/w04.ml new file mode 100644 index 00000000..e46b6bf7 --- /dev/null +++ b/testsuite/tests/warnings/w04.ml @@ -0,0 +1,12 @@ +[@@@ocaml.warning "+4"] + +type expr = E of int [@@unboxed] + + +let f x = match x with (E e) -> e + +type t = A | B + +let g x = match x with +| A -> 0 +| _ -> 1 diff --git a/testsuite/tests/warnings/w04.reference b/testsuite/tests/warnings/w04.reference new file mode 100644 index 00000000..df194ead --- /dev/null +++ b/testsuite/tests/warnings/w04.reference @@ -0,0 +1,3 @@ +File "w04.ml", line 10, characters 10-40: +Warning 4: this pattern-matching is fragile. +It will remain exhaustive when constructors are added to type t. diff --git a/testsuite/tests/warnings/w33.ml b/testsuite/tests/warnings/w33.ml new file mode 100644 index 00000000..628fae3f --- /dev/null +++ b/testsuite/tests/warnings/w33.ml @@ -0,0 +1,16 @@ +(** Test unused opens, in particular in presence of + pattern open *) + +module M = struct end +module N = struct type t = A | B end +module R = struct type r = {x: int} end + +let f M.(x) = x (* useless open *) +let g N.(A|B) = () (* used open *) +let h R.{x} = R.{x} + +open N (* used open *) +let i (A|B) = B + +open! M (* open! also deactivates unused open warning *) +open M (* useless open *) diff --git a/testsuite/tests/warnings/w33.reference b/testsuite/tests/warnings/w33.reference new file mode 100644 index 00000000..9915965c --- /dev/null +++ b/testsuite/tests/warnings/w33.reference @@ -0,0 +1,4 @@ +File "w33.ml", line 8, characters 6-11: +Warning 33: unused open M. +File "w33.ml", line 16, characters 0-6: +Warning 33: unused open M. diff --git a/testsuite/tests/warnings/w60.ml b/testsuite/tests/warnings/w60.ml new file mode 100755 index 00000000..01aed6f8 --- /dev/null +++ b/testsuite/tests/warnings/w60.ml @@ -0,0 +1,23 @@ +(* PR#7314 *) + +module type Comparable = sig + val id: int +end + +module Make_graph (P:sig module Id:Comparable end) = struct + let foo = P.Id.id +end + +module Fold_ordered(P: sig module Id:Comparable end) = +struct + include Make_graph(struct module Id = P.Id end) +end + + +(* PR#7314 *) + +module M = struct + module N = struct end +end + +module O = M.N diff --git a/testsuite/tests/warnings/w60.mli b/testsuite/tests/warnings/w60.mli new file mode 100755 index 00000000..f3c5740c --- /dev/null +++ b/testsuite/tests/warnings/w60.mli @@ -0,0 +1,12 @@ +module type Comparable = sig + val id: int +end + +module Fold_ordered(P: sig module Id:Comparable end): sig + val foo: int +end + + + +module M : sig end +module O : sig end diff --git a/testsuite/tests/warnings/w60.reference b/testsuite/tests/warnings/w60.reference new file mode 100644 index 00000000..e69de29b diff --git a/tools/.depend b/tools/.depend index b578b0ec..5dcb7ed8 100644 --- a/tools/.depend +++ b/tools/.depend @@ -30,13 +30,23 @@ eqparsetree.cmo : ../parsing/parsetree.cmi ../parsing/longident.cmi \ ../parsing/location.cmi ../parsing/asttypes.cmi eqparsetree.cmx : ../parsing/parsetree.cmi ../parsing/longident.cmx \ ../parsing/location.cmx ../parsing/asttypes.cmi -objinfo.cmo : ../asmcomp/printclambda.cmi ../utils/misc.cmi \ +lintapidiff.cmo : ../typing/printtyp.cmi ../driver/pparse.cmi \ + ../typing/path.cmi ../parsing/parsetree.cmi ../parsing/parse.cmi \ + ../utils/misc.cmi ../parsing/location.cmi ../typing/ident.cmi +lintapidiff.cmx : ../typing/printtyp.cmx ../driver/pparse.cmx \ + ../typing/path.cmx ../parsing/parsetree.cmi ../parsing/parse.cmx \ + ../utils/misc.cmx ../parsing/location.cmx ../typing/ident.cmx +make_opcodes.cmo : +make_opcodes.cmx : +objinfo.cmo : ../utils/tbl.cmi ../middle_end/base_types/symbol.cmi \ + ../asmcomp/printclambda.cmi ../utils/misc.cmi \ ../middle_end/base_types/linkage_name.cmi ../typing/ident.cmi \ ../asmcomp/export_info.cmi ../utils/config.cmi \ ../middle_end/base_types/compilation_unit.cmi ../asmcomp/cmx_format.cmi \ ../typing/cmt_format.cmi ../bytecomp/cmo_format.cmi \ ../typing/cmi_format.cmi ../bytecomp/bytesections.cmi -objinfo.cmx : ../asmcomp/printclambda.cmx ../utils/misc.cmx \ +objinfo.cmx : ../utils/tbl.cmx ../middle_end/base_types/symbol.cmx \ + ../asmcomp/printclambda.cmx ../utils/misc.cmx \ ../middle_end/base_types/linkage_name.cmx ../typing/ident.cmx \ ../asmcomp/export_info.cmx ../utils/config.cmx \ ../middle_end/base_types/compilation_unit.cmx ../asmcomp/cmx_format.cmi \ @@ -49,15 +59,15 @@ ocamlcp.cmx : ../driver/main_args.cmx ocamldep.cmo : ../driver/pparse.cmi ../parsing/parsetree.cmi \ ../parsing/parser.cmi ../parsing/parse.cmi ../utils/misc.cmi \ ../parsing/longident.cmi ../parsing/location.cmi ../parsing/lexer.cmi \ - ../parsing/depend.cmi ../utils/config.cmi ../driver/compenv.cmi \ - ../utils/clflags.cmi + ../parsing/depend.cmi ../utils/config.cmi ../driver/compplugin.cmi \ + ../driver/compenv.cmi ../utils/clflags.cmi ocamldep.cmx : ../driver/pparse.cmx ../parsing/parsetree.cmi \ ../parsing/parser.cmx ../parsing/parse.cmx ../utils/misc.cmx \ ../parsing/longident.cmx ../parsing/location.cmx ../parsing/lexer.cmx \ - ../parsing/depend.cmx ../utils/config.cmx ../driver/compenv.cmx \ - ../utils/clflags.cmx -ocamlmklib.cmo : ocamlmklibconfig.cmo ../utils/config.cmi -ocamlmklib.cmx : ocamlmklibconfig.cmx ../utils/config.cmx + ../parsing/depend.cmx ../utils/config.cmx ../driver/compplugin.cmx \ + ../driver/compenv.cmx ../utils/clflags.cmx +ocamlmklib.cmo : ocamlmklibconfig.cmo ../utils/misc.cmi ../utils/config.cmi +ocamlmklib.cmx : ocamlmklibconfig.cmx ../utils/misc.cmx ../utils/config.cmx ocamlmklibconfig.cmo : ocamlmklibconfig.cmx : ocamlmktop.cmo : ../utils/ccomp.cmi diff --git a/tools/Makefile b/tools/Makefile index 7ab2f11f..9a8cf652 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -13,4 +13,385 @@ #* * #************************************************************************** -include Makefile.shared +MAKEFLAGS := -r -R +include ../config/Makefile +INSTALL_BINDIR:=$(DESTDIR)$(BINDIR) +INSTALL_LIBDIR:=$(DESTDIR)$(LIBDIR) +INSTALL_COMPLIBDIR:=$(DESTDIR)$(COMPLIBDIR) +INSTALL_STUBLIBDIR:=$(DESTDIR)$(STUBLIBDIR) +INSTALL_MANDIR:=$(DESTDIR)$(MANDIR) + +ifeq ($(SYSTEM),unix) +override define shellquote +$i := $$(subst ",\",$$(subst $$$$,\$$$$,$$(subst `,\`,$i)))#")# +endef +$(foreach i,BINDIR LIBDIR COMPLIBDIR STUBLIBDIR MANDIR,$(eval $(shellquote))) +endif + +CAMLRUN ?= ../boot/ocamlrun +CAMLYACC ?= ../boot/ocamlyacc +DESTDIR ?= +# Setup GNU make variables storing per-target source and target, +# a list of installed tools, and a function to quote a filename for +# the shell. +override installed_tools := ocamldep ocamlprof ocamlcp ocamloptp \ + ocamlmktop ocamlmklib ocamlobjinfo + +install_files := +define byte2native +$(patsubst %.cmo,%.cmx,$(patsubst %.cma,%.cmxa,$1)) +endef + +# $1 = target, $2 = OCaml object dependencies, $3 = other dependencies +# There is a lot of subtle code here. The multiple layers of expansion +# are due to `make`'s eval() function, which evaluates the string +# passed to it as a makefile fragment. So it is crucial that variables +# not get expanded too many times. +define byte_and_opt_ +# This check is defensive programming +$(and $(filter-out 1,$(words $1)),$(error \ + cannot build file with whitespace in name)) +$1: $3 $2 + $$(CAMLC) $$(LINKFLAGS) -I .. -o $$@ $2 + +$1.opt: $3 $$(call byte2native,$2) + $$(CAMLOPT) $$(LINKFLAGS) -I .. -o $$@ $$(call byte2native,$2) + +all: $1 + +opt.opt: $1.opt + +ifeq '$(filter $(installed_tools),$1)' '$1' +install_files += $1 +endif +clean:: + rm -f -- $1 $1.opt + +endef + +# Escape any $ characters in the arguments and eval the result. +define byte_and_opt +$(eval $(call \ + byte_and_opt_,$(subst $$,$$$$,$1),$(subst $$,$$$$,$2),$(subst $$,$$$$,$3))) +endef + +ROOTDIR=.. + +ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" +export OCAML_FLEXLINK:= +else +export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe +endif + +CAMLC=$(CAMLRUN) ../boot/ocamlc -nostdlib -I ../boot \ + -use-prims ../byterun/primitives -I .. +CAMLOPT=$(CAMLRUN) ../ocamlopt -nostdlib -I ../stdlib +ifeq "$(UNIX_OR_WIN32)" "win32" + ifneq "$(wildcard ../flexdll/Makefile)" "" + CAMLOPT := OCAML_FLEXLINK="../boot/ocamlrun ../flexdll/flexlink.exe" \ + $(CAMLOPT) + endif +endif +CAMLLEX=$(CAMLRUN) ../boot/ocamllex +INCLUDES=-I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../asmcomp \ + -I ../middle_end -I ../middle_end/base_types -I ../driver \ + -I ../toplevel +COMPFLAGS= -absname -w +a-4-9-41-42-44-45-48 -strict-sequence -warn-error A \ + -safe-string -strict-formats -bin-annot $(INCLUDES) +LINKFLAGS=$(INCLUDES) +VPATH := $(filter-out -I,$(INCLUDES)) + +# scrapelabels addlabels + +.PHONY: all opt.opt + +# The dependency generator + +CAMLDEP_OBJ=ocamldep.cmo +CAMLDEP_IMPORTS= \ + ../compilerlibs/ocamlcommon.cma \ + ../compilerlibs/ocamlbytecomp.cma +ocamldep: LINKFLAGS += -compat-32 +$(call byte_and_opt,ocamldep,$(CAMLDEP_IMPORTS) $(CAMLDEP_OBJ),) +ocamldep: depend.cmi +ocamldep.opt: depend.cmi + +# ocamldep is precious: sometimes we are stuck in the middle of a +# bootstrap and we need to remake the dependencies +clean:: + if test -f ocamldep; then mv -f ocamldep ocamldep.bak; else :; fi + rm -f ocamldep.opt + + +# The profiler + +CSLPROF=ocamlprof.cmo +CSLPROF_IMPORTS=misc.cmo config.cmo identifiable.cmo numbers.cmo \ + arg_helper.cmo clflags.cmo terminfo.cmo \ + warnings.cmo location.cmo longident.cmo docstrings.cmo \ + syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo + +$(call byte_and_opt,ocamlprof,$(CSLPROF_IMPORTS) profiling.cmo $(CSLPROF),) + +ocamlcp_cmos = misc.cmo warnings.cmo config.cmo identifiable.cmo numbers.cmo \ + arg_helper.cmo clflags.cmo main_args.cmo + +$(call byte_and_opt,ocamlcp,$(ocamlcp_cmos) ocamlcp.cmo,) +$(call byte_and_opt,ocamloptp,$(ocamlcp_cmos) ocamloptp.cmo,) + +opt:: profiling.cmx + +install:: + cp -- profiling.cmi profiling.cmo profiling.cmt profiling.cmti "$(INSTALL_LIBDIR)" + +installopt:: + cp -- profiling.cmx profiling.$(O) "$(INSTALL_LIBDIR)" + +# To help building mixed-mode libraries (OCaml + C) + +$(call byte_and_opt,ocamlmklib,ocamlmklibconfig.cmo config.cmo misc.cmo \ + ocamlmklib.cmo,) + + +ocamlmklibconfig.ml: ../config/Makefile Makefile + (echo 'let bindir = "$(BINDIR)"'; \ + echo 'let supports_shared_libraries = $(SUPPORTS_SHARED_LIBRARIES)';\ + echo 'let byteccrpath = "$(BYTECCRPATH)"'; \ + echo 'let nativeccrpath = "$(NATIVECCRPATH)"'; \ + echo 'let mksharedlibrpath = "$(MKSHAREDLIBRPATH)"'; \ + echo 'let toolpref = "$(TOOLPREF)"'; \ + sed -n -e 's/^#ml //p' ../config/Makefile) \ + > ocamlmklibconfig.ml + +beforedepend:: ocamlmklibconfig.ml + +clean:: + rm -f ocamlmklibconfig.ml + +# To make custom toplevels + +OCAMLMKTOP=ocamlmktop.cmo +OCAMLMKTOP_IMPORTS=misc.cmo identifiable.cmo numbers.cmo config.cmo \ + arg_helper.cmo clflags.cmo ccomp.cmo + +$(call byte_and_opt,ocamlmktop,$(OCAMLMKTOP_IMPORTS) $(OCAMLMKTOP),) + +# Converter olabl/ocaml 2.99 to ocaml 3 + +OCAML299TO3= lexer299.cmo ocaml299to3.cmo +LIBRARY3= misc.cmo warnings.cmo location.cmo + +ocaml299to3: $(OCAML299TO3) + $(CAMLC) $(LINKFLAGS) -o ocaml299to3 $(LIBRARY3) $(OCAML299TO3) + +lexer299.ml: lexer299.mll + $(CAMLLEX) lexer299.mll + +#install:: +# cp ocaml299to3 "$(INSTALL_BINDIR)/ocaml299to3$(EXE)" + +clean:: + rm -f ocaml299to3 lexer299.ml + +# Label remover for interface files (upgrade 3.02 to 3.03) + +SCRAPELABELS= lexer301.cmo scrapelabels.cmo + +scrapelabels: $(SCRAPELABELS) + $(CAMLC) $(LINKFLAGS) -o scrapelabels $(LIBRARY3) $(SCRAPELABELS) + +lexer301.ml: lexer301.mll + $(CAMLLEX) lexer301.mll + +#install:: +# cp scrapelabels "$(INSTALL_LIBDIR)" + +clean:: + rm -f scrapelabels lexer301.ml + +# Insert labels following an interface file (upgrade 3.02 to 3.03) + +ADDLABELS_IMPORTS=misc.cmo config.cmo arg_helper.cmo clflags.cmo \ + identifiable.cmo numbers.cmo terminfo.cmo \ + warnings.cmo location.cmo longident.cmo docstrings.cmo \ + syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo + +addlabels: addlabels.cmo + $(CAMLC) $(LINKFLAGS) -w sl -o addlabels \ + $(ADDLABELS_IMPORTS) addlabels.cmo + +#install:: +# cp addlabels "$(INSTALL_LIBDIR)" + +ifeq ($(UNIX_OR_WIN32),unix) +LN := ln -sf +else +LN := cp -pf +endif + +install:: + for i in $(install_files); \ + do \ + cp -- "$$i" "$(INSTALL_BINDIR)/$$i.byte$(EXE)" && \ + if test -f "$$i".opt; then \ + cp -- "$$i.opt" "$(INSTALL_BINDIR)/$$i.opt$(EXE)" && \ + (cd "$(INSTALL_BINDIR)/" && $(LN) "$$i.opt$(EXE)" "$$i$(EXE)"); \ + else \ + (cd "$(INSTALL_BINDIR)/" && $(LN) "$$i.byte$(EXE)" "$$i$(EXE)"); \ + fi; \ + done + +clean:: + rm -f addlabels + +# The preprocessor for asm generators + +CVT_EMIT=cvt_emit.cmo + +cvt_emit: $(CVT_EMIT) + $(CAMLC) $(LINKFLAGS) -o cvt_emit $(CVT_EMIT) + +# cvt_emit is precious: sometimes we are stuck in the middle of a +# bootstrap and we need to remake the dependencies +.PRECIOUS: cvt_emit +clean:: + if test -f cvt_emit; then mv -f cvt_emit cvt_emit.bak; else :; fi + +cvt_emit.ml: cvt_emit.mll + $(CAMLLEX) cvt_emit.mll + +clean:: + rm -f cvt_emit.ml + +beforedepend:: cvt_emit.ml + +# Reading cmt files + +READ_CMT= \ + ../compilerlibs/ocamlcommon.cma \ + ../compilerlibs/ocamlbytecomp.cma \ + \ + cmt2annot.cmo read_cmt.cmo + +# Reading cmt files +$(call byte_and_opt,read_cmt,$(READ_CMT),) + + +# The bytecode disassembler + +DUMPOBJ=opnames.cmo dumpobj.cmo + +$(call byte_and_opt,dumpobj,misc.cmo identifiable.cmo numbers.cmo tbl.cmo \ + config.cmo ident.cmo opcodes.cmo bytesections.cmo \ + $(DUMPOBJ),) + +make_opcodes.ml: make_opcodes.mll + $(CAMLLEX) make_opcodes.mll + +make_opcodes: make_opcodes.ml + $(CAMLC) make_opcodes.ml -o $@ + +opnames.ml: ../byterun/caml/instruct.h make_opcodes + $(CAMLRUN) make_opcodes -opnames < $< > $@ + +clean:: + rm -f opnames.ml make_opcodes make_opcodes.ml + +beforedepend:: opnames.ml + +# Display info on compiled files + +ifeq "$(SYSTEM)" "macosx" +DEF_SYMBOL_PREFIX = '-Dsymbol_prefix="_"' +else +DEF_SYMBOL_PREFIX = '-Dsymbol_prefix=""' +endif + +ifeq "$(CCOMPTYPE)" "msvc" +CCOUT = -Fe +else +EMPTY = +CCOUT = -o $(EMPTY) +endif + +objinfo_helper$(EXE): objinfo_helper.c ../config/s.h + $(BYTECC) $(CCOUT)objinfo_helper$(EXE) $(BYTECCCOMPOPTS) \ + $(DEF_SYMBOL_PREFIX) $(LIBBFD_INCLUDE) objinfo_helper.c $(LIBBFD_LINK) + +OBJINFO=../compilerlibs/ocamlcommon.cma \ + ../compilerlibs/ocamlbytecomp.cma \ + ../compilerlibs/ocamlmiddleend.cma \ + ../asmcomp/printclambda.cmo \ + ../asmcomp/export_info.cmo \ + objinfo.cmo + +$(call byte_and_opt,ocamlobjinfo,$(OBJINFO),objinfo_helper$(EXE)) + +install:: + cp objinfo_helper$(EXE) "$(INSTALL_LIBDIR)/objinfo_helper$(EXE)" + +# Scan object files for required primitives +$(call byte_and_opt,primreq,config.cmo primreq.cmo,) + +LINTAPIDIFF=../compilerlibs/ocamlcommon.cmxa \ + ../compilerlibs/ocamlbytecomp.cmxa \ + ../compilerlibs/ocamlmiddleend.cmxa \ + ../asmcomp/printclambda.cmx \ + ../asmcomp/export_info.cmx \ + ../otherlibs/str/str.cmxa \ + lintapidiff.cmx + +lintapidiff.opt: INCLUDES+= -I ../otherlibs/str +lintapidiff.opt: $(LINTAPIDIFF) + $(CAMLOPT) $(LINKFLAGS) -I .. -o $@ $(LINTAPIDIFF) +clean:: + rm -f -- lintapidiff.opt lintapidiff.cm? lintapidiff.o + + +clean:: + rm -f "objinfo_helper$(EXE)" "objinfo_helper$(EXE).manifest" + + +# Copy a bytecode executable, stripping debug info + +stripdebug=../compilerlibs/ocamlcommon.cma \ + ../compilerlibs/ocamlbytecomp.cma \ + stripdebug.cmo + +$(call byte_and_opt,stripdebug,$(stripdebug),) + +# Compare two bytecode executables + +CMPBYT=../compilerlibs/ocamlcommon.cma \ + ../compilerlibs/ocamlbytecomp.cma \ + cmpbyt.cmo + +$(call byte_and_opt,cmpbyt,$(CMPBYT),) + +ifeq "$(RUNTIMEI)" "true" +install:: + cp ocaml-instr-graph ocaml-instr-report "$(INSTALL_BINDIR)/" +endif + +# Common stuff + +.SUFFIXES: + +%.cmo: %.ml + $(CAMLC) -c $(COMPFLAGS) - $< + +%.cmi: %.mli + $(CAMLC) -c $(COMPFLAGS) - $< + +%.cmx: %.ml + $(CAMLOPT) $(COMPFLAGS) -c - $< + +clean:: + rm -f *.cmo *.cmi *.cma *.dll *.so *.lib *.a + +depend: beforedepend + $(CAMLRUN) ./ocamldep -slash $(INCLUDES) *.mli *.ml > .depend + +.PHONY: clean install beforedepend depend + +include .depend diff --git a/tools/Makefile.nt b/tools/Makefile.nt index 8ebcf29e..ed9900bb 100644 --- a/tools/Makefile.nt +++ b/tools/Makefile.nt @@ -13,12 +13,4 @@ #* * #************************************************************************** -include Makefile.shared - -ifneq "$(wildcard ../flexdll/Makefile)" "" -CAMLOPT := OCAML_FLEXLINK="../boot/ocamlrun ../flexdll/flexlink.exe" \ - $(CAMLOPT) -endif - -clean:: - rm -f "objinfo_helper$(EXE).manifest" +include Makefile diff --git a/tools/Makefile.shared b/tools/Makefile.shared deleted file mode 100644 index 2803d786..00000000 --- a/tools/Makefile.shared +++ /dev/null @@ -1,383 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** -MAKEFLAGS := -r -R -include ../config/Makefile -INSTALL_BINDIR:=$(DESTDIR)$(BINDIR) -INSTALL_LIBDIR:=$(DESTDIR)$(LIBDIR) -INSTALL_COMPLIBDIR:=$(DESTDIR)$(COMPLIBDIR) -INSTALL_STUBLIBDIR:=$(DESTDIR)$(STUBLIBDIR) -INSTALL_MANDIR:=$(DESTDIR)$(MANDIR) - -ifeq ($(SYSTEM),unix) -override define shellquote -$i := $$(subst ",\",$$(subst $$$$,\$$$$,$$(subst `,\`,$i)))#")# -endef -$(foreach i,BINDIR LIBDIR COMPLIBDIR STUBLIBDIR MANDIR,$(eval $(shellquote))) -endif - -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc -DESTDIR ?= -# Setup GNU make variables storing per-target source and target, -# a list of installed tools, and a function to quote a filename for -# the shell. -override installed_tools := ocamldep ocamlprof ocamlcp ocamloptp \ - ocamlmktop ocamlmklib ocamlobjinfo - -install_files := -define byte2native -$(patsubst %.cmo,%.cmx,$(patsubst %.cma,%.cmxa,$1)) -endef - -# $1 = target, $2 = OCaml object dependencies, $3 = other dependencies -# There is a lot of subtle code here. The multiple layers of expansion -# are due to `make`'s eval() function, which evaluates the string -# passed to it as a makefile fragment. So it is crucial that variables -# not get expanded too many times. -define byte_and_opt_ -# This check is defensive programming -$(and $(filter-out 1,$(words $1)),$(error \ - cannot build file with whitespace in name)) -$1: $3 $2 - $$(CAMLC) $$(LINKFLAGS) -I .. -o $$@ $2 - -$1.opt: $3 $$(call byte2native,$2) - $$(CAMLOPT) $$(LINKFLAGS) -I .. -o $$@ $$(call byte2native,$2) - -all: $1 - -opt.opt: $1.opt - -ifeq '$(filter $(installed_tools),$1)' '$1' -install_files += $1 -endif -clean:: - rm -f -- $1 $1.opt - -endef - -# Escape any $ characters in the arguments and eval the result. -define byte_and_opt -$(eval $(call \ - byte_and_opt_,$(subst $$,$$$$,$1),$(subst $$,$$$$,$2),$(subst $$,$$$$,$3))) -endef - -ROOTDIR=.. - -ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" -export OCAML_FLEXLINK:= -else -export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe -endif - -CAMLC=$(CAMLRUN) ../boot/ocamlc -nostdlib -I ../boot \ - -use-prims ../byterun/primitives -I .. -CAMLOPT=$(CAMLRUN) ../ocamlopt -nostdlib -I ../stdlib -CAMLLEX=$(CAMLRUN) ../boot/ocamllex -INCLUDES=-I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../asmcomp \ - -I ../middle_end -I ../middle_end/base_types -I ../driver \ - -I ../toplevel -COMPFLAGS= -absname -w +a-4-9-41-42-44-45-48 -strict-sequence -warn-error A \ - -safe-string -strict-formats $(INCLUDES) -LINKFLAGS=$(INCLUDES) -VPATH := $(filter-out -I,$(INCLUDES)) - -# scrapelabels addlabels - -.PHONY: all opt.opt - -# The dependency generator - -CAMLDEP_OBJ=ocamldep.cmo -CAMLDEP_IMPORTS=timings.cmo misc.cmo config.cmo identifiable.cmo numbers.cmo \ - arg_helper.cmo clflags.cmo terminfo.cmo \ - warnings.cmo location.cmo longident.cmo docstrings.cmo \ - syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo \ - ccomp.cmo ast_mapper.cmo ast_iterator.cmo \ - builtin_attributes.cmo ast_invariants.cmo \ - pparse.cmo compenv.cmo depend.cmo - -ocamldep: LINKFLAGS += -compat-32 -$(call byte_and_opt,ocamldep,$(CAMLDEP_IMPORTS) $(CAMLDEP_OBJ),) -ocamldep: depend.cmi -ocamldep.opt: depend.cmi - -# ocamldep is precious: sometimes we are stuck in the middle of a -# bootstrap and we need to remake the dependencies -clean:: - if test -f ocamldep; then mv -f ocamldep ocamldep.bak; else :; fi - rm -f ocamldep.opt - - -# The profiler - -CSLPROF=ocamlprof.cmo -CSLPROF_IMPORTS=misc.cmo config.cmo identifiable.cmo numbers.cmo \ - arg_helper.cmo clflags.cmo terminfo.cmo \ - warnings.cmo location.cmo longident.cmo docstrings.cmo \ - syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo - -$(call byte_and_opt,ocamlprof,$(CSLPROF_IMPORTS) profiling.cmo $(CSLPROF),) - -ocamlcp_cmos = misc.cmo warnings.cmo config.cmo identifiable.cmo numbers.cmo \ - arg_helper.cmo clflags.cmo main_args.cmo - -$(call byte_and_opt,ocamlcp,$(ocamlcp_cmos) ocamlcp.cmo,) -$(call byte_and_opt,ocamloptp,$(ocamlcp_cmos) ocamloptp.cmo,) - -opt:: profiling.cmx - -install:: - cp -- profiling.cmi profiling.cmo "$(INSTALL_LIBDIR)" - -installopt:: - cp -- profiling.cmx profiling.$(O) "$(INSTALL_LIBDIR)" - -# To help building mixed-mode libraries (OCaml + C) - -$(call byte_and_opt,ocamlmklib,ocamlmklibconfig.cmo config.cmo \ - ocamlmklib.cmo,) - - -ocamlmklibconfig.ml: ../config/Makefile Makefile - (echo 'let bindir = "$(BINDIR)"'; \ - echo 'let supports_shared_libraries = $(SUPPORTS_SHARED_LIBRARIES)';\ - echo 'let byteccrpath = "$(BYTECCRPATH)"'; \ - echo 'let nativeccrpath = "$(NATIVECCRPATH)"'; \ - echo 'let mksharedlibrpath = "$(MKSHAREDLIBRPATH)"'; \ - echo 'let toolpref = "$(TOOLPREF)"'; \ - sed -n -e 's/^#ml //p' ../config/Makefile) \ - > ocamlmklibconfig.ml - -beforedepend:: ocamlmklibconfig.ml - -clean:: - rm -f ocamlmklibconfig.ml - -# To make custom toplevels - -OCAMLMKTOP=ocamlmktop.cmo -OCAMLMKTOP_IMPORTS=misc.cmo identifiable.cmo numbers.cmo config.cmo \ - arg_helper.cmo clflags.cmo ccomp.cmo - -$(call byte_and_opt,ocamlmktop,$(OCAMLMKTOP_IMPORTS) $(OCAMLMKTOP),) - -# Converter olabl/ocaml 2.99 to ocaml 3 - -OCAML299TO3= lexer299.cmo ocaml299to3.cmo -LIBRARY3= misc.cmo warnings.cmo location.cmo - -ocaml299to3: $(OCAML299TO3) - $(CAMLC) $(LINKFLAGS) -o ocaml299to3 $(LIBRARY3) $(OCAML299TO3) - -lexer299.ml: lexer299.mll - $(CAMLLEX) lexer299.mll - -#install:: -# cp ocaml299to3 "$(INSTALL_BINDIR)/ocaml299to3$(EXE)" - -clean:: - rm -f ocaml299to3 lexer299.ml - -# Label remover for interface files (upgrade 3.02 to 3.03) - -SCRAPELABELS= lexer301.cmo scrapelabels.cmo - -scrapelabels: $(SCRAPELABELS) - $(CAMLC) $(LINKFLAGS) -o scrapelabels $(LIBRARY3) $(SCRAPELABELS) - -lexer301.ml: lexer301.mll - $(CAMLLEX) lexer301.mll - -#install:: -# cp scrapelabels "$(INSTALL_LIBDIR)" - -clean:: - rm -f scrapelabels lexer301.ml - -# Insert labels following an interface file (upgrade 3.02 to 3.03) - -ADDLABELS_IMPORTS=misc.cmo config.cmo arg_helper.cmo clflags.cmo \ - identifiable.cmo numbers.cmo terminfo.cmo \ - warnings.cmo location.cmo longident.cmo docstrings.cmo \ - syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo - -addlabels: addlabels.cmo - $(CAMLC) $(LINKFLAGS) -w sl -o addlabels \ - $(ADDLABELS_IMPORTS) addlabels.cmo - -#install:: -# cp addlabels "$(INSTALL_LIBDIR)" - -ifeq ($(UNIX_OR_WIN32),unix) -LN := ln -sf -else -LN := cp -pf -endif - -install:: - for i in $(install_files); \ - do \ - cp -- "$$i" "$(INSTALL_BINDIR)/$$i.byte$(EXE)" && \ - if test -f "$$i".opt; then \ - cp -- "$$i.opt" "$(INSTALL_BINDIR)/$$i.opt$(EXE)" && \ - (cd "$(INSTALL_BINDIR)/" && $(LN) "$$i.opt$(EXE)" "$$i$(EXE)"); \ - else \ - (cd "$(INSTALL_BINDIR)/" && $(LN) "$$i.byte$(EXE)" "$$i$(EXE)"); \ - fi; \ - done - -clean:: - rm -f addlabels - -# The preprocessor for asm generators - -CVT_EMIT=cvt_emit.cmo - -cvt_emit: $(CVT_EMIT) - $(CAMLC) $(LINKFLAGS) -o cvt_emit $(CVT_EMIT) - -# cvt_emit is precious: sometimes we are stuck in the middle of a -# bootstrap and we need to remake the dependencies -.PRECIOUS: cvt_emit -clean:: - if test -f cvt_emit; then mv -f cvt_emit cvt_emit.bak; else :; fi - -cvt_emit.ml: cvt_emit.mll - $(CAMLLEX) cvt_emit.mll - -clean:: - rm -f cvt_emit.ml - -beforedepend:: cvt_emit.ml - -# Reading cmt files - -READ_CMT= \ - ../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma \ - \ - cmt2annot.cmo read_cmt.cmo - -# Reading cmt files -$(call byte_and_opt,read_cmt,$(READ_CMT),) - - -# The bytecode disassembler - -DUMPOBJ=opnames.cmo dumpobj.cmo - -$(call byte_and_opt,dumpobj,misc.cmo identifiable.cmo numbers.cmo tbl.cmo \ - config.cmo ident.cmo opcodes.cmo bytesections.cmo \ - $(DUMPOBJ),) - -opnames.ml: ../byterun/caml/instruct.h - unset LC_ALL || : ; \ - unset LC_CTYPE || : ; \ - unset LC_COLLATE LANG || : ; \ - sed -e '/[/][*]/d' \ - -e '/^#/d' \ - -e 's/enum \(.*\) {/let names_of_\1 = [|/' \ - -e 's/.*};$$/ |]/' \ - -e 's/\([A-Z][A-Z_0-9a-z]*\)/"\1"/g' \ - -e 's/,/;/g' \ - ../byterun/caml/instruct.h > opnames.ml - -clean:: - rm -f opnames.ml - -beforedepend:: opnames.ml - -# Display info on compiled files - -ifeq "$(SYSTEM)" "macosx" -DEF_SYMBOL_PREFIX = '-Dsymbol_prefix="_"' -else -DEF_SYMBOL_PREFIX = '-Dsymbol_prefix=""' -endif - -ifeq "$(CCOMPTYPE)" "msvc" -CCOUT = -Fe -else -EMPTY = -CCOUT = -o $(EMPTY) -endif - -objinfo_helper$(EXE): objinfo_helper.c ../config/s.h - $(BYTECC) $(CCOUT)objinfo_helper$(EXE) $(BYTECCCOMPOPTS) \ - $(DEF_SYMBOL_PREFIX) $(LIBBFD_INCLUDE) objinfo_helper.c $(LIBBFD_LINK) - -OBJINFO=../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma \ - ../compilerlibs/ocamlmiddleend.cma \ - ../asmcomp/printclambda.cmo \ - ../asmcomp/export_info.cmo \ - objinfo.cmo - -$(call byte_and_opt,ocamlobjinfo,$(OBJINFO),objinfo_helper$(EXE)) - -install:: - cp objinfo_helper$(EXE) "$(INSTALL_LIBDIR)/objinfo_helper$(EXE)" - -# Scan object files for required primitives -$(call byte_and_opt,primreq,config.cmo primreq.cmo,) - -clean:: - rm -f "objinfo_helper$(EXE)" - - -# Copy a bytecode executable, stripping debug info - -stripdebug=../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma \ - stripdebug.cmo - -$(call byte_and_opt,stripdebug,$(stripdebug),) - -# Compare two bytecode executables - -CMPBYT=../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma \ - cmpbyt.cmo - -$(call byte_and_opt,cmpbyt,$(CMPBYT),) - -ifeq "$(RUNTIMEI)" "true" -install:: - cp ocaml-instr-graph ocaml-instr-report "$(INSTALL_BINDIR)/" -endif - -# Common stuff - -.SUFFIXES: - -%.cmo: %.ml - $(CAMLC) -c $(COMPFLAGS) - $< - -%.cmi: %.mli - $(CAMLC) -c $(COMPFLAGS) - $< - -%.cmx: %.ml - $(CAMLOPT) $(COMPFLAGS) -c - $< - -clean:: - rm -f *.cmo *.cmi *.cma *.dll *.so *.lib *.a - -depend: beforedepend - $(CAMLRUN) ./ocamldep -slash $(INCLUDES) *.mli *.ml > .depend - -.PHONY: clean install beforedepend depend - -include .depend diff --git a/tools/check-typo b/tools/check-typo index a19943a6..550ce252 100755 --- a/tools/check-typo +++ b/tools/check-typo @@ -159,7 +159,7 @@ IGNORE_DIRS=" ocamldoc/*|*/ocamldoc/*) rules="long-line,$rules";; esac - (cat "$f"; echo) \ + (cat "$f" | tr -d '\r'; echo) \ | awk -v rules="$rules" -v svnrules="$svnrules" -v file="$f" \ ' function err(name, msg) { diff --git a/tools/ci-build b/tools/ci-build index 8e0969cd..46af368b 100755 --- a/tools/ci-build +++ b/tools/ci-build @@ -17,21 +17,37 @@ # This script is run on our continuous-integration servers to recompile # from scratch and run the test suite. +# To know the slave's architecture, this script looks at the OCAML_ARCH +# environment variable. For a given node NODe, this variable can be defined +# in Jenkins at the following address: +# https://ci.inria.fr/ocaml/computer/NODE/configure + # arguments: -# 1. architecture: bsd, macos, linux, cygwin, mingw, mingw64, msvc, msvc64 -# 2. directory in which to build (trunk, 4.02, etc) -# for windows, this is relative to $HOME/jenkins-workspace -# for bsd, macos, linux, this is ignored and the build is always in . -# 3. options: -# -conf configure-option add configure-option to configure cmd line -# -patch1 file-name apply patch with -p1 -# -newmakefiles do not use Makefile.nt even for Windows +# -conf configure-option add configure-option to configure cmd line +# -patch1 file-name apply patch with -p1 +# -no-native do not build "opt" and "opt.opt" error () { echo "$1" >&2 exit 3 } +arch_error() { + configure_url="https://ci.inria.fr/ocaml/computer/${NODE_NAME}/configure" + msg="Unknown architecture. Make sure the OCAML_ARCH environemnt" + msg="$msg variable has been defined." + msg="$msg\nSee ${configure_url}" + error "$msg" +} + +# Kill a task on Windows +# Errors are ignored +kill_task() +{ + task=$1 + taskkill /f /im ${task} || true +} + quote1 () { printf "'%s'" "`printf %s "$1" | sed -e "s/'/'\\\\\\\\''/g"`"; } @@ -41,17 +57,15 @@ quote1 () { set -x ######################################################################### -# "Parse" mandatory command-line arguments. - -arch="$1" -branch="$2" -shift 2 +# Save the current directory (on cygwin, /etc/profile changes it) +jenkinsdir="$(pwd)" +echo jenkinsdir=${jenkinsdir} ######################################################################### # If we are called from a Windows batch script, we must set up the # Unix environment variables (e.g. PATH). -case "$arch" in +case "${OCAML_ARCH}" in bsd|macos|linux) ;; cygwin|mingw|mingw64) . /etc/profile @@ -67,7 +81,7 @@ case "$arch" in . "$HOME/.profile" . "$HOME/.msenv64" ;; - *) error "unknown architecture: $arch";; + *) arch_error;; esac ######################################################################### @@ -81,72 +95,67 @@ set -ex # default values make=make instdir="$HOME/ocaml-tmp-install" -docheckout=false -makefile=Makefile configure=unix +confoptions="${OCAML_CONFIGURE_OPTIONS}" +make_native=true +cleanup=false -case "$arch" in - bsd) - make=gmake - workdir=. - ;; - macos) - workdir=. - ;; +case "${OCAML_ARCH}" in + bsd) make=gmake ;; + macos) ;; linux) - workdir=. + confoptions="${confoptions} -with-instrumented-runtime" ;; cygwin) - workdir="$HOME/jenkins-workspace/$branch" - docheckout=true - ;; + cleanup=true;; mingw) - instdir=/cygdrive/c/ocamlmgw - workdir="$HOME/jenkins-workspace/$branch" - docheckout=true - makefile=Makefile.nt + instdir='C:/ocamlmgw' configure=nt + cleanup=true ;; mingw64) - instdir=/cygdrive/c/ocamlmgw64 - workdir="$HOME/jenkins-workspace/$branch" - docheckout=true - makefile=Makefile.nt + instdir='C:/ocamlmgw64' configure=nt + cleanup=true ;; msvc) - instdir=/cygdrive/c/ocamlms - workdir="$HOME/jenkins-workspace/$branch" - docheckout=true - makefile=Makefile.nt + instdir='C:/ocamlms' configure=nt + cleanup=true ;; msvc64) - instdir=/cygdrive/c/ocamlms64 - workdir="$HOME/jenkins-workspace/$branch" - docheckout=true - makefile=Makefile.nt + instdir='C:/ocamlms64' configure=nt + cleanup=true ;; - *) error "unknown architecture: $arch";; + *) arch_error;; esac +# Make sure two builds won't use the same install directory +instdir="$instdir-$$" + +######################################################################### +# On Windows, cleanup processes that may remain from previous run + +if $cleanup; then + tasks="tee ocamlrun program" + for task in ${tasks}; do kill_task ${task}.exe; done +fi + ######################################################################### # Go to the right directory pwd -cd "$workdir" +cd "$jenkinsdir" ######################################################################### # parse optional command-line arguments (has to be done after the "cd") -# Configure options are not allowed to have spaces or special characters -# for the moment. We'll fix that when needed. -confoptions="" + while [ $# -gt 0 ]; do case $1 in -conf) confoptions="$confoptions `quote1 "$2"`"; shift;; -patch1) patch -f -p1 <"$2"; shift;; - -newmakefiles) makefile=Makefile;; + -no-native) make_native=false;; *) error "unknown option $1";; esac shift @@ -158,24 +167,42 @@ done # Tell gcc to use only ASCII in its diagnostic outputs. export LC_ALL=C -$make -f $makefile distclean || : +$make distclean || : -if $docheckout; then - git pull -fi +# `make distclean` does not clean the files from previous versions that +# are not produced by the current version, so use `git clean` in addition. +git clean -f -d -x case $configure in - unix) eval "./configure -prefix '$instdir' $confoptions";; + unix) + confoptions="$confoptions -with-debug-runtime" + if $flambda; then + confoptions="$confoptions -flambda" + fi + eval "./configure -prefix '$instdir' $confoptions" + ;; nt) cp config/m-nt.h config/m.h cp config/s-nt.h config/s.h - cp config/Makefile.$arch config/Makefile + cp config/Makefile.${OCAML_ARCH} config/Makefile + sed -i "s%PREFIX=\(.\+\)%PREFIX=${instdir}%" config/Makefile + sed -i 's%RUNTIMED=.\+%RUNTIMED=true%' config/Makefile + if $flambda; then + sed -i 's%FLAMBDA=.\+%FLAMBDA=true%' config/Makefile + fi ;; *) error "internal error";; esac -$make -f $makefile world.opt -$make -f $makefile install +$make coldstart +$make core +$make coreboot +$make world +if $make_native; then + $make opt + $make opt.opt +fi +$make install rm -rf "$instdir" cd testsuite diff --git a/tools/cmt2annot.ml b/tools/cmt2annot.ml index 69dcca78..53299f98 100644 --- a/tools/cmt2annot.ml +++ b/tools/cmt2annot.ml @@ -96,7 +96,7 @@ let rec iterator ~scope rebuild_env = | Texp_match (_, f1, f2, _) -> bind_cases f1; bind_cases f2 - | Texp_function (_, f, _) + | Texp_function { cases = f; } | Texp_try (_, f) -> bind_cases f | _ -> () diff --git a/tools/dumpobj.ml b/tools/dumpobj.ml index e4c8186c..c3d60bff 100644 --- a/tools/dumpobj.ml +++ b/tools/dumpobj.ml @@ -547,6 +547,12 @@ let dump_exe ic = let arg_list = [ "-noloc", Arg.Clear print_locations, " : don't print source information"; "-reloc", Arg.Set print_reloc_info, " : print relocation information"; + "-args", Arg.Expand Arg.read_arg, + " Read additional newline separated command line arguments \n\ + \ from "; + "-args0", Arg.Expand Arg.read_arg0, + " Read additional NUL separated command line arguments from \n\ + \ "; ] let arg_usage = Printf.sprintf "%s [OPTIONS] FILES : dump content of bytecode files" @@ -568,7 +574,7 @@ let arg_fun filename = printf "## end of ocaml dump of %S\n%!" filename let main() = - Arg.parse arg_list arg_fun arg_usage; + Arg.parse_expand arg_list arg_fun arg_usage; exit 0 let _ = main () diff --git a/tools/lintapidiff.ml b/tools/lintapidiff.ml new file mode 100644 index 00000000..87cf1d4b --- /dev/null +++ b/tools/lintapidiff.ml @@ -0,0 +1,313 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Copyright 2016--2017 Edwin Török *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(* Detects newly added symbols that are missing "@since" annotations, + or removed symbols that didn't have "@deprecated" annotation before. + + Handles: values, exceptions. + Ignores: variants, record fields, classes, module aliasing or includes, ... + Out of scope: changes in arity, parameters, ... + + Missing attributes on undocumented identifiers in undocumented modules + are not reported. + + Use 'make lintapidiff' in the root directory to run +*) +open Location +open Parsetree + +(* oldest Ocaml version that we show missing @since errors for *) +let oldest = "4.00.0" + +(* do not check @since annotations for these *) +let ignore_changes_for = [ + "type Pervasives.format6" (* this used to be a built-in type *); + (* discarded by stop comments: *) + "type Unix.map_file_impl"; + "value Unix.map_file_impl"; +] + +module IdMap = Map.Make(String) + +module Version : sig + type t + val oldest : t + val is_same : t -> t -> bool + val is_strictly_older: t -> than:t -> bool + val of_string_exn : string -> t + val pp : Format.formatter -> t -> unit +end = struct + type t = int * int * int + + let is_same a b = a = b + let is_strictly_older a ~than = a < than + let of_string_exn str = + try Scanf.sscanf str "%u.%u.%u" (fun a b c -> (a,b,c)) + with _ -> Scanf.sscanf str "%u.%u" (fun a b -> (a,b,0)) + + let oldest = of_string_exn oldest + let pp ppf (major,minor,patch) = + Format.fprintf ppf "%u.%02u.%u" major minor patch +end + +module Doc = struct + type t = { + since: Version.t option; + deprecated: bool; + loc: Location.t; + has_doc_parent: bool; + has_doc: bool; + } + + let empty = {since = None; deprecated=false; loc=Location.none; + has_doc_parent=false;has_doc=false} + + let since = Str.regexp "\\(.\\|\n\\)*@since +\\([^ ]+\\).*" + + let find_attr lst attrs = + try Some (List.find (fun (loc, _) -> List.mem loc.txt lst) attrs) + with Not_found -> None + + let get_doc lst attrs = match find_attr lst attrs with + | Some (_, PStr [{pstr_desc=Pstr_eval( + {pexp_desc=Pexp_constant(Pconst_string (doc, _));_}, _);_}]) + when doc <> "/*" && doc <> "" -> Some doc + | _ -> None + + let is_deprecated attrs = + find_attr ["ocaml.deprecated"; "deprecated"] attrs <> None || + match get_doc ["ocaml.text"] attrs with (* for toplevel module annotation *) + | None -> false + | Some text -> + try Misc.search_substring "@deprecated" text 0 >= 0 + with Not_found -> false + + let get parent_info loc attrs = + let doc = get_doc ["ocaml.doc"; "ocaml.text"] attrs in + { + since = (match doc with + | Some doc -> + if Str.string_match since doc 0 then + Some (Str.matched_group 2 doc |> String.trim + |> Version.of_string_exn) + else parent_info.since + | None -> parent_info.since); + deprecated = parent_info.deprecated || is_deprecated attrs; + loc; + has_doc_parent = parent_info.has_doc_parent || parent_info.has_doc; + has_doc = doc <> None + } +end + +module Ast = struct + let add_path ~f prefix path name attrs inherits map = + let path = Path.Pdot (path, name.txt, 0) in + let id = prefix ^ " " ^ (Printtyp.string_of_path path) in + (* inherits: annotation on parent is inherited by all children, + so it suffices to annotate just the new module, and not all its elements + *) + let info = f inherits name.loc attrs in + IdMap.add id info map + + let rec add_item ~f path inherits map item = + let rec add_module_type path ty (inherits, map) = + let self = add_item ~f path inherits in + match ty.pmty_desc with + | Pmty_signature lst -> List.fold_left self map lst + | Pmty_functor ({txt;_}, _, m) -> + let path = Path.Papply(path, Path.Pident (Ident.create txt)) in + add_module_type path m (inherits, map) + | Pmty_ident _ | Pmty_with _ | Pmty_typeof _| Pmty_extension _ + | Pmty_alias _ -> map + in + let enter_path path name ty attrs map = + let path = Path.Pdot (path, name.txt, 0) in + let inherits = f inherits name.loc attrs in + add_module_type path ty (inherits, map) + in + let add_module map m = + enter_path path m.pmd_name m.pmd_type m.pmd_attributes map + in + match item.psig_desc with + | Psig_value vd -> + add_path ~f "value" path vd.pval_name vd.pval_attributes inherits map + | Psig_type (_,lst) -> + List.fold_left (fun map t -> + add_path ~f "type" path t.ptype_name t.ptype_attributes inherits map + ) map lst + | Psig_exception e -> + add_path ~f "exception" path e.pext_name e.pext_attributes inherits map + | Psig_module m -> add_module map m + | Psig_recmodule lst -> List.fold_left add_module map lst + | Psig_modtype s -> + begin match s.pmtd_type with + | None -> map + | Some ty -> + enter_path path s.pmtd_name ty s.pmtd_attributes map + end + | Psig_typext _|Psig_open _|Psig_include _|Psig_class _|Psig_class_type _ + | Psig_attribute _|Psig_extension _ -> map + + let add_items ~f path (inherits,map) items = + (* module doc *) + let inherits = List.fold_left (fun inherits -> function + | {psig_desc=Psig_attribute a;_} + when (Doc.get_doc ["ocaml.doc";"ocaml.text"][a] <> None) -> + f inherits (Location.none) [a] + | _ -> inherits + ) inherits items in + List.fold_left (add_item ~f path inherits) map items + + let parse_file ~orig ~f ~init input = + try + let id = + orig |> Filename.chop_extension |> Filename.basename |> + String.capitalize_ascii |> Ident.create in + let ast = Pparse.file ~tool_name:"lintapidiff" Format.err_formatter input + Parse.interface Pparse.Signature in + Location.input_name := orig; + add_items ~f (Path.Pident id) (init,IdMap.empty) ast + with e -> + Format.eprintf "%a@." Location.report_exception e; + raise e +end + +module Git = struct + let with_show ~f rev path = + let obj = rev ^ ":" ^ path in + let suffix = Printf.sprintf "-%s:%s" rev (Filename.basename path) in + let tmp = Filename.temp_file "lintapidiff" suffix in + let cmd = Printf.sprintf "git show %s >%s 2>/dev/null" + (Filename.quote obj) (Filename.quote tmp) in + Misc.try_finally (fun () -> + match Sys.command cmd with + | 0 -> Ok (f tmp) + | 128 -> Error `Not_found + | r -> + Location.errorf ~loc:(in_file obj) "exited with code %d" r |> + Format.eprintf "%a@." Location.report_error; + Error `Exit) + (fun () -> Misc.remove_file tmp) +end + +module Diff = struct + type seen_info = { + last_not_seen: Version.t option; + first_seen: Version.t; + deprecated: bool; + } + + let err k (loc, msg, seen, latest) = + let info_seen ppf = function + | None -> + Format.fprintf ppf "%s was not seen in any analyzed version" k + | Some a -> + begin match a.last_not_seen with + | Some v -> + Format.fprintf ppf "%s was not seen in version %a" k Version.pp v + | None -> Format.fprintf ppf "%s was seen in all analyzed versions" k + end; + Format.fprintf ppf "@,%s was seen in version %a" + k Version.pp a.first_seen; + if a.deprecated then + Format.fprintf ppf "@,%s was marked as deprecated" k + in + let info_latest ppf = function + | None -> Format.fprintf ppf "%s was deleted in HEAD" k + | Some s -> + begin match s.Doc.since with + | Some v -> Format.fprintf ppf "%s has @since %a" k Version.pp v + | None -> Format.fprintf ppf "%s has no @since annotation" k + end; + if s.Doc.deprecated then + Format.fprintf ppf "@,%s is marked as deprecated" k + in + Location.errorf ~loc "@[%s %s@,%a@,%a@]" msg k + info_seen seen info_latest latest |> + Format.eprintf "%a@." Location.report_error + + let parse_file_at_rev ~path (prev,accum) rev = + let merge _ a b = match a, b with + | Some a, Some b -> + Some { a with deprecated=b.deprecated } + | None, Some a -> Some { a with last_not_seen=prev } + | Some _, None -> None (* deleted *) + | None, None -> assert false + in + let first_seen = Version.of_string_exn rev in + let empty = {last_not_seen=None;first_seen;deprecated=false} in + let f = Ast.parse_file ~orig:path ~init:empty ~f:(fun _ _ attrs -> + { last_not_seen=None;first_seen; deprecated=Doc.is_deprecated attrs }) in + let map = match Git.with_show ~f rev path with + | Ok r -> r + | Error `Not_found -> IdMap.empty + | Error `Exit -> raise Exit in + Some first_seen, IdMap.merge merge accum map + + let check_changes ~first ~last default k seen latest = + let is_old v = Version.is_strictly_older v ~than:Version.oldest || + Version.is_same v first + in + if List.mem k ignore_changes_for then None (* ignored *) + else let open! Doc in + match (seen:seen_info option), latest with + | None, None -> assert false + | _, Some {has_doc_parent=false;has_doc=false;deprecated=false;_} -> + None (* undocumented *) + | Some {deprecated=true;_}, None -> None (* deleted deprecated *) + | Some _, None -> + Some (default, "deleted non-deprecated", seen, latest) + | _, Some {deprecated=true;since=None;_} -> None (* marked as deprecated *) + | None, Some {loc; since=None; _} -> + Some (loc, "missing @since for new", seen, latest) + | Some {first_seen;_}, Some {loc; since=None;_} -> + if is_old first_seen then None + else Some (loc, "missing @since", seen, latest) + | Some {first_seen;_}, Some {loc; since=Some s;_} -> + if Version.is_same first_seen s then None (* OK, @since matches *) + else Some (loc, "mismatched @since", seen, latest) + | None, Some {loc; since=Some s;_} -> + if Version.is_strictly_older s ~than:last || + Version.is_same s last then + Some (loc, "too old @since for new", seen, latest) + else None + + let file path tags = + let _,syms_vers = List.fold_left (parse_file_at_rev ~path) + (None,IdMap.empty) tags in + let current = Ast.parse_file ~orig:path ~f:Doc.get ~init:Doc.empty path in + let loc = Location.in_file path in + let first = List.hd tags |> Version.of_string_exn + and last = List.hd (List.rev tags) |> Version.of_string_exn in + IdMap.merge (check_changes ~first ~last loc) syms_vers current +end + +let rec read_lines accum = + match input_line stdin with + | line -> read_lines (line :: accum) + | exception End_of_file -> accum + +let () = + let tags = Sys.argv |> Array.to_list |> List.tl in + if tags = [] then begin + Printf.eprintf "tags list is empty!\n"; + exit 1; + end; + let paths = read_lines [] in + Printf.printf "Parsing\n%!"; + let count = List.fold_left (fun count path -> + let problems = Diff.file path tags in + IdMap.iter Diff.err problems; + count + IdMap.cardinal problems + ) 0 paths in + Printf.printf "Found %d potential problems\n%!" count; + if count > 0 then exit 2 diff --git a/tools/make-version-header.sh b/tools/make-version-header.sh index 7b37298e..ce3b70c6 100755 --- a/tools/make-version-header.sh +++ b/tools/make-version-header.sh @@ -32,8 +32,8 @@ # be used. case $# in - 0) version="`ocamlc -v | sed -n -e 's/.*version //p'`";; - 1) version="`sed -e 1q $1`";; + 0) version="`ocamlc -v | tr -d '\r' | sed -n -e 's/.*version //p'`";; + 1) version="`sed -e 1q $1 | tr -d '\r'`";; *) echo "usage: make-version-header.sh [version-file]" >&2 exit 2;; esac diff --git a/tools/make_opcodes.mll b/tools/make_opcodes.mll new file mode 100644 index 00000000..5c7cd854 --- /dev/null +++ b/tools/make_opcodes.mll @@ -0,0 +1,47 @@ +(***********************************************************************) +(* *) +(* OCaml *) +(* *) +(* Nicolas Ojeda Bar, LexiFi *) +(* *) +(* Copyright 2016 Institut National de Recherche en Informatique et *) +(* en Automatique. All rights reserved. This file is distributed *) +(* under the terms of the Q Public License version 1.0. *) +(* *) +(***********************************************************************) + +let ident = ['a'-'z''A'-'Z''_']['a'-'z''A'-'Z''0'-'9''_']* +let space = [' ''\n''\r''\t']* + +rule find_enum = parse +| "enum" space (ident as id) space '{' { id, opnames lexbuf } +| _ { find_enum lexbuf } + +and opnames = parse +| space (ident as op) space ',' { op :: opnames lexbuf } +| space ident space '}' { [] } + +{ + let print_opnames = ref false + let print_opcodes = ref false + + open Printf + + let () = + let spec = + [ + "-opnames", Arg.Set print_opnames, " Dump opcode names"; + "-opcodes", Arg.Set print_opcodes, " Dump opcode numbers"; + ] + in + Arg.parse (Arg.align spec) ignore "Extract opcode info from instruct.h"; + let lexbuf = Lexing.from_channel stdin in + let id, opnames = find_enum lexbuf in + if !print_opnames then begin + printf "let names_of_%s = [|\n" id; + List.iter (fun s -> printf " %S;\n" s) opnames; + printf "|]\n" + end; + if !print_opcodes then + List.iteri (fun i op -> printf "let op%s = %i\n" op i) opnames +} diff --git a/tools/objinfo.ml b/tools/objinfo.ml index 924f61fe..6f0dfaac 100644 --- a/tools/objinfo.ml +++ b/tools/objinfo.ml @@ -23,6 +23,10 @@ open Misc open Config open Cmo_format +(* Command line option to prevent printing approximation and function code *) +let no_approx = ref false +let no_code = ref false + let input_stringlist ic len = let get_string_list sect len = let rec fold s e acc = @@ -115,6 +119,12 @@ let print_general_infos name crc defines cmi cmx = printf "Implementations imported:\n"; List.iter print_name_crc cmx +let print_global_table table = + printf "Globals defined:\n"; + Tbl.iter + (fun id _ -> print_line (Ident.name id)) + table.num_tbl + open Cmx_format let print_cmx_infos (ui, crc) = @@ -122,16 +132,33 @@ let print_cmx_infos (ui, crc) = ui.ui_name crc ui.ui_defines ui.ui_imports_cmi ui.ui_imports_cmx; begin match ui.ui_export_info with | Clambda approx -> - printf "Approximation:\n"; - Format.fprintf Format.std_formatter " %a@." Printclambda.approx approx + if not !no_approx then begin + printf "Clambda approximation:\n"; + Format.fprintf Format.std_formatter " %a@." Printclambda.approx approx + end else + Format.printf "Clambda unit@."; | Flambda export -> - printf "Flambda export information:\n"; - let cu = - Compilation_unit.create (Ident.create_persistent ui.ui_name) - (Linkage_name.create "__dummy__") - in - Compilation_unit.set_current cu; - Format.printf " %a\n" Export_info.print_all export + if not !no_approx || not !no_code then + printf "Flambda export information:\n" + else + printf "Flambda unit\n"; + if not !no_approx then begin + let cu = + Compilation_unit.create (Ident.create_persistent ui.ui_name) + (Linkage_name.create "__dummy__") + in + Compilation_unit.set_current cu; + let root_symbols = + List.map (fun s -> + Symbol.unsafe_create cu (Linkage_name.create ("caml"^s))) + ui.ui_defines + in + Format.printf "approximations@ %a@.@." + Export_info.print_approx (export, root_symbols) + end; + if not !no_code then + Format.printf "functions@ %a@.@." + Export_info.print_functions export end; let pr_funs _ fns = List.iter (fun arity -> printf " %d" arity) fns in @@ -201,6 +228,8 @@ let dump_byte ic = "Primitives used" print_line (input_stringlist ic len) + | "SYMB" -> + print_global_table (input_value ic) | _ -> () with _ -> () ) @@ -291,12 +320,21 @@ let dump_obj filename = end end -let arg_list = [] +let arg_list = [ + "-no-approx", Arg.Set no_approx, " Do not print module approximation information"; + "-no-code", Arg.Set no_code, " Do not print code from exported flambda functions"; + "-args", Arg.Expand Arg.read_arg, + " Read additional newline separated command line arguments \n\ + \ from "; + "-args0", Arg.Expand Arg.read_arg0, + " Read additional NUL separated command line arguments from \n\ + \ "; +] let arg_usage = Printf.sprintf "%s [OPTIONS] FILES : give information on files" Sys.argv.(0) let main() = - Arg.parse arg_list dump_obj arg_usage; + Arg.parse_expand arg_list dump_obj arg_usage; exit 0 let _ = main () diff --git a/tools/objinfo_helper.c b/tools/objinfo_helper.c index 125c2c1d..7a36b388 100644 --- a/tools/objinfo_helper.c +++ b/tools/objinfo_helper.c @@ -13,8 +13,6 @@ /**************************************************************************/ #include "../config/s.h" -#include "../byterun/caml/mlvalues.h" -#include "../byterun/caml/alloc.h" #include #ifdef HAS_LIBBFD diff --git a/tools/ocamlcp.ml b/tools/ocamlcp.ml index 22d1e29a..278952f7 100644 --- a/tools/ocamlcp.ml +++ b/tools/ocamlcp.ml @@ -126,6 +126,8 @@ module Options = Main_args.Make_bytecomp_options (struct let _dflambda = option "-dflambda" let _dinstr = option "-dinstr" let _dtimings = option "-dtimings" + let _args = Arg.read_arg + let _args0 = Arg.read_arg0 let anonymous = process_file end);; @@ -145,7 +147,7 @@ let optlist = :: ("-p", Arg.String add_profarg, "[afilmt] Same as option -P") :: Options.list in -Arg.parse optlist process_file usage; +Arg.parse_expand optlist process_file usage; if !with_impl && !with_intf then begin fprintf stderr "ocamlcp cannot deal with both \"-impl\" and \"-intf\"\n"; fprintf stderr "please compile interfaces and implementations separately\n"; diff --git a/tools/ocamldep.ml b/tools/ocamldep.ml index 4fd3f1cf..215de187 100644 --- a/tools/ocamldep.ml +++ b/tools/ocamldep.ml @@ -293,7 +293,7 @@ let read_parse_and_extract parse_function extract_function def ast_kind let bound_vars = List.fold_left (fun bv modname -> - Depend.open_module bv (Longident.Lident modname)) + Depend.open_module bv (Longident.parse modname)) !module_map ((* PR#7248 *) List.rev !Clflags.open_modules) in let r = extract_function bound_vars ast in @@ -546,7 +546,7 @@ let _ = Clflags.classic := false; add_to_list first_include_dirs Filename.current_dir_name; Compenv.readenv ppf Before_args; - Arg.parse [ + Clflags.add_arguments __LOC__ [ "-absname", Arg.Set Location.absname, " Show absolute filenames in error messages"; "-all", Arg.Set all_dependencies, @@ -580,6 +580,8 @@ let _ = " Output one line per file, regardless of the length"; "-open", Arg.String (add_to_list Clflags.open_modules), " Opens the module before typing"; + "-plugin", Arg.String Compplugin.load, + " Load dynamic plugin "; "-pp", Arg.String(fun s -> Clflags.preprocessor := Some s), " Pipe sources through preprocessor "; "-ppx", Arg.String (add_to_list first_ppx), @@ -592,7 +594,14 @@ let _ = " Print version and exit"; "-vnum", Arg.Unit print_version_num, " Print version number and exit"; - ] file_dependencies usage; + "-args", Arg.Expand Arg.read_arg, + " Read additional newline separated command line arguments \n\ + \ from "; + "-args0", Arg.Expand Arg.read_arg0, + " Read additional NUL separated command line arguments from \n\ + \ " + ]; + Clflags.parse_arguments file_dependencies usage; Compenv.readenv ppf Before_link; if !sort_files then sort_files_by_dependencies !files else List.iter print_file_dependencies (List.sort compare !files); diff --git a/tools/ocamlmklib.ml b/tools/ocamlmklib.ml index 391bad54..e5dda65e 100644 --- a/tools/ocamlmklib.ml +++ b/tools/ocamlmklib.ml @@ -242,11 +242,27 @@ let transl_path s = in Bytes.to_string (aux 0) | _ -> s +let flexdll_dirs = + let dirs = + let expand = Misc.expand_directory Config.standard_library in + List.map expand Config.flexdll_dirs + in + let f dir = + let dir = + if String.contains dir ' ' then + "\"" ^ dir ^ "\"" + else + dir + in + "-L" ^ dir + in + List.map f dirs + let build_libs () = if !c_objs <> [] then begin if !dynlink then begin let retcode = command - (Printf.sprintf "%s %s -o %s %s %s %s %s %s" + (Printf.sprintf "%s %s -o %s %s %s %s %s %s %s" Config.mkdll (if !debug then "-g" else "") (prepostfix "dll" !output_c Config.ext_dll) @@ -255,6 +271,7 @@ let build_libs () = (String.concat " " !ld_opts) (make_rpath mksharedlibrpath) (String.concat " " !c_libs) + (String.concat " " flexdll_dirs) ) in if retcode <> 0 then if !failsafe then dynlink := false else exit 2 diff --git a/tools/ocamloptp.ml b/tools/ocamloptp.ml index 188674af..33147ea7 100644 --- a/tools/ocamloptp.ml +++ b/tools/ocamloptp.ml @@ -51,6 +51,8 @@ let incompatible o = module Options = Main_args.Make_optcomp_options (struct let _a () = make_archive := true; option "-a" () let _absname = option "-absname" + let _afl_instrument = option "-afl-instrument" + let _afl_inst_ratio n = option_with_int "-afl-inst-ratio" n let _annot = option "-annot" let _binannot = option "-bin-annot" let _c = option "-c" @@ -172,6 +174,8 @@ module Options = Main_args.Make_optcomp_options (struct let _dtimings = option "-dtimings" let _opaque = option "-opaque" + let _args = Arg.read_arg + let _args0 = Arg.read_arg0 let anonymous = process_file end);; @@ -190,7 +194,7 @@ let optlist = \032 t try ... with") :: Options.list in -Arg.parse optlist process_file usage; +Arg.parse_expand optlist process_file usage; if !with_impl && !with_intf then begin fprintf stderr "ocamloptp cannot deal with both \"-impl\" and \"-intf\"\n"; fprintf stderr "please compile interfaces and implementations separately\n"; diff --git a/tools/ocamlprof.ml b/tools/ocamlprof.ml index 0a22fa46..fb08ffd5 100644 --- a/tools/ocamlprof.ml +++ b/tools/ocamlprof.ml @@ -490,7 +490,7 @@ let print_version_num () = let main () = try Warnings.parse_options false "a"; - Arg.parse [ + Arg.parse_expand [ "-f", Arg.String (fun s -> dumpfile := s), " Use as dump file (default ocamlprof.dump)"; "-F", Arg.String (fun s -> special_id := s), @@ -505,7 +505,13 @@ let main () = " Print version and exit"; "-vnum", Arg.Unit print_version_num, " Print version number and exit"; - ] process_anon_file usage; + "-args", Arg.Expand Arg.read_arg, + " Read additional newline separated command line arguments \n\ + \ from "; + "-args0", Arg.Expand Arg.read_arg0, + " Read additional NUL separated command line arguments from \n\ + \ " + ] process_anon_file usage; exit 0 with | Profiler msg -> diff --git a/tools/primreq.ml b/tools/primreq.ml index bef375fc..c84543ae 100644 --- a/tools/primreq.ml +++ b/tools/primreq.ml @@ -69,7 +69,7 @@ let exclude filename = | x -> close_in ic; raise x let main() = - Arg.parse + Arg.parse_expand ["-used", Arg.Unit(fun () -> used := true; defined := false), "show primitives referenced in the object files"; "-defined", Arg.Unit(fun () -> defined := true; used := false), @@ -77,7 +77,13 @@ let main() = "-all", Arg.Unit(fun () -> defined := true; used := true), "show primitives defined or referenced in the object files"; "-exclude", Arg.String(fun s -> exclude_file := s), - " don't print the primitives mentioned in "] + " don't print the primitives mentioned in "; + "-args", Arg.Expand Arg.read_arg, + " Read additional newline separated command line arguments \n\ + \ from "; + "-args0", Arg.Expand Arg.read_arg0, + " Read additional NUL separated command line arguments from \n\ + \ ";] scan_obj "Usage: primreq [options] <.cmo and .cma files>\nOptions are:"; if String.length !exclude_file > 0 then exclude !exclude_file; diff --git a/tools/read_cmt.ml b/tools/read_cmt.ml index ad3c50ad..ea8e3c05 100644 --- a/tools/read_cmt.ml +++ b/tools/read_cmt.ml @@ -25,6 +25,12 @@ let arg_list = [ "-src", Arg.Set gen_ml, " : convert .cmt or .cmti back to source code (without comments)"; "-info", Arg.Set print_info_arg, " : print information on the file"; + "-args", Arg.Expand Arg.read_arg, + " Read additional newline separated command line arguments \n\ + \ from "; + "-args0", Arg.Expand Arg.read_arg0, + " Read additional NUL separated command line arguments from \n\ + \ "; ] let arg_usage = @@ -79,7 +85,7 @@ let print_info cmt = let _ = Clflags.annotations := true; - Arg.parse arg_list (fun filename -> + Arg.parse_expand arg_list (fun filename -> if Filename.check_suffix filename ".cmt" || Filename.check_suffix filename ".cmti" diff --git a/toplevel/genprintval.ml b/toplevel/genprintval.ml index 28682a9d..8c7ce660 100644 --- a/toplevel/genprintval.ml +++ b/toplevel/genprintval.ml @@ -151,15 +151,15 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct (fun x -> Oval_int64 (O.obj x : int64)) )) ] : (Path.t * printer) list) - let exn_printer ppf path = - fprintf ppf "" Printtyp.path path + let exn_printer ppf path exn = + fprintf ppf "" Printtyp.path path (Printexc.to_string exn) - let out_exn path = - Oval_printer (fun ppf -> exn_printer ppf path) + let out_exn path exn = + Oval_printer (fun ppf -> exn_printer ppf path exn) let install_printer path ty fn = let print_val ppf obj = - try fn ppf obj with _exn -> exn_printer ppf path in + try fn ppf obj with exn -> exn_printer ppf path exn in let printer obj = Oval_printer (fun ppf -> print_val ppf obj) in printers := (path, Simple (ty, printer)) :: !printers @@ -172,7 +172,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct | Zero fn -> let out_printer obj = let printer ppf = - try fn ppf obj with _ -> exn_printer ppf function_path in + try fn ppf obj with exn -> exn_printer ppf function_path exn in Oval_printer printer in Zero out_printer | Succ fn -> @@ -559,13 +559,13 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct begin match (Ctype.expand_head env ty).desc with | Tconstr (p, args, _) when Path.same p path -> begin try apply_generic_printer path (fn depth) args - with _ -> (fun _obj -> out_exn path) end + with exn -> (fun _obj -> out_exn path exn) end | _ -> find remainder end in find !printers and apply_generic_printer path printer args = match (printer, args) with - | (Zero fn, []) -> (fun (obj : O.t)-> try fn obj with _ -> out_exn path) + | (Zero fn, []) -> (fun (obj : O.t)-> try fn obj with exn -> out_exn path exn) | (Succ fn, arg :: args) -> let printer = fn (fun depth obj -> tree_of_val depth obj arg) in apply_generic_printer path printer args diff --git a/toplevel/opttoploop.ml b/toplevel/opttoploop.ml index 32e9905f..6ca12efa 100644 --- a/toplevel/opttoploop.ml +++ b/toplevel/opttoploop.ml @@ -222,14 +222,14 @@ let load_lambda ppf ~module_ident ~required_globals lam size = if not Config.flambda then Asmgen.compile_implementation_clambda ~source_provenance:Timings.Toplevel ~toplevel:need_symbol fn ppf - { Lambda.code=lam ; main_module_block_size=size; + { Lambda.code=slam ; main_module_block_size=size; module_ident; required_globals } else Asmgen.compile_implementation_flambda ~source_provenance:Timings.Toplevel ~required_globals ~backend ~toplevel:need_symbol fn ppf (Middle_end.middle_end ppf ~source_provenance:Timings.Toplevel ~prefixname:"" ~backend ~size - ~module_ident ~module_initializer:lam ~filename:"toplevel"); + ~module_ident ~module_initializer:slam ~filename:"toplevel"); Asmlink.call_linker_shared [fn ^ ext_obj] dll; Sys.remove (fn ^ ext_obj); diff --git a/toplevel/opttopmain.ml b/toplevel/opttopmain.ml index 3f5c5c00..96d22185 100644 --- a/toplevel/opttopmain.ml +++ b/toplevel/opttopmain.ml @@ -20,6 +20,23 @@ let usage = let preload_objects = ref [] +(* Position of the first non expanded argument *) +let first_nonexpanded_pos = ref 0 + +let current = ref (!Arg.current) + +let argv = ref Sys.argv + +(* Test whether the option is part of a responsefile *) +let is_expanded pos = pos < !first_nonexpanded_pos + +let expand_position pos len = + if pos < !first_nonexpanded_pos then + first_nonexpanded_pos := !first_nonexpanded_pos + len (* Shift the position *) + else + first_nonexpanded_pos := pos + len + 2 (* New last position *) + + let prepare ppf = Opttoploop.set_paths (); try @@ -40,10 +57,18 @@ let file_argument name = || Filename.check_suffix name ".cmx" || Filename.check_suffix name ".cmxa" then preload_objects := name :: !preload_objects - else - begin - let newargs = Array.sub Sys.argv !Arg.current - (Array.length Sys.argv - !Arg.current) + else if is_expanded !current then begin + (* Script files are not allowed in expand options because otherwise the + check in override arguments may fail since the new argv can be larger + than the original argv. + *) + Printf.eprintf "For implementation reasons, the toplevel does not support\ + \ having script files (here %S) inside expanded arguments passed through the\ + \ -args{,0} command-line option.\n" name; + exit 2 + end else begin + let newargs = Array.sub !argv !Arg.current + (Array.length !argv - !Arg.current) in if prepare ppf && Opttoploop.run_script ppf name newargs then exit 0 @@ -60,6 +85,12 @@ let print_version_num () = exit 0; ;; +let wrap_expand f s = + let start = !current in + let arr = f s in + expand_position start (Array.length arr); + arr + module Options = Main_args.Make_opttop_options (struct let set r () = r := true let clear r () = r := false @@ -204,11 +235,21 @@ module Options = Main_args.Make_opttop_options (struct let _open s = open_modules := s :: !open_modules let _plugin p = Compplugin.load p + let _args = wrap_expand Arg.read_arg + let _args0 = wrap_expand Arg.read_arg0 + let anonymous = file_argument end);; let main () = native_code := true; - Arg.parse Options.list file_argument usage; + let list = ref Options.list in + begin + try + Arg.parse_and_expand_argv_dynamic current argv list file_argument usage; + with + | Arg.Bad msg -> Format.fprintf Format.err_formatter "%s%!" msg; exit 2 + | Arg.Help msg -> Format.fprintf Format.std_formatter "%s%!" msg; exit 0 + end; if not (prepare Format.err_formatter) then exit 2; Opttoploop.loop Format.std_formatter diff --git a/toplevel/topmain.ml b/toplevel/topmain.ml index 16f0c76b..1a8757b3 100644 --- a/toplevel/topmain.ml +++ b/toplevel/topmain.ml @@ -21,6 +21,22 @@ let usage = "Usage: ocaml [script-file [arguments]]\n\ let preload_objects = ref [] +(* Position of the first non expanded argument *) +let first_nonexpanded_pos = ref 0 + +let current = ref (!Arg.current) + +let argv = ref Sys.argv + +(* Test whether the option is part of a responsefile *) +let is_expanded pos = pos < !first_nonexpanded_pos + +let expand_position pos len = + if pos < !first_nonexpanded_pos then + first_nonexpanded_pos := !first_nonexpanded_pos + len (* Shift the position *) + else + first_nonexpanded_pos := pos + len + 2 (* New last position *) + let prepare ppf = Toploop.set_paths (); try @@ -43,10 +59,18 @@ let file_argument name = let ppf = Format.err_formatter in if Filename.check_suffix name ".cmo" || Filename.check_suffix name ".cma" then preload_objects := name :: !preload_objects - else - begin - let newargs = Array.sub Sys.argv !Arg.current - (Array.length Sys.argv - !Arg.current) + else if is_expanded !current then begin + (* Script files are not allowed in expand options because otherwise the + check in override arguments may fail since the new argv can be larger + than the original argv. + *) + Printf.eprintf "For implementation reasons, the toplevel does not support\ + \ having script files (here %S) inside expanded arguments passed through the\ + \ -args{,0} command-line option.\n" name; + exit 2 + end else begin + let newargs = Array.sub !argv !current + (Array.length !argv - !current) in Compenv.readenv ppf Before_link; if prepare ppf && Toploop.run_script ppf name newargs @@ -64,6 +88,12 @@ let print_version_num () = exit 0; ;; +let wrap_expand f s = + let start = !current in + let arr = f s in + expand_position start (Array.length arr); + arr + module Options = Main_args.Make_bytetop_options (struct let set r () = r := true let clear r () = r := false @@ -117,6 +147,9 @@ module Options = Main_args.Make_bytetop_options (struct let _dtimings = set print_timings let _dinstr = set dump_instr + let _args = wrap_expand Arg.read_arg + let _args0 = wrap_expand Arg.read_arg0 + let anonymous s = file_argument s end);; @@ -124,7 +157,14 @@ end);; let main () = let ppf = Format.err_formatter in Compenv.readenv ppf Before_args; - Arg.parse Options.list file_argument usage; + let list = ref Options.list in + begin + try + Arg.parse_and_expand_argv_dynamic current argv list file_argument usage; + with + | Arg.Bad msg -> Printf.eprintf "%s" msg; exit 2 + | Arg.Help msg -> Printf.printf "%s" msg; exit 0 + end; Compenv.readenv ppf Before_link; if not (prepare ppf) then exit 2; Toploop.loop Format.std_formatter diff --git a/typing/HACKING.adoc b/typing/HACKING.adoc new file mode 100644 index 00000000..101bf8ed --- /dev/null +++ b/typing/HACKING.adoc @@ -0,0 +1,58 @@ +The implementation of the OCaml typechecker is complex. Modifying it +will need a good understanding of the OCaml type system and type +inference. Here is a reading list to ease your discovery of the +typechecker: + +http://caml.inria.fr/pub/docs/u3-ocaml/index.html[Using, Understanding, and Unraveling the OCaml Language by Didier Rémy] :: +This book provides (among other things) a formal description of parts +of the core OCaml language, starting with a simple Core ML. + +http://okmij.org/ftp/ML/generalization.html[Efficient and Insightful Generalization by Oleg Kiselyov] :: +This article describes the basis of the type inference algorithm used +by the OCaml type checker. It is a recommended read if you want to +understand the type-checker codebase, in particular its handling of +polymorphism/generalization. + +After that, it is best to dive right in. There is no real "entry +point", but an understanding of both the parsetree and the typedtree +is necessary. + +The datastructures :: +link:types.mli[Types] and link:typedtree.mli[Typedtree] +are the two main datastructures in the typechecker. They correspond to +the source code annotated with all the information needed for type +checking and type inference. link:env.mli[Env] contains all the +environments that are used in the typechecker. Each node in the +typedtree is annotated with the local environment in which it was +type-checked. + +Core utilities :: +link:btype.mli[Btype] and link:ctype.mli[Ctype] contain +the various low-level function needed for typing, in particular +related to levels, unification and +backtracking. link:mtype.mli[Mtype] contains utilities related +to modules. + +Inference and checking:: +The `Type..` modules are related to inference and typechecking, each +for a different part of the language: +link:typetexp.mli[Typetexp] for type expressions, +link:typecore.mli[Typecore] for the core language, +link:typemod.mli[Typemod] for modules, +link:typedecl.mli[Typedecl] for type declarations and finally +link:typeclass.mli[Typeclass] for the object system. + +Inclusion/Module subtyping:: +Handling of inclusion relations are separated in the `Include...` +modules: link:includecore.ml[Includecore] for the type and +value declarations, link:includemod.mli[Includemod] for modules +and finally link:includeclass.mli[Includeclass] for the object +system. + +Dependencies between modules:: +Most of the modules presented above are inter-dependent. Since OCaml +does not permit circular dependencies between files, the +implementation uses forward declarations, implemented with references +to functions that are filled later on. An example can be seen in +link:typecore.ml[Typecore.type_module], which is filled in +link:typemod.ml[Typemod]. diff --git a/typing/btype.ml b/typing/btype.ml index 686bfc44..d94693b1 100644 --- a/typing/btype.ml +++ b/typing/btype.ml @@ -59,6 +59,7 @@ let newmarkedgenvar () = let is_Tvar = function {desc=Tvar _} -> true | _ -> false let is_Tunivar = function {desc=Tunivar _} -> true | _ -> false +let is_Tconstr = function {desc=Tconstr _} -> true | _ -> false let dummy_method = "*dummy method*" let default_mty = function @@ -208,27 +209,31 @@ let proxy ty = (**** Utilities for fixed row private types ****) -let has_constr_row t = +let row_of_type t = match (repr t).desc with Tobject(t,_) -> - let rec check_row t = - match (repr t).desc with - Tfield(_,_,_,t) -> check_row t - | Tconstr _ -> true - | _ -> false - in check_row t + let rec get_row t = + let t = repr t in + match t.desc with + Tfield(_,_,_,t) -> get_row t + | _ -> t + in get_row t | Tvariant row -> - (match row_more row with {desc=Tconstr _} -> true | _ -> false) + row_more row | _ -> - false + t + +let has_constr_row t = + not (is_Tconstr t) && is_Tconstr (row_of_type t) let is_row_name s = let l = String.length s in if l < 4 then false else String.sub s (l-4) 4 = "#row" -let is_constr_row t = +let is_constr_row ~allow_ident t = match t.desc with - Tconstr (Path.Pident id, _, _) -> is_row_name (Ident.name id) + Tconstr (Path.Pident id, _, _) when allow_ident -> + is_row_name (Ident.name id) | Tconstr (Path.Pdot (_, s, _), _, _) -> is_row_name s | _ -> false diff --git a/typing/btype.mli b/typing/btype.mli index 08d8d047..aaa426a8 100644 --- a/typing/btype.mli +++ b/typing/btype.mli @@ -46,6 +46,7 @@ val newmarkedgenvar: unit -> type_expr val is_Tvar: type_expr -> bool val is_Tunivar: type_expr -> bool +val is_Tconstr: type_expr -> bool val dummy_method: label val default_mty: module_type option -> module_type @@ -80,9 +81,10 @@ val proxy: type_expr -> type_expr or a row variable *) (**** Utilities for private abbreviations with fixed rows ****) +val row_of_type: type_expr -> type_expr val has_constr_row: type_expr -> bool val is_row_name: string -> bool -val is_constr_row: type_expr -> bool +val is_constr_row: allow_ident:bool -> type_expr -> bool (**** Utilities for type traversal ****) diff --git a/typing/cmt_format.ml b/typing/cmt_format.ml index e552ca39..56cfba39 100644 --- a/typing/cmt_format.ml +++ b/typing/cmt_format.ml @@ -164,27 +164,13 @@ let record_value_dependency vd1 vd2 = if vd1.Types.val_loc <> vd2.Types.val_loc then value_deps := (vd1, vd2) :: !value_deps -let save_cmt filename modname binary_annots sourcefile initial_env sg = +let save_cmt filename modname binary_annots sourcefile initial_env cmi = if !Clflags.binary_annotations && not !Clflags.print_types then begin - let imports = Env.imports () in - let flags = - List.concat [ - if !Clflags.recursive_types then [Cmi_format.Rectypes] else []; - if !Clflags.opaque then [Cmi_format.Opaque] else []; - ] - in let oc = open_out_bin filename in let this_crc = - match sg with - None -> None - | Some (sg) -> - let cmi = { - cmi_name = modname; - cmi_sign = sg; - cmi_flags = flags; - cmi_crcs = imports; - } in - Some (output_cmi filename oc cmi) + match cmi with + | None -> None + | Some cmi -> Some (output_cmi filename oc cmi) in let source_digest = Misc.may_map Digest.file sourcefile in let cmt = { @@ -199,7 +185,7 @@ let save_cmt filename modname binary_annots sourcefile initial_env sg = cmt_source_digest = source_digest; cmt_initial_env = if need_to_clear_env then keep_only_summary initial_env else initial_env; - cmt_imports = List.sort compare imports; + cmt_imports = List.sort compare (Env.imports ()); cmt_interface_digest = this_crc; cmt_use_summaries = need_to_clear_env; } in diff --git a/typing/cmt_format.mli b/typing/cmt_format.mli index b1514433..617bc1ed 100644 --- a/typing/cmt_format.mli +++ b/typing/cmt_format.mli @@ -83,7 +83,7 @@ val read : string -> Cmi_format.cmi_infos option * cmt_infos option val read_cmt : string -> cmt_infos val read_cmi : string -> Cmi_format.cmi_infos -(** [save_cmt modname filename binary_annots sourcefile initial_env sg] +(** [save_cmt filename modname binary_annots sourcefile initial_env cmi] writes a cmt(i) file. *) val save_cmt : string -> (* filename.cmt to generate *) @@ -91,8 +91,7 @@ val save_cmt : binary_annots -> string option -> (* source file *) Env.t -> (* initial env *) - Types.signature option -> (* if a .cmi was generated, - the signature saved there *) + Cmi_format.cmi_infos option -> (* if a .cmi was generated *) unit (* Miscellaneous functions *) diff --git a/typing/ctype.ml b/typing/ctype.ml index 96dbbb2b..3135e4a2 100644 --- a/typing/ctype.ml +++ b/typing/ctype.ml @@ -2426,7 +2426,8 @@ and unify3 env t1 t1' t2 t2' = try begin match (d1, d2) with (Tarrow (l1, t1, u1, c1), Tarrow (l2, t2, u2, c2)) when l1 = l2 || - !Clflags.classic && not (is_optional l1 || is_optional l2) -> + (!Clflags.classic || !umode = Pattern) && + not (is_optional l1 || is_optional l2) -> unify env t1 t2; unify env u1 u2; begin match commu_repr c1, commu_repr c2 with Clink r, c2 -> set_commu r c2 @@ -3049,7 +3050,9 @@ and moregen_row inst_nongen type_pairs env row1 row2 = raise (Unify []) | _ when static_row row1 -> () | _ when may_inst -> - let ext = newgenty (Tvariant {row2 with row_fields = r2}) in + let ext = + newgenty (Tvariant {row2 with row_fields = r2; row_name = None}) + in moregen_occur env rm1.level ext; link_type rm1 ext | Tconstr _, Tconstr _ -> @@ -4195,7 +4198,15 @@ let rec normalize_type_rec env visited ty = let ty = repr ty in if not (TypeSet.mem ty !visited) then begin visited := TypeSet.add ty !visited; - begin match ty.desc with + let tm = row_of_type ty in + begin if not (is_Tconstr ty) && is_constr_row ~allow_ident:false tm then + match tm.desc with (* PR#7348 *) + Tconstr (Path.Pdot(m,i,pos), tl, _abbrev) -> + let i' = String.sub i 0 (String.length i - 4) in + log_type ty; + ty.desc <- Tconstr(Path.Pdot(m,i',pos), tl, ref Mnil) + | _ -> assert false + else match ty.desc with | Tvariant row -> let row = row_repr row in let fields = List.map diff --git a/typing/env.ml b/typing/env.ml index 7a0beff0..224e2c8d 100644 --- a/typing/env.ml +++ b/typing/env.ml @@ -308,7 +308,7 @@ let diff env1 env2 = (* Forward declarations *) let components_of_module' = - ref ((fun ~deprecated:_ ~loc:__env _sub _path _mty -> assert false) : + ref ((fun ~deprecated:_ ~loc:_ _env _sub _path _mty -> assert false) : deprecated:string option -> loc:Location.t -> t -> Subst.t -> Path.t -> module_type -> module_components) @@ -1376,12 +1376,8 @@ let prefix_idents_and_subst root sub sg = let (pl, sub) = prefix_idents root 0 sub sg in pl, sub, lazy (subst_signature sub sg) -let set_nongen_level sub path = - Subst.set_nongen_level sub (Path.binding_time path - 1) - let prefix_idents_and_subst root sub sg = - let sub = set_nongen_level sub root in - if sub = set_nongen_level Subst.identity root then + if sub = Subst.identity then let sgs = try Hashtbl.find prefixed_sg root @@ -1499,7 +1495,7 @@ and components_of_module_maker (env, sub, path, mty) = (* fcomp_arg and fcomp_res must be prefixed eagerly, because they are interpreted in the outer environment *) fcomp_arg = may_map (Subst.modtype sub) ty_arg; - fcomp_res = Subst.modtype (set_nongen_level sub path) ty_res; + fcomp_res = Subst.modtype sub ty_res; fcomp_cache = Hashtbl.create 17; fcomp_subst_cache = Hashtbl.create 17 } | Mty_ident _ @@ -1919,7 +1915,7 @@ let save_signature_with_imports ~deprecated sg modname filename imports = ps_flags = cmi.cmi_flags; } in save_pers_struct crc ps; - sg + cmi with exn -> close_out oc; remove_file filename; diff --git a/typing/env.mli b/typing/env.mli index aa57630d..1bf072c4 100644 --- a/typing/env.mli +++ b/typing/env.mli @@ -189,12 +189,12 @@ val get_unit_name: unit -> string val read_signature: string -> string -> signature (* Arguments: module name, file name. Results: signature. *) val save_signature: - deprecated:string option -> signature -> string -> string -> signature + deprecated:string option -> signature -> string -> string -> Cmi_format.cmi_infos (* Arguments: signature, module name, file name. *) val save_signature_with_imports: deprecated:string option -> signature -> string -> string -> (string * Digest.t option) list - -> signature + -> Cmi_format.cmi_infos (* Arguments: signature, module name, file name, imported units with their CRCs. *) diff --git a/typing/mtype.ml b/typing/mtype.ml index 063cc366..479f12e3 100644 --- a/typing/mtype.ml +++ b/typing/mtype.ml @@ -403,3 +403,20 @@ let remove_aliases env sg = (* PathSet.iter (fun p -> Format.eprintf "%a@ " Printtyp.path p) excl; Format.eprintf "@."; *) remove_aliases env excl sg + + +(* Lower non-generalizable type variables *) + +let lower_nongen nglev mty = + let open Btype in + let it_type_expr it ty = + let ty = repr ty in + match ty with + {desc=Tvar _; level} -> + if level < generic_level && level > nglev then set_level ty nglev + | _ -> + type_iterators.it_type_expr it ty + in + let it = {type_iterators with it_type_expr} in + it.it_module_type it mty; + it.it_module_type unmark_iterators mty diff --git a/typing/mtype.mli b/typing/mtype.mli index 3f07db4a..84e870ac 100644 --- a/typing/mtype.mli +++ b/typing/mtype.mli @@ -42,3 +42,4 @@ val enrich_typedecl: Env.t -> Path.t -> type_declaration -> type_declaration val type_paths: Env.t -> Path.t -> module_type -> Path.t list val contains_type: Env.t -> module_type -> bool val remove_aliases: Env.t -> module_type -> module_type +val lower_nongen: int -> module_type -> unit diff --git a/typing/oprint.ml b/typing/oprint.ml index 02f236cc..b0145ec6 100644 --- a/typing/oprint.ml +++ b/typing/oprint.ml @@ -212,8 +212,8 @@ and print_simple_out_type ppf = Ovar_fields fields -> print_list print_row_field (fun ppf -> fprintf ppf "@;<1 -2>| ") ppf fields - | Ovar_name (id, tyl) -> - fprintf ppf "@[%a%a@]" print_typargs tyl print_ident id + | Ovar_typ typ -> + print_simple_out_type ppf typ in fprintf ppf "%s[%s@[@[%a@]%a ]@]" (if non_gen then "_" else "") (if closed then if tags = None then " " else "< " diff --git a/typing/outcometree.mli b/typing/outcometree.mli index b926c920..17c4862d 100644 --- a/typing/outcometree.mli +++ b/typing/outcometree.mli @@ -70,7 +70,7 @@ type out_type = and out_variant = | Ovar_fields of (string * bool * out_type list) list - | Ovar_name of out_ident * out_type list + | Ovar_typ of out_type type out_class_type = | Octy_constr of out_ident * out_type list diff --git a/typing/parmatch.ml b/typing/parmatch.ml index 1ebae6e8..9e935730 100644 --- a/typing/parmatch.ml +++ b/typing/parmatch.ml @@ -137,13 +137,6 @@ let get_type_path ty tenv = open Format ;; -let pretty_record_elision_mark ppf = function - | [] -> () (* should not happen, empty record pattern *) - | (_, lbl, _) :: q -> - (* we assume that there is no label repetitions here *) - if Array.length lbl.lbl_all > 1 + List.length q then - fprintf ppf ";@ _@ " - let is_cons = function | {cstr_name = "::"} -> true | _ -> false @@ -198,9 +191,17 @@ let rec pretty_val ppf v = (function | (_,_,{pat_desc=Tpat_any}) -> false (* do not show lbl=_ *) | _ -> true) lvs in - fprintf ppf "@[{%a%a}@]" - pretty_lvals filtered_lvs - pretty_record_elision_mark filtered_lvs + begin match filtered_lvs with + | [] -> fprintf ppf "_" + | (_, lbl, _) :: q -> + let elision_mark ppf = + (* we assume that there is no label repetitions here *) + if Array.length lbl.lbl_all > 1 + List.length q then + fprintf ppf ";@ _@ " + else () in + fprintf ppf "@[{%a%t}@]" + pretty_lvals filtered_lvs elision_mark + end | Tpat_array vs -> fprintf ppf "@[[| %a |]@]" (pretty_vals " ;") vs | Tpat_lazy v -> @@ -654,17 +655,31 @@ let full_match closing env = match env with | ({pat_desc = Tpat_record(_)},_) :: _ -> true | ({pat_desc = Tpat_array(_)},_) :: _ -> false | ({pat_desc = Tpat_lazy(_)},_) :: _ -> true -| _ -> fatal_error "Parmatch.full_match" +| ({pat_desc = (Tpat_any|Tpat_var _|Tpat_alias _|Tpat_or _)},_) :: _ +| [] + -> + assert false +(* Written as a non-fragile matching, PR7451 originated from a fragile matching below. *) let should_extend ext env = match ext with | None -> false -| Some ext -> match env with - | ({pat_desc = - Tpat_construct(_, {cstr_tag=(Cstr_constant _|Cstr_block _)},_)} - as p, _) :: _ -> - let path = get_type_path p.pat_type p.pat_env in - Path.same path ext - | _ -> false +| Some ext -> begin match env with + | [] -> assert false + | (p,_)::_ -> + begin match p.pat_desc with + | Tpat_construct + (_, {cstr_tag=(Cstr_constant _|Cstr_block _|Cstr_unboxed)},_) -> + let path = get_type_path p.pat_type p.pat_env in + Path.same path ext + | Tpat_construct + (_, {cstr_tag=(Cstr_extension _)},_) -> false + | Tpat_constant _|Tpat_tuple _|Tpat_variant _ + | Tpat_record _|Tpat_array _ | Tpat_lazy _ + -> false + | Tpat_any|Tpat_var _|Tpat_alias _|Tpat_or _ + -> assert false + end +end (* complement constructor tags *) let complete_tags nconsts nconstrs tags = diff --git a/typing/printtyp.ml b/typing/printtyp.ml index e5dc6157..64f8d0cb 100644 --- a/typing/printtyp.ml +++ b/typing/printtyp.ml @@ -559,6 +559,8 @@ let rec tree_of_typexp sch ty = let pr_typ () = match ty.desc with | Tvar _ -> + (*let lev = + if is_non_gen sch ty then "/" ^ string_of_int ty.level else "" in*) Otyp_var (is_non_gen sch ty, name_of_type ty) | Tarrow(l, ty1, ty2, _) -> let pr_arrow l ty1 ty2 = @@ -602,20 +604,15 @@ let rec tree_of_typexp sch ty = let (p', s) = best_type_path p in let id = tree_of_path p' in let args = tree_of_typlist sch (apply_subst s tyl) in + let out_variant = + if is_nth s then List.hd args else Otyp_constr (id, args) in if row.row_closed && all_present then - if is_nth s then List.hd args else Otyp_constr (id, args) + out_variant else let non_gen = is_non_gen sch px in let tags = if all_present then None else Some (List.map fst present) in - let inh = - match args with - [Otyp_constr (i, a)] when is_nth s -> Ovar_name (i, a) - | _ -> - (* fallback case, should change outcometree... *) - Ovar_name (tree_of_path p, tree_of_typlist sch tyl) - in - Otyp_variant (non_gen, inh, row.row_closed, tags) + Otyp_variant (non_gen, Ovar_typ out_variant, row.row_closed, tags) | _ -> let non_gen = not (row.row_closed && all_present) && is_non_gen sch px in @@ -1326,7 +1323,8 @@ let rec filter_trace keep_last = function [] | (t1, t1') :: (t2, t2') :: rem -> let rem' = filter_trace keep_last rem in - if is_constr_row t1' || is_constr_row t2' + if is_constr_row ~allow_ident:true t1' + || is_constr_row ~allow_ident:true t2' || same_path t1 t1' && same_path t2 t2' && not (keep_last && rem' = []) then rem' else (t1, t1') :: (t2, t2') :: rem' diff --git a/typing/printtyped.ml b/typing/printtyped.ml index 410cc1c9..78e1b60a 100644 --- a/typing/printtyped.ml +++ b/typing/printtyped.ml @@ -297,10 +297,10 @@ and expression i ppf x = line i ppf "Texp_let %a\n" fmt_rec_flag rf; list i value_binding ppf l; expression i ppf e; - | Texp_function (p, l, _partial) -> + | Texp_function { arg_label = p; param = _; cases; partial = _; } -> line i ppf "Texp_function\n"; arg_label i ppf p; - list i case ppf l; + list i case ppf cases; | Texp_apply (e, l) -> line i ppf "Texp_apply\n"; expression i ppf e; diff --git a/typing/subst.ml b/typing/subst.ml index 85da130b..e6fc9e3d 100644 --- a/typing/subst.ml +++ b/typing/subst.ml @@ -24,12 +24,11 @@ type t = { types: (Ident.t, Path.t) Tbl.t; modules: (Ident.t, Path.t) Tbl.t; modtypes: (Ident.t, module_type) Tbl.t; - for_saving: bool; - nongen_level: int } + for_saving: bool } let identity = { types = Tbl.empty; modules = Tbl.empty; modtypes = Tbl.empty; - for_saving = false; nongen_level = generic_level } + for_saving = false } let add_type id p s = { s with types = Tbl.add id p s.types } @@ -39,8 +38,6 @@ let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes } let for_saving s = { s with for_saving = true } -let set_nongen_level s lev = { s with nongen_level = lev } - let loc s x = if s.for_saving && not !Clflags.keep_locs then Location.none else x @@ -128,11 +125,7 @@ let rec typexp s ty = else newty2 ty.level desc in save_desc ty desc; ty.desc <- Tsubst ty'; ty' - else begin (* when adding a module to the environment *) - if ty.level < generic_level then - ty.level <- min ty.level s.nongen_level; - ty - end + else ty | Tsubst ty -> ty | Tfield (m, k, _t1, _t2) when not s.for_saving && m = dummy_method @@ -146,11 +139,20 @@ let rec typexp s ty = | _ -> let desc = ty.desc in save_desc ty desc; + let tm = row_of_type ty in + let has_fixed_row = + not (is_Tconstr ty) && is_constr_row ~allow_ident:false tm in (* Make a stub *) let ty' = if s.for_saving then newpersty (Tvar None) else newgenvar () in ty.desc <- Tsubst ty'; ty'.desc <- - begin match desc with + begin if has_fixed_row then + match tm.desc with (* PR#7348 *) + Tconstr (Pdot(m,i,pos), tl, _abbrev) -> + let i' = String.sub i 0 (String.length i - 4) in + Tconstr(type_path s (Pdot(m,i',pos)), tl, ref Mnil) + | _ -> assert false + else match desc with | Tconstr(p, tl, _abbrev) -> Tconstr(type_path s p, List.map (typexp s) tl, ref Mnil) | Tpackage(p, n, tl) -> @@ -435,5 +437,4 @@ let compose s1 s2 = { types = merge_tbls (type_path s2) s1.types s2.types; modules = merge_tbls (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; - for_saving = s1.for_saving || s2.for_saving; - nongen_level = min s1.nongen_level s2.nongen_level } + for_saving = s1.for_saving || s2.for_saving } diff --git a/typing/subst.mli b/typing/subst.mli index 74931ffc..55eee757 100644 --- a/typing/subst.mli +++ b/typing/subst.mli @@ -36,7 +36,6 @@ val identity: t val add_type: Ident.t -> Path.t -> t -> t val add_module: Ident.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t -val set_nongen_level: t -> int -> t val for_saving: t -> t val reset_for_saving: unit -> unit diff --git a/typing/tast_mapper.ml b/typing/tast_mapper.ml index e77299ce..0873dd4c 100644 --- a/typing/tast_mapper.ml +++ b/typing/tast_mapper.ml @@ -230,8 +230,9 @@ let expr sub x = | Texp_let (rec_flag, list, exp) -> let (rec_flag, list) = sub.value_bindings sub (rec_flag, list) in Texp_let (rec_flag, list, sub.expr sub exp) - | Texp_function (l, cases, p) -> - Texp_function (l, sub.cases sub cases, p) + | Texp_function { arg_label; param; cases; partial; } -> + Texp_function { arg_label; param; cases = sub.cases sub cases; + partial; } | Texp_apply (exp, list) -> Texp_apply ( sub.expr sub exp, diff --git a/typing/typeclass.ml b/typing/typeclass.ml index daaeab47..51f8a256 100644 --- a/typing/typeclass.ml +++ b/typing/typeclass.ml @@ -423,13 +423,13 @@ let rec class_type_field env self_type meths (mkctf (Tctf_inherit parent) :: fields, val_sig, concr_meths, inher) - | Pctf_val (lab, mut, virt, sty) -> + | Pctf_val ({txt=lab}, mut, virt, sty) -> let cty = transl_simple_type env false sty in let ty = cty.ctyp_type in (mkctf (Tctf_val (lab, mut, virt, cty)) :: fields, add_val lab (mut, virt, ty) val_sig, concr_meths, inher) - | Pctf_method (lab, priv, virt, sty) -> + | Pctf_method ({txt=lab}, priv, virt, sty) -> let cty = declare_method env meths self_type lab priv sty ctf.pctf_loc in let concr_meths = @@ -590,17 +590,17 @@ let rec class_field self_loc cl_num self_type meths vars cl_sig.csig_concr [] in (* Super *) - let (val_env, met_env, par_env) = + let (val_env, met_env, par_env,super) = match super with None -> - (val_env, met_env, par_env) - | Some name -> + (val_env, met_env, par_env,None) + | Some {txt=name} -> let (_id, val_env, met_env, par_env) = enter_met_env ~check:(fun s -> Warnings.Unused_ancestor s) sparent.pcl_loc name (Val_anc (inh_meths, cl_num)) self_type val_env met_env par_env in - (val_env, met_env, par_env) + (val_env, met_env, par_env,Some name) in (val_env, met_env, par_env, lazy (mkcf (Tcf_inherit (ovf, parent, super, inh_vars, inh_meths))) @@ -1833,7 +1833,7 @@ let report_error env ppf = function Printtyp.reset_and_mark_loops_list [params; cstrs]; fprintf ppf "@[The abbreviation %a@ is used with parameters@ %a@ \ - wich are incompatible with constraints@ %a@]" + which are incompatible with constraints@ %a@]" Printtyp.ident id Printtyp.type_expr params Printtyp.type_expr cstrs | Class_match_failure error -> Includeclass.report_error ppf error diff --git a/typing/typecore.ml b/typing/typecore.ml index 116dc1b9..f80b81be 100644 --- a/typing/typecore.ml +++ b/typing/typecore.ml @@ -560,14 +560,14 @@ let rec build_as_type env p = | Tpat_array _ | Tpat_lazy _ -> p.pat_type let build_or_pat env loc lid = - let path, decl = Typetexp.find_type env loc lid + let path, decl = Typetexp.find_type env lid.loc lid.txt in let tyl = List.map (fun _ -> newvar()) decl.type_params in let row0 = let ty = expand_head env (newty(Tconstr(path, tyl, ref Mnil))) in match ty.desc with Tvariant row when static_row row -> row - | _ -> raise(Error(loc, env, Not_a_variant_type lid)) + | _ -> raise(Error(lid.loc, env, Not_a_variant_type lid.txt)) in let pats, fields = List.fold_left @@ -598,7 +598,7 @@ let build_or_pat env loc lid = pats in match pats with - [] -> raise(Error(loc, env, Not_a_variant_type lid)) + [] -> raise(Error(lid.loc, env, Not_a_variant_type lid.txt)) | pat :: pats -> let r = List.fold_left @@ -1320,7 +1320,8 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~explode ~env let nv = newvar () in unify_pat_types loc !env (instance_def (Predef.type_lazy_t nv)) expected_ty; - type_pat sp1 nv (fun p1 -> + (* do not explode under lazy: PR#7421 *) + type_pat ~explode:0 sp1 nv (fun p1 -> rp k { pat_desc = Tpat_lazy p1; pat_loc = loc; pat_extra=[]; @@ -1360,7 +1361,7 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~explode ~env pat_extra = extra :: p.pat_extra} in k p) | Ppat_type lid -> - let (path, p,ty) = build_or_pat !env loc lid.txt in + let (path, p,ty) = build_or_pat !env loc lid in unify_pat_types loc !env ty expected_ty; k { p with pat_extra = (Tpat_type (path, lid), loc, sp.ppat_attributes) :: p.pat_extra } @@ -1852,7 +1853,7 @@ let contains_gadt env p = with Not_found -> () end; iter_ppat (loop env) p | Ppat_open (lid,sub_p) -> - let _, new_env = !type_open Asttypes.Fresh env p.ppat_loc lid in + let _, new_env = !type_open Asttypes.Override env p.ppat_loc lid in loop new_env sub_p | _ -> iter_ppat (loop env) p in @@ -1910,6 +1911,16 @@ let proper_exp_loc exp = in aux exp.exp_extra +(* To find reasonable names for let-bound and lambda-bound idents *) + +let rec name_pattern default = function + [] -> Ident.create default + | {c_lhs=p; _} :: rem -> + match p.pat_desc with + Tpat_var (id, _) -> id + | Tpat_alias(_, id, _) -> id + | _ -> name_pattern default rem + (* Typing of expressions *) let unify_exp env exp expected_ty = @@ -1946,7 +1957,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = match sexp.pexp_desc with | Pexp_ident lid -> begin - let (path, desc) = Typetexp.find_value env loc lid.txt in + let (path, desc) = Typetexp.find_value env lid.loc lid.txt in if !Clflags.annotations then begin let dloc = desc.Types.val_loc in let annot = @@ -2320,16 +2331,16 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = | Some exp -> let ty_exp = instance env exp.exp_type in let unify_kept lbl = + let _, ty_arg1, ty_res1 = instance_label false lbl in + unify_exp_types exp.exp_loc env ty_exp ty_res1; match matching_label lbl with | lid, _lbl, lbl_exp -> + (* do not connect result types for overridden labels *) Overridden (lid, lbl_exp) | exception Not_found -> begin - (* do not connect overridden labels *) - let _, ty_arg1, ty_res1 = instance_label false lbl - and _, ty_arg2, ty_res2 = instance_label false lbl in + let _, ty_arg2, ty_res2 = instance_label false lbl in unify env ty_arg1 ty_arg2; unify env (instance env ty_expected) ty_res2; - unify_exp_types exp.exp_loc env ty_exp ty_res1; Kept ty_arg1 end in @@ -2573,7 +2584,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = exp_extra = (Texp_coerce (cty, cty'), loc, sexp.pexp_attributes) :: arg.exp_extra; } - | Pexp_send (e, met) -> + | Pexp_send (e, {txt=met}) -> if !Clflags.principal then begin_def (); let obj = type_exp env e in let obj_meths = ref None in @@ -2688,7 +2699,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = Undefined_method (obj.exp_type, met, valid_methods))) end | Pexp_new cl -> - let (cl_path, cl_decl) = Typetexp.find_class env loc cl.txt in + let (cl_path, cl_decl) = Typetexp.find_class env cl.loc cl.txt in begin match cl_decl.cty_new with None -> raise(Error(loc, env, Virtual_class cl.txt)) @@ -2888,7 +2899,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = in re { exp with exp_extra = (Texp_poly cty, loc, sexp.pexp_attributes) :: exp.exp_extra } - | Pexp_newtype(name, sbody) -> + | Pexp_newtype({txt=name}, sbody) -> let ty = newvar () in (* remember original level *) begin_def (); @@ -3041,8 +3052,9 @@ and type_function ?in_function loc attrs env ty_expected l caselist = if is_optional l && not_function ty_res then Location.prerr_warning (List.hd cases).c_lhs.pat_loc Warnings.Unerasable_optional_argument; + let param = name_pattern "param" cases in re { - exp_desc = Texp_function(l,cases, partial); + exp_desc = Texp_function { arg_label = l; param; cases; partial; }; exp_loc = loc; exp_extra = []; exp_type = instance env (newgenty (Tarrow(l, ty_arg, ty_res, Cok))); exp_attributes = attrs; @@ -3440,8 +3452,11 @@ and type_argument ?recarg env sarg ty_expected' ty_expected = (texp, args @ [Nolabel, Some eta_var])} in + let cases = [case eta_pat e] in + let param = name_pattern "param" cases in { texp with exp_type = ty_fun; exp_desc = - Texp_function(Nolabel, [case eta_pat e], Total) } + Texp_function { arg_label = Nolabel; param; cases; + partial = Total; } } in Location.prerr_warning texp.exp_loc (Warnings.Eliminated_optional_arguments diff --git a/typing/typecore.mli b/typing/typecore.mli index 85fd0a82..7b64ee34 100644 --- a/typing/typecore.mli +++ b/typing/typecore.mli @@ -66,6 +66,8 @@ val generalizable: int -> type_expr -> bool val reset_delayed_checks: unit -> unit val force_delayed_checks: unit -> unit +val name_pattern : string -> Typedtree.case list -> Ident.t + val self_coercion : (Path.t * Location.t list ref) list ref type error = diff --git a/typing/typedecl.ml b/typing/typedecl.ml index 25afa6b5..4872da67 100644 --- a/typing/typedecl.ml +++ b/typing/typedecl.ml @@ -78,7 +78,13 @@ let get_unboxed_from_attributes sdecl = (* Enter all declared types in the environment as abstract types *) -let enter_type env sdecl id = +let enter_type rec_flag env sdecl id = + let needed = + match rec_flag with + | Asttypes.Nonrecursive -> Btype.is_row_name (Ident.name id) + | Asttypes.Recursive -> true + in + if not needed then env else let decl = { type_params = List.map (fun _ -> Btype.newgenvar ()) sdecl.ptype_params; @@ -133,7 +139,8 @@ let rec get_unboxed_type_representation env ty fuel = | _ -> Some ty let get_unboxed_type_representation env ty = - get_unboxed_type_representation env ty 100000 + (* Do not give too much fuel: PR#7424 *) + get_unboxed_type_representation env ty 100 ;; (* Determine if a type's values are represented by floats at run-time. *) @@ -269,13 +276,63 @@ let make_constructor env type_path type_params sargs sret_type = widen z; targs, Some tret_type, args, Some ret_type +(* Check that the variable [id] is present in the [univ] list. *) +let check_type_var loc univ id = + let f t = (Btype.repr t).id = id in + if not (List.exists f univ) then raise (Error (loc, Wrong_unboxed_type_float)) + +(* Check that all the variables found in [ty] are in [univ]. + Because [ty] is the argument to an abstract type, the representation + of that abstract type could be any subexpression of [ty], in particular + any type variable present in [ty]. +*) +let rec check_unboxed_abstract_arg loc univ ty = + match ty.desc with + | Tvar _ -> check_type_var loc univ ty.id + | Tarrow (_, t1, t2, _) + | Tfield (_, _, t1, t2) -> + check_unboxed_abstract_arg loc univ t1; + check_unboxed_abstract_arg loc univ t2 + | Ttuple args + | Tconstr (_, args, _) + | Tpackage (_, _, args) -> + List.iter (check_unboxed_abstract_arg loc univ) args + | Tobject (fields, r) -> + check_unboxed_abstract_arg loc univ fields; + begin match !r with + | None -> () + | Some (_, args) -> List.iter (check_unboxed_abstract_arg loc univ) args + end + | Tnil + | Tunivar _ -> () + | Tlink e -> check_unboxed_abstract_arg loc univ e + | Tsubst _ -> assert false + | Tvariant { row_fields; row_more; row_name } -> + List.iter (check_unboxed_abstract_row_field loc univ) row_fields; + check_unboxed_abstract_arg loc univ row_more; + begin match row_name with + | None -> () + | Some (_, args) -> List.iter (check_unboxed_abstract_arg loc univ) args + end + | Tpoly (t, _) -> check_unboxed_abstract_arg loc univ t + +and check_unboxed_abstract_row_field loc univ (_, field) = + match field with + | Rpresent (Some ty) -> check_unboxed_abstract_arg loc univ ty + | Reither (_, args, _, r) -> + List.iter (check_unboxed_abstract_arg loc univ) args; + begin match !r with + | None -> () + | Some f -> check_unboxed_abstract_row_field loc univ ("", f) + end + | Rabsent + | Rpresent None -> () + (* Check that the argument to a GADT constructor is compatible with unboxing - the type, given the existential variables introduced by this constructor. *) -let rec check_unboxed_gadt_arg loc ex env ty = + the type, given the universal parameters of the type. *) +let rec check_unboxed_gadt_arg loc univ env ty = match get_unboxed_type_representation env ty with - | Some {desc = Tvar _; id} -> - let f t = (Btype.repr t).id = id in - if List.exists f ex then raise(Error(loc, Wrong_unboxed_type_float)) + | Some {desc = Tvar _; id} -> check_type_var loc univ id | Some {desc = Tarrow _ | Ttuple _ | Tpackage _ | Tobject _ | Tnil | Tvariant _; _} -> () @@ -285,10 +342,10 @@ let rec check_unboxed_gadt_arg loc ex env ty = let tydecl = Env.find_type p env in assert (not tydecl.type_unboxed.unboxed); if tydecl.type_kind = Type_abstract then - List.iter (check_unboxed_gadt_arg loc ex env) args + List.iter (check_unboxed_abstract_arg loc univ) args | Some {desc = Tfield _ | Tlink _ | Tsubst _; _} -> assert false | Some {desc = Tunivar _; _} -> () - | Some {desc = Tpoly (t2, _); _} -> check_unboxed_gadt_arg loc ex env t2 + | Some {desc = Tpoly (t2, _); _} -> check_unboxed_gadt_arg loc univ env t2 | None -> () (* This case is tricky: the argument is another (or the same) type in the same recursive definition. In this case we don't have to @@ -381,10 +438,14 @@ let transl_declaration env sdecl id = unboxed (or abstract) type constructor applied to some existential type variable. Of course we also have to rule out any abstract type constructor applied to anything that - might be an existential type variable. *) + might be an existential type variable. + There is a difficulty with existential variables created + out of thin air (rather than bound by the declaration). + See PR#7511 and GPR#1133 for details. *) match Datarepr.constructor_existentials args ret_type with | _, [] -> () - | [argty], ex -> check_unboxed_gadt_arg sdecl.ptype_loc ex env argty + | [argty], _ex -> + check_unboxed_gadt_arg sdecl.ptype_loc params env argty | _ -> assert false end; let tcstr = @@ -1204,10 +1265,7 @@ let transl_type_decl env rec_flag sdecl_list = Ctype.begin_def(); (* Enter types. *) let temp_env = - match rec_flag with - | Asttypes.Nonrecursive -> env - | Asttypes.Recursive -> List.fold_left2 enter_type env sdecl_list id_list - in + List.fold_left2 (enter_type rec_flag) env sdecl_list id_list in (* Translate each declaration. *) let current_slot = ref None in let warn_unused = Warnings.is_active (Warnings.Unused_type_declaration "") in @@ -1330,7 +1388,7 @@ let transl_extension_constructor env type_path type_params in args, ret_type, Text_decl(targs, tret_type) | Pext_rebind lid -> - let cdescr = Typetexp.find_constructor env sext.pext_loc lid.txt in + let cdescr = Typetexp.find_constructor env lid.loc lid.txt in let usage = if cdescr.cstr_private = Private || priv = Public then Env.Positive else Env.Privatize @@ -1438,7 +1496,8 @@ let transl_type_extension check_open env loc styext = reset_type_variables(); Ctype.begin_def(); let (type_path, type_decl) = - Typetexp.find_type env loc styext.ptyext_path.txt + let lid = styext.ptyext_path in + Typetexp.find_type env lid.loc lid.txt in begin match type_decl.type_kind with diff --git a/typing/typedtree.ml b/typing/typedtree.ml index d06a13b9..db4440c1 100644 --- a/typing/typedtree.ml +++ b/typing/typedtree.ml @@ -77,7 +77,8 @@ and expression_desc = Texp_ident of Path.t * Longident.t loc * Types.value_description | Texp_constant of constant | Texp_let of rec_flag * value_binding list * expression - | Texp_function of arg_label * case list * partial + | Texp_function of { arg_label : arg_label; param : Ident.t; + cases : case list; partial : partial; } | Texp_apply of expression * (arg_label * expression option) list | Texp_match of expression * case list * case list * partial | Texp_try of expression * case list diff --git a/typing/typedtree.mli b/typing/typedtree.mli index c773083b..ee26bca3 100644 --- a/typing/typedtree.mli +++ b/typing/typedtree.mli @@ -143,10 +143,14 @@ and expression_desc = (** let P1 = E1 and ... and Pn = EN in E (flag = Nonrecursive) let rec P1 = E1 and ... and Pn = EN in E (flag = Recursive) *) - | Texp_function of arg_label * case list * partial + | Texp_function of { arg_label : arg_label; param : Ident.t; + cases : case list; partial : partial; } (** [Pexp_fun] and [Pexp_function] both translate to [Texp_function]. See {!Parsetree} for more details. + [param] is the identifier that is to be used to name the + parameter of the function. + partial = [Partial] if the pattern match is partial [Total] otherwise. diff --git a/typing/typedtreeIter.ml b/typing/typedtreeIter.ml index 86b96531..fd04e552 100644 --- a/typing/typedtreeIter.ml +++ b/typing/typedtreeIter.ml @@ -270,7 +270,7 @@ module MakeIterator(Iter : IteratorArgument) : sig | Texp_let (rec_flag, list, exp) -> iter_bindings rec_flag list; iter_expression exp - | Texp_function (_label, cases, _) -> + | Texp_function { cases; _ } -> iter_cases cases | Texp_apply (exp, list) -> iter_expression exp; diff --git a/typing/typedtreeMap.ml b/typing/typedtreeMap.ml index 0695b2fe..58249be2 100644 --- a/typing/typedtreeMap.ml +++ b/typing/typedtreeMap.ml @@ -271,8 +271,8 @@ module MakeMap(Map : MapArgument) = struct Texp_let (rec_flag, map_bindings list, map_expression exp) - | Texp_function (label, cases, partial) -> - Texp_function (label, map_cases cases, partial) + | Texp_function { arg_label; param; cases; partial; } -> + Texp_function { arg_label; param; cases = map_cases cases; partial; } | Texp_apply (exp, list) -> Texp_apply (map_expression exp, List.map (fun (label, expo) -> diff --git a/typing/typemod.ml b/typing/typemod.ml index 0aa95e5d..cdff23ee 100644 --- a/typing/typemod.ml +++ b/typing/typemod.ml @@ -78,7 +78,7 @@ let extract_sig_open env loc mty = Mty_signature sg -> sg | Mty_alias(_, path) -> raise(Error(loc, env, Cannot_scrape_alias path)) - | _ -> raise(Error(loc, env, Structure_expected mty)) + | mty -> raise(Error(loc, env, Structure_expected mty)) (* Compute the environment after opening a module *) @@ -125,7 +125,7 @@ let check_type_decl env loc id row_id newdecl decl rs rem = let env = match row_id with | None -> env - | Some id -> Env.add_type ~check:true id newdecl env + | Some id -> Env.add_type ~check:false id newdecl env in let env = if rs = Trec_not then env else add_rec_types env rem in Includemod.type_declarations env id newdecl decl; @@ -188,7 +188,7 @@ let merge_constraint initial_env loc sg constr = } and id_row = Ident.create (s^"#row") in let initial_env = - Env.add_type ~check:true id_row decl_row initial_env + Env.add_type ~check:false id_row decl_row initial_env in let tdecl = Typedecl.transl_with_constraint initial_env id (Some(Pident id_row)) decl sdecl in @@ -1291,6 +1291,8 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = md_loc = pmb_loc; } in + (*prerr_endline (Ident.unique_toplevel_name id);*) + Mtype.lower_nongen (Ident.binding_time id - 1) md.md_type; let newenv = Env.enter_module_declaration id md env in Tstr_module {mb_id=id; mb_name=name; mb_expr=modl; mb_attributes=attrs; mb_loc=pmb_loc; @@ -1635,13 +1637,13 @@ let type_implementation sourcefile outputprefix modulename initial_env ast = case, the inferred signature contains only the last declaration. *) if not !Clflags.dont_write_files then begin let deprecated = Builtin_attributes.deprecated_of_str ast in - let sg = + let cmi = Env.save_signature ~deprecated simple_sg modulename (outputprefix ^ ".cmi") in Cmt_format.save_cmt (outputprefix ^ ".cmt") modulename (Cmt_format.Implementation str) - (Some sourcefile) initial_env (Some sg); + (Some sourcefile) initial_env (Some cmi); end; (str, coercion) end @@ -1722,13 +1724,13 @@ let package_units initial_env objfiles cmifile modulename = (Env.imports()) in (* Write packaged signature *) if not !Clflags.dont_write_files then begin - let sg = + let cmi = Env.save_signature_with_imports ~deprecated:None sg modulename (prefix ^ ".cmi") imports in Cmt_format.save_cmt (prefix ^ ".cmt") modulename - (Cmt_format.Packed (sg, objfiles)) None initial_env (Some sg) + (Cmt_format.Packed (cmi.Cmi_format.cmi_sign, objfiles)) None initial_env (Some cmi) end; Tcoerce_none end diff --git a/typing/typemod.mli b/typing/typemod.mli index 40172bcc..fab7cdae 100644 --- a/typing/typemod.mli +++ b/typing/typemod.mli @@ -47,7 +47,7 @@ val path_of_module : Typedtree.module_expr -> Path.t option val save_signature: string -> Typedtree.signature -> string -> string -> - Env.t -> Types.signature_item list -> unit + Env.t -> Cmi_format.cmi_infos -> unit val package_units: Env.t -> string list -> string -> string -> Typedtree.module_coercion diff --git a/typing/typetexp.ml b/typing/typetexp.ml index e0d06dd1..f37a5c13 100644 --- a/typing/typetexp.ml +++ b/typing/typetexp.ml @@ -340,7 +340,7 @@ let rec transl_type env policy styp = let ty = newty (Ttuple (List.map (fun ctyp -> ctyp.ctyp_type) ctys)) in ctyp (Ttyp_tuple ctys) ty | Ptyp_constr(lid, stl) -> - let (path, decl) = find_type env styp.ptyp_loc lid.txt in + let (path, decl) = find_type env lid.loc lid.txt in let stl = match stl with | [ {ptyp_desc=Ptyp_any} as t ] when decl.type_arity > 1 -> @@ -374,7 +374,7 @@ let rec transl_type env policy styp = ctyp (Ttyp_constr (path, lid, args)) constr | Ptyp_object (fields, o) -> let fields = - List.map (fun (s, a, t) -> (s, a, transl_poly_type env policy t)) + List.map (fun (s, a, t) -> (s.txt, a, transl_poly_type env policy t)) fields in let ty = newobj (transl_fields loc env policy [] o fields) in @@ -408,7 +408,7 @@ let rec transl_type env policy styp = let decl = Env.find_type path env in (path, decl, false) with Not_found -> - ignore (find_class env styp.ptyp_loc lid.txt); assert false + ignore (find_class env lid.loc lid.txt); assert false in if List.length stl <> decl.type_arity then raise(Error(styp.ptyp_loc, env, @@ -598,7 +598,8 @@ let rec transl_type env policy styp = in let ty = newty (Tvariant row) in ctyp (Ttyp_variant (tfields, closed, present)) ty - | Ptyp_poly(vars, st) -> + | Ptyp_poly(vars, st) -> + let vars = List.map (fun v -> v.txt) vars in begin_def(); let new_univars = List.map (fun name -> name, newvar ~name ()) vars in let old_univars = !univars in @@ -869,7 +870,7 @@ let report_error env ppf = function fprintf ppf "Multiple constraints for type %a" longident s | Repeated_method_label s -> fprintf ppf "@[This is the second method `%s' of this object type.@ %s@]" - s "Multiple occurences are not allowed." + s "Multiple occurrences are not allowed." | Unbound_value lid -> fprintf ppf "Unbound value %a" longident lid; spellcheck ppf fold_values env lid; diff --git a/typing/untypeast.ml b/typing/untypeast.ml index 3b62145d..0cb58f48 100644 --- a/typing/untypeast.ml +++ b/typing/untypeast.ml @@ -331,7 +331,7 @@ let exp_extra sub (extra, loc, attrs) sexp = | Texp_open (ovf, _path, lid, _) -> Pexp_open (ovf, map_loc sub lid, sexp) | Texp_poly cto -> Pexp_poly (sexp, map_opt (sub.typ sub) cto) - | Texp_newtype s -> Pexp_newtype (s, sexp) + | Texp_newtype s -> Pexp_newtype (mkloc s loc, sexp) in Exp.mk ~loc ~attrs desc @@ -365,13 +365,15 @@ let expression sub exp = (* Pexp_function can't have a label, so we split in 3 cases. *) (* One case, no guard: It's a fun. *) - | Texp_function (label, [{c_lhs=p; c_guard=None; c_rhs=e}], _) -> - Pexp_fun (label, None, sub.pat sub p, sub.expr sub e) + | Texp_function { arg_label; cases = [{c_lhs=p; c_guard=None; c_rhs=e}]; + _ } -> + Pexp_fun (arg_label, None, sub.pat sub p, sub.expr sub e) (* No label: it's a function. *) - | Texp_function (Nolabel, cases, _) -> + | Texp_function { arg_label = Nolabel; cases; _; } -> Pexp_function (sub.cases sub cases) (* Mix of both, we generate `fun ~label:$name$ -> match $name$ with ...` *) - | Texp_function (Labelled s | Optional s as label, cases, _) -> + | Texp_function { arg_label = Labelled s | Optional s as label; cases; + _ } -> let name = fresh_name s exp.exp_env in Pexp_fun (label, None, Pat.var ~loc {loc;txt = name }, Exp.match_ ~loc (Exp.ident ~loc {loc;txt= Lident name}) @@ -438,8 +440,8 @@ let expression sub exp = dir, sub.expr sub exp3) | Texp_send (exp, meth, _) -> Pexp_send (sub.expr sub exp, match meth with - Tmeth_name name -> name - | Tmeth_val id -> Ident.name id) + Tmeth_name name -> mkloc name loc + | Tmeth_val id -> mkloc (Ident.name id) loc) | Texp_new (_path, lid, _) -> Pexp_new (map_loc sub lid) | Texp_instvar (_, path, name) -> Pexp_ident ({loc = sub.location sub name.loc ; txt = lident_of_path path}) @@ -661,9 +663,9 @@ let class_type_field sub ctf = let desc = match ctf.ctf_desc with Tctf_inherit ct -> Pctf_inherit (sub.class_type sub ct) | Tctf_val (s, mut, virt, ct) -> - Pctf_val (s, mut, virt, sub.typ sub ct) + Pctf_val (mkloc s loc, mut, virt, sub.typ sub ct) | Tctf_method (s, priv, virt, ct) -> - Pctf_method (s, priv, virt, sub.typ sub ct) + Pctf_method (mkloc s loc, priv, virt, sub.typ sub ct) | Tctf_constraint (ct1, ct2) -> Pctf_constraint (sub.typ sub ct1, sub.typ sub ct2) | Tctf_attribute x -> Pctf_attribute x @@ -684,14 +686,17 @@ let core_type sub ct = List.map (sub.typ sub) list) | Ttyp_object (list, o) -> Ptyp_object - (List.map (fun (s, a, t) -> (s, a, sub.typ sub t)) list, o) + (List.map (fun (s, a, t) -> + (mkloc s loc, a, sub.typ sub t)) list, o) | Ttyp_class (_path, lid, list) -> Ptyp_class (map_loc sub lid, List.map (sub.typ sub) list) | Ttyp_alias (ct, s) -> Ptyp_alias (sub.typ sub ct, s) | Ttyp_variant (list, bool, labels) -> Ptyp_variant (List.map (sub.row_field sub) list, bool, labels) - | Ttyp_poly (list, ct) -> Ptyp_poly (list, sub.typ sub ct) + | Ttyp_poly (list, ct) -> + let list = List.map (fun v -> mkloc v loc) list in + Ptyp_poly (list, sub.typ sub ct) | Ttyp_package pack -> Ptyp_package (sub.package_type sub pack) in Typ.mk ~loc ~attrs desc @@ -723,7 +728,8 @@ let class_field sub cf = let attrs = sub.attributes sub cf.cf_attributes in let desc = match cf.cf_desc with Tcf_inherit (ovf, cl, super, _vals, _meths) -> - Pcf_inherit (ovf, sub.class_expr sub cl, super) + Pcf_inherit (ovf, sub.class_expr sub cl, + map_opt (fun v -> mkloc v loc) super) | Tcf_constraint (cty, cty') -> Pcf_constraint (sub.typ sub cty, sub.typ sub cty') | Tcf_val (lab, mut, _, Tcfk_virtual cty, _) -> @@ -734,7 +740,8 @@ let class_field sub cf = Pcf_method (lab, priv, Cfk_virtual (sub.typ sub cty)) | Tcf_method (lab, priv, Tcfk_concrete (o, exp)) -> let remove_fun_self = function - | { exp_desc = Texp_function(Nolabel, [case], _) } + | { exp_desc = + Texp_function { arg_label = Nolabel; cases = [case]; _ } } when is_self_pat case.c_lhs && case.c_guard = None -> case.c_rhs | e -> e in @@ -742,7 +749,8 @@ let class_field sub cf = Pcf_method (lab, priv, Cfk_concrete (o, sub.expr sub exp)) | Tcf_initializer exp -> let remove_fun_self = function - | { exp_desc = Texp_function(Nolabel, [case], _) } + | { exp_desc = + Texp_function { arg_label = Nolabel; cases = [case]; _ } } when is_self_pat case.c_lhs && case.c_guard = None -> case.c_rhs | e -> e in diff --git a/utils/ccomp.ml b/utils/ccomp.ml index b90090c3..30115b0b 100644 --- a/utils/ccomp.ml +++ b/utils/ccomp.ml @@ -101,6 +101,19 @@ let compile_file name = then display_msvc_output file name; exit +let macos_create_empty_archive ~quoted_archive = + let result = + command (Printf.sprintf "%s rc %s /dev/null" Config.ar quoted_archive) + in + if result <> 0 then result + else + let result = + command (Printf.sprintf "%s %s 2> /dev/null" Config.ranlib quoted_archive) + in + if result <> 0 then result + else + command (Printf.sprintf "%s d %s /dev/null" Config.ar quoted_archive) + let create_archive archive file_list = Misc.remove_file archive; let quoted_archive = Filename.quote archive in @@ -110,12 +123,20 @@ let create_archive archive file_list = quoted_archive (quote_files file_list)) | _ -> assert(String.length Config.ar > 0); - let r1 = - command(Printf.sprintf "%s rc %s %s" - Config.ar quoted_archive (quote_files file_list)) in - if r1 <> 0 || String.length Config.ranlib = 0 - then r1 - else command(Config.ranlib ^ " " ^ quoted_archive) + let is_macosx = + match Config.system with + | "macosx" -> true + | _ -> false + in + if is_macosx && file_list = [] then (* PR#6550 *) + macos_create_empty_archive ~quoted_archive + else + let r1 = + command(Printf.sprintf "%s rc %s %s" + Config.ar quoted_archive (quote_files file_list)) in + if r1 <> 0 || String.length Config.ranlib = 0 + then r1 + else command(Config.ranlib ^ " " ^ quoted_archive) let expand_libname name = if String.length name < 2 || String.sub name 0 2 <> "-l" diff --git a/utils/clflags.ml b/utils/clflags.ml index bd884872..04c95847 100644 --- a/utils/clflags.ml +++ b/utils/clflags.ml @@ -159,6 +159,9 @@ let unsafe_string = ref (not Config.safe_string) let classic_inlining = ref false (* -Oclassic *) let inlining_report = ref false (* -inlining-report *) +let afl_instrument = ref Config.afl_instrument (* -afl-instrument *) +let afl_inst_ratio = ref 100 (* -afl-inst-ratio *) + let simplify_rounds = ref None (* -rounds *) let default_simplify_rounds = ref 1 (* -rounds *) let rounds () = @@ -355,6 +358,36 @@ let parse_color_setting = function | "always" -> Some Misc.Color.Always | "never" -> Some Misc.Color.Never | _ -> None -let color = ref Misc.Color.Auto ;; (* -color *) +let color = ref None ;; (* -color *) let unboxed_types = ref false + +let arg_spec = ref [] +let arg_names = ref Misc.StringMap.empty +let add_arguments loc args = + List.iter (function (arg_name, _, _) as arg -> + try + let loc2 = Misc.StringMap.find arg_name !arg_names in + Printf.eprintf + "Warning: plugin argument %s is already defined:\n" arg_name; + Printf.eprintf " First definition: %s\n" loc2; + Printf.eprintf " New definition: %s\n" loc; + with Not_found -> + arg_spec := !arg_spec @ [ arg ]; + arg_names := Misc.StringMap.add arg_name loc !arg_names + ) args + +let print_arguments usage = + Arg.usage !arg_spec usage + +(* This function is almost the same as [Arg.parse_expand], except + that [Arg.parse_expand] could not be used because it does not take a + reference for [arg_spec].*) +let parse_arguments f msg = + try + let argv = ref Sys.argv in + let current = ref (!Arg.current) in + Arg.parse_and_expand_argv_dynamic current argv arg_spec f msg + with + | Arg.Bad msg -> Printf.eprintf "%s" msg; exit 2 + | Arg.Help msg -> Printf.printf "%s" msg; exit 0 diff --git a/utils/clflags.mli b/utils/clflags.mli index f7939eb6..79e79aad 100644 --- a/utils/clflags.mli +++ b/utils/clflags.mli @@ -193,12 +193,31 @@ val inline_max_depth : Int_arg_helper.parsed ref val remove_unused_arguments : bool ref val dump_flambda_verbose : bool ref val classic_inlining : bool ref +val afl_instrument : bool ref +val afl_inst_ratio : int ref val all_passes : string list ref val dumped_pass : string -> bool val set_dumped_pass : string -> bool -> unit val parse_color_setting : string -> Misc.Color.setting option -val color : Misc.Color.setting ref +val color : Misc.Color.setting option ref val unboxed_types : bool ref + +val arg_spec : (string * Arg.spec * string) list ref + +(* [add_arguments __LOC__ args] will add the arguments from [args] at + the end of [arg_spec], checking that they have not already been + added by [add_arguments] before. A warning is printed showing the + locations of the function from which the argument was previously + added. *) +val add_arguments : string -> (string * Arg.spec * string) list -> unit + +(* [parse_arguments anon_arg usage] will parse the arguments, using + the arguments provided in [Clflags.arg_spec]. It allows plugins to + provide their own arguments. +*) +val parse_arguments : Arg.anon_fun -> string -> unit + +val print_arguments : string -> unit diff --git a/utils/config.mli b/utils/config.mli index 9b050056..07be0f12 100644 --- a/utils/config.mli +++ b/utils/config.mli @@ -128,6 +128,9 @@ val default_executable_name: string val systhread_supported : bool (* Whether the system thread library is implemented *) +val flexdll_dirs : string list + (* Directories needed for the FlexDLL objects *) + val host : string (* Whether the compiler is a cross-compiler *) @@ -136,11 +139,16 @@ val target : string val print_config : out_channel -> unit;; +val profiling : bool + (* Whether profiling with gprof is supported on this platform *) + val flambda : bool (* Whether the compiler was configured for flambda *) val spacetime : bool (* Whether the compiler was configured for Spacetime profiling *) +val profinfo : bool + (* Whether the compiler was configured for profiling *) val profinfo_width : int (* How many bits are to be used in values' headers for profiling information *) @@ -151,3 +159,5 @@ val libunwind_link_flags : string val safe_string: bool (* Whether the compiler was configured with -safe-string *) +val afl_instrument : bool + (* Whether afl-fuzz instrumentation is generated by default *) diff --git a/utils/config.mlp b/utils/config.mlp index e821ef07..28bff73a 100644 --- a/utils/config.mlp +++ b/utils/config.mlp @@ -14,16 +14,6 @@ (* *) (**************************************************************************) -(***********************************************************************) -(** **) -(** WARNING WARNING WARNING **) -(** **) -(** When you change this file, you must make the parallel change **) -(** in config.mlbuild **) -(** **) -(***********************************************************************) - - (* The main OCaml version string has moved to ../VERSION *) let version = Sys.ocaml_version @@ -40,9 +30,9 @@ let standard_library = let standard_runtime = "%%BYTERUN%%" let ccomp_type = "%%CCOMPTYPE%%" -let bytecomp_c_compiler = "%%BYTECC%%" +let bytecomp_c_compiler = "%%BYTECODE_C_COMPILER%%" let bytecomp_c_libraries = "%%BYTECCLIBS%%" -let native_c_compiler = "%%NATIVECC%%" +let native_c_compiler = "%%NATIVE_C_COMPILER%%" let native_c_libraries = "%%NATIVECCLIBS%%" let native_pack_linker = "%%PACKLD%%" let ranlib = "%%RANLIBCMD%%" @@ -67,9 +57,12 @@ let mkdll, mkexe, mkmaindll = else "%%MKDLL%%", "%%MKEXE%%", "%%MKMAINDLL%%" +let profiling = %%PROFILING%% let flambda = %%FLAMBDA%% let safe_string = %%SAFE_STRING%% +let afl_instrument = %%AFL_INSTRUMENT%% + let exec_magic_number = "Caml1999X011" and cmi_magic_number = "Caml1999I021" and cmo_magic_number = "Caml1999O011" @@ -87,7 +80,7 @@ and cmxa_magic_number = and ast_impl_magic_number = "Caml1999M020" and ast_intf_magic_number = "Caml1999N018" and cmxs_magic_number = "Caml2007D002" -and cmt_magic_number = "Caml2012T008" +and cmt_magic_number = "Caml2012T009" let load_path = ref ([] : string list) @@ -113,8 +106,10 @@ let with_frame_pointers = %%WITH_FRAME_POINTERS%% let spacetime = %%WITH_SPACETIME%% let libunwind_available = %%LIBUNWIND_AVAILABLE%% let libunwind_link_flags = "%%LIBUNWIND_LINK_FLAGS%%" +let profinfo = %%WITH_PROFINFO%% let profinfo_width = %%PROFINFO_WIDTH%% +let ext_exe = "%%EXT_EXE%%" let ext_obj = "%%EXT_OBJ%%" let ext_asm = "%%EXT_ASM%%" let ext_lib = "%%EXT_LIB%%" @@ -131,8 +126,11 @@ let default_executable_name = let systhread_supported = %%SYSTHREAD_SUPPORT%%;; +let flexdll_dirs = [%%FLEXDLL_DIR%%];; + let print_config oc = let p name valu = Printf.fprintf oc "%s: %s\n" name valu in + let p_int name valu = Printf.fprintf oc "%s: %d\n" name valu in let p_bool name valu = Printf.fprintf oc "%s: %B\n" name valu in p "version" version; p "standard_library_default" standard_library_default; @@ -148,10 +146,13 @@ let print_config oc = p "cc_profile" cc_profile; p "architecture" architecture; p "model" model; + p_int "int_size" Sys.int_size; + p_int "word_size" Sys.word_size; p "system" system; p "asm" asm; p_bool "asm_cfi_supported" asm_cfi_supported; p_bool "with_frame_pointers" with_frame_pointers; + p "ext_exe" ext_exe; p "ext_obj" ext_obj; p "ext_asm" ext_asm; p "ext_lib" ext_lib; @@ -161,6 +162,7 @@ let print_config oc = p_bool "systhread_supported" systhread_supported; p "host" host; p "target" target; + p_bool "profiling" profiling; p_bool "flambda" flambda; p_bool "spacetime" spacetime; p_bool "safe_string" safe_string; diff --git a/utils/identifiable.ml b/utils/identifiable.ml index 0a2f3be9..8bbafcd3 100644 --- a/utils/identifiable.ml +++ b/utils/identifiable.ml @@ -53,14 +53,21 @@ module Make_map (T : Thing) = struct let of_list l = List.fold_left (fun map (id, v) -> add id v map) empty l - let disjoint_union ?eq m1 m2 = + let disjoint_union ?eq ?print m1 m2 = union (fun id v1 v2 -> let ok = match eq with | None -> false | Some eq -> eq v1 v2 in if not ok then - let err = Format.asprintf "Map.disjoint_union %a" T.print id in + let err = + match print with + | None -> + Format.asprintf "Map.disjoint_union %a" T.print id + | Some print -> + Format.asprintf "Map.disjoint_union %a => %a <> %a" + T.print id print v1 print v2 + in Misc.fatal_error err else Some v1) m1 m2 @@ -195,7 +202,7 @@ module type S = sig val filter_map : 'a t -> f:(key -> 'a -> 'b option) -> 'b t val of_list : (key * 'a) list -> 'a t - val disjoint_union : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t + val disjoint_union : ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> 'a t -> 'a t val union_right : 'a t -> 'a t -> 'a t val union_left : 'a t -> 'a t -> 'a t val union_merge : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t diff --git a/utils/identifiable.mli b/utils/identifiable.mli index 255a6a59..55ed4446 100644 --- a/utils/identifiable.mli +++ b/utils/identifiable.mli @@ -57,7 +57,7 @@ module type S = sig (** [disjoint_union m1 m2] contains all bindings from [m1] and [m2]. If some binding is present in both and the associated value is not equal, a Fatal_error is raised *) - val disjoint_union : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t + val disjoint_union : ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> 'a t -> 'a t (** [union_right m1 m2] contains all bindings from [m1] and [m2]. If some binding is present in both, the one from [m2] is taken *) diff --git a/utils/misc.ml b/utils/misc.ml index 8ff77775..fa084bf1 100644 --- a/utils/misc.ml +++ b/utils/misc.ml @@ -601,10 +601,10 @@ module Color = struct Format.set_mark_tags true; List.iter set_color_tag_handling formatter_l; color_enabled := (match o with - | Always -> true - | Auto -> should_enable_color () - | Never -> false - ) + | Some Always -> true + | Some Auto -> should_enable_color () + | Some Never -> false + | None -> should_enable_color ()) ); () end diff --git a/utils/misc.mli b/utils/misc.mli index bdcbae95..0cd23baa 100644 --- a/utils/misc.mli +++ b/utils/misc.mli @@ -130,7 +130,7 @@ val no_overflow_add: int -> int -> bool (* [no_overflow_add n1 n2] returns [true] if the computation of [n1 + n2] does not overflow. *) val no_overflow_sub: int -> int -> bool - (* [no_overflow_add n1 n2] returns [true] if the computation of + (* [no_overflow_sub n1 n2] returns [true] if the computation of [n1 - n2] does not overflow. *) val no_overflow_mul: int -> int -> bool (* [no_overflow_mul n1 n2] returns [true] if the computation of @@ -160,8 +160,8 @@ val search_substring: string -> string -> int -> int does not occur. *) val replace_substring: before:string -> after:string -> string -> string - (* [search_substring ~before ~after str] replaces all - occurences of [before] with [after] in [str] and returns + (* [replace_substring ~before ~after str] replaces all + occurrences of [before] with [after] in [str] and returns the resulting string. *) val rev_split_words: string -> string list @@ -277,7 +277,7 @@ module Color : sig type setting = Auto | Always | Never - val setup : setting -> unit + val setup : setting option -> unit (* [setup opt] will enable or disable color handling on standard formatters according to the value of color setting [opt]. Only the first call to this function has an effect. *) @@ -322,7 +322,7 @@ exception HookExnWrapper of val raise_direct_hook_exn: exn -> 'a (** A hook can use [raise_unwrapped_hook_exn] to raise an exception that will - not be wrapped into a [HookExnWrapper]. *) + not be wrapped into a {!HookExnWrapper}. *) module type HookSig = sig type t diff --git a/utils/numbers.mli b/utils/numbers.mli index 3e2c622c..873f409f 100644 --- a/utils/numbers.mli +++ b/utils/numbers.mli @@ -14,7 +14,7 @@ (* *) (**************************************************************************) -(** Modules about numbers that satisfy [Identifiable.S]. *) +(** Modules about numbers that satisfy {!Identifiable.S}. *) module Int : sig include Identifiable.S with type t = int diff --git a/utils/targetint.ml b/utils/targetint.ml new file mode 100644 index 00000000..78405a36 --- /dev/null +++ b/utils/targetint.ml @@ -0,0 +1,98 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Nicolas Ojeda Bar, LexiFi *) +(* *) +(* Copyright 2016 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type repr = + | Int32 of int32 + | Int64 of int64 + +module type S = sig + type t + val zero : t + val one : t + val minus_one : t + val neg : t -> t + val add : t -> t -> t + val sub : t -> t -> t + val mul : t -> t -> t + val div : t -> t -> t + val rem : t -> t -> t + val succ : t -> t + val pred : t -> t + val abs : t -> t + val max_int : t + val min_int : t + val logand : t -> t -> t + val logor : t -> t -> t + val logxor : t -> t -> t + val lognot : t -> t + val shift_left : t -> int -> t + val shift_right : t -> int -> t + val shift_right_logical : t -> int -> t + val of_int : int -> t + val of_int_exn : int -> t + val to_int : t -> int + val of_float : float -> t + val to_float : t -> float + val of_int32 : int32 -> t + val to_int32 : t -> int32 + val of_int64 : int64 -> t + val to_int64 : t -> int64 + val of_string : string -> t + val to_string : t -> string + val compare: t -> t -> int + val equal: t -> t -> bool + val repr: t -> repr +end + +let size = Sys.word_size +(* Later, this will be set by the configure script + in order to support cross-compilation. *) + +module Int32 = struct + include Int32 + let of_int_exn = + match Sys.word_size with (* size of [int] *) + | 32 -> + Int32.of_int + | 64 -> + fun n -> + if n < Int32.(to_int min_int) || n > Int32.(to_int max_int) then + Misc.fatal_errorf "Targetint.of_int_exn: 0x%x out of range" n + else + Int32.of_int n + | _ -> + assert false + let of_int32 x = x + let to_int32 x = x + let of_int64 = Int64.to_int32 + let to_int64 = Int64.of_int32 + let repr x = Int32 x +end + +module Int64 = struct + include Int64 + let of_int_exn = Int64.of_int + let of_int64 x = x + let to_int64 x = x + let repr x = Int64 x +end + +include (val + (match size with + | 32 -> (module Int32) + | 64 -> (module Int64) + | _ -> assert false + ) : S) diff --git a/utils/targetint.mli b/utils/targetint.mli new file mode 100644 index 00000000..005e2501 --- /dev/null +++ b/utils/targetint.mli @@ -0,0 +1,188 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Nicolas Ojeda Bar, LexiFi *) +(* *) +(* Copyright 2016 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Target processor-native integers. + + This module provides operations on the type of + signed 32-bit integers (on 32-bit target platforms) or + signed 64-bit integers (on 64-bit target platforms). + This integer type has exactly the same width as that of a + pointer type in the C compiler. All arithmetic operations over + are taken modulo 2{^32} or 2{^64} depending + on the word size of the target architecture. +*) + +type t +(** The type of target integers. *) + +val zero : t +(** The target integer 0.*) + +val one : t +(** The target integer 1.*) + +val minus_one : t +(** The target integer -1.*) + +val neg : t -> t +(** Unary negation. *) + +val add : t -> t -> t +(** Addition. *) + +val sub : t -> t -> t +(** Subtraction. *) + +val mul : t -> t -> t +(** Multiplication. *) + +val div : t -> t -> t +(** Integer division. Raise [Division_by_zero] if the second + argument is zero. This division rounds the real quotient of + its arguments towards zero, as specified for {!Pervasives.(/)}. *) + +val rem : t -> t -> t +(** Integer remainder. If [y] is not zero, the result + of [Targetint.rem x y] satisfies the following properties: + [Targetint.zero <= Nativeint.rem x y < Targetint.abs y] and + [x = Targetint.add (Targetint.mul (Targetint.div x y) y) + (Targetint.rem x y)]. + If [y = 0], [Targetint.rem x y] raises [Division_by_zero]. *) + +val succ : t -> t +(** Successor. + [Targetint.succ x] is [Targetint.add x Targetint.one]. *) + +val pred : t -> t +(** Predecessor. + [Targetint.pred x] is [Targetint.sub x Targetint.one]. *) + +val abs : t -> t +(** Return the absolute value of its argument. *) + +val size : int +(** The size in bits of a target native integer. *) + +val max_int : t +(** The greatest representable target integer, + either 2{^31} - 1 on a 32-bit platform, + or 2{^63} - 1 on a 64-bit platform. *) + +val min_int : t +(** The smallest representable target integer, + either -2{^31} on a 32-bit platform, + or -2{^63} on a 64-bit platform. *) + +val logand : t -> t -> t +(** Bitwise logical and. *) + +val logor : t -> t -> t +(** Bitwise logical or. *) + +val logxor : t -> t -> t +(** Bitwise logical exclusive or. *) + +val lognot : t -> t +(** Bitwise logical negation *) + +val shift_left : t -> int -> t +(** [Targetint.shift_left x y] shifts [x] to the left by [y] bits. + The result is unspecified if [y < 0] or [y >= bitsize], + where [bitsize] is [32] on a 32-bit platform and + [64] on a 64-bit platform. *) + +val shift_right : t -> int -> t +(** [Targetint.shift_right x y] shifts [x] to the right by [y] bits. + This is an arithmetic shift: the sign bit of [x] is replicated + and inserted in the vacated bits. + The result is unspecified if [y < 0] or [y >= bitsize]. *) + +val shift_right_logical : t -> int -> t +(** [Targetint.shift_right_logical x y] shifts [x] to the right + by [y] bits. + This is a logical shift: zeroes are inserted in the vacated bits + regardless of the sign of [x]. + The result is unspecified if [y < 0] or [y >= bitsize]. *) + +val of_int : int -> t +(** Convert the given integer (type [int]) to a target integer + (type [t]), module the target word size. *) + +val of_int_exn : int -> t +(** Convert the given integer (type [int]) to a target integer + (type [t]). Raises a fatal error if the conversion is not exact. *) + +val to_int : t -> int +(** Convert the given target integer (type [t]) to an + integer (type [int]). The high-order bit is lost during + the conversion. *) + +val of_float : float -> t +(** Convert the given floating-point number to a target integer, + discarding the fractional part (truncate towards 0). + The result of the conversion is undefined if, after truncation, + the number is outside the range + \[{!Targetint.min_int}, {!Targetint.max_int}\]. *) + +val to_float : t -> float +(** Convert the given target integer to a floating-point number. *) + +val of_int32 : int32 -> t +(** Convert the given 32-bit integer (type [int32]) + to a target integer. *) + +val to_int32 : t -> int32 +(** Convert the given target integer to a + 32-bit integer (type [int32]). On 64-bit platforms, + the 64-bit native integer is taken modulo 2{^32}, + i.e. the top 32 bits are lost. On 32-bit platforms, + the conversion is exact. *) + +val of_int64 : int64 -> t +(** Convert the given 64-bit integer (type [int64]) + to a target integer. *) + +val to_int64 : t -> int64 +(** Convert the given target integer to a + 64-bit integer (type [int64]). *) + +val of_string : string -> t +(** Convert the given string to a target integer. + The string is read in decimal (by default) or in hexadecimal, + octal or binary if the string begins with [0x], [0o] or [0b] + respectively. + Raise [Failure "int_of_string"] if the given string is not + a valid representation of an integer, or if the integer represented + exceeds the range of integers representable in type [nativeint]. *) + +val to_string : t -> string +(** Return the string representation of its argument, in decimal. *) + +val compare: t -> t -> int +(** The comparison function for target integers, with the same specification as + {!Pervasives.compare}. Along with the type [t], this function [compare] + allows the module [Targetint] to be passed as argument to the functors + {!Set.Make} and {!Map.Make}. *) + +val equal: t -> t -> bool +(** The equal function for target ints. *) + +type repr = + | Int32 of int32 + | Int64 of int64 + +val repr : t -> repr +(** The concrete representation of a native integer. *) diff --git a/utils/timings.ml b/utils/timings.ml index 881bba8b..4fe6ec3a 100644 --- a/utils/timings.ml +++ b/utils/timings.ml @@ -24,7 +24,9 @@ type source_provenance = type compiler_pass = | All | Parsing of file - | Preprocessing of file + | Parser of file + | Dash_pp of file + | Dash_ppx of file | Typing of file | Transl of file | Generate of file @@ -48,28 +50,33 @@ type compiler_pass = let timings : (compiler_pass, float * float option) Hashtbl.t = Hashtbl.create 20 +external time_include_children: bool -> float = "caml_sys_time_include_children" +let cpu_time () = time_include_children true + let reset () = Hashtbl.clear timings let start pass = (* Cannot assert it is not here: a source file can be compiled multiple times on the same command line *) (* assert(not (Hashtbl.mem timings pass)); *) - let time = Sys.time () in + let time = cpu_time () in Hashtbl.add timings pass (time, None) let stop pass = assert(Hashtbl.mem timings pass); - let time = Sys.time () in + let time = cpu_time () in let (start, stop) = Hashtbl.find timings pass in assert(stop = None); Hashtbl.replace timings pass (start, Some (time -. start)) -let time pass f x = +let time_call pass f = start pass; - let r = f x in + let r = f () in stop pass; r +let time pass f x = time_call pass (fun () -> f x) + let restart pass = let previous_duration = match Hashtbl.find timings pass with @@ -77,11 +84,11 @@ let restart pass = | (_, Some duration) -> duration | _, None -> assert false in - let time = Sys.time () in + let time = cpu_time () in Hashtbl.replace timings pass (time, Some previous_duration) let accumulate pass = - let time = Sys.time () in + let time = cpu_time () in match Hashtbl.find timings pass with | exception Not_found -> assert false | _, None -> assert false @@ -110,7 +117,9 @@ let kind_name = function let pass_name = function | All -> "all" | Parsing file -> Printf.sprintf "parsing(%s)" file - | Preprocessing file -> Printf.sprintf "preprocessing(%s)" file + | Parser file -> Printf.sprintf "parser(%s)" file + | Dash_pp file -> Printf.sprintf "-pp(%s)" file + | Dash_ppx file -> Printf.sprintf "-ppx(%s)" file | Typing file -> Printf.sprintf "typing(%s)" file | Transl file -> Printf.sprintf "transl(%s)" file | Generate file -> Printf.sprintf "generate(%s)" file @@ -134,15 +143,16 @@ let pass_name = function let timings_list () = let l = Hashtbl.fold (fun pass times l -> (pass, times) :: l) timings [] in - List.sort (fun (_, (start1, _)) (_, (start2, _)) -> compare start1 start2) l + List.sort (fun (pass1, (start1, _)) (pass2, (start2, _)) -> + compare (start1, pass1) (start2, pass2)) l let print ppf = - let current_time = Sys.time () in + let current_time = cpu_time () in List.iter (fun (pass, (start, stop)) -> match stop with | Some duration -> Format.fprintf ppf "%s: %.03fs@." (pass_name pass) duration | None -> - Format.fprintf ppf "%s: running since %.03fs@." (pass_name pass) + Format.fprintf ppf "%s: running for %.03fs@." (pass_name pass) (current_time -. start)) (timings_list ()) diff --git a/utils/timings.mli b/utils/timings.mli index c02c5e47..1983a9ce 100644 --- a/utils/timings.mli +++ b/utils/timings.mli @@ -26,7 +26,9 @@ type source_provenance = type compiler_pass = | All | Parsing of file - | Preprocessing of file + | Parser of file + | Dash_pp of file + | Dash_ppx of file | Typing of file | Transl of file | Generate of file @@ -53,8 +55,11 @@ val reset : unit -> unit val get : compiler_pass -> float option (** returns the runtime in seconds of a completed pass *) +val time_call : compiler_pass -> (unit -> 'a) -> 'a +(** [time_call pass f] calls [f] and records its runtime. *) + val time : compiler_pass -> ('a -> 'b) -> 'a -> 'b -(** [time pass f arg] Record the runtime of [f arg] *) +(** [time pass f arg] records the runtime of [f arg] *) val accumulate_time : compiler_pass -> ('a -> 'b) -> 'a -> 'b (** Like time for passes that can run multiple times *) diff --git a/yacc/Makefile b/yacc/Makefile index 6c32474b..d5be9f96 100644 --- a/yacc/Makefile +++ b/yacc/Makefile @@ -20,6 +20,12 @@ include ../config/Makefile CC=$(BYTECC) CFLAGS=-DNDEBUG $(BYTECCCOMPOPTS) +ifeq "$(TOOLCHAIN)" "mingw" + CFLAGS += -DNO_UNIX +else ifeq "$(TOOLCHAIN)" "msvc" + CFLAGS += -DNO_UNIX +endif + OBJS= closure.$(O) error.$(O) lalr.$(O) lr0.$(O) main.$(O) \ mkpar.$(O) output.$(O) reader.$(O) \ skeleton.$(O) symtab.$(O) verbose.$(O) warshall.$(O) @@ -30,7 +36,7 @@ ocamlyacc$(EXE): $(OBJS) $(MKEXE) -o ocamlyacc$(EXE) $(OBJS) $(EXTRALIBS) version.h : ../VERSION - echo "#define OCAML_VERSION \"`sed -e 1q ../VERSION`\"" >version.h + echo "#define OCAML_VERSION \"`sed -e 1q $^ | tr -d '\r'`\"" > $@ clean: rm -f *.$(O) ocamlyacc$(EXE) *~ version.h @@ -49,3 +55,9 @@ skeleton.$(O): defs.h symtab.$(O): defs.h verbose.$(O): defs.h warshall.$(O): defs.h + +# The following rule is similar to make's default one, except that it +# also works for .obj files. + +%.$(O): %.c + $(CC) $(CFLAGS) -c $< diff --git a/yacc/Makefile.nt b/yacc/Makefile.nt index 917f48bd..ed9900bb 100644 --- a/yacc/Makefile.nt +++ b/yacc/Makefile.nt @@ -14,6 +14,3 @@ #************************************************************************** include Makefile - -%.$(O): %.c - $(BYTECC) -DNDEBUG -DNO_UNIX $(BYTECCCOMPOPTS) -c $< diff --git a/yacc/reader.c b/yacc/reader.c index 85ee63ea..3e99e8c8 100644 --- a/yacc/reader.c +++ b/yacc/reader.c @@ -102,7 +102,12 @@ void get_line(void) line = REALLOC(line, linesize); if (line == 0) no_space(); } - if (c == '\n') { line[i] = '\0'; cptr = line; return; } + if (c == '\n') { + if (i >= 2 && line[i-2] == '\r') { + line[i-2] = '\n'; i--; + } + line[i] = '\0'; cptr = line; return; + } c = getc(f); if (c == EOF) { saw_eof = 1; c = '\n'; } } -- 2.30.2